一种基于OpenCV的多扇区圆检测方法
opencv 实时计算相机拍摄的圆半径的算法

opencv 实时计算相机拍摄的圆半径的算法好的,下面是使用`opencv`计算相机拍摄的圆半径的算法步骤:1. 导入图片,将其转换为灰度图。
2. 使用`cv2.HoughCircles()`函数对图片中的圆形进行检测。
3. 循环遍历检测到的圆形,使用`cv2.circle()`函数绘制出检测到的圆形。
下面是上述步骤的代码实现:```pythonimport numpy as npimport cv2# 读取图片image = cv2.imread("123.jpg")# 复制图片output = image.copy()# 将图片转换为灰度图gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 检测图片中的圆形circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1.2, 100)# 如果检测到圆形if circles is not None:# 将检测到的圆形转换为整数类型circles = np.round(circles(0, :)).astype("int")# 遍历检测到的圆形for (x, y, r) in circles:# 绘制检测到的圆形cv2.circle(output, (x, y), r, (0, 255, 0), 4)# 绘制圆形轮廓cv2.rectangle(output, (x - 5, y - 5), (x + 5, y + 5), (0, 128, 255), -1)# 显示结果cv2.imshow("output", np.hstack((image, output)))# 等待用户按下任意键cv2.waitKey(0)```在上述代码中,首先使用`cv2.imread()`函数读取图片,并通过`cv2.copy()`函数复制一份原始图片。
一种基于OpenCV的多扇区圆检测方法

根据 圆的特 性 , 究 学 者 们 进 行 了 广 泛 的研 究 , 研 提 出了几何 特征 的 圆检源自测方 法、 曲线 拟合 圆检 测技
术 、 度方 向角 的 圆 检 测 方 法 、 于 共 形 几 何 代 数 梯 基 与 R dn变换 的 圆 检 测 方 法 等 多 种 检 测 技 术 J ao ,
dw 和 Ma S操作 系统 上 。 目前 , 最新 版本 22 os cO 其 .
已发 布 。O e C pn V致 力 于 真 实 世 界 的 实 时 应 用 , 通
过 优化 的 c代 码 的编 写 对 其 执 行 速 度 带 来 了可 观 的提 升 , 且 可 以通 过 购买 Itl IP高 性 能 多媒 并 ne 的 P
1 1期
矣昕宝 , : 等 一种基于 O eC p n V的多扇 区圆检测方法
3 9 69
2 2 多扇 区 圆检测模 型 与算 法原 理 .
被检测 图像与模 板第 i 扇区对应 的区域用点集 表 个
@
2 1 SiT c. nn . 0 1 c. eh E g g
一
种 基 于 O e C 的 多 扇 区 圆检 测 方 法 pn V
矣 昕 宝 全 海 燕 许伶 俐
( 双版纳 职业技 术学 院 西 ,西双版纳 6 60 6 10;昆明理工大学信息工程 与 自动化学 院 ,昆明 6 0 5 ) 50 1
者 和研 究 单 位 仍 致 力 于 如 何 进 一 步 提 高 圆检 测 正
体识别 、 图象分割、 人脸识 别、 动作识别 、 运动跟踪、
机器 人 等领域 。
2 多扇 区圆检测 原理
2 1 常用 的 圆检测 方法 .
确 率 方 面 的研 究 。O eC 作 为 开 源 的 机 器 视 觉 pnV 库 , 图像 检 浸 中得到 了广 泛 的应 用 。 在 4
2017-5-28圆弧检测(opencv-qt)

