zoukankan      html  css  js  c++  java
  • 霍夫变换(直线检测、圆检测)

    可以看出如果笛卡尔坐标系的点共线,这些点在霍夫空间对应的直线交于一点:这也是必然,共线只有一种取值可能。

    如果不止一条直线呢?再看看多个点的情况(有两条直线):

     

     

     

    在opencv中步骤解读:

    具体步骤:

    1. 彩色图像->灰度图

    2. 去噪(高斯核)

    3. 边缘提取(梯度算子、拉普拉斯算子、canny、sobel) 

    4. 二值化(判断此处是否为边缘点,就看灰度值==255)

    5. 映射到霍夫空间(准备两个容器,一个用来展示hough-space概况,一个数组hough-space用来储存voting的值,因为投票过程往往有某个极大值超过阈值,多达几千,不能直接用灰度图来记录投票信息)

    6. 取局部极大值,设定阈值,过滤干扰直线

    7. 绘制直线、标定角点

    函数HoughLines的实现代码

    #include "opencv2/core/core.hpp"
    #include "opencv2/imgproc/imgproc.hpp"
    #include "opencv2/highgui/highgui.hpp"
    #include "opencv2/opencv.hpp"
    #include <iostream>
    using namespace cv;
    using namespace std;
    using std::cout;
    int main()
    {
    
    	Mat g_srcImage, midImage, dstImage;
    	namedWindow("[原始图]");
    	g_srcImage = imread("E:\VS2015Opencv\vs2015\project\picture\01.jpg");
    	if (!g_srcImage.data) { cout << "error read image" << endl; return 0; }
    
    	imshow("[原始图]", g_srcImage);
    
    	Canny(g_srcImage, midImage, 50, 200, 3);
    	cvtColor(midImage, dstImage, CV_GRAY2BGR);
    
    	vector<Vec2f> lines;
    	HoughLines(midImage, lines, 0.5, CV_PI / 18, 150, 0, 0);
    
    	for (size_t i = 0; i < lines.size(); i++)
    	{
    		float rho = lines[i][0], theta = lines[i][1];
    		Point pt1, pt2;
    		double a = cos(theta), b = sin(theta);
    		double x0 = a*rho, y0 = b*rho;
    		pt1.x = cvRound(x0 + 2000 * (-b));  //把浮点数转化成整数
    		pt1.y = cvRound(y0 + 2000 * (a));
    		pt2.x = cvRound(x0 - 2000 * (-b));
    		pt2.y = cvRound(y0 - 2000 * (a));
    		line(dstImage, pt1, pt2, Scalar(128, 128, 0), 1, CV_AA);
    	}
    	imshow("边缘检测后的图", midImage);
    	imshow("标准霍夫线变换效果图", dstImage);
    
    	waitKey(0);
    	return 0;
    }
    

      

     函数HoughLinesP的代码

    #include <opencv2/opencv.hpp>
    #include <iostream>
    #include <math.h>
    
    using namespace cv;
    using namespace std;
    
    
    int main(int argc, char** argv)
    {
        Mat src, src_gray, dst;
        src = imread("E:\VS2015Opencv\vs2015\project\picture\01.jpg");
    
        char INPUT_TITLE[] = "input image";
    
        imshow(INPUT_TITLE, src);
    
        Canny(src, src_gray, 150, 200);
        cvtColor(src_gray, dst, CV_GRAY2BGR);
        imshow("edge image", src_gray);
        imshow("gray", dst);
    
        //方法1(标准霍夫变换)
        //vector<Vec2f> lines;
        //HoughLines(src_gray, lines, 1, CV_PI / 180, 150, 0, 0);
        //for (size_t i = 0; i < lines.size(); i++) {
        //    float rho = lines[i][0]; // 极坐标中的r长度
        //    float theta = lines[i][1]; // 极坐标中的角度
        //    Point pt1, pt2;
        //    double a = cos(theta), b = sin(theta);
        //    double x0 = a * rho, y0 = b * rho;
        //    // 转换为平面坐标的四个点
        //    pt1.x = cvRound(x0 + 1000 * (-b));//对一个double型的数进行四舍五入,并返回一个整型数!
        //    pt1.y = cvRound(y0 + 1000 * (a));
        //    pt2.x = cvRound(x0 - 1000 * (-b));
        //    pt2.y = cvRound(y0 - 1000 * (a));
        //    line(dst, pt1, pt2, Scalar(0, 0, 255), 1, CV_AA);
        //}
    
    
        //第二种方法(概率霍夫变换)
        vector<Vec4f> plines;
        HoughLinesP(src_gray, plines, 1, CV_PI / 180.0, 10, 0, 10);
        Scalar color = Scalar(0, 0, 255);
        for (size_t i = 0; i < plines.size(); i++) {
            Vec4f hline = plines[i];
            line(dst, Point(hline[0], hline[1]), Point(hline[2], hline[3]), color, 3, LINE_AA);
        }
    
        imshow("效果图", dst);
    
        waitKey(0);
        return 0;
    
    }

     

    主要参考博客:

    原理部分:http://www.cnblogs.com/php-rearch/p/6760683.html(相当清楚,不解释,)

    源码分析1:http://blog.csdn.net/zhaocj/article/details/50281537(赵春江老师,很多源码都给出了详解,尤其是那篇sift,看的热血沸腾)

    源码分析2:http://blog.csdn.net/traumland/article/details/51319644

    源码分析3:http://blog.csdn.net/sunshine_in_moon/article/details/45271647

    Samples1:http://blog.csdn.net/poem_qianmo/article/details/26977557/   (还是浅墨)

    Samples2:http://www.cnblogs.com/skyfsm/p/6881686.html
    讲解:https://blog.csdn.net/qq_37059483/article/details/77891698
     这篇博客的博主在进行Canny之前使用了大津法先进行分割:http://blog.csdn.net/dcrmg/article/details/52464209

    园检测

    #include <opencv2/opencv.hpp>
    using namespace cv;
    using namespace std;
    
    const int kvalue = 15;//双边滤波邻域大小
    
    int main()
    {
        Mat src_color = imread("E:\VS2015Opencv\vs2015\project\picture\08.jpg");//读取原彩色图
        imshow("原图-彩色", src_color);
    
        //声明一个三通道图像,像素值全为0,用来将霍夫变换检测出的圆画在上面
        Mat dst(src_color.size(), src_color.type());
        dst = Scalar::all(0);
    
        Mat src_gray;//彩色图像转化成灰度图
        cvtColor(src_color, src_gray, COLOR_BGR2GRAY);
        imshow("原图-灰度", src_gray);
        imwrite("src_gray.png", src_gray);
    
        Mat bf;//对灰度图像进行双边滤波
        bilateralFilter(src_gray, bf, kvalue, kvalue * 2, kvalue / 2);
        imshow("灰度双边滤波处理", bf);
        imwrite("src_bf.png", bf);
    
        vector<Vec3f> circles;//声明一个向量,保存检测出的圆的圆心坐标和半径
        HoughCircles(bf, circles, CV_HOUGH_GRADIENT, 1.5, 20, 130, 38, 10, 50);//霍夫变换检测圆
    
        cout << "x=	y=	r=" << endl;
        for (size_t i = 0; i < circles.size(); i++)//把霍夫变换检测出的圆画出来
        {
            Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));
            int radius = cvRound(circles[i][2]);
    
            circle(dst, center, 0, Scalar(0, 255, 0), -1, 8, 0);
            circle(dst, center, radius, Scalar(0, 0, 255), 1, 8, 0);
    
            cout << cvRound(circles[i][0]) << "	" << cvRound(circles[i][1]) << "	"
                << cvRound(circles[i][2]) << endl;//在控制台输出圆心坐标和半径                
        }
    
        imshow("特征提取", dst);
        imwrite("dst.png", dst);
    
        waitKey();
    }

     可以参考:http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/table_of_content_imgproc/table_of_content_imgproc.html#table-of-content-imgproc

  • 相关阅读:
    Codeforces 845E Fire in the City 线段树
    Codeforces 542D Superhero's Job dp (看题解)
    Codeforces 797F Mice and Holes dp
    Codeforces 408D Parcels dp (看题解)
    Codeforces 464D World of Darkraft
    Codeforces 215E Periodical Numbers 容斥原理
    Codeforces 285E Positions in Permutations dp + 容斥原理
    Codeforces 875E Delivery Club dp
    Codeforces 888F Connecting Vertices 区间dp (看题解)
    Codeforces 946F Fibonacci String Subsequences dp (看题解)
  • 原文地址:https://www.cnblogs.com/fcfc940503/p/11303533.html
Copyright © 2011-2022 走看看