#define _USE_MATH_DEFINES
#include <math.h>
#include<iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include<imgproc/imgproc.hpp>
using namespace std;
using namespace cv;
class LineFinder {
private:
Mat img; //原图
vector<Vec4i>lines; //向量中检测到的直线的端点
double deltaRho;
double deltaTheta;
int minVote;
double minLength;
double maxGap;
public:
LineFinder() :deltaRho(1), deltaTheta(M_PI / 180), minVote(10), minLength(0.), maxGap(0.) {};
void setAccResolution(double dRho, double dTheta) {
deltaRho = dRho;
deltaTheta = dTheta;
}
void setMinVote(int minv) {
minVote = minv;
}
void setLineLengthAndGap(double length, double gap) {
minLength = length;
maxGap = gap;
}
vector<Vec4i>findLines(Mat &binary) {
lines.clear();
HoughLinesP(binary, lines, deltaRho, deltaTheta, minVote, minLength, maxGap);
return lines;
}
//绘制检测到的直线
void drawDetectedLines(Mat &image, Scalar color = Scalar(255, 255, 255)) {
//画线
vector<Vec4i>::const_iterator it2 = lines.begin();
while (it2 != lines.end())
{
Point pt1((*it2)[0], (*it2)[1]);
Point pt2((*it2)[2], (*it2)[3]);
line(image, pt1, pt2, color);
++it2;
}
}
};
int main() {
Mat image = imread("G:/Opencv/road.jpg");
namedWindow("image");
imshow("image", image);
Mat result;
cvtColor(image, result, CV_BGR2GRAY);
//应用Canny算法
Mat contours;
Canny(result,
contours,
125,
350);
LineFinder finder;
finder.setLineLengthAndGap(100, 20);
finder.setMinVote(80);
vector<Vec4i>lines = finder.findLines(contours);
int n = 0; //选择line 0
Mat oneline(contours.size(), CV_8U, Scalar(0));
line(oneline,
Point(lines[n][0], lines[n][1]),
Point(lines[n][2], lines[n][3]),
Scalar(255),
5
);
bitwise_and(contours, oneline, oneline);
Mat oneLineInv; //白色直线反转后的图像
threshold(oneline,
oneLineInv,
128,
255,
THRESH_BINARY_INV);
cvNamedWindow("One line");
imshow("One line", oneLineInv);
vector<Point>points;
for (int y = 0; y < oneline.rows; y++)
{
//y行
uchar *rowPtr = oneline.ptr<uchar>(y);
for (int x = 0; x < oneline.cols; x++)
{
if (rowPtr[x])
{
points.push_back(Point(x, y));
}
}
}
Vec4f lineVec;
fitLine(Mat(points),
lineVec,
CV_DIST_L2,
0,
0.01, 0.01);
int x0 = lineVec[2];
int y0 = lineVec[3];
int x1 = x0 - 200 * lineVec[0];
int y1 = y0 - 200 * lineVec[1];
cv::line(result, Point(x0, y0), Point(x1, y1), Scalar(0), 3);
cvNamedWindow("Estimated line");
imshow("Estimated line", result);
waitKey(0);
return 0;
}