? (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