一:线段检测
程序如下:
// 11HoughLines.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <opencv2/opencv.hpp> using namespace std; #pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"") int main() { const char *pstrWindowsSrcTitle = "原图"; const char *pstrWindowsLineName = "线段检测"; // 从文件中加载原图 IplImage *pSrcImage = cvLoadImage("111.jpg", CV_LOAD_IMAGE_UNCHANGED); // 灰度图 IplImage *pGrayImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1); cvCvtColor(pSrcImage, pGrayImage, CV_BGR2GRAY); // 边缘图 IplImage *pCannyImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1); cvCanny(pGrayImage, pCannyImage, 30, 90); //cvSmooth(pCannyImage, pCannyImage); // 线段检测(只能针对二值图像) CvMemStorage *pcvMStorage = cvCreateMemStorage(); double fRho = 1; double fTheta = CV_PI / 180; int nMaxLineNumber = 50; //最多检测条直线 double fMinLineLen = 50; //最小线段长度 double fMinLineGap = 10; //最小线段间隔 CvSeq *pcvSeqLines = cvHoughLines2(pCannyImage, pcvMStorage, CV_HOUGH_PROBABILISTIC, fRho, fTheta, nMaxLineNumber, fMinLineLen, fMinLineGap); // 绘制线段 IplImage *pColorImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 3); cvCvtColor(pCannyImage, pColorImage, CV_GRAY2BGR); int i; for(i = 0; i < pcvSeqLines->total; i++) { CvPoint* line = (CvPoint*)cvGetSeqElem(pcvSeqLines, i); cvLine(pColorImage, line[0], line[1], CV_RGB(255,0,0), 2); } cvNamedWindow(pstrWindowsSrcTitle, CV_WINDOW_AUTOSIZE); cvShowImage(pstrWindowsSrcTitle, pSrcImage); cvNamedWindow(pstrWindowsLineName, CV_WINDOW_AUTOSIZE); cvShowImage(pstrWindowsLineName, pColorImage); cvWaitKey(0); cvReleaseMemStorage(&pcvMStorage); cvDestroyWindow(pstrWindowsSrcTitle); cvDestroyWindow(pstrWindowsLineName); cvReleaseImage(&pSrcImage); cvReleaseImage(&pGrayImage); cvReleaseImage(&pCannyImage); cvReleaseImage(&pColorImage); return 0; }
函数功能:检测图像中的线段
函数原型:
CvSeq* cvHoughLines2(
CvArr* image,
void* line_storage,
int method,
double rho,
double theta,
int threshold,
double param1=0, double param2=0
);
参数说明:
第一个参数表示输入图像,必须为二值图像(黑白图)。
第二个参数表示存储容器,和上一篇的轮廓检测一样,可以传入CvMemStorage类型的指针。
第三个参数表示变换变量,可以取下面的值:
CV_HOUGH_STANDARD - 传统或标准 Hough 变换. 每一个线段由两个浮点数 (ρ, θ) 表示,其中 ρ 是线段与原点(0,0) 之间的距离,θ 线段与 x-轴之间的夹角。
CV_HOUGH_PROBABILISTIC - 概率 Hough 变换(如果图像包含一些长的线性分割,则效率更高)。它返回线段分割而不是整个线段。每个分割用起点和终点来表示。
CV_HOUGH_MULTI_SCALE - 传统 Hough 变换的多尺度变种。线段的编码方式与 CV_HOUGH_STANDARD 的一致。
第四个参数表示与象素相关单位的距离精度。
第五个参数表示弧度测量的角度精度。
第六个参数表示检测线段的最大条数,如果已经检测这么多条线段,函数返回。
第七个参数与第三个参数有关,其意义如下:
对传统 Hough 变换,不使用(0).
对概率 Hough 变换,它是最小线段长度.
对多尺度 Hough 变换,它是距离精度 rho 的分母 (大致的距离精度是 rho 而精确的应该是 rho / param1 ).
第八个参数与第三个参数有关,其意义如下:
对传统 Hough 变换,不使用 (0).
对概率 Hough 变换,这个参数表示在同一条线段上进行碎线段连接的最大间隔值(gap), 即当同一条线段上的两条碎线段之间的间隔小于param2时,将其合二为一。
对多尺度 Hough 变换,它是角度精度 theta 的分母 (大致的角度精度是 theta 而精确的角度应该是 theta / param2).
运行结果如下
二:圆检测
程序如下:
// 12Houghcircles.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <opencv2/opencv.hpp> using namespace std; #pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"") int main() { const char *pstrWindowsSrcTitle = "原图"; const char *pstrWindowsLineName = "圆检测"; // 从文件中加载原图 IplImage *pSrcImage = cvLoadImage("111.jpg", CV_LOAD_IMAGE_UNCHANGED); // 灰度图 IplImage *pGrayImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 1); cvCvtColor(pSrcImage, pGrayImage, CV_BGR2GRAY); //cvSmooth(pGrayImage, pGrayImage); // 圆检测(灰度图) CvMemStorage *pcvMStorage = cvCreateMemStorage(); double fMinCircleGap = pGrayImage->height / 10; CvSeq *pcvSeqCircles = cvHoughCircles(pGrayImage, pcvMStorage, CV_HOUGH_GRADIENT, 1, fMinCircleGap); //每个圆由三个浮点数表示:圆心坐标(x,y)和半径 // 绘制直线 IplImage *pColorImage = cvCreateImage(cvGetSize(pSrcImage), IPL_DEPTH_8U, 3); cvCvtColor(pGrayImage, pColorImage, CV_GRAY2BGR); int i; for (i = 0; i < pcvSeqCircles->total; i++) { float* p = (float*)cvGetSeqElem(pcvSeqCircles, i); cvCircle(pColorImage, cvPoint(cvRound(p[0]), cvRound(p[1])), cvRound(p[2]), CV_RGB(255, 0, 0), 2); } cvNamedWindow(pstrWindowsSrcTitle, CV_WINDOW_AUTOSIZE); cvShowImage(pstrWindowsSrcTitle, pSrcImage); cvNamedWindow(pstrWindowsLineName, CV_WINDOW_AUTOSIZE); cvShowImage(pstrWindowsLineName, pColorImage); cvWaitKey(0); cvReleaseMemStorage(&pcvMStorage); cvDestroyWindow(pstrWindowsSrcTitle); cvDestroyWindow(pstrWindowsLineName); cvReleaseImage(&pSrcImage); cvReleaseImage(&pGrayImage); cvReleaseImage(&pColorImage); return 0; }
圆检测函数要用到cvHoughCircles这个函数的函数原形如下:
CVAPI(CvSeq*) cvHoughCircles(
CvArr* image, void* circle_storage,
int method,
double dp,
double min_dist,
double param1 CV_DEFAULT(100),
double param2 CV_DEFAULT(100),
int min_radius CV_DEFAULT(0),
int max_radius CV_DEFAULT(0)
);
可以看出cvHoughCircles与上面的cvHoughLines2函数比较类似,因此讲下部分参数的意思就可以了:
第二个参数表示Hough变换方式,目前只能用CV_HOUGH_GRADIENT。
第三个参数表示寻找圆弧圆心的累计分辨率,通常设置成1就可以了。
第四个参数表示两个不同圆之间的最小距离,由于是按圆心来计算距离的,因此对同心圆的检测就无能为力了。
注意,圆检测函数可以使用灰度图。