2017-5-28圆弧检测(opencv-qt)F:\学科、技能、编程\【编程-⽂件\proj\圆弧检测(opencv-qt)可以⾃动或者⼿动测量圆弧液柱的⾓度:使⽤说明:找圆⼼(最⼩⼆乘拟合)相关代码#include <iostream>#include <opencv2/opencv.hpp>using namespace std;using namespace cv;bool circleLeastFit(CvSeq* points, double ¢er_x, double ¢er_y, double &radius);//最⼩⼆乘法拟合函数int main(){const char* winname ="winname";//const char* winname1 ="winname1";//const char* winname2 ="winname2";//const char* winname3 ="winname3";char * picname = "P11.jpg";//加载原图IplImage * pImage = cvLoadImage(picname);//分量图像IplImage *pR = cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U,1);IplImage *pG = cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U,1);IplImage *pB = cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U,1);IplImage *temp = cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U,1);IplImage *binary = cvCreateImage(cvGetSize(pImage),IPL_DEPTH_8U,1);//trackbar的变量值 //对应各个通道int b_low =20;int b_high = 100;int g_low = 20;int g_high = 100;int r_low = 0;int r_high = 100;//轮廓相关CvMemStorage *storage = cvCreateMemStorage(0);CvSeq * seq = cvCreateSeq(CV_SEQ_ELTYPE_POINT, sizeof(CvSeq), sizeof(CvPoint), storage);//窗⼝cvNamedWindow(winname);cvShowImage(winname, pImage); //显⽰原图cvNamedWindow("r",2);cvNamedWindow("g",2);cvNamedWindow("b",2); //各个通道cvNamedWindow("binary",2);//⼆值化图//在相应的窗⼝建⽴滑动条cvCreateTrackbar( "b1","b", &b_low, 254, NULL); //H通道分量范围0-180cvSetTrackbarPos("b1","b",0 ); //设置默认位置cvCreateTrackbar( "b2","b", &b_high, 254, NULL);//H通道分量范围0-180cvSetTrackbarPos("b2","b",110 );cvCreateTrackbar( "g1","g", &g_low, 254, NULL);cvSetTrackbarPos("g1","g",0 );cvCreateTrackbar( "g2","g", &g_high, 254, NULL);cvSetTrackbarPos("g2","g",158 );cvCreateTrackbar( "r1","r", &r_low, 254, NULL);cvSetTrackbarPos("r1","r",68 );cvCreateTrackbar( "r2","r", &r_high, 254, NULL);cvSetTrackbarPos("r2","r",137);while(1){//各个通道分离cvSplit(pImage,pB,pG,pR,NULL);//阈值化cvThreshold(pB, temp,b_low , 255, CV_THRESH_BINARY);cvThreshold(pB, pB,b_high , 255, CV_THRESH_BINARY_INV);cvAnd(temp,pB,pB,NULL);//与操作,合成⼀张图cvThreshold(pG, temp,g_low , 255, CV_THRESH_BINARY);cvThreshold(pG, pG,g_high , 255, CV_THRESH_BINARY_INV);cvAnd(temp,pG,pG,NULL);//与操作,合成⼀张图cvThreshold(pR, temp,r_low , 255, CV_THRESH_BINARY);cvThreshold(pR, pR,r_high , 255, CV_THRESH_BINARY_INV);cvAnd(temp,pR,pR,NULL);//与操作,合成⼀张图//显⽰各个通道的图像cvShowImage("b",pB);cvShowImage("g",pG);cvShowImage("r",pR);//合成到⼀张图⾥cvAnd(pB, pG, binary, NULL);cvAnd(pR, binary, binary, NULL);//膨胀腐蚀操作去除⿊点//cvDilate(binary,binary);//cvErode(binary,binary);//显⽰合成的⼆值化图cvShowImage("binary",binary);//cvSaveImage("erzhitu.jpg",binary);// 处理轮廓int cnt = cvFindContours(binary,storage,&seq,sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);//返回轮廓的数⽬ CvSeq* _contour =seq;cout<<"number of contours "<<cnt<<endl;////////////////////_//找到长度最⼤轮廓;double maxarea=0;int ind_max = -1;int m=0;for( ; seq != 0; seq = seq->h_next ){m++;double tmparea = abs(cvArcLength(seq,CV_WHOLE_SEQ,-1));//double contArea = fabs(cvContourArea(pcontour,CV_WHOLE_SEQ));if(tmparea > maxarea){maxarea = tmparea;ind_max=m;}// cout<<"seqfor: "<<seq->total<<endl;}m=0;seq = _contour;for( ; seq != 0; seq = seq->h_next ){m++;if(m == ind_max){break;}}CvSeq* cur_cont = seq;cout<<"seq: "<<seq->total<<endl;cout<<"cur_cont: "<<cur_cont->total<<endl;//for (int i=0;i<cur_cont->total;++i)//{// CvPoint* p = CV_GET_SEQ_ELEM(CvPoint,cur_cont,i);//输出轮廓上点的坐标// printf("(%d,%d)\n",p->x,p->y);//}//cvWaitKey(0);//建⽴彩⾊输出图像IplImage *pOutlineImage = cvCreateImage(cvGetSize(pImage), IPL_DEPTH_8U, 3);cvCopy(pImage,pOutlineImage);//int nLevels = 5;//获取最⼤轮廓的凸包点集CvSeq* hull=NULL;hull = cvConvexHull2(cur_cont,0,CV_CLOCKWISE,0);cout<<"hull total points number:"<<hull->total<<endl;CvPoint pt0 = **(CvPoint**)cvGetSeqElem(hull,hull->total - 1);for(int i = 0;i<hull->total;++i){CvPoint pt1 = **(CvPoint**)cvGetSeqElem(hull,i);cvLine(pOutlineImage,pt0,pt1,CV_RGB(0,0,255));pt0 = pt1;}//最⼩⼆乘法拟合圆double center_x=0;double center_y=0;double radius=0;cout<<"nihe :"<<circleLeastFit(hull, center_x, center_y, radius);cout<<"canshu: "<<center_x<<endl<<center_y<<endl<<radius<<endl;//绘制圆cvCircle(pOutlineImage,Point2f(center_x,center_y),radius,CV_RGB(0,100,100));////////////////////////////////////////////////////////////////////////////绘制轮廓//cvDrawContours(pOutlineImage, cur_cont, CV_RGB(255,0,0), CV_RGB(0,255,0),0);//cvDrawContours(dst,contour,CV_RGB(255,0,0),CV_RGB(0,255,0),0);cvShowImage(winname, pOutlineImage); //显⽰原图jiangshang luokuoif (cvWaitKey(1000) == 27){cvSaveImage("tutu.jpg",pOutlineImage);break;}cvClearMemStorage( storage ); //清除轮廓所占⽤的内存cvReleaseImage(&pOutlineImage);//清除彩⾊输出图像}cvDestroyAllWindows();cvReleaseImage(&pImage);cvReleaseImage(&pR);cvReleaseImage(&pG);cvReleaseImage(&pB);cvReleaseImage(&temp);cvReleaseImage(&binary);return0;}//最⼩⼆乘法拟合,输出圆⼼的xy坐标值和半径⼤⼩;bool circleLeastFit(CvSeq* points, double ¢er_x, double ¢er_y, double &radius) {center_x = 0.0f;center_y = 0.0f;radius = 0.0f;if (points->total < 3){return false;}double sum_x = 0.0f, sum_y = 0.0f;double sum_x2 = 0.0f, sum_y2 = 0.0f;double sum_x3 = 0.0f, sum_y3 = 0.0f;double sum_xy = 0.0f, sum_x1y2 = 0.0f, sum_x2y1 = 0.0f;int N = points->total ;for (int i = 0; i < N; i++){CvPoint pt1 = **(CvPoint**)cvGetSeqElem(points,i);double x =pt1.x;double y = pt1.y ;double x2 = x * x;double y2 = y * y;sum_x += x;sum_y += y;sum_x2 += x2;sum_y2 += y2;sum_x3 += x2 * x;sum_y3 += y2 * y;sum_xy += x * y;sum_x1y2 += x * y2;sum_x2y1 += x2 * y;}double C, D, E, G, H;double a, b, c;C = N * sum_x2 - sum_x * sum_x;D = N * sum_xy - sum_x * sum_y;E = N * sum_x3 + N * sum_x1y2 - (sum_x2 + sum_y2) * sum_x;G = N * sum_y2 - sum_y * sum_y;H = N * sum_x2y1 + N * sum_y3 - (sum_x2 + sum_y2) * sum_y;a = (H * D - E * G) / (C * G - D * D);b = (H * C - E * D) / (D * D - G * C);c = -(a * sum_x + b * sum_y + sum_x2 + sum_y2) / N;center_x = a / (-2);center_y = b / (-2);radius = sqrt(a * a + b * b - 4 * c) / 2;return true;}标定相关代码#include "opencv2/core/core.hpp"#include "opencv2/imgproc/imgproc.hpp"#include "opencv2/calib3d/calib3d.hpp"#include "opencv2/highgui/highgui.hpp"#include <iostream>#include <fstream>using namespace cv;using namespace std;#define MAX_GRAY_VALUE 255#define MIN_GRAY_VALUE 0using namespace cv;using namespace std;#include <opencv2/imgproc/imgproc.hpp>#include <iostream>#include <stdio.h>using namespace std;using namespace cv;bool check_line_state=false;IplImage* workImg;IplImage* imgshow;CvRect ROI_rect;IplImage* src=0;void on_mouse( int event, int x, int y, int flags, void* ustc){CvFont font;cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.5, 0.5, 0, 1, CV_AA);if( event == CV_EVENT_LBUTTONDOWN ){CvPoint pt = cvPoint(x,y);char temp[16];sprintf(temp,"(%d,%d)",pt.x,pt.y);cout<<"("<<pt.x<<","<<pt.y<<")"<<endl;x1=pt.x;y1=pt.y;cvPutText(src,temp, pt, &font, cvScalar(255, 255, 255, 0));cvCircle( src, pt, 2,cvScalar(255,0,0,0) ,CV_FILLED, CV_AA, 0 );cvShowImage( "src", src );}}int main(){//获取端点的坐标src=cvLoadImage("dst7.png",1);cvNamedWindow("src",1);cvSetMouseCallback( "src", on_mouse, 0 );cvShowImage("src",src);cvWaitKey(0);cvDestroyAllWindows();cvReleaseImage(&src);return0;}/*//寻找圆⼼坐标int main(int args,char** argv){ static double radius;static int i;Mat srcImage = imread("dst7.png");if (!srcImage.data)return -1;imshow("srcImage", srcImage);Mat srcGray;cvtColor(srcImage, srcGray, COLOR_BGR2GRAY);//⾼斯平滑滤波GaussianBlur(srcGray, srcGray, Size(9, 9), 2,2);static vector<Vec3f> circles;//Hough圆检测HoughCircles(srcGray, circles, CV_HOUGH_GRADIENT,1,srcGray.rows/8,200,16,0,0);//将得到的结果绘图for (size_t i = 0; i < circles.size(); i++){Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));cout<<center<<endl;radius = cvRound(circles[i][2]);cout<<radius<<endl;//检测圆中⼼circle(srcImage, center, 3, Scalar(0, 255, 0), -1, 8, 0);//检测圆轮廓circle(srcImage, center, radius, Scalar(120, 120, 120), 3, 8, 0);}imshow("HoughResult", srcImage);imwrite("HoughResult.jpg",srcImage);IplImage* image=cvLoadImage("dst5.png");int p=0;int q=0;for (int k=0;k<=360;k++){double m = 3.1415926535*2*k/360;CvScalar s;s=cvGet2D(image,cvRound(circles[i][0])+radius*cos(m),cvRound(circles[i][1])+radius*sin(m)); if(s.val[0]!=255){p++;q++;}elseq++;cout<<m<<p<<q<<endl;}waitKey(0);return 0;}//⼆值化部分//otsu函数计算最佳阈值int otsu(Mat dst){int i, j;int tmp;double u0, u1, w0, w1, u, uk;double cov;double maxcov = 0.0;int maxthread = 0;int hst[MAX_GRAY_VALUE] = { 0 };double pro_hst[MAX_GRAY_VALUE] = { 0.0 };int height = dst.cols;int width = dst.rows;//统计每个灰度的数量for (i = 0; i<width; i++){for (j = 0; j<height; j++){tmp = dst.at<uchar>(i, j);hst[tmp]++;}}//计算每个灰度级占图像中的概率for (i = MIN_GRAY_VALUE; i<MAX_GRAY_VALUE; i++) pro_hst[i] = (double)hst[i] / (double)(width*height);//计算全局平均灰度值u = 0.0;for (i = MIN_GRAY_VALUE; i<MAX_GRAY_VALUE; i++) u += i*pro_hst[i];//统计前景和背景的平均灰度值,并计算类间⽅差for (i = MIN_GRAY_VALUE; i<MAX_GRAY_VALUE; i++){ w0 = 0.0; w1 = 0.0; u0 = 0.0; u1 = 0.0; uk = 0.0;for (j = MIN_GRAY_VALUE; j < i; j++){uk += j*pro_hst[j];w0 += pro_hst[j];//前景占图像画幅⽐例}u0 = uk / w0;//前景平均灰度w1 = 1 - w0;//背景占图像画幅⽐例u1 = (u - uk) / (1 - w0);//背景平均灰度//计算类间⽅差cov = w0*w1*(u1 - u0)*(u1 - u0);if (cov > maxcov){maxcov = cov;maxthread = i;}}cout << maxthread << endl;return maxthread;}int main(){int width, height;int i, j;Mat obj = imread("22.jpg");Mat dst1;cvtColor(obj, dst1, CV_RGB2GRAY);//灰度化height = dst1.cols;//计算图像⾼度width = dst1.rows;//计算图像宽度int thd = otsu(dst1);imshow("原图", dst1);for (i = 0; i < width; i++)for (j = 0; j< height; j++)if (dst1.at<uchar>(i, j) > thd)dst1.at<uchar>(i, j) = MAX_GRAY_VALUE-1;elsedst1.at<uchar>(i, j) = MIN_GRAY_VALUE;imwrite("dst1.png",dst1);imshow("⼆值化", dst1);//膨胀(闭运算消除内部⽶粒)Mat dst2=imread("dst1.png");Mat dst3;Mat element = getStructuringElement(MORPH_RECT,Size(3,3));//imshow("闭运算消除内部空隙原图", dst2);dilate( dst2,dst3,element); //膨胀imshow("闭运算消除内部空隙效果图", dst3);imwrite("dst3.png",dst3);//腐蚀(开运算去除⽑刺)Mat dst4=imread("dst3.png");Mat dst5;//imshow("开运算去除⽑刺原图",dst4);erode(dst4,dst5,element);imshow("开运算去除⽑刺效果图",dst5);imwrite("dst5.png",dst5);//边缘检测Mat dst6=imread("dst5.png");Mat dst7;//imshow("边缘检测原图",dst6);Canny(dst6,dst7,150.100,3);imshow("边缘检测效果图",dst7);imwrite("dst7.png",dst7);waitKey(0);return 0;}int main(){cv::Mat image, Extractcorner;cv::vector<cv::Point2f> corners; //⽤来储存所有⾓点坐标cv::Size board_size = cv::Size(7, 7); //标定板每⾏,每列⾓点数image = cv::imread("2.jpg");Extractcorner = image.clone();cv::Mat imageGray;cv::cvtColor(image, imageGray, CV_RGB2GRAY);bool patternfound = cv::findChessboardCorners(image, board_size, corners, cv::CALIB_CB_FAST_CHECK + cv::CALIB_CB_ADAPTIVE_THRESH + cv::CALIB_CB_NORMALIZE_IMAGE);if (!patternfound){std::cout << "can not find chessboard corners!" << std::endl;exit(1);}else{//亚像素精确化cv::cornerSubPix(imageGray, corners, cv::Size(11, 11), cv::Size(-1, -1), cv::TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));}//⾓点检测图像显⽰for (int i = 0; i < corners.size(); i++){cv::circle(Extractcorner, corners[i], 5, cv::Scalar(255, 0, 255), 2);}cv::imshow("Extractcorner", Extractcorner);cv::imwrite("Extractcorner.jpg", Extractcorner);//输出⾓点坐标cout<<corners<<endl;//参考图像cv::Mat image2, Extractcorner2;cv::vector<cv::Point2f> corners2; //⽤来储存所有⾓点坐标cv::Size board_size2 = cv::Size(7, 7); //标定板每⾏,每列⾓点数image2 = cv::imread("1.jpg");Extractcorner2 = image2.clone();cv::Mat imageGray2;cv::cvtColor(image2, imageGray2, CV_RGB2GRAY);bool patternfound2 = cv::findChessboardCorners(image2, board_size, corners2, cv::CALIB_CB_FAST_CHECK + cv::CALIB_CB_ADAPTIVE_THRESH + cv::CALIB_CB_NORMALIZE_IMAGE); if (!patternfound2){std::cout << "can not find chessboard corners!" << std::endl;exit(1);}else{//亚像素精确化cv::cornerSubPix(imageGray2, corners2, cv::Size(11, 11), cv::Size(-1, -1), cv::TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));}//⾓点检测图像显⽰for (int i = 0; i < corners2.size(); i++){cv::circle(Extractcorner2, corners2[i], 5, cv::Scalar(255, 0, 255), 2);}cv::imshow("Extractcorner2", Extractcorner2);cv::imwrite("Extractcorner2.jpg", Extractcorner2);//输出⾓点坐标cout<<corners2<<endl;//仿射变换1Mat src = imread("2.jpg");Mat dst_warp;Point2f srcPoints[3];//原图中的三点Point2f dstPoints[3];//⽬标图中的三点//三个点对的值srcPoints[0] = Point2f(142.52786,115.98566);srcPoints[1] = Point2f(110.28358,409.29211);srcPoints[2] = Point2f(438.46851,126.58415);dstPoints[0] = Point2f(44.506947, 46.233685);dstPoints[1] = Point2f(44.496399, 325.76706);dstPoints[2] = Point2f(314.50659, 46.230354);Mat M1 = getAffineTransform(srcPoints,dstPoints);//由三个点对计算变换矩阵warpAffine(src,dst_warp,M1,src.size());//仿射变换imshow("src",src);imshow("dst_warp",dst_warp);imwrite("dst_warp.jpg",dst_warp);//⼀次变换后图像cv::Mat image3, Extractcorner3;cv::vector<cv::Point2f> corners3; //⽤来储存所有⾓点坐标cv::Size board_size3 = cv::Size(7, 7); //标定板每⾏,每列⾓点数image3 = cv::imread("dst_warp.jpg");Extractcorner3 = image3.clone();cv::Mat imageGray3;cv::cvtColor(image3, imageGray3, CV_RGB2GRAY);bool patternfound3 = cv::findChessboardCorners(image3, board_size, corners3, cv::CALIB_CB_FAST_CHECK + cv::CALIB_CB_ADAPTIVE_THRESH + cv::CALIB_CB_NORMALIZE_IMAGE); if (!patternfound3){std::cout << "can not find chessboard corners!" << std::endl;exit(1);}else{//亚像素精确化cv::cornerSubPix(imageGray3, corners3, cv::Size(11, 11), cv::Size(-1, -1), cv::TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));}//⾓点检测图像显⽰for (int i = 0; i < corners3.size(); i++){cv::circle(Extractcorner3, corners3[i], 5, cv::Scalar(255, 0, 255), 2);}cv::imshow("Extractcorner3", Extractcorner3);cv::imwrite("Extractcorner3.jpg", Extractcorner3);//输出⾓点坐标cout<<corners3<<endl;ofstream outfile;outfile.open("date.txt");outfile<<corners<<endl<<endl<<endl<<corners2<<corners3<<endl;outfile.close();//仿射变换2Mat src2 = imread("dst_warp.jpg");Mat dst_warp2;Point2f src2Points[3];//原图中的三点Point2f dst2Points[3];//⽬标图中的三点//三个点对的值src2Points[0] = Point2f(395.12207, 306.01523);src2Points[1] = Point2f(44.515686, 325.73227);src2Points[2] = Point2f(314.53482, 46.279831);dst2Points[0] = Point2f(314.49469, 325.76535);dst2Points[1] = Point2f(44.496399, 325.76706);dst2Points[2] = Point2f(314.50659, 46.230354);Mat M2 = getAffineTransform(src2Points,dst2Points);//由三个点对计算变换矩阵warpAffine(src2,dst_warp2,M2,src2.size());//仿射变换imshow("src2",src);imshow("dst_warp2",dst_warp2);imwrite("dst_warp2.jpg",dst_warp2);cv::waitKey(0);return 0;}*/。
opencv hough找圆算法

