原图

- //对输入图像进行细化
- cv::Mat ThinLine(const cv::Mat& matsrc, const int& iterations)
- {
- //CvSize size = cvGetSize(src);
- cv::Mat dst = matsrc.clone();//拷贝一个数组给另一个数组
- int _iwidth = dst.cols;
- int _iheight = dst.rows;
- int n = 0, i = 0, j = 0;
- for (n = 0; n < iterations; n++)
- {
- cv::Mat temp = dst.clone();
- for (i = 0; i < temp.rows; i++)
- {
- for (int j = 0; j < temp.cols; j++)
- {
- if ((*temp.ptr
(i, j)) == 1) - {
- int ap = 0;
- int p2 = (i == 0) ? 0 : (*temp.ptr
(i - 1, j)); - int p3 = (i == 0 || j == _iwidth - 1) ? 0 : (*temp.ptr
(i - 1, j + 1)); - if (p2 == 0 && p3 == 1)
- {
- ap++;
- }
- int p4 = (j == _iwidth - 1) ? 0 : (*temp.ptr
(i, j + 1)); - if (p3 == 0 && p4 == 1)
- {
- ap++;
- }
- int p5 = (i == _iwidth - 1 || j == _iwidth - 1) ? 0 : (*temp.ptr
(i + 1, j + 1)); - if (p4 == 0 && p5 == 1)
- {
- ap++;
- }
- int p6 = (i == _iwidth - 1) ? 0 : (*temp.ptr
(i + 1, j)); - if (p5 == 0 && p6 == 1)
- {
- ap++;
- }
- int p7 = (i == _iwidth - 1 || j == 0) ? 0 : (*temp.ptr
(i + 1, j - 1)); - if (p6 == 0 && p7 == 1)
- {
- ap++;
- }
- int p8 = (j == 0) ? 0 : (*temp.ptr
(i, j - 1)); - if (p7 == 0 && p8 == 1)
- {
- ap++;
- }
- int p9 = (i == 0 || j == 0) ? 0 : (*temp.ptr
(i - 1, j - 1)); - if (p8 == 0 && p9 == 1)
- {
- ap++;
- }
- if (p9 == 0 && p2 == 1)
- {
- ap++;
- }
- if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) > 1 && (p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) < 7)
- {
- if (ap == 1)
- {
- if (p2 * p4 * p8 == 0)
- {
- if (p2 * p6 * p8 == 0)
- {
- (*dst.ptr
(i, j)) = 0; - }
- }
- }
- }
- }
-
- }
-
- }
- }
-
- //将二值图像转换成灰度,以便显示
- for (i = 0; i < dst.rows; i++)
- {
- for (j = 0; j < dst.cols; j++)
- {
- if ((*dst.ptr
(i, j)) == 1) - {
- (*dst.ptr
(i, j)) = 255; - }
- else
- {
- (*dst.ptr
(i, j)) = 0; - }
- }
- }
-
- return dst;
- }
-
- void LineDistance()
- {
- cv::Mat src = cv::imread("平行线求距离.png", cv::IMREAD_COLOR);
-
- cv::Mat gray;
- cv::cvtColor(src, gray, cv::COLOR_BGR2GRAY);
-
- cv::Mat thre;
- cv::threshold(gray, thre, 128, 1, cv::THRESH_BINARY_INV);
-
- //第一步 对图像中的直线进行细化
- cv::Mat line = ThinLine(thre, 50);
-
- //第二步 提取直线的轮廓坐标
- std::vector
> contours; - cv::findContours(line, contours, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE);
-
- cv::Mat show = src.clone();
- cv::drawContours(show, contours, -1, cv::Scalar(255));
-
- //直线拟合
- //拟合结果为一个四元素的容器,比如Vec4f - (vx, vy, x0, y0)
- //其中(vx, vy) 是直线的方向向量 (x0, y0) 是直线上的一个点
- cv::Vec4d l0;
- cv::fitLine(contours[0], l0, cv::DIST_L2, 0, 0.01, 0.01);//拟合方法采用最小二乘法
-
- double cos_theta0 = l0[0];
- double sin_theta0 = l0[1];
- double x0 = l0[2], y0 = l0[3];
-
- double k0 = sin_theta0 / cos_theta0;
- double b0 = y0 - k0 * x0;
- printf("line0: y = %f * x + %f \n", k0 * 180.0 / CV_PI, b0);
-
- double x = 0;
- double y = k0 * x + b0;
-
- cv::Vec4d l1;
- //拟合方法采用最小二乘法
- cv::fitLine(contours[1], l1, cv::DIST_L2, 0, 0.01, 0.01);
- double cos_theta1 = l1[0];
- double sin_theta1 = l1[1];
- double x1 = l1[2], y1 = l1[3];
-
- double k1 = sin_theta1 / cos_theta1;
- double b1 = y1 - k1 * x1;
- printf("line1: y = %f * x + %f \n", k1 * 180.0 / CV_PI, b1);
-
- //第四部 计算两条直线之间的距离 公式是: |b1 - b0| / sqrt(A * A + B * B)
- double A = k0;
- double B = 1.0;
- double dis = abs(b1 - b0) / sqrt(A * A + B * B);
- printf("dis is %f \n", dis);
- }