OpenCV 学习(Hough 变换提取直线)
来源:互联网 发布:powershell linux 编辑:程序博客网 时间:2024/05/21 10:47
OpenCV 学习(Hough 变换提取直线)
在机器视觉应用中,我们经常要提取图像中的各种特征,最基本的特征就是图像中的线条、拐角等。这篇笔记就来讲讲如何提取图像中的直线。这里使用的方法叫做 Hough 变换。
Hough 变换这个名称最早是在 Richard Duda 和 Peter Hart 两人于 1972 年合写的发表于 Comm. ACM 文章 《Use of the Hough Transformation to Detect Lines and Curves in Pictures》 中提出的。 大家可能会好奇,这俩人没一个叫 Hough,为啥这个变换叫 Hough 变换呢。这还要追溯到更早的年代,1962 年 Paul Hough 申请了一个美国专利,专利的名称叫做 《Method and means for recognizing complex patterns》,这个专利中提出了 Hough 变换基本方法。不过 1962 年那时还没有所谓的机器视觉这个学科,计算机也不是一般人能见到的。所以这个专利并没有受到特别的重视。 Richard Duda 和 Peter Hart 不知是如何翻到这个 10 年前的专利,并敏锐的发现了它的价值,并将其用于机器视觉领域。从此就有了大名鼎鼎的 Hough 变换。
关于 Hough 更详细的历史发展大家可以参考:
https://en.wikipedia.org/wiki/Hough_transform
Hough 变换的原理介绍也可以参考上面的 wiki。简单的说 Hough 变换采用的是一种证据收集的方式,遍历一幅图像上所有的直线位置,哪条直线上的特征点(证据)更多,哪条直线就更可能是我们希望找到的直线。
这里不准备详细介绍Hough 变换的原理。但是Hough 变换如何表示图像中的直线还是要介绍的。否则,我们都不知道如何使用获得的结果。
Hough 变换时,我们采用参数方程来表示直线。
OpenCV 中提供了两个Hough变换提取直线的函数。
- cv::HoughLines 函数
- cv::HoughLinesP 函数
下面分别介绍。
cv::HoughLines 函数
这个函数采用最原始的Hough 变换来计算直线的位置。
void HoughLines( InputArray image, OutputArray lines, double rho, // rho 的步长 double theta, // 角度步长 int threshold, // 阈值 double srn=0, double stn=0 );
输入图像必须是单通道的。输出的直线存在一个
std::vector<cv::Vec2f> lines;
首先给出一个简单的测试图片。这个图片上有四条直线。没有其他的干扰物体。这属于最基本的情形。
下面是个测试代码。
#include <QCoreApplication>#include <math.h>#define PI 3.14159265358979#include "opencv2/highgui/highgui.hpp"#include "opencv2/imgproc/imgproc.hpp" int main(int argc, char *argv[]){ QCoreApplication a(argc, argv); cv::Mat image = cv::imread("c:\\test.png"); cv::Mat contours; cv::cvtColor(image, contours, cv::COLOR_BGR2GRAY); cv::bitwise_not(contours, contours); //cv::Canny(image, contours, 155, 350); std::vector<cv::Vec2f> lines; cv::HoughLines(contours, lines, 1, PI/180, 180); //cv::imshow("cany",contours ); std::vector<cv::Vec2f>::const_iterator it= lines.begin(); while (it!=lines.end()) { float rho= (*it)[0]; // first element is distance rho float theta= (*it)[1]; // second element is angle theta if (theta < PI/4. || theta > 3.*PI/4.)// ~vertical line { // point of intersection of the line with first row cv::Point pt1(rho/cos(theta), 0); // point of intersection of the line with last row cv::Point pt2((rho - image.rows * sin(theta))/cos(theta), image.rows); // draw a white line cv::line( image, pt1, pt2, cv::Scalar(255), 1); } else { // ~horizontal line // point of intersection of the // line with first column cv::Point pt1(0,rho/sin(theta)); // point of intersection of the line with last column cv::Point pt2(image.cols, (rho - image.cols * cos(theta))/sin(theta)); // draw a white line cv::line(image, pt1, pt2, cv::Scalar(255), 1); } ++it; } cv::imshow("", image); return a.exec();}
输出结果如下:
这几条线找的还是蛮准的。
cv::HoughLinesP 函数
与 cv::HoughLines函数不同, cv::HoughLinesP 函数可以提取线段。
输出的直线存在一个
std::vector<cv::Vec4i> lines;
中。
cv::Vec4i 的四个整数分别是线段的起点和终点坐标。
void HoughLinesP( InputArray image, OutputArray lines, double rho, // rho 的步长 double theta, // 角度的步长,单位是度 int threshold, // 阈值 double minLineLength=0, // 线段的最小长度 double maxLineGap=0 ); // 线段之间的最小距离
下面把 HoughLinesP 函数封装到一个类中。
class LineFinder{private: cv::Mat img; // original image std::vector<cv::Vec4i> lines; double deltaRho; double deltaTheta; int minVote; double minLength; // min length for a line double maxGap; // max allowed gap along the linepublic: // Default accumulator resolution is 1 pixel by 1 degree // no gap, no mimimum length LineFinder() : deltaRho(1), deltaTheta(PI/180), minVote(10), minLength(0.), maxGap(0.) {} // Set the resolution of the accumulator void setAccResolution(double dRho, double dTheta) { deltaRho= dRho; deltaTheta= dTheta; } // Set the minimum number of votes void setMinVote(int minv) { minVote= minv; } // Set line length and gap void setLineLengthAndGap(double length, double gap) { minLength= length; maxGap= gap; } // Apply probabilistic Hough Transform std::vector<cv::Vec4i> findLines(cv::Mat& binary) { lines.clear(); cv::HoughLinesP(binary, lines, deltaRho, deltaTheta, minVote, minLength, maxGap); return lines; } // Draw the detected lines on an image void drawDetectedLines(cv::Mat &image, cv::Scalar color = cv::Scalar(255, 255, 255)) { // Draw the lines std::vector<cv::Vec4i>::const_iterator it2 = lines.begin(); while (it2 != lines.end()) { cv::Point pt1((*it2)[0],(*it2)[1]); cv::Point pt2((*it2)[2],(*it2)[3]); cv::line( image, pt1, pt2, color, 2); ++it2; } }};
用这个类实现图中线段的检测。
int main(int argc, char *argv[]){ QCoreApplication a(argc, argv); cv::Mat image = cv::imread("c:\\test.png"); cv::Mat contours; cv::cvtColor(image, contours, cv::COLOR_BGR2GRAY); cv::bitwise_not(contours, contours); //cv::Canny(image, contours, 155, 350); LineFinder finder; // Set probabilistic Hough parameters finder.setLineLengthAndGap(100, 20); finder.setMinVote(80); // Detect lines and draw them std::vector<cv::Vec4i> lines = finder.findLines(contours); finder.drawDetectedLines(image, cv::Scalar(0, 0, 255)); cv::namedWindow("Detected Lines with HoughP"); cv::imshow("Detected Lines with HoughP",image); return a.exec();}
- OpenCV 学习(Hough 变换提取直线)
- Hough变换提取直线
- OpenCV学习之Hough变换检测直线
- OpenCV学习之基于Hough变换的直线检测
- Hough变换在直线提取中的改进
- 关于MATLAB中Hough变换提取直线
- 学习opencv之Hough变换
- 毕业课题之------------图像的直线提取--hough变换
- Hough变换检测直线
- hough直线变换
- Hough 变换检测直线
- Hough变换检测直线
- Hough变换直线检测
- hough变换检测直线
- Hough变换检测直线
- Hough变换直线检测
- Hough变换-直线检测
- 【opencv2】直线hough变换
- 应云而生 联想服务器支撑企业走向“互联网+”时代
- JS array相关方法
- SSH网上商城
- 使用百度地图API
- php缓存技术详细介绍及php缓存的实现代码
- OpenCV 学习(Hough 变换提取直线)
- 输入输出重定向,迭代器绑定cin
- LeetCode(2)--Add Two Numbers
- “南大软院大神养成计划“_第十四天的学习“
- 2.0 Linux系统的安装之Fedora安装单系统(2)
- 工业的4.0时代
- C++内存管理
- 递归与尾递归
- IMAGE INPAINTING