四、直线拟合
在一些应用,不仅要求检测出图像中的直线,还要求对图像中的直线精准的估计出位置和方向。下面我们将介绍opencv中如何通过一些点拟合出最适合的直线。
直线拟合的主要原理是,最小二乘法,即计算各点与直线的最小距离,求出最小距离之和的直线就是最合适的直线。
我们选择前面通过概率霍夫变换(cv::HoughLinesP)求出的第一个线段为实例,与Canny算子实现出的边缘按位与,得到一系列边缘点,程序和结果如下:
// Display one line
image= cv::imread("road.jpg",0);
int n=0;
cv::line(image, cv::Point(li[n][0],li[n][1]),cv::Point(li[n][2],li[n][3]),cv::Scalar(255),5);
cv::namedWindow("One line of the Image");
cv::imshow("One line of the Image",image);
cv::imwrite("One line of the Image.jpg",image);
// Extract the contour pixels of the first detected line
cv::Mat oneline(image.size(),CV_8U,cv::Scalar(0));
cv::line(oneline, cv::Point(li[n][0],li[n][1]),cv::Point(li[n][2],li[n][3]),cv::Scalar(255),5);
cv::bitwise_and(contours,oneline,oneline);
cv::Mat onelineInv;
cv::threshold(oneline,onelineInv,128,255,cv::THRESH_BINARY_INV);
cv::namedWindow("One line");
cv::imshow("One line",onelineInv);
cv::imwrite("One line.jpg",onelineInv);
One line of the Image.jpg
One line.jpg
然后将这条直线存入Point中
std::vector<cv::Point> points;
// Iterate over the pixels to obtain all point positions
for( int y = 0; y < oneline.rows; y++ ) {
uchar* rowPtr = oneline.ptr<uchar>(y);
for( int x = 0; x < oneline.cols; x++ ) {
// if on a contour
if (rowPtr[x]) {
points.push_back(cv::Point(x,y));
}
}
}
最后通过opencv提供的cv::fitLine函数,进行直线拟合,
cv::Vec4f line;
cv::f