本系列代码托管于:https://github.com/chintsan-code/opencv4-tutorials
本篇使用的项目为:hough_lines
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
void hough_lines_demo(Mat &image);
void hough_linesp_demo(Mat &image);
int main(int argc, const char** argv) {
Mat src1 = imread("../sample/lines.png");
Mat src2 = imread("../sample/morph01.png");
if (src1.empty() || src2.empty()) {
cout << "could not load image..." << endl;
return -1;
}
hough_lines_demo(src1);
hough_linesp_demo(src2);
waitKey(0);
destroyAllWindows();
return 0;
}
void hough_lines_demo(Mat &image) {
// 二值化
Mat gray, binary;
cvtColor(image, gray, COLOR_BGR2GRAY);
threshold(gray, binary, 0, 255, THRESH_BINARY | THRESH_OTSU);
namedWindow("binary", WINDOW_AUTOSIZE);
imshow("binary", binary);
// 霍夫直线检测
vector<Vec3f> lines;
HoughLines(binary, lines, 1, CV_PI / 180.0, 100, 0, 0);
// 绘制直线
Point pt1, pt2;
for (size_t i = 0; i < lines.size(); i++) {
float rho = lines[i][0]; // 距离
float theta = lines[i][1]; // 角度
float acc = lines[i][2];// 累加值
printf("rho: %.2f, theta : %.2f, acc: %.2f \n", rho, theta, acc);
double a = cos(theta);
double 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));
int angle = round((theta / CV_PI) * 180);
printf("angle : %d \n", angle);
if (rho > 0) { // 右倾
line(image, pt1, pt2, Scalar(0, 0, 255), 1, 8, 0);
if (angle == 90) { // 水平线
line(image, pt1, pt2, Scalar(0, 255, 255), 2, 8, 0);
}
if (angle <= 1) {// 垂直线
line(image, pt1, pt2, Scalar(255, 255, 0), 4, 8, 0);
}
}
else { // 左倾
line(image, pt1, pt2, Scalar(255, 0, 0), 2, 8, 0);
}
}
imshow("hough line detection", image);
}
void hough_linesp_demo(Mat &image) {
Mat binary;
Canny(image, binary, 80, 160, 3, false);
imshow("binary", binary);
vector<Vec4i> lines;
HoughLinesP(binary, lines, 1, CV_PI / 180, 80, 200, 10);
Mat result = Mat::zeros(image.size(), image.type());
for (int i = 0; i < lines.size(); i++) {
line(result, Point(lines[i][0], lines[i][1]), Point(lines[i][2], lines[i][3]), Scalar(0, 0, 255), 1, 8);
}
imshow("hough linesp demo", result);
}
直线在平面坐标(笛卡尔坐标系)有两个参数决定(截距B,斜率K);在极坐标空间两个参数决定(半径R,角度θ):
HoughLines:霍夫直线检测
对噪声敏感,使用前需要降噪
void 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 );
- image:输入8-bit单通道二值图,可能会被该函数修改
- lines:输出直线vector(r,θ) 或 (r,θ,votes)
- r是距坐标原点的距离
- θ是以弧度表示的线旋转角度(0∼垂直直线,π/2∼水平直线)
- votes 曲线交点累加计数
- rho:以像素为单位的累加器的距离分辨率。 推荐用1.0。步长
- theta:以弧度表示的累加器角度分辨率。 CV_PI/180。弧长
- threshold:累加计数大于此阈值才返回 累加平面的阈值参数,int类型,超过设定阈值才被检测出线段,值越大,基本上意味着检出的线段越长,检出的线段个数越少。根据情况推荐先用100试试
- srn:0
- stn:0
- min_theta:检查线条的最小角度。必须介于0和maxn_theta之间
- max_theta:要检查线条的最大角度。必须介于min_theta和CV_PI之间。
HoughLinesP:霍夫线段检测
void HoughLinesP( InputArray image, OutputArray lines, double rho, double theta, int threshold, double minLineLength = 0, double maxLineGap = 0 );
- image:输入8-bit单通道二值图,可能会被该函数修改
- lines:输入vector包含4个元素x1,x2,y1,y2,代表线段起点和终点坐标
- rho:以像素为单位的累加器的距离分辨率。 推荐用1.0。步长
- theta:以弧度表示的累加器角度分辨率。 CV_PI/180。弧长
- threshold:累加计数大于此阈值才返回 累加平面的阈值参数,int类型,超过设定阈值才被检测出线段,值越大,基本上意味着检出的线段越长,检出的线段个数越少。根据情况推荐先用100试试
- minLineLength:小于该值长度的线程会被过滤掉,单位像素
- maxLineGap:线段中间可以断多少个像素
评论 (0)