您好,登錄后才能下訂單哦!
本篇文章給大家分享的是有關(guān)使用OpenCV怎么識(shí)別圓與矩形,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
識(shí)別圓
在識(shí)別圓方面,OpenCV有內(nèi)置的方法:霍夫圓變化:
HoughCircles(edges, circles, CV_HOUGH_GRADIENT, 1.5, 10, 200, 100, 0, 0);
參數(shù)分析:
edges:灰度圖像
circles: std::vector<Vec3f> circles;數(shù)組,用來存儲(chǔ)圓的坐標(biāo)信息
CV_HOUGH_GRADIENT:Hough 變換方式,目前只支持CV_HOUGH_GRADIENT, which is basically 21HT, described in [Yuen03].默認(rèn)用這個(gè)
1.5:累加器圖像的分辨率,1的時(shí)候是與獲取到的圖像相同,1.5就是1.5倍
10:圓與圓的最小距離,兩個(gè)圓心距離如果在范圍內(nèi)則被認(rèn)定為1個(gè)圓
200:100-200兩個(gè)參數(shù)選就夠了
100:默認(rèn)100,數(shù)值越低識(shí)別圓越不精確(圓的數(shù)量識(shí)別變多可能有個(gè)弧線就被識(shí)別是圓)
最后兩個(gè)參數(shù)分別是識(shí)別 圓的最小,最大的面積。
矩形識(shí)別
矩形識(shí)別并沒有內(nèi)置方法,需要自己手寫。
最主要的方法是二值化。通過二值化來調(diào)節(jié)識(shí)別的強(qiáng)度。
cvThreshold(tgray, gray, 75, 250, CV_THRESH_BINARY);
參數(shù)分析:
src:原始數(shù)組 (單通道 , 8-bit of 32-bit 浮點(diǎn)數(shù))。
dst:輸出數(shù)組,必須與 src 的類型一致,或者為 8-bit。
threshold:閾值
max_value:使用 CV_THRESH_BINARY 和 CV_THRESH_BINARY_INV 的最大值。
threshold_type:閾值類型
threshold_type=CV_THRESH_BINARY:如果 src(x,y)>threshold ,dst(x,y) = max_value; 否則,dst(x,y)=0;
threshold_type=CV_THRESH_BINARY_INV:如果 src(x,y)>threshold,dst(x,y) = 0; 否則,dst(x,y) = max_value.
threshold_type=CV_THRESH_TRUNC:如果 src(x,y)>threshold,dst(x,y) = max_value; 否則dst(x,y) = src(x,y).
threshold_type=CV_THRESH_TOZERO:如果src(x,y)>threshold,dst(x,y) = src(x,y) ; 否則 dst(x,y) = 0。
threshold_type=CV_THRESH_TOZERO_INV:如果 src(x,y)>threshold,dst(x,y) = 0 ; 否則dst(x,y) = src(x,y).
效果圖如下:
在矩形識(shí)別里面的二值化圖:
圓識(shí)別:
源碼:
#include <opencv2/opencv.hpp> #include <opencv2/imgproc/imgproc.hpp> #include <WINSOCK2.H> #include<iostream> #include<thread> #include <winsock2.h> #include <stdio.h> #include<string> #include <windows.h> #pragma comment(lib,"ws2_32.lib") #include<vector> using namespace cv; ////////////////////////////////////////////////////////////////// //函數(shù)功能:用向量來做COSα=兩向量之積/兩向量模的乘積求兩條線段夾角 //輸入: 線段3個(gè)點(diǎn)坐標(biāo)pt1,pt2,pt0,最后一個(gè)參數(shù)為公共點(diǎn) //輸出: 線段夾角,單位為角度 ////////////////////////////////////////////////////////////////// double angle(CvPoint* pt1, CvPoint* pt2, CvPoint* pt0) { double dx1 = pt1->x - pt0->x; double dy1 = pt1->y - pt0->y; double dx2 = pt2->x - pt0->x; double dy2 = pt2->y - pt0->y; double angle_line = (dx1*dx2 + dy1 * dy2) / sqrt((dx1*dx1 + dy1 * dy1)*(dx2*dx2 + dy2 * dy2) + 1e-10);//余弦值 return acos(angle_line) * 180 / 3.141592653; } ////////////////////////////////////////////////////////////////// //函數(shù)功能:采用多邊形檢測(cè),通過約束條件尋找矩形 //輸入: img 原圖像 // storage 存儲(chǔ) // minarea,maxarea 檢測(cè)矩形的最小/最大面積 // minangle,maxangle 檢測(cè)矩形邊夾角范圍,單位為角度 //輸出: 矩形序列 ////////////////////////////////////////////////////////////////// CvSeq* findSquares4(IplImage* img, CvMemStorage* storage, int minarea, int maxarea, int minangle, int maxangle, int(&temp)[30]) { CvSeq* contours;//邊緣 int N = 6; //閾值分級(jí) CvSize sz = cvSize(img->width & -2, img->height & -2); IplImage* timg = cvCloneImage(img);//拷貝一次img IplImage* gray = cvCreateImage(sz, 8, 1); //img灰度圖 IplImage* pyr = cvCreateImage(cvSize(sz.width / 2, sz.height / 2), 8, 3); //金字塔濾波3通道圖像中間變量 IplImage* tgray = cvCreateImage(sz, 8, 1); ; CvSeq* result; double s, t; int sk = 0; CvSeq* squares = cvCreateSeq(0, sizeof(CvSeq), sizeof(CvPoint), storage); cvSetImageROI(timg, cvRect(0, 0, sz.width, sz.height)); //金字塔濾波 cvPyrDown(timg, pyr, 7); cvPyrUp(pyr, timg, 7); //在3個(gè)通道中尋找矩形 for (int c = 0; c < 3; c++) //對(duì)3個(gè)通道分別進(jìn)行處理 { cvSetImageCOI(timg, c + 1); cvCopy(timg, tgray, 0); //依次將BGR通道送入tgray for (int l = 0; l < N; l++) { //不同閾值下二值化 cvThreshold(tgray, gray, 75, 250, CV_THRESH_BINARY); cvShowImage("111", gray); cvFindContours(gray, storage, &contours, sizeof(CvContour), CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE, cvPoint(0, 0)); while (contours) { //多邊形逼近 result = cvApproxPoly(contours, sizeof(CvContour), storage, CV_POLY_APPROX_DP, cvContourPerimeter(contours)*0.02, 0); //如果是凸四邊形并且面積在范圍內(nèi) if (result->total == 4 && fabs(cvContourArea(result, CV_WHOLE_SEQ)) > minarea && fabs(cvContourArea(result, CV_WHOLE_SEQ)) < maxarea && cvCheckContourConvexity(result)) { s = 0; //判斷每一條邊 for (int i = 0; i < 5; i++) { if (i >= 2) { //角度 t = fabs(angle((CvPoint*)cvGetSeqElem(result, i), (CvPoint*)cvGetSeqElem(result, i - 2), (CvPoint*)cvGetSeqElem(result, i - 1))); s = s > t ? s : t; } } //這里的S為直角判定條件 單位為角度 if (s > minangle && s < maxangle) { for (int i = 0; i < 4; i++) cvSeqPush(squares, (CvPoint*)cvGetSeqElem(result, i)); CvRect rect = cvBoundingRect(contours, 1); // 獲取矩形邊界框 CvPoint p1; p1 = cvPoint(rect.x + rect.width / 2, rect.y + rect.height / 2); //矩形中心坐標(biāo) std::cout << "X:" << p1.x << "Y:" << p1.y << std::endl; } } contours = contours->h_next; } } std::cout << "圓的數(shù)量是"<<sk << std::endl; temp[26] = sk; sk = 0; } cvReleaseImage(&gray); cvReleaseImage(&pyr); cvReleaseImage(&tgray); cvReleaseImage(&timg); return squares; } ////////////////////////////////////////////////////////////////// //函數(shù)功能:畫出所有矩形 //輸入: img 原圖像 // squares 矩形序列 // wndname 窗口名稱 //輸出: 圖像中標(biāo)記矩形 ////////////////////////////////////////////////////////////////// void drawSquares(IplImage* img, CvSeq* squares, const char* wndname) { CvSeqReader reader; IplImage* cpy = cvCloneImage(img); CvPoint pt[4]; int i; cvStartReadSeq(squares, &reader, 0); for (i = 0; i < squares->total; i += 4) { CvPoint* rect = pt; int count = 4; memcpy(pt, reader.ptr, squares->elem_size); CV_NEXT_SEQ_ELEM(squares->elem_size, reader); memcpy(pt + 1, reader.ptr, squares->elem_size); CV_NEXT_SEQ_ELEM(squares->elem_size, reader); memcpy(pt + 2, reader.ptr, squares->elem_size); CV_NEXT_SEQ_ELEM(squares->elem_size, reader); memcpy(pt + 3, reader.ptr, squares->elem_size); CV_NEXT_SEQ_ELEM(squares->elem_size, reader); //cvPolyLine( cpy, &rect, &count, 1, 1, CV_RGB(0,255,0), 3, CV_AA, 0 ); cvPolyLine(cpy, &rect, &count, 1, 1, CV_RGB(rand() & 255, rand() & 255, rand() & 255), 1, CV_AA, 0);//彩色繪制 } cvShowImage("22", cpy); cvReleaseImage(&cpy); } void SendMessageOne() { //開起攝像頭 VideoCapture capture; capture.open(0); Mat edges; //定義轉(zhuǎn)化的灰度圖 if (!capture.isOpened()) namedWindow("【效果圖】", CV_WINDOW_NORMAL); const char* winn = "1111"; if (!capture.isOpened()) //namedWindow(winn, CV_WINDOW_NORMAL); CvMemStorage* storage = 0; CvMemStorage* storage = 0; storage = cvCreateMemStorage(0); while (1) { int Y=0, J=0; Mat frame; capture >> frame; IplImage img0 = frame; //drawSquares(&img0, findSquares4(&img0, storage, 100, 2000, 80, 100, a), winn); //cvClearMemStorage(storage); //清空存儲(chǔ) Mat E = frame(Range(1, 320), Range(1, 240)); cvtColor(frame, edges, CV_BGR2GRAY); //高斯濾波 GaussianBlur(edges, edges, Size(7, 7), 2, 2); std::vector<Vec3f> circles;//存儲(chǔ)每個(gè)圓的位置信息 //霍夫圓 HoughCircles(edges, circles, CV_HOUGH_GRADIENT, 1.5, 10, 100, 100, 0, 50); for (size_t i = 0; i < circles.size(); i++) { Point center(cvRound(circles[i][0]), cvRound(circles[i][1])); int radius = cvRound(circles[i][2]); //std::cout << "圓的X是" << circles[i][0] << "圓的Y是" << circles[i][1] << std:: endl; //繪制圓輪廓 circle(frame, center, radius, Scalar(155, 50, 255), 3, 8, 0); int R = frame.at<Vec3b>(cvRound(circles[i][1]), cvRound(circles[i][0]))[2];//R int G = frame.at<Vec3b>(cvRound(circles[i][1]), cvRound(circles[i][0]))[1];//G int B = frame.at<Vec3b>(cvRound(circles[i][1]), cvRound(circles[i][0]))[0];//B int num = R + G + B; std::cout << "圓心顏色是" << num << std::endl; } imshow("【效果圖】", frame); waitKey(30); } } int main() { std::thread *a = new std::thread(SendMessageOne); a->join(); return 0; }
以上就是使用OpenCV怎么識(shí)別圓與矩形,小編相信有部分知識(shí)點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過這篇文章學(xué)到更多知識(shí)。更多詳情敬請(qǐng)關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。