霍夫变换是一种在图像中寻找直线和圆及其它简单形状的方法。
霍夫线变换原理:二值图像中的任何点都可能是一些直线集合的一部分,例如在原始图像上的一条直线表示为y = ax + b ,这是原始图像上以x和y为坐标系进行表示的,但是如果我们以a和b为新的变量坐标,那么在新的图像中,某一个点代表了所有过原始图像上点的直线。
CvSeq * cvHoughLines2 (CvArr * image, void * line_storage, int method, double rho, double theta, int threshold, double param1 = 0,double param2 = 0 );
第一个变量是输入图像,必须是8位的,但输入信息可以被看成是二值的(即所有非0像素可以看成是相等的)。
第二个参数是指保存结果位置的指针,即可以是内存块(CvMemoryStorage),也可以是N*1的矩阵数列(行数N有助于限制直线的最大数量)。
Method可以取值为CV_HOUGH_STANDARD 代表SHT 标准霍夫变换
CV_HOUGH_PROBABILISTIC 代表PPHT 累计概率霍夫变换
CV_HOUGH_MULTI_SCALE 代表SHT的多尺度变种。
rho和theta代表设置直线所需要的分辨率;tho的单位是像素,theta的单位是弧度。累加平面可以看成是rho和theta所组成的二维直方图。
threshold表示认定为一条直线时在累计平面中必须达到的值。
#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/highgui.hpp>
using namespace std;
using namespace cv;
int main(int argc, const char * argv[]) {
/*1、加载一幅灰度图像*/
const char filename[] = "/Users/linwang/Downloads/bike.jpeg";
IplImage * Img = cvLoadImage(filename,CV_LOAD_IMAGE_GRAYSCALE);
/*2、缩小一倍*/
IplImage *out = cvCreateImage(cvSize(Img->width/2,Img->height/2), Img->depth, Img->nChannels);
cvResize(Img, out);
cvShowImage("Src", out);
/*3、霍夫直线变换*/
CvMemStorage * sto_line = cvCreateMemStorage(0);
IplImage * bike = cvCloneImage(out);
cvCanny(bike, bike, 50, 150);
CvSeq * Res = cvHoughLines2(bike, sto_line, CV_HOUGH_PROBABILISTIC, 1, CV_PI/180, 1);
for (int i = 0; i <= Res->total; i++) //序列元素个数
{
CvPoint* Line = (CvPoint*)cvGetSeqElem(Res, i);
cvLine(bike, Line[0], Line[1], CV_RGB(200, 200, 200), 4); //画线
}
cvShowImage("bile line", bike);
/*4、霍夫圆变换*/
CvMemStorage * storage = cvCreateMemStorage(0);
cvSmooth(out, out,CV_GAUSSIAN,5,5);
cvCanny(out, out, 50, 150);
CvSeq * results = cvHoughCircles(out, storage, CV_HOUGH_GRADIENT, 2, out->width/10, 50, 100, 0, 0);
for(int i = 0;i<results->total;i++)
{
float * p = (float *)cvGetSeqElem(results, i);
CvPoint pt = cvPoint(cvRound(p[0]),cvRound(p[1]));
cvCircle(out, pt, cvRound(p[2]), CV_RGB(200, 200, 200));
}
cvShowImage("bike Circle", out);
cvWaitKey(0);
cvReleaseImage(&Img);
cvReleaseImage(&out);
cvReleaseImage(&bike);
return 0;
}