opencv中的Hough变换是一种常用的图像处理算法,它可以用来检测图像中的圆形。
在本文中,将介绍如何使用opencv的Hough变换算法来找到图像中的圆。
1. 算法原理Hough变换是一种常用的图像处理算法,它可以用来检测图像中的直线、圆形等几何形状。
Hough变换的原理是将图像空间中的像素点映射到参数空间中,从而能够在参数空间中找到拟合图像中特定几何形状的参数。
对于找圆算法来说,Hough变换的参数空间通常是圆心坐标和半径。
具体而言,对于一幅图像,我们需要在参数空间中建立一个累加器数组,数组的每一个元素表示一个可能的圆心坐标和半径。
然后对图像中的每一个像素点,我们计算它到每一个可能的圆心的距离,如果距离小于某个阈值,则在累加器数组中相应的位置加一。
我们就可以在累加器数组中找到累加值最大的位置,从而得到图像中的圆。
2. opencv中的实现在opencv中,我们可以使用HoughCircles函数来实现找圆算法。
该函数原型如下:void HoughCircles(InputArray image, OutputArray circles, int method, double dp, double minDist, double param1=100, double param2=100, int minRadius=0, int maxRadius=0 )其中,InputArray表示输入图像,OutputArray表示输出的圆的参数,method表示检测方法,dp表示累加器分辨率和图像分辨率的比值,minDist表示检测到的圆之间的最小距离,param1和param2分别表示Canny边缘检测的两个阈值,minRadius和maxRadius表示圆的最小半径和最大半径。
使用HoughCircles函数,我们可以简单地找到图像中的圆。
下面是一个示例代码:Mat src = imread("circle.jpg");Mat gray;cvtColor(src, gray, COLOR_BGR2GRAY);GaussianBlur(gray, gray, Size(9, 9), 2, 2);vector<Vec3f> circles;HoughCircles(gray, circles, HOUGH_GRADIENT, 1, gray.rows / 8, 200, 100, 0, 0);在这段示例代码中,我们首先读入一张图像,并将其转换为灰度图像。
opencv直径的识别方法

opencv直径的识别方法在OpenCV中,识别图像中的圆并测量其直径通常涉及以下几个步骤:1. 加载图像并转换为灰度图像:首先,需要将图像加载到OpenCV中,并将其转换为灰度图像。
这样可以简化后续的处理步骤并减少计算量。
2. 高斯模糊减少噪声:为了减少图像中的噪声,可以使用高斯模糊。
这有助于提高后续圆检测的准确性。
3. 霍夫圆变换:使用霍夫圆变换来检测图像中的圆。
OpenCV提供了`HoughCircles`函数,该函数可以检测图像中的圆,并返回其中心点和半径。
4. 计算直径:一旦获得了圆的中心点和半径,就可以计算其直径。
在OpenCV中,`HoughCircles`函数返回的半径值就是圆的直径。
以下是一个简单的Python代码示例,展示了如何使用OpenCV识别图像中的圆并测量其直径:```pythonimport cv2import numpy as np1. 加载图像并转换为灰度图像img = ('')gray = (img, _BGR2GRAY)2. 高斯模糊减少噪声gray = (gray, (5, 5), 0)3. 霍夫圆变换circles = (gray, _GRADIENT, 1, / 8, 200, 100, 0, 0)4. 计算直径并绘制圆if circles is not None:circles = (circles[0, :]).astype('int')for i in circles:绘制外圆(img, (i[0], i[1]), i[2], (0, 255, 0), 2)绘制圆心(img, (i[0], i[1]), 2, (0, 0, 255), 3)计算并打印直径diameter = 2 i[2]print(f"Diameter of circle {i[0]} is {diameter}")('Detected circles', img)(0)()```请注意,这只是一个基本的示例,实际应用中可能需要根据具体情况进行调整和优化。
基于OpenCV的圆形标记点的提取

2 0 1 3年 5月
组 合 机 床 与 自 动 化 加 工 技 术
M o d ul a r M a c h i ne To ol& A ut o ma t i c M an uf a c t ur i ng Te c hn i qu e
NO . 5
M a y 2 01 3
O 引 言
多视点云拼 接是将不 同坐标 系下 采集到 的点云经 过空间变换 , 转 为一个坐 标系下 的点云 , 进而将 模 型各 个 部分拼接 在一 起 。近年 来 , 国际上 许 多学 者 做 了大 量 的研究 , 提 出大 量 的拼接 方 法 。标 记 点拼 接 法 以操 作 方便 , 稳定性 高 , 得到 了广泛的应用 。世界级 的 C r e - a f o r m公 司就 采 用 标 记 点 拼接 法 来 拼 接 扫 描 的 点 云 。 另外德 国的 A T O S系统也 是采用这种方 法 。 标 记 点拼 接方 法首 先 要对 贴在 被 测 物 上 的 一组 或多组 标 记 点 中 心 进 行 提 取 , 得 到 同 组 标 记 点 在 不 同坐标 系 下 的 坐标 位 置 , 换 算 出 两 组 坐 标 系 的变 换 矩阵 , 从而 将 两 组 坐 标 系 下 被测 物 的 点 云 转 换 到相
( S c h o o l o f Me c h a n i c a l E n g i n e e r i n g , U n i v e r s i t y o f S c i e n c e a n d T e c h n o l o g y B e i j i n g , B e i j i n g 1 0 0 0 8 3 , C h i n a )
od i s f a s t a n d e ic f i e nt t o e x t r a c t c i r c u l a r ma r k e r s . Ke y wor ds:Op e n CV ;c i r c ul a r ma r ke r s ;e x t r a c t i on
如何基于OpenCVPython实现霍夫变换圆形检测

如何基于OpenCVPython实现霍夫变换圆形检测简述基于python使⽤opencv实现在⼀张图⽚中检测出圆形,并且根据坐标和半径标记出圆。
不涉及理论,只讲应⽤。
霍夫变换检测圆形的原理其实检测圆形和检测直线的原理差别不⼤,只不过直线是在⼆维空间,因为y=kx+b,只有k和b两个⾃由度。
⽽圆形的⼀般性⽅程表⽰为(x-a)²+(y-b)²=r²。
那么就有三个⾃由度圆⼼坐标a,b,和半径r。
这就意味着需要更多的计算量,⽽OpenCV中提供的cvHoughCircle()函数⾥⾯可以设定半径r的取值范围,相当于有⼀个先验设定,在每⼀个r来说,在⼆维空间内寻找a和b就可以了,能够减少计算量。
相关函数函数说明:Python: cv2.HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]]) →circles参数说明:image- 8位,单通道,灰度输⼊图像。
circles- 找到的圆的输出向量。
每个向量被编码为3元素的浮点向量(x,y,半径)。
circle_storage - 在C函数中,这是⼀个将包含找到的圆的输出序列的内存存储。
method- 使⽤检测⽅法。
⽬前,唯⼀实现的⽅法是 CV_HOUGH_GRADIENT,基本上是 21HT,在[Yuen90]中有描述。
dp - 累加器分辨率与图像分辨率的反⽐。
例如,如果 dp = 1,则累加器具有与输⼊图像相同的分辨率。
如果 dp = 2,则累加器的宽度和⾼度都是⼀半。
minDist -检测到的圆的中⼼之间的最⼩距离。
如果参数太⼩,除了真正的参数外,可能会错误地检测到多个邻居圈。
如果太⼤,可能会错过⼀些圈⼦。
param1 - 第⼀个⽅法特定的参数。
在CV_HOUGH_GRADIENT的情况下,两个传递给Canny()边缘检测器的阈值较⾼(较⼩的两个⼩于两倍)。
opencv生成圆 原理

opencv生成圆原理(原创实用版)目录一、OpenCV 生成圆的原理概述二、霍夫圆检测原理三、霍夫圆检测在 OpenCV 中的应用四、总结正文一、OpenCV 生成圆的原理概述OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉库,它包含了大量的图像处理和计算机视觉方面的算法。
在OpenCV 中,生成圆的方法主要是通过霍夫圆变换来实现的。
霍夫圆变换是一种基于极坐标的图像变换方法,它可以将图像中的圆转换为霍夫空间中的点,从而实现对圆的检测和分析。
二、霍夫圆检测原理霍夫圆检测的原理基于极坐标系下的圆的数学表达式。
在极坐标系中,一个圆可以表示为:x = a * cos(theta)y = b * sin(theta)其中,a 和 b 分别是圆心的横纵坐标,r 是圆的半径。
通过将极坐标转换为直角坐标,我们可以得到圆的一般方程:(x - a) + (y - b) = r在霍夫空间中,一个点可以唯一确定一个圆。
因此,通过将图像中的所有点映射到霍夫空间,我们可以检测出所有可能的圆。
三、霍夫圆检测在 OpenCV 中的应用在 OpenCV 中,霍夫圆检测是通过调用 cv::HoughCircles 函数来实现的。
这个函数接受两个参数,一个是输入图像,另一个是霍夫圆参数。
霍夫圆参数包括圆的阈值、圆心距阈值、半径比阈值等。
通过调整这些参数,我们可以控制圆检测的灵敏度和准确性。
以下是一个使用 OpenCV 进行霍夫圆检测的示例代码:```cpp#include <iostream>#include <opencv2/opencv.hpp>using namespace std;using namespace cv;int main(){// 读取输入图像Mat img = imread("input_image.jpg", IMREAD_GRAYSCALE);// 将图像转换为霍夫空间Mat hough_img;cv::HoughTransform(img, hough_img, CV_HOUGH_GRADIENT, 1, 60, 100, 20, 10, 60);// 检测圆vector<Vec4i> circles;cv::HoughCircles(hough_img, circles, CV_HOUGH_CIRCLE, 0, 0, 0, 0, 0, 0);// 绘制检测到的圆Mat result;drawCircles(img, circles, result, Scalar(0, 255, 0), 2);// 显示结果imshow("Result", result);waitKey(0);return 0;}```四、总结通过使用 OpenCV 库中的霍夫圆检测方法,我们可以在图像中检测出所有的圆。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
11 期
矣昕宝,等: 一种基于 OpenCV 的多扇区圆检测方法
3699
2. 2 多扇区圆检测模型与算法原理 为进一步提高圆检测识别效率,本文提出了一
种多扇区圆检测方法。在对数字图形进行圆检测 前,首先生成一个多扇区模板,如图 1 所示。
图 1 多扇区圆检测模板
该模板为一圆环点集,规定圆环圆心 o 的正右
( 5) 若检测结果不是圆,在步骤二的结果图上 滑动多扇区模板,重复执行步骤( 4) ,一次的步进量 由具体情况决定; 若检测结果为圆,滑动模板,重复 步骤( 4) 进行再检测。若再次检测的结果为圆,计 算上次检测到圆的质心与本次检测到圆的质心间
的距离,若 其 距 离 小 于 某 一 设 定 值,认 为 两 次 检 测 到的是同一 个 圆,放 弃 本 次 检 测 结 果,根 据 需 要 决 定是否重绘检测到圆; 若检测到不是圆,滑动模板, 重复步骤( 4) ,直至模板滑动到图像尾部。
1 OpenCV 简介
OpenCV 是一个基于 BSD 许可证授权( 开源) 发 行的跨平台开源计算机视觉库于 1999 年由 Intel 建 立,现在由 Willow Garage 提供支持。它由一系列 C 函数和少量 C++ 类构成,同时提供了 Python、Ruby、 MATLAB 等语言的接口,实现了图像处理和计算机 视觉方面的很多通用算法,可以运行在 Linux、Win-
本检测方 法 将 不 存 在 该 问 题,根 据 算 法 原 理 可 知,
对内存的需求几乎不变,在进行检测时仅执行简单
的数学运算不会带来大的计算开销。在工程应用
中,干扰同时满足检测阈值 η 和判决门限 τ 的概率
极小,因此,该算法具有较高的识别准确率,具有很
强的抗 干 扰 能 力。同 时,该 方 法 具 有 检 测 修 复 功
图 5 多扇区圆检测结果
而使用随机 Hough 变换检测结果如图 6 所示, 检测出圆的数目为 101 个,检测耗时 514 ms 通过对 比原图发现,产 生 两 次 错 误 检 测 和 一 次 漏 检,如 图 中绿色圆圈标记所示。
图 6 随机 Hough 变换检测结果
通过实验发现,虽然原始图像经过与处理后含 有很大的干扰成分,但使用多扇区圆检测方法仍然 能将其中的圆准确无误的识别出来,并对有残缺的 圆进行了修复,与常用的随机 Hough 变换圆检测相 比,具有较高的识别准确率,算法计算开销小,耗时 较少,达到了通过计算机准确识别检测物体目的。
参考文献
1 Lam W C Y; Yuen S Y. Efficient technique for circle detection using hypothesis filtering and Hough transform. IEEE Transactions on Image and Signal,1996; 143( 5) : 292—300
2 多扇区圆检测原理
2. 1 常用的圆检测方法 圆形特征是自然界中的基本元素,成功地从数
字图像中检测与识别圆在机器视觉领域有着重要 的意义。人 们 相 继 提 出 了 很 多 圆 检 测 方 法,其 中, 最基础,使用最广泛的是基于 Hough 变换的圆检测 技术。但常规的 Hough 变换存有不少缺憾[1],于是 很多改进 的 Hough 变 换 圆 检 测 技 术 被 相 继 提 出。 根据圆的特 性,研 究 学 者 们 进 行 了 广 泛 的 研 究,提 出了几何 特 征 的 圆 检 测 方 法、曲 线 拟 合 圆 检 测 技 术、梯度方 向 角 的 圆 检 测 方 法、基 于 共 形 几 何 代 数 与 Radon 变换的圆检测方法等多种检测技术[2—5], 根据计算机图形学中圆的生成算法理论,有人提出 了亚像素 圆 检 测 方 法[6]。 虽 然,圆 检 测 算 法 很 多, 且各自取的了一定的研究效果,但目前还没有一种 能将圆的识别与检测做到完美的算法[7]。
[ ] 扇区 6: 54π,32π ( x < 0,y < 0,0 < tanα ≤ 1) ;
[ ] 扇区 7: 32π,74π ( x > 0,y < 0,tanα ≤ - 1) ;
[ ] 扇区 8: 74π,2π ( x > 0,y < 0,- 1 < tanα ≤0) 。
设第 i 个扇区对应点集 Mi。当对数字图像进行圆 检测时,将模板坐标系作为图像的局部坐标系,将模板
4 结束语
结合 OpenCV,使用本文提出的多扇区圆检测 方法,可以 准 确 的 识 别 出 数 字 图 像 中 圆 形,该 方 法 具有较高的识别准确率,在图像干扰较大情况下仍 然将各个圆形无误的识别出来。因此,该方法用于 工业现场或生产流水线,通过机器视觉来达到监控 识别的目 的。 然 而,本 方 法 还 存 有 一 些 不 足 之 处, 即使用本方法进行圆检测时,要根据具体情况实验 估计阈值和判决门限,这将是本论文以后继续研究 的方向。
的各个扇区分别与图像的对应区域执行相关运算,设
被检测图像与模板第 i 个扇区对应的区域用点集 Ni 表 示,那么 Mi 和 Ni 的相关值 Ri 可由如下公式求得。
j=p
∑ Ri = mij·nij ( i = 1,2,…,8) 。 j =1
其中,p 表示点集中点数目,mij 表示 Mi 的第 j 个点, nij 表示 Ni 的第 j 个点。
检测出来,与随机 Hough 变换相比,有较高的识别准确率和较小的计算开销。
关键词 圆检测 OpenCV 多扇区 Hough 变换
中图法分类号 TP391. 41;
文献标志码 A
在工业控制现场或生产流水线上,常常需要检 测设备运行状况或记录流水线上产品数目。然而, 很多工业控制现场环境不适于人作业,流水线上靠 人工清点产品数目又存在着效率低下且容易出错 等诸多问题。长期以来,人们一直探索解决此类问 题的方法。计算机视觉的出现与发展,给解决此类 问题带来了全新的视角。通过实时采集图像,利用 图像检测 技 术,即 可 让 计 算 机 完 成 识 别 与 检 测 任 务。虽然计算机视觉技术已应用于不少领域,但其 识别检测效 率 始 终 是 被 研 究 的 热 点,目 前,不 少 学 者和研究单位仍致力于如何进一步提高圆检测正 确率方 面 的 研 究。OpenCV 作 为 开 源 的 机 器 视 觉 库,在图像检测中得到了广泛的应用。
时,第一扇区检测结束,开始第二扇区检测。
根据检测精度要求,可设定一检测阈值 η。当相
关值 Ri ≥ η 时,令扇区检测结果 si 的值为 1,否则, 将其结果置为 0,然后计算各个扇区检测结果 S: S =
8
∑si,S 最大可取值为 8。最后,根据圆的判决门限
i =1
τ( τ ∈ { 1,2,3,…,8} ) 来判决图形是否为圆。若 S ≥
[ ] 扇区 2:
π 4
,π2
(x
> 0,y
> 0,1
<
tanα) ;
[ ] 扇区 3:
π 2
,34π
(x
<
0,y
>
0,tanα ≤ - 1)
;
[ ] 扇区 4: 34π,π ( x < 0,y > 0,- 1 < tanα ≤ 0) ;
[ ] 扇区 5: π,54π ( x < 0,y < 0,1 < tanα) ;
在进行相关运算的同时,计算点到两坐标轴的
距离 x,y,以及点与 x 轴正方向的夹角 α 的 tanα,( 为
了计算方便,可使用 y / x 的值代替 tanα) ,当点不满
足扇区约束条件时,当前扇区检测结束,例如在执行
第一扇区检测时,从 x 轴正方向起按逆时针方向开始
检测,当点( x,y) 不满足( x > 0,y > 0,0 < tanα ≤ 1)
胀处理,为多扇区圆检测做准备; ( 3) 根据边缘检测的结果确定多扇区圆检测的
阈值 η 和判决门限 τ,η 和 τ 的确定需要根据轮廓 的周长和 轮 廓 的 残 缺 度 进 行 测 试 估 计,一 般 情 况 下,轮廓越清晰、周长越长,η 的取值越大,轮廓的残 缺度越小,τ 的取值越小;
( 4) 在步骤( 2) 的结果图上执行多扇区相关运 算,根据运算结果判断是否为圆;
图 3 待检测源图像
通过使用 OpenCV 函数库对源图像进行中值滤 波、二值化、边缘提取、轮廓过滤和膨胀处理等预处 理后,得到预处理后的图像如图 4 所示。
图 2 多扇区圆检测流程图
图 4 预处理后图像
11 期
矣昕宝,等: 一种基于 OpenCV 的多扇区圆检测方法
ห้องสมุดไป่ตู้
3701
对预处理后的图像进行多扇区圆检测后的结 果如图 5 所示,在进行试验中,阈值设定为 13,判决 门限设置为 6,检测出圆的数目为 100 个,检测耗时 123 ms 并对有残缺的圆进行了修复。
方为 x 轴的正方向,正上方为 y 轴的正方向,那么圆
环中的任意点可以用到横轴和纵轴的距离 x、y 表示
为点( x,y) ,将点( x,y) 与 x 轴正方向的夹角记为 α。
根据 x,y 的符号及点与 x 轴的夹角的正切值,可将该
模板划分为如下 8 个扇区。
[ ] 扇区 1: 0,π4 ( x > 0,y > 0,0 < tanα ≤ 1) ;
第 11 卷 第 16 期 2011 年 6 月 1671—1815( 2011) 16-3698-05
科学技术与工程
Science Technology and Engineering
Vol. 11 No. 16 June 2011 2011 Sci. Tech. Engng.
一种基于 OpenCV 的多扇区圆检测方法
本方法的检测流程图如图 2 所示。
3 实验结果及分析
为测试该多扇区圆检测方法的准确性,对如图 3 所示的原始图像分别使用随机 Hough 变换和本方 法进行圆检测与识别。测试主机处理器为 Intel( R) Pentium( R) T2390 双核处理器,主频 1. 86 GHz,内 存 1 GB,原始图片为 640 × 480 的装有 100 个小钢 管的产品盒,实验目的就是利用多扇区圆检测方法 对产品盒中的小钢管进行识别统计。使用 VC6. 0 开发环境,通过调用 OpenCV 函数库,使用 C++ 语言 实现对多扇区圆检测方法的描述。