本篇文章給大家分享的是有關使用OpenCV怎么識別圓與矩形,小編覺得挺實用的,因此分享給大家學習,希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。
創(chuàng)新互聯(lián)公司主營西城網(wǎng)站建設的網(wǎng)絡公司,主營網(wǎng)站建設方案,手機APP定制開發(fā),西城h5成都小程序開發(fā)搭建,西城網(wǎng)站營銷推廣歡迎西城等地區(qū)企業(yè)咨詢
識別圓
在識別圓方面,OpenCV有內置的方法:霍夫圓變化:
HoughCircles(edges, circles, CV_HOUGH_GRADIENT, 1.5, 10, 200, 100, 0, 0);
參數(shù)分析:
edges:灰度圖像
circles: std::vector<Vec3f> circles;數(shù)組,用來存儲圓的坐標信息
CV_HOUGH_GRADIENT:Hough 變換方式,目前只支持CV_HOUGH_GRADIENT, which is basically 21HT, described in [Yuen03].默認用這個
1.5:累加器圖像的分辨率,1的時候是與獲取到的圖像相同,1.5就是1.5倍
10:圓與圓的最小距離,兩個圓心距離如果在范圍內則被認定為1個圓
200:100-200兩個參數(shù)選就夠了
100:默認100,數(shù)值越低識別圓越不精確(圓的數(shù)量識別變多可能有個弧線就被識別是圓)
最后兩個參數(shù)分別是識別 圓的最小,最大的面積。
矩形識別
矩形識別并沒有內置方法,需要自己手寫。
最主要的方法是二值化。通過二值化來調節(jié)識別的強度。
cvThreshold(tgray, gray, 75, 250, CV_THRESH_BINARY);
參數(shù)分析:
src:原始數(shù)組 (單通道 , 8-bit of 32-bit 浮點數(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).
效果圖如下:
在矩形識別里面的二值化圖:

圓識別:

源碼:
#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個點坐標pt1,pt2,pt0,最后一個參數(shù)為公共點
//輸出: 線段夾角,單位為角度
//////////////////////////////////////////////////////////////////
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ù)功能:采用多邊形檢測,通過約束條件尋找矩形
//輸入: img 原圖像
// storage 存儲
// minarea,maxarea 檢測矩形的最小/最大面積
// minangle,maxangle 檢測矩形邊夾角范圍,單位為角度
//輸出: 矩形序列
//////////////////////////////////////////////////////////////////
CvSeq* findSquares4(IplImage* img, CvMemStorage* storage, int minarea, int maxarea, int minangle, int maxangle, int(&temp)[30])
{
CvSeq* contours;//邊緣
int N = 6; //閾值分級
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個通道中尋找矩形
for (int c = 0; c < 3; c++) //對3個通道分別進行處理
{
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);
//如果是凸四邊形并且面積在范圍內
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); //矩形中心坐標
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 窗口名稱
//輸出: 圖像中標記矩形
//////////////////////////////////////////////////////////////////
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; //定義轉化的灰度圖
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); //清空存儲
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;//存儲每個圓的位置信息
//霍夫圓
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怎么識別圓與矩形,小編相信有部分知識點可能是我們日常工作會見到或用到的。希望你能通過這篇文章學到更多知識。更多詳情敬請關注創(chuàng)新互聯(lián)行業(yè)資訊頻道。
分享文章:使用OpenCV怎么識別圓與矩形
標題路徑:http://chinadenli.net/article4/gesdoe.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供域名注冊、定制開發(fā)、微信公眾號、動態(tài)網(wǎng)站、云服務器、虛擬主機
聲明:本網(wǎng)站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯(lián)