OpenCV實(shí)現(xiàn)繪制輪廓外接矩形
1.尋找輪廓
api
void cv::findContours( InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset = Point()
各個(gè)參數(shù)詳解如下:
Image表示輸入圖像,必須是二值圖像,二值圖像可以threshold輸出、Canny輸出、inRange輸出、自適應(yīng)閾值輸出等。
Contours獲取的輪廓,每個(gè)輪廓是一系列的點(diǎn)集合
Hierarchy輪廓的層次信息,每個(gè)輪廓有四個(gè)相關(guān)信息,分別是同層下一個(gè)、前一個(gè)、第一個(gè)子節(jié)點(diǎn)、父節(jié)點(diǎn)
mode 表示輪廓尋找時(shí)候的拓?fù)浣Y(jié)構(gòu)返回 -RETR_EXTERNAL表示只返回最外層輪廓 -RETR_TREE表示返回輪廓樹結(jié)構(gòu)
- CV_RETR_EXTERNAL:只檢測(cè)外輪廓。忽略輪廓內(nèi)部的洞
- CV_RETR_LIST:檢測(cè)所有輪廓,但不建立繼承(包含)關(guān)系
- CV_RETR_TREE:檢測(cè)所有輪廓,并且建立所有的繼承(包含)關(guān)系。也就是說(shuō)用CV_RETR_EXTERNAL和CV_RETR_LIST方法的時(shí)候hierarchy這個(gè)變量是沒用的,因?yàn)榍罢邲]有包含關(guān)系,找到的都是外輪廓,后者僅僅是找到所喲的輪廓但并不把包含關(guān)系區(qū)分。用TREE這種檢測(cè)方法的時(shí)候我們的hierarchy這個(gè)參數(shù)才是有意義的
- CV_RETR_CCOMP:檢測(cè)所有輪廓,但是僅僅建立兩層包含關(guān)系。外輪廓放到頂層,外輪廓包含的第一層內(nèi)輪廓放到底層,如果內(nèi)輪廓還包含輪廓,那就把這些內(nèi)輪廓放到頂層去。
Method表示輪廓點(diǎn)集合取得是基于什么算法,常見的是基于CHAIN_APPROX_SIMPLE鏈?zhǔn)骄幋a方法
注意,如果圖像底色是白色,則檢測(cè)最外層的輪廓為圖像邊框
2.繪制輪廓外接矩形
繪制外接矩形包括兩種:
繪制最大外接矩形
(Rect cv::boundingRect( InputArray points ))
其中,輸入?yún)?shù)points為一系列點(diǎn)的集合(findContours中contours中的一個(gè)元素),對(duì)輪廓來(lái)說(shuō)就是該輪廓的點(diǎn)集 返回結(jié)果是一個(gè)矩形,x, y, w, h
繪制最小外接矩形
RotatedRect cv::minAreaRect( InputArray points )
其中,輸入?yún)?shù)points為一系列點(diǎn)的集合(findContours中contours中的一個(gè)元素) ,對(duì)輪廓來(lái)說(shuō)就是該輪廓的點(diǎn)集 返回結(jié)果是一個(gè)旋轉(zhuǎn)矩形,包含下面的信息: - 矩形中心位置 - 矩形的寬高 - 旋轉(zhuǎn)角度。
3.代碼
EdgeDetection.h
#pragma once #include<opencv2/opencv.hpp> #include<iostream> using namespace std; using namespace cv; class EdgeDetection { cv::Mat m_img; cv::Mat m_canny; public: EdgeDetection(cv::Mat iamge); bool cannyProcess(unsigned int downThreshold,unsigned int upThreshold); bool getContours(); ~EdgeDetection(); };
EdgeDetection.cpp
#include "EdgeDetection.h" EdgeDetection::EdgeDetection(cv::Mat image) { m_img = image; } bool EdgeDetection::cannyProcess(unsigned int downThreshold, unsigned int upThreshold) { bool ret=true; if (m_img.empty()) { ret = false; } cv::Canny(m_img, m_canny, downThreshold, upThreshold); cv::imshow("Canny", m_canny); return ret; } bool EdgeDetection::getContours() { bool ret = true; if (m_canny.empty()) { ret = false; } cv::Mat k = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3, 3), cv::Point(-1, -1)); cv::dilate(m_canny, m_canny, k); imshow("dilate", m_canny); // 輪廓發(fā)現(xiàn)與繪制 vector<vector<cv::Point> > contours; vector<Vec4i> hierarchy; findContours(m_canny, contours, cv::RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point()); for (size_t i = 0; i < contours.size();++i) { // 最大外接輪廓 cv::Rect rect = cv::boundingRect(contours[i]); cv::rectangle(m_img,rect,cv::Scalar(0,255,0),2,LINE_8); // 最小外接輪廓 RotatedRect rrt = minAreaRect(contours[i]); Point2f pts[4]; rrt.points(pts); // 繪制旋轉(zhuǎn)矩形與中心位置 for (int i = 0; i < 4; i++) { line(m_img, pts[i % 4], pts[(i + 1) % 4], Scalar(0, 0, 255), 2, 8, 0); } Point2f cpt = rrt.center; circle(m_img, cpt, 2, Scalar(255, 0, 0), 2, 8, 0); } imshow("contours", m_img); return ret; } EdgeDetection::~EdgeDetection() { }
main.cpp
#include"EdgeDetection.h" using namespace std; using namespace cv; int main(int argc, char* argv[]) { Mat src = imread("rect.jpg"); if (src.empty()) { cout << "image is empty" << endl; return -1; } imshow("input", src); EdgeDetection ed(src); ed.cannyProcess(80,160); ed.getContours(); waitKey(0); return 0; }
原圖
canny
目標(biāo)圖
到此這篇關(guān)于OpenCV實(shí)現(xiàn)繪制輪廓外接矩形的文章就介紹到這了,更多相關(guān)OpenCV輪廓外接矩形內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Opencv實(shí)現(xiàn)邊緣檢測(cè)與輪廓發(fā)現(xiàn)及繪制輪廓方法詳解
這篇文章主要介紹了Opencv實(shí)現(xiàn)邊緣檢測(cè)與輪廓發(fā)現(xiàn)及繪制輪廓方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)吧2022-12-12C語(yǔ)言運(yùn)算符及其優(yōu)先級(jí)匯總表口訣
由于C語(yǔ)言的運(yùn)算符優(yōu)先級(jí)與C++的不完全一樣(主要是增加了幾個(gè)運(yùn)算符),所以這個(gè)口訣不能完全實(shí)用于C++.但是應(yīng)該能夠兼容,大家可以比較一下他們的區(qū)別應(yīng)該就能夠很快掌握C++的優(yōu)先級(jí)的2013-07-07浮點(diǎn)數(shù)在計(jì)算機(jī)中存儲(chǔ)方式是怎樣的
這篇文章介紹了浮點(diǎn)數(shù)在計(jì)算機(jī)中是如何存儲(chǔ)的,講解的比較詳細(xì),有需要的朋友可以參考一下。2016-06-06C語(yǔ)言中將日期和時(shí)間以字符串格式輸出的方法
這篇文章主要介紹了C語(yǔ)言中將日期和時(shí)間以字符串格式輸出的方法,分別是ctime()函數(shù)和asctime()函數(shù),注意參數(shù)區(qū)別,需要的朋友可以參考下2015-08-08