? (r, theta) 坐标:r是到(0,0)的距离而theta是与一条参考线的夹角,通常是x轴。如图6-3所示。
图6-3 (r, theta) 坐标表示
这些坐标之间的关系是:
x*cos(theta) + y*sin(theta) = 2*r
正如你所见,点(x,y)在(r,theta)参数空间的绘图是一个正弦曲线。因此,笛卡尔空间里共线的点在霍夫空间里对应不同的正弦曲线,会相交在一个共同的(r,theta)点,这个(r,theta)点代表笛卡尔空间里通过所有这些点的一条直线。给你一些例子,图6-4分别展示了一个点、一对点、和五个点在霍夫空间里的表现。生成该图的Matlab代码见清单6-3 。
图 -6-4 一个点,一对点和五个点(从上至下,顺时针)各自的霍夫变换
清单6-3 用Matlab代码来理解霍夫变换
%% one point theta = linspace(0, 2*pi, 500); x = 1; y = 1; r = 0.5 * (x * cos(theta) + y * sin(theta)); figure; plot(theta, r); xlabel(‘theta‘); ylabel(‘r‘); %% two points theta = linspace(0, 2*pi, 500); x = [1 3]; y = 2*x + 1; r1 = 0.5 * (x(1) * cos(theta) + y(1) * sin(theta)); r2 = 0.5 * (x(2) * cos(theta) + y(2) * sin(theta)); figure; plot(theta, r1, theta, r2); xlabel(‘theta‘); ylabel(‘r‘); %% five collinear points theta = linspace(0, 2*pi, 500); x = [1 3 5 7 9]; y = 2*x + 1; figure; hold on; r = zeros(numel(x), numel(theta)); for i = 1 : size(r, 1) r(i, :) = 0.5 * (x(i) * cos(theta) + y(i) * sin(theta)); plot(theta, r(i, :)); end xlabel(‘theta‘); ylabel(‘r‘);
图 6-5 利用霍夫变换在不同累加器阈值下的圆和直线检测
清单 6-5 编程展现利用霍夫变换的直线和圆形检测
// Program to illustrate line and circle detection using Hough transform // Author: Samarth Manoj Brahmbhatt, University of Pennsylvania #include <opencv2/opencv.hpp> #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> using namespace std; using namespace cv; Mat img; int shape = 0; //0 -> lines, 1 -> circles int thresh = 100; // Accumulator threshold void on_trackbar(int, void *) { // Circles if(shape == 1) { Mat img_gray; cvtColor(img, img_gray, CV_RGB2GRAY); // Find circles vector<Vec3f> circles; HoughCircles(img_gray, circles, CV_HOUGH_GRADIENT, 1, 10, 100, thresh, 5); // Draw circles Mat img_show = img.clone(); for(int i = 0; i < circles.size(); i++) { Point center(cvRound(circles[i][0]), cvRound(circles[i][1])); int radius = cvRound(circles[i][2]); // draw the circle center circle(img_show, center, 3, Scalar(0, 0, 255), -1); // draw the circle outline circle(img_show, center, radius, Scalar(0, 0, 255), 3, 8, 0); } imshow("Shapes", img_show); } else if(shape == 0) { // Lines Mat edges; Canny(img, edges, 50, 100); // Find lines vector<Vec2f> lines; HoughLines(edges, lines, 1, CV_PI/180.f, thresh); // Draw lines Mat img_show = img.clone(); for(int i = 0; i < lines.size(); i++) { float rho = lines[i][0]; float theta = lines[i][1]; double a = cos(theta), b = sin(theta); double x0 = a * rho, y0 = b * rho; Point pt1(cvRound(x0 + 1000 * (-b)), cvRound(y0 + 1000 * (a))); Point pt2(cvRound(x0 - 1000 * (-b)), cvRound(y0 - 1000 * (a))); line(img_show, pt1, pt2, Scalar(0, 0, 255)); } imshow("Shapes", img_show); } } int main() { img = imread("hough.jpg"); namedWindow("Shapes"); // Create sliders createTrackbar("Lines/Circles", "Shapes", &shape, 1, on_trackbar); createTrackbar("Acc. Thresh.", "Shapes", &thresh, 300, on_trackbar); // Initialize window on_trackbar(0, 0); while(char(waitKey(1)) != ‘q‘) {} return 0; }
原文:http://blog.csdn.net/wlj613613/article/details/18241401