嵌入式设计应用
霍夫变换(Hough Transform)是图像处理中的一种特征提取技术,该过程在一个参数空间中通过计算累计结果的局部最大值得到一个符合该特征的集合作为霍夫变换的结果。
霍夫线变换是一种寻找直线的方法,在寻找霍夫变换之前,要对图像进行边缘检测,即霍夫线的输入为二值图像。
1、对于直角坐标系中的任意一点A(x0,y0),经过点A的直线满足Y0=k*X0+b.(k是斜率,b是截距)
2、那么在X-Y平面过点A(x0,y0)的直线簇可以用Y0=k*X0+b表示,但对于垂直于X轴的直线斜率是无穷大的则无法表示。因此将直角坐标系转换到极坐标系就能解决该特殊情况。
3、在极坐标系中表示直线的方程为ρ=xCosθ+ySinθ(ρ为原点到直线的距离),如图所示:
4、如上图,假定在一个8*8的平面像素中有一条直线,并且从左上角(1,8)像素点开始分别计算θ为0°、45°、90°、135°、180°时的ρ,图中可以看出ρ分别为1、(9√2)/2、8、(7√2)/2、-1,并给这5个值分别记一票,同理计算像素点(3,6)点θ为0°、45°、90°、135°、180°时的ρ,再给计算出来的5个ρ值分别记一票,此时就会发现ρ = (9√2)/2的这个值已经记了两票了,以此类推,遍历完整个8*8的像素空间的时候ρ = (9√2)/2就记了5票, 别的ρ值的票数均小于5票,所以得到该直线在这个8*8的像素坐标中的极坐标方程为 (9√2)/2=x*Cos45°+y*Sin45°,到此该直线方程就求出来了。(PS:但实际中θ的取值不会跨度这么大,一般是PI/180)。
1.如何知道这些正弦曲线公共交点呢,我们可以将rho,theta这两个参数取值范围等分成m,n分,用一个二维数组来装。
2.对于图像边缘中的每一点看成直线系映射到极坐标成为正弦曲线,然后用一个变量比如theta,求出每个取值后对应的rho,然后落入的二维数组的分组中加1,以此类推。
3.当遍历所有的点后,二维数组最高的值或过阈值的值,其数组的坐标即为直角坐标检测出的直线。
4.m、n划分越细越精确,但运算量大。反之亦然。
#include “opencv2/opencv.hpp”
using namespace cv;
using namespace std;
int main()
{
Mat image = imread(“D:\\乱\\1.jpg”);
Mat result;
cvtColor(image,result,CV_BGR2GRAY);
Mat contours;
Canny(result, contours, 125, 350);
vector《Vec2f》 lines;
HoughLines(contours, lines, 1, CV_PI / 180, 100);
vector《Vec2f》::const_iterator it = lines.begin();
cout 《《 lines.size() 《《 endl;
printf(“OK”);
while (it != lines.end())
{
printf(“OK”);
float r = (*it)[0];
float theta = (*it)[1];
double a = cos(theta), b = sin(theta);
double x0 = a*r, y0 = b*r;
Point pt1(cvRound(x0 + 1000 * (-b)),
cvRound(y0 + 1000 * (a)));
Point pt2(cvRound(x0 - 1000 * (-b)),
cvRound(y0 - 1000 * (a)));
line(image, pt1, pt2, Scalar(0, 0, 255), 3, 8);
it++;
}
printf(“OK”);
namedWindow(“houghline”);
imshow(“houghline”, image);
waitKey(0);
Opencv实现直线检测:
1、Opencv1.0版本:
[cpp] view plain copy print?
#include《cv.h》
#include《highgui.h》
int main()
{
IplImage* pImgSrc = NULL; //源图像
IplImage* pImg8u = NULL; //灰度图
IplImage* pImgCanny = NULL; //边缘检测后的图
IplImage* pImgDst = NULL; //在图像上画上检测到的直线后的图像
CvSeq* lines = NULL;
CvMemStorage* storage = NULL;
/*边缘检测*/
pImgSrc = cvLoadImage(“。\\res\\street.jpg”, 1);
pImg8u = cvCreateImage(cvGetSize(pImgSrc), IPL_DEPTH_8U, 1);
pImgCanny = cvCreateImage(cvGetSize(pImgSrc), IPL_DEPTH_8U, 1);
pImgDst = cvCreateImage(cvGetSize(pImgSrc), IPL_DEPTH_8U, 1);
cvCvtColor(pImgSrc, pImg8u, CV_BGR2GRAY);
cvCanny(pImg8u, pImgCanny, 20, 200, 3);
/*检测直线*/
storage = cvCreateMemStorage(0);
lines = cvHoughLines2(pImgCanny, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI / 180, 80, 200, 10);
pImgDst = cvCreateImage(cvGetSize(pImgSrc), IPL_DEPTH_8U, 3);
cvCvtColor(pImg8u, pImgDst, CV_GRAY2BGR);
/*在pImgDst上画出检测到的直线*/
for (int i = 0; i 《 lines-》total; i++)
{
CvPoint* line = (CvPoint*)cvGetSeqElem(lines, i);
cvLine(pImgDst, line[0], line[1], CV_RGB(255, 0, 0), 3, 8);
}
cvNamedWindow(“src”, 1);
cvNamedWindow(“canny”, 1);
cvNamedWindow(“hough”, 1);
cvShowImage(“src”, pImgSrc);
cvShowImage(“canny”, pImgCanny);
cvShowImage(“hough”, pImgDst);
cvWaitKey(0);
cvReleaseImage(&pImgSrc);
cvReleaseImage(&pImg8u);
cvReleaseImage(&pImgCanny);
cvReleaseImage(&pImgDst);
cvReleaseMemStorage(&storage);
return 0;
}
2、Opencv2.4.9版本:
[cpp] view plain copy print?
#include《opencv2\imgproc\imgproc.hpp》
#include《opencv2\opencv.hpp》
#include《opencv2\highgui\highgui.hpp》
using namespace std;
using namespace cv;
int main()
{
Mat Image = imread(“。//res//street.jpg”, 0);
Mat CannyImg;
Canny(Image, CannyImg, 140, 250, 3);
imshow(“CannyImg”, CannyImg);
Mat DstImg;
cvtColor(Image, DstImg, CV_GRAY2BGR);
vector《Vec4i》 Lines;
HoughLinesP(CannyImg, Lines, 1, CV_PI / 360, 170,30,15);
for (size_t i = 0; i 《 Lines.size(); i++)
{
line(DstImg, Point(Lines[i][0], Lines[i][1]), Point(Lines[i][2], Lines[i][3]), Scalar(0, 0, 255), 2, 8);
}
imshow(“HoughLines_Detect”, DstImg);
imwrite(“。//res//HoughLines_Detect.jpg”, DstImg);
waitKey(0);
return 0;
}
全部0条评论
快来发表一下你的评论吧 !