Hough直线检测
使用 HoughLines()和HoughLinesP() 检测图像中的直线。
void cv::HoughLines ( InputArray image, OutputArray lines,
double rho, double theta,
int threshold, double srn = 0,
double stn = 0, double min_theta = 0,
double max_theta = CV_PI
)
void cv::HoughLinesP( InputArray image, OutputArray lines,
double rho, double theta,
int threshold, double minLineLength = 0,
double maxLineGap = 0
)
说明:image是输入的8位单通道二进制图像,lines是线的输出向量,
rho是累加器的距离分辨率,theta是累加器角度分辨率弧度,threshold是阈值。
在Hough变换中,我们使用极坐标而非笛卡尔坐标。
原理参考:https://docs.opencv.org/master/d9/db0/tutorial_hough_lines.html
代码示例
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
Mat src, dst, cdst, cdstP;
char* filename = "../data/sudoku.png";
src = imread(filename, IMREAD_GRAYSCALE);
if (src.empty()) { return -1; }
Canny(src, dst, 50, 200, 3); // Canny算子边缘检测
cvtColor(dst, cdst, COLOR_GRAY2BGR); // 转换灰度图像
cdstP = cdst.clone();
vector<Vec2f> lines;
HoughLines(dst, lines, 1, CV_PI / 180, 150, 0, 0); // hough检测
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 + 1000 * (-b));
pt1.y = cvRound(y0 + 1000 * (a));
pt2.x = cvRound(x0 - 1000 * (-b));
pt2.y = cvRound(y0 - 1000 * (a));
line(cdst, pt1, pt2, Scalar(0, 0, 255), 3, CV_AA);
}
vector<Vec4i> linesP;
HoughLinesP(dst, linesP, 1, CV_PI / 180, 50, 50, 10);
for (size_t i = 0; i < linesP.size(); i++)
{
Vec4i l = linesP[i];
line(cdstP, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(0, 0, 255), 3, LINE_AA);
}
imshow("Source", src);
imshow("HoughLines", cdst);
imshow("HoughLinesP", cdstP);
waitKey();
return 0;
}
运行结果
Hough圆检测
void cv::HoughCircles ( InputArray image, OutputArray circles,
int method, double dp,
double minDist,
double param1 = 100, double param2 = 100,
int minRadius = 0, int maxRadius = 0
)
说明:dp是累加器分辨率与图像分辨率的反比。例如,如果dp = 1,则累加器具有与输入图像相同的分辨率。如果dp = 2,则累加器的宽度和高度只有一半。
minDist指检测到的圆圈中心之间的最小距离。
param1:用于Canny的边缘阀值上限,下限被置为上限的一半。
param2:累加器的阀值。
代码示例
#include "opencv2/imgcodecs.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
using namespace cv;
using namespace std;
int main(int argc, char** argv)
{
char* filename = "../data/smarties.png";
Mat src = imread(filename, IMREAD_COLOR);
if (src.empty()) { return -1; }
Mat gray;
cvtColor(src, gray, COLOR_BGR2GRAY);
medianBlur(gray, gray, 5); // 中值滤波,滤除噪声,避免错误检测
vector<Vec3f> circles;
HoughCircles(gray, circles, HOUGH_GRADIENT, 1, gray.rows / 16, 100, 30, 1, 30); // Hough圆检测
for (size_t i = 0; i < circles.size(); i++)
{
Vec3i c = circles[i];
Point center = Point(c[0], c[1]);
circle(src, center, 1, Scalar(0, 100, 100), 3, LINE_AA); // 画圆
int radius = c[2];
circle(src, center, radius, Scalar(255, 0, 255), 3, LINE_AA);
}
imshow("detected circles", src);
waitKey();
return 0;
}
运行结果