• 通过霍夫直线检测方式获取直线,自定义提取直线(提取出两条接近平行的直线),将直线进行拟合


    由于项目的需要,需要使用霍夫直线检测进行处理图像。这里进行笔记记录,话不多说,先上代码:

    1. #include
    2. #include
    3. using namespace cv;
    4. using namespace std;
    5. int main()
    6. {
    7. Mat img = imread("result1.png");
    8. Mat gray, canny, binaryImage;
    9. cvtColor(img, gray, CV_RGB2GRAY);
    10. threshold(gray, binaryImage, 100, 225, THRESH_BINARY);
    11. imshow("binaryImage", binaryImage);
    12. Canny(binaryImage, canny, 50, 120);
    13. vector lines;
    14. HoughLinesP(canny, lines, 1, CV_PI / 180, 50, 200, 30);
    15. for (size_t i = 0; i < lines.size(); i++)
    16. {
    17. Vec4i I = lines[i];
    18. double x1 = I[0];
    19. double y1 = I[1];
    20. double x2 = I[2];
    21. double y2 = I[3];
    22. //筛选满足条件的点
    23. if (abs(x1 - x2) + abs(y1 - y2) > 50)
    24. {
    25. //将满足条件的点画出
    26. line(img, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255), 2);
    27. cout << " " << "(" << x1 << "," << y1 << ")" << " " << "(" << x2 << "," << y2 << ")" << endl;
    28. //line(canny, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255), 2);
    29. }
    30. }
    31. imshow("img2", img);
    32. imwrite("shuchu.png", img);
    33. waitKey(0);
    34. return 0;
    35. }

    上面的代码并没有进行什么滤波与二值化处理,是最简单的一种方式。

    霍夫直线检测函数的使用

    首先是对霍夫直线检测代码之中HoughLinesP函数进行解释:

    void HoughLinesP(InputArray image, OutputArray lines, double rho, double theta, int threshold, double minLineLength=0, double maxLineGap=0 )

    第一个参数:InputArray image,表示输入的图像。

    第二个参数:OutputArray lines,表示输出的量,其中包含有相应的输出的直线的坐标。

    第三个参数:double rho, 以像素为单位的距离精度。

    第四个参数:double theta,以弧度为单位的角度精度。


    一般前四个参数是不用管的,主要是看后面的三个参数。

    第五个参数:int threshold,累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值。 大于阈值 threshold 的线段才可以被检测通过并返回到结果中。

    第六个参数: double minLineLength,存在默认值0,表示可以显示的最低线段长度。

    第七个参数:double maxLineGap,有默认值0,允许将同一行点与点之间连接起来的最大的距离。

    这里每个参数的含义可以详见博客如下所示:

    HoughLinesP参数设置(看完还不会你砍死我!!!)_无情的搬砖机器的博客-CSDN博客_houghlinesp一、我是个标题1、随便在PPt画个图如下(1602*750):2、测试代码#include#includeusing namespace std;using namespace cv;int detect(cv::Mat img) {cv::Mat can_img, gray_img;cv::cvtColor(img, gray_img, CV_BGR2GRAY);cv::Mat ..https://blog.csdn.net/Li_haiyu/article/details/106397532?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522166746636316800182746543%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=166746636316800182746543&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~top_positive~default-1-106397532-null-null.142%5Ev62%5Econtrol,201%5Ev3%5Eadd_ask,213%5Ev1%5Econtrol&utm_term=HoughLinesP&spm=1018.2226.3001.4187

    自定义方式进行线段提取

    网上只是给出了如何进行霍夫直线的提取,但是具体信息的提取过程,网上并没有,所以由于项目的需要,想了以下的方式可以进行对于可用信息的提取。

    使用的图片是已经截取好的,因为实际的项目之中,背景的干扰是非常小的。由于此处进行的是模拟实验,我想到的办法只有是在不进行原有的像素改变的过程之中,对于图片内容的截取。具体的截取过程见我的另一篇博客:基于OpenCV使用鼠标在图片之中提取自己想要的信息进行显示_YllasdW的博客-CSDN博客基于OpenCV使用鼠标在图片之中圈出自己想要的信息进行显示https://blog.csdn.net/m0_47489229/article/details/126959813

    上面写的代码的运行结果如下所示:

    但是我需要进行提取的是在直板两端平行的线,由上面结果可知实际图像之中是存在五条线,那么这里如何进行提取两端的线呢?

    我这个地方也是仔细想了一想,但是也是非常的简单,我的思路如下所示:
    ①两个直线之间的间距问题,既然是存在三条直线,提取两端的直线,那两端的直线的间距必然是相对而言比较大的。
    ②起始点和终止点之间的距离,这个地方只能是作为第二个条件存在,在判断出第一个条件之后,提取两边最长的线段(当然这个思路不是特别好,但是我这里想着这样其实也是可以的)。
    ③提取两边直线的斜率最为相近的两条直线(相比于条件②,这个更加靠谱一点)

    代码思路,上面几个条件使用过程,我采用使用思路①和思路③进行结合的方式,所需要使用的信息是在输出结果之中,输出点之中起始点和终止点就是可以的。

    在正式进行的过程,发现存在一个问题,就是思路①之中,直线可能并不是平行线,那么如何进行评价呢?所以对于思路①不如选定自己直线上面的同一纵坐标对应的横坐标进行比对,选取第一组的横坐标作为标准,依次进行相减,得到的数值取一个平均值,当数值大于这个数是一组,小于又是另外一组,进而可以分为左右两组直线。(发现自己好机智😀)

    (由于我要提取的是4096*2160像素的图片,因此要恢复信息)见到上面的图片是没有问题的,但是当我恢复到原始的图像的大小的时候,发现是存在干扰问题的。

    因此,图片进行提取的时候特别注意平行线的提取,一定要提取满足符合要求的地方,其余地方进行选取的时候,不要提取干扰的地方。

    上面的数据就是很正常了。但是在写上述实现功能①代码时候,出现

    这种情况也是需要进行考虑.

    代码修改成为如下所示:

    1. #include
    2. #include
    3. using namespace cv;
    4. using namespace std;
    5. int main()
    6. {
    7. Mat img = imread("result1.png");
    8. //设定图片的大小
    9. resize(img, img, Size(4096, 2160));
    10. Mat gray, canny, binaryImage;
    11. cvtColor(img, gray, CV_RGB2GRAY);
    12. threshold(gray, binaryImage, 100, 225, THRESH_BINARY);
    13. imshow("binaryImage", binaryImage);
    14. Canny(binaryImage, canny, 50, 120);
    15. vector lines;
    16. HoughLinesP(canny, lines, 1, CV_PI / 180, 50, 200, 30);
    17. int q1 = 0; //垂直直线
    18. int q = 0; //不是垂直直线的条数
    19. double k[20] ,b[20];//用来存放至直线的y=kx+b,这个地方用来存放k和b,为什么要变成20,因为他里面不能够放入变量
    20. //这里设定当y相同的时候求取x的值,y设定为2160/2
    21. double X[20];
    22. double avX = 0;//x的平均值
    23. for (size_t i = 0; i < lines.size(); i++)
    24. {
    25. Vec4i I = lines[i];
    26. double x1 = I[0];
    27. double y1 = I[1];
    28. double x2 = I[2];
    29. double y2 = I[3];
    30. //筛选满足条件的点
    31. if (abs(x1 - x2) + abs(y1 - y2) > 50)
    32. {
    33. //将满足条件的点画出
    34. line(img, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255 ), 2);
    35. cout << i << " " << "(" << x1 << "," << y1 << ")" << " " << "(" << x2 << "," << y2 << ")" << endl;
    36. if (x1 != x2)
    37. {
    38. //求取直线
    39. k[i] = (double)((y1 - y2) / (x1 - x2));
    40. b[i] = (double)(y1 - k[i] * x1);
    41. X[i] = (double)((2160.0f / 2.0f) - b[i]) / k[i];
    42. avX = avX + X[i];
    43. cout << "k[i]:" << k[i] << " " << "b[i]:" << b[i] << " X[i]:" << b[i] << " avX:" << avX << endl;
    44. q++;
    45. }
    46. else {
    47. X[i] = x1;
    48. avX = avX + X[i];
    49. q1++;
    50. }
    51. }
    52. }
    53. cout << "直线的条数:" << q +q1 <
    54. avX = (double)(avX / (double)(q + q1));
    55. for (size_t i = 0; i < lines.size(); i++)
    56. {
    57. Vec4i I = lines[i];
    58. double x1 = I[0];
    59. double y1 = I[1];
    60. double x2 = I[2];
    61. double y2 = I[3];
    62. //筛选满足条件的点
    63. if (abs(x1 - x2) + abs(y1 - y2) > 50)
    64. {
    65. if (X[i] > avX)
    66. {
    67. cout << "右侧直线:" << i << endl;
    68. }
    69. else
    70. {
    71. cout << "左侧直线:" << i << endl;
    72. }
    73. }
    74. }
    75. imshow("img2", img);
    76. imwrite("shuchu.png", img);
    77. waitKey(0);
    78. return 0;
    79. }

    运行结果如下所示:

    可见线条2是竖直的直线,并且这里的直线分成了左右两个部分,接下来就是提取出左右斜率最为相近的两条直线.

    1. #include
    2. #include
    3. using namespace cv;
    4. using namespace std;
    5. int main()
    6. {
    7. Mat img = imread("result1.png");
    8. //设定图片的大小
    9. resize(img, img, Size(4096, 2160));
    10. Mat gray, canny, binaryImage;
    11. cvtColor(img, gray, CV_RGB2GRAY);
    12. threshold(gray, binaryImage, 100, 225, THRESH_BINARY);
    13. imshow("binaryImage", binaryImage);
    14. Canny(binaryImage, canny, 50, 120);
    15. vector lines;
    16. HoughLinesP(canny, lines, 1, CV_PI / 180, 50, 200, 30);
    17. int q1 = 0; //垂直直线
    18. int q = 0; //不是垂直直线的条数
    19. double k[20] ,b[20];//用来存放至直线的y=kx+b,这个地方用来存放k和b,为什么要变成20,因为他里面不能够放入变量
    20. //这里设定当y相同的时候求取x的值,y设定为2160/2
    21. double X[20];
    22. double avX = 0;//x的平均值
    23. for (size_t i = 0; i < lines.size(); i++)
    24. {
    25. Vec4i I = lines[i];
    26. double x1 = I[0];
    27. double y1 = I[1];
    28. double x2 = I[2];
    29. double y2 = I[3];
    30. //筛选满足条件的点
    31. if (abs(x1 - x2) + abs(y1 - y2) > 50)
    32. {
    33. //将满足条件的点画出
    34. line(img, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255 ), 2);
    35. cout << i << " " << "(" << x1 << "," << y1 << ")" << " " << "(" << x2 << "," << y2 << ")" << endl;
    36. if (x1 != x2)
    37. {
    38. //求取直线
    39. k[i] = (double)((y1 - y2) / (x1 - x2));
    40. b[i] = (double)(y1 - k[i] * x1);
    41. X[i] = (double)((2160.0f / 2.0f) - b[i]) / k[i];
    42. avX = avX + X[i];
    43. cout << "k[i]:" << k[i] << " " << "b[i]:" << b[i] << " X[i]:" << b[i] << " avX:" << avX << endl;
    44. q++;
    45. }
    46. else {
    47. X[i] = x1;
    48. avX = avX + X[i];
    49. q1++;
    50. }
    51. }
    52. }
    53. imshow("img2", img);
    54. imwrite("shuchu.png", img);
    55. cout << "直线的条数:" << q +q1 <
    56. avX = (double)(avX / (double)(q + q1));
    57. double min = 0;//标记最小值---斜率差值
    58. int i1, i2;//左右直线
    59. for (size_t i = 0; i < lines.size(); i++)
    60. {
    61. Vec4i I = lines[i];
    62. double x1 = I[0];
    63. double y1 = I[1];
    64. double x2 = I[2];
    65. double y2 = I[3];
    66. //筛选满足条件的点
    67. if (abs(x1 - x2) + abs(y1 - y2) > 50)
    68. {
    69. if (X[i] > avX)
    70. {
    71. cout << "右侧直线:" << i << endl;
    72. double e = k[i];//抽取右侧直线的斜率
    73. int i3 = i;//记录此时的右侧直线的i值
    74. for (size_t i = 0; i < lines.size(); i++)
    75. {
    76. Vec4i I = lines[i];
    77. double x1 = I[0];
    78. double y1 = I[1];
    79. double x2 = I[2];
    80. double y2 = I[3];
    81. //筛选满足条件的点
    82. if (abs(x1 - x2) + abs(y1 - y2) > 50)
    83. {
    84. if (X[i] <= avX)//左侧直线操作
    85. {
    86. if (min < abs(k[i] - e))
    87. {
    88. min = abs(k[i] - e);
    89. i2 = i;
    90. i1 = i3;
    91. }
    92. }
    93. }
    94. }
    95. }
    96. else
    97. {
    98. cout << "左侧直线:" << i << endl;
    99. }
    100. }
    101. }
    102. cout << "两条最为相近的直线: " << "左边直线:" << i2 << " 右边直线:" << i1 << endl;
    103. waitKey(0);
    104. return 0;
    105. }

    运行结果:

    注意:上面提取出来的两条直线不是两个都是垂直的,如果要是有垂直的情况需要再想(后面再想) 

    并且注意上面标出的地方两条直线,代码如下所示:

    1. #include
    2. #include
    3. using namespace cv;
    4. using namespace std;
    5. int main()
    6. {
    7. Mat img = imread("result1.png");
    8. Mat img1 = img;
    9. //设定图片的大小
    10. resize(img, img, Size(4096, 2160));
    11. Mat gray, canny, binaryImage;
    12. cvtColor(img, gray, CV_RGB2GRAY);
    13. threshold(gray, binaryImage, 100, 225, THRESH_BINARY);
    14. imshow("binaryImage", binaryImage);
    15. Canny(binaryImage, canny, 50, 120);
    16. vector lines;
    17. HoughLinesP(canny, lines, 1, CV_PI / 180, 50, 200, 30);
    18. int q1 = 0; //垂直直线
    19. int q = 0; //不是垂直直线的条数
    20. double k[20] ,b[20];//用来存放至直线的y=kx+b,这个地方用来存放k和b,为什么要变成20,因为他里面不能够放入变量
    21. //这里设定当y相同的时候求取x的值,y设定为2160/2
    22. double X[20];
    23. double avX = 0;//x的平均值
    24. for (size_t i = 0; i < lines.size(); i++)
    25. {
    26. Vec4i I = lines[i];
    27. double x1 = I[0];
    28. double y1 = I[1];
    29. double x2 = I[2];
    30. double y2 = I[3];
    31. //筛选满足条件的点
    32. if (abs(x1 - x2) + abs(y1 - y2) > 50)
    33. {
    34. //将满足条件的点画出
    35. line(img, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255 ), 2);
    36. cout << i << " " << "(" << x1 << "," << y1 << ")" << " " << "(" << x2 << "," << y2 << ")" << endl;
    37. if (x1 != x2)
    38. {
    39. //求取直线
    40. k[i] = (double)((y1 - y2) / (x1 - x2));
    41. b[i] = (double)(y1 - k[i] * x1);
    42. X[i] = (double)((2160.0f / 2.0f) - b[i]) / k[i];
    43. avX = avX + X[i];
    44. cout << "k[i]:" << k[i] << " " << "b[i]:" << b[i] << " X[i]:" << b[i] << " avX:" << avX << endl;
    45. q++;
    46. }
    47. else {
    48. X[i] = x1;
    49. avX = avX + X[i];
    50. q1++;
    51. }
    52. }
    53. }
    54. imshow("img2", img);
    55. imwrite("shuchu.png", img);
    56. cout << "直线的条数:" << q +q1 <
    57. avX = (double)(avX / (double)(q + q1));
    58. double min = 0;//标记最小值---斜率差值
    59. int i1, i2;//左右直线
    60. for (size_t i = 0; i < lines.size(); i++)
    61. {
    62. Vec4i I = lines[i];
    63. double x1 = I[0];
    64. double y1 = I[1];
    65. double x2 = I[2];
    66. double y2 = I[3];
    67. //筛选满足条件的点
    68. if (abs(x1 - x2) + abs(y1 - y2) > 50)
    69. {
    70. if (X[i] > avX && (x1-x2 !=0 ))
    71. {
    72. cout << "右侧直线:" << i << endl;
    73. double e = k[i];//抽取右侧直线的斜率
    74. int i3 = i;//记录此时的右侧直线的i值
    75. for (size_t i = 0; i < lines.size(); i++)
    76. {
    77. Vec4i I = lines[i];
    78. double x1 = I[0];
    79. double y1 = I[1];
    80. double x2 = I[2];
    81. double y2 = I[3];
    82. //筛选满足条件的点
    83. if (abs(x1 - x2) + abs(y1 - y2) > 50 )
    84. {
    85. if (X[i] <= avX && (x1 - x2 != 0))//左侧直线操作
    86. {
    87. if (min < abs(k[i] - e))
    88. {
    89. min = abs(k[i] - e);
    90. i2 = i;
    91. i1 = i3;
    92. }
    93. }
    94. }
    95. }
    96. }
    97. else
    98. {
    99. cout << "左侧直线:" << i << endl;
    100. }
    101. }
    102. }
    103. cout << "两条最为相近的直线: " << "左边直线:" << i2 << " 右边直线:" << i1 << endl;
    104. /*
    105. int x31 = 0,x32 = 4096,x41 = 0,x42 = 4096 ;
    106. int y31, y32, y41, y42;
    107. y31 = k[i2] * x31 + b[i2];
    108. y32 = k[i2] * x32 + b[i2];
    109. y41 = k[i1] * x41 + b[i1];
    110. y42 = k[i1] * x42 + b[i1];
    111. */
    112. resize(img1, img1, Size(4096, 2160));
    113. Vec4i I = lines[i2];
    114. double x31 = I[0];
    115. double y31 = I[1];
    116. double x32 = I[2];
    117. double y32 = I[3];
    118. line(img1, Point2d(x31, y31), Point2d(x32, y32), Scalar(0, 255, 255), 2);
    119. line(img1, Point2d(1706, 999), Point2d(1725, 1354), Scalar(0, 255, 255), 2);
    120. line(img1, Point2d(1767, 479), Point2d(1781, 693), Scalar(0, 255, 255), 2);
    121. I = lines[i1];
    122. double x41 = I[0];
    123. double y41 = I[1];
    124. double x42 = I[2];
    125. double y42 = I[3];
    126. line(img1, Point2d(x41, y41), Point2d(x42, y42), Scalar(0, 255, 255), 2);
    127. imshow("img3", img1);
    128. imwrite("shuchu3.png", img1);
    129. waitKey(0);
    130. return 0;
    131. }

    输出结果:

    进而得到最为相似的平行的两条直线.

    接下来就是将上述的直线进行拟合成为一条直线.

    1. #include
    2. #include
    3. using namespace cv;
    4. using namespace std;
    5. int main()
    6. {
    7. Mat img = imread("result1.png");
    8. Mat img1 = img;
    9. //设定图片的大小
    10. resize(img, img, Size(4096, 2160));
    11. Mat gray, canny, binaryImage;
    12. cvtColor(img, gray, CV_RGB2GRAY);
    13. threshold(gray, binaryImage, 100, 225, THRESH_BINARY);
    14. imshow("binaryImage", binaryImage);
    15. Canny(binaryImage, canny, 50, 120);
    16. vector lines;
    17. HoughLinesP(canny, lines, 1, CV_PI / 180, 50, 200, 30);
    18. int q1 = 0; //垂直直线
    19. int q = 0; //不是垂直直线的条数
    20. double k[20] ,b[20];//用来存放至直线的y=kx+b,这个地方用来存放k和b,为什么要变成20,因为他里面不能够放入变量
    21. //这里设定当y相同的时候求取x的值,y设定为2160/2
    22. double X[20];
    23. double avX = 0;//x的平均值
    24. for (size_t i = 0; i < lines.size(); i++)
    25. {
    26. Vec4i I = lines[i];
    27. double x1 = I[0];
    28. double y1 = I[1];
    29. double x2 = I[2];
    30. double y2 = I[3];
    31. //筛选满足条件的点
    32. if (abs(x1 - x2) + abs(y1 - y2) > 50)
    33. {
    34. //将满足条件的点画出
    35. line(img, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255 ), 2);
    36. cout << i << " " << "(" << x1 << "," << y1 << ")" << " " << "(" << x2 << "," << y2 << ")" << endl;
    37. if (x1 != x2)
    38. {
    39. //求取直线
    40. k[i] = (double)((y1 - y2) / (x1 - x2));
    41. b[i] = (double)(y1 - k[i] * x1);
    42. X[i] = (double)((2160.0f / 2.0f) - b[i]) / k[i];
    43. avX = avX + X[i];
    44. cout << "k[i]:" << k[i] << " " << "b[i]:" << b[i] << " X[i]:" << b[i] << " avX:" << avX << endl;
    45. q++;
    46. }
    47. else {
    48. X[i] = x1;
    49. avX = avX + X[i];
    50. q1++;
    51. }
    52. }
    53. }
    54. imshow("img2", img);
    55. imwrite("shuchu.png", img);
    56. cout << "直线的条数:" << q +q1 <
    57. avX = (double)(avX / (double)(q + q1));
    58. double min = 0;//标记最小值---斜率差值
    59. int i1, i2;//左右直线
    60. for (size_t i = 0; i < lines.size(); i++)
    61. {
    62. Vec4i I = lines[i];
    63. double x1 = I[0];
    64. double y1 = I[1];
    65. double x2 = I[2];
    66. double y2 = I[3];
    67. //筛选满足条件的点
    68. if (abs(x1 - x2) + abs(y1 - y2) > 50)
    69. {
    70. if (X[i] > avX && (x1-x2 !=0 ))
    71. {
    72. cout << "右侧直线:" << i << endl;
    73. double e = k[i];//抽取右侧直线的斜率
    74. int i3 = i;//记录此时的右侧直线的i值
    75. for (size_t i = 0; i < lines.size(); i++)
    76. {
    77. Vec4i I = lines[i];
    78. double x1 = I[0];
    79. double y1 = I[1];
    80. double x2 = I[2];
    81. double y2 = I[3];
    82. //筛选满足条件的点
    83. if (abs(x1 - x2) + abs(y1 - y2) > 50 )
    84. {
    85. if (X[i] <= avX && (x1 - x2 != 0))//左侧直线操作
    86. {
    87. if (min < abs(k[i] - e))
    88. {
    89. min = abs(k[i] - e);
    90. i2 = i;
    91. i1 = i3;
    92. }
    93. }
    94. }
    95. }
    96. }
    97. else
    98. {
    99. cout << "左侧直线:" << i << endl;
    100. }
    101. }
    102. }
    103. cout << "两条最为相近的直线: " << "左边直线:" << i2 << " 右边直线:" << i1 << endl;
    104. /*
    105. int x31 = 0,x32 = 4096,x41 = 0,x42 = 4096 ;
    106. int y31, y32, y41, y42;
    107. y31 = k[i2] * x31 + b[i2];
    108. y32 = k[i2] * x32 + b[i2];
    109. y41 = k[i1] * x41 + b[i1];
    110. y42 = k[i1] * x42 + b[i1];
    111. */
    112. resize(img1, img1, Size(4096, 2160));
    113. Vec4i I = lines[i2];
    114. double x31 = I[0];
    115. double y31 = I[1];
    116. double x32 = I[2];
    117. double y32 = I[3];
    118. line(img1, Point2d(x31, y31), Point2d(x32, y32), Scalar(0, 255, 255), 2);
    119. I = lines[i1];
    120. double x41 = I[0];
    121. double y41 = I[1];
    122. double x42 = I[2];
    123. double y42 = I[3];
    124. line(img1, Point2d(x41, y41), Point2d(x42, y42), Scalar(0, 255, 255), 2);
    125. //画出拟合直线
    126. double K = (double)(k[i2] + k[i1]) / 2.0;
    127. double B = (double)(b[i2] + b[i1]) / 2.0;
    128. double x51 = 0;
    129. double y51 = K * x51 + B;
    130. double x52 = 4096;
    131. double y52 = K * x52 + B;
    132. line(img1, Point2d(x51, y51), Point2d(x52, y52), Scalar(255, 0, 0), 3);
    133. imshow("img3", img1);
    134. imwrite("shuchu3.png", img1);
    135. waitKey(0);
    136. return 0;
    137. }

    输出结果:

    就是这样,上述思路之中主要是进行提取两条平行线的思路需要注意,一步一步来就是非常简单的. 

    最终版,但是上面的代码并不能检测到竖直直线的存在,反正最后写出来了,可麻烦了,代码不想看第二遍,代码如下所示:

    1. #include
    2. #include
    3. using namespace cv;
    4. using namespace std;
    5. int main()
    6. {
    7. Mat img = imread("左相机123.bmp");
    8. Mat img1 = img;
    9. Mat img3 = imread("左相机123.bmp");
    10. //设定图片的大小
    11. resize(img, img, Size(4096, 2160));
    12. Mat gray, canny, binaryImage;
    13. cvtColor(img, gray, CV_RGB2GRAY);
    14. threshold(gray, binaryImage, 150, 220, THRESH_BINARY);
    15. imshow("binaryImage", binaryImage);
    16. Canny(binaryImage, canny, 50, 120);
    17. vector lines;
    18. HoughLinesP(canny, lines, 1, CV_PI / 180, 50, 200, 30);
    19. int q1 = 0; //垂直直线
    20. int q2 = 0;
    21. int qs = 0;
    22. bool S = false;//是否存在左右直线
    23. int q = 0; //不是垂直直线的条数
    24. double k[20] ,b[20];//用来存放至直线的y=kx+b,这个地方用来存放k和b,为什么要变成20,因为他里面不能够放入变量
    25. //这里设定当y相同的时候求取x的值,y设定为2160/2
    26. double X[20];//放入的是数竖直的线
    27. double avX = 0;//x的平均值 __ 不包括竖直直线
    28. double avXS = 0;//数值直线
    29. double maxR = 0;//记录竖直差
    30. double maxL = 0;
    31. double xr, xl;
    32. for (size_t i = 0; i < lines.size(); i++)
    33. {
    34. Vec4i I = lines[i];
    35. double x1 = I[0];
    36. double y1 = I[1];
    37. double x2 = I[2];
    38. double y2 = I[3];
    39. //筛选满足条件的点
    40. if (abs(x1 - x2) + abs(y1 - y2) > 50)
    41. {
    42. //将满足条件的点画出
    43. line(img, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255), 2);
    44. cout << i << " " << "(" << x1 << "," << y1 << ")" << " " << "(" << x2 << "," << y2 << ")" << endl;
    45. if (x1 != x2)
    46. {
    47. //求取直线
    48. k[i] = (double)((y1 - y2) / (x1 - x2));
    49. b[i] = (double)(y1 - k[i] * x1);
    50. X[i] = (double)((2160.0f / 2.0f) - b[i]) / k[i];
    51. avX = avX + X[i];
    52. cout << "k[i]:" << k[i] << " " << "b[i]:" << b[i] << " X[i]:" << b[i] << " avX:" << avX << endl;
    53. q++;
    54. }
    55. else {//竖直直线
    56. X[i] = x1;
    57. avX = avX + X[i];
    58. avXS = avXS + X[i];
    59. qs++;
    60. if ((avX / qs - X[i]) > 5)/**************************************************************************************************************************************************/
    61. {
    62. S = true;
    63. }
    64. }
    65. }
    66. }
    67. avXS = avXS / qs;
    68. cout << "中间竖直直线x坐标" << avXS << endl;
    69. for (size_t i = 0; i < lines.size(); i++)
    70. {
    71. Vec4i I = lines[i];
    72. double x1 = I[0];
    73. double y1 = I[1];
    74. double x2 = I[2];
    75. double y2 = I[3];
    76. //筛选满足条件的点
    77. if (abs(x1 - x2) + abs(y1 - y2) > 50)
    78. {
    79. if(S == true && x1 == x2)//两条直线之间的距离大于5个像素
    80. {
    81. if ((maxR < abs(x1 - avXS)) && x1 >= avXS)//选出最小的右侧竖直直线
    82. {
    83. maxR = abs(x1 - avXS);
    84. cout << "maxR:" << maxR << endl;
    85. q2++;
    86. }
    87. else if (x1 >= avXS) {
    88. q2++;
    89. cout << "maxR:" << maxR << endl;
    90. }
    91. if ((maxL < abs(x1 - avXS)) && x1 <= avXS)//选出最小的右侧竖直直线
    92. {
    93. maxL = abs(x1 - avXS);
    94. cout << "maxL:" << maxL << endl;
    95. q1++;
    96. }
    97. else if (x1 <= avXS)
    98. {
    99. q1++;
    100. cout << "maxL:" << maxL << endl;
    101. }
    102. }
    103. }
    104. }
    105. imshow("img2", img);
    106. imwrite("shuchu.png", img);
    107. waitKey(0);
    108. cout << "直线的总条数:" << q + q1 + q2 <
    109. cout << "左侧竖直直线条数:" << q1 << endl;
    110. cout << "右侧竖直直线条数:" << q2 << endl;
    111. avX = (double)(avX / (double)(q + q1 + q2));
    112. cout << "总直线x平均坐标" << avX << endl;
    113. cout << "竖直直线x平均坐标" << avXS << endl;
    114. double min = 0;//标记最小值---斜率差值
    115. double xrpoint, xlpoint;
    116. int i1, i2;//左右直线
    117. for (size_t i = 0; i < lines.size(); i++)
    118. {
    119. Vec4i I = lines[i];
    120. double x1 = I[0];
    121. double y1 = I[1];
    122. double x2 = I[2];
    123. double y2 = I[3];
    124. //筛选满足条件的点
    125. if (abs(x1 - x2) + abs(y1 - y2) > 50)
    126. {
    127. if ((q1 > 0) && (q2 > 0) && (x1 - x2 == 0 ))//说明是存在两条竖直的直线
    128. {
    129. if ( (x1 >= avXS) && (maxR == abs(x1 - avXS)))//选出最大的右侧竖直直线
    130. {
    131. //划线并且记录
    132. line(img3, Point2d(x1, 0), Point2d(x1, 2160), Scalar(0, 255, 255), 2);
    133. xrpoint = x1;
    134. cout << "总直线x平均坐标1" << xrpoint << endl;
    135. cout << "划线" << endl;
    136. }
    137. if ((x1 <= avXS) && (maxL == abs(x1 - avXS)))//选出最小的左侧竖直直线
    138. {
    139. //划线并且记录
    140. line(img3, Point2d(x1, 0), Point2d(x1, 2160), Scalar(0, 255, 255), 2);
    141. xlpoint = x1;
    142. cout << "总直线x平均坐标2" << xlpoint << endl;
    143. cout << "划线" << endl;
    144. }
    145. }
    146. else if ((x1-x2 !=0 ))//右侧不是竖直直线---这个地方是之前写的,可以运行
    147. {
    148. cout << "右侧不是竖直的直线:" << i << endl;
    149. double e = k[i];//抽取右侧直线的斜率
    150. int i3 = i;//记录此时的右侧直线的i值
    151. for (size_t i = 0; i < lines.size(); i++)
    152. {
    153. Vec4i I = lines[i];
    154. double x1 = I[0];
    155. double y1 = I[1];
    156. double x2 = I[2];
    157. double y2 = I[3];
    158. //筛选满足条件的点
    159. if (abs(x1 - x2) + abs(y1 - y2) > 50 )
    160. {
    161. if (X[i] <= avX && (x1 - x2 != 0))//左侧不是竖直直线操作
    162. {
    163. if (min < abs(k[i] - e))
    164. {
    165. min = abs(k[i] - e);
    166. i2 = i;
    167. i1 = i3;
    168. }
    169. }
    170. }
    171. }
    172. }
    173. else
    174. {
    175. cout << "左侧直线:" << i << endl;
    176. }
    177. }
    178. }
    179. /*
    180. int x31 = 0,x32 = 4096,x41 = 0,x42 = 4096 ;
    181. int y31, y32, y41, y42;
    182. y31 = k[i2] * x31 + b[i2];
    183. y32 = k[i2] * x32 + b[i2];
    184. y41 = k[i1] * x41 + b[i1];
    185. y42 = k[i1] * x42 + b[i1];
    186. */
    187. if (q1 > 0 && q2 > 0)
    188. {
    189. //resize(img3, img3, Size(4096, 2160));
    190. line(img3, Point2d((xlpoint+ xrpoint)/2.0, 0), Point2d((xlpoint + xrpoint) / 2.0, 2160), Scalar(255, 0, 255), 2);
    191. cout << "存在两条竖直直线:" << "情况一:" << endl;
    192. imwrite("输出最终结果直线.png", img3);
    193. resize(img3, img3, Size(1024, 540));//显示改变大小
    194. imshow("img3", img3);
    195. waitKey(0);
    196. }
    197. else {
    198. resize(img1, img1, Size(4096, 2160));
    199. Vec4i I = lines[i2];
    200. double x31 = I[0];
    201. double y31 = I[1];
    202. double x32 = I[2];
    203. double y32 = I[3];
    204. line(img1, Point2d(x31, y31), Point2d(x32, y32), Scalar(0, 255, 255), 2);
    205. I = lines[i1];
    206. double x41 = I[0];
    207. double y41 = I[1];
    208. double x42 = I[2];
    209. double y42 = I[3];
    210. line(img1, Point2d(x41, y41), Point2d(x42, y42), Scalar(0, 255, 255), 2);
    211. //画出拟合直线
    212. double K = (double)(k[i2] + k[i1]) / 2.0;
    213. double B = (double)(b[i2] + b[i1]) / 2.0;
    214. double x51 = 0;
    215. double y51 = K * x51 + B;
    216. double x52 = 4096;
    217. double y52 = K * x52 + B;
    218. line(img1, Point2d(x51, y51), Point2d(x52, y52), Scalar(255, 0, 0), 3);
    219. cout << "斜率K:" << K << " B:" << B << endl;
    220. imwrite("shuchu3.png", img1);
    221. resize(img1, img1, Size(1024, 540));//显示改变大小
    222. imshow("img3", img1);
    223. waitKey(0);
    224. }
    225. return 0;
    226. }

    效果图:

    左右两条是提取的竖直直线,中间就是自己想要的那一条直线.

  • 相关阅读:
    硫化锌量子点/ZnS QDs 巯基SH/氨基/NH2/羧基COOH修饰硫化锌量子点/ZnS QDs
    Day42——MySQL数据库基础操作
    【Gazebo要素02】系统构成
    基于SSM的概念可视化程序设计学习系统毕业设计源码021009
    OCP Java17 SE Developers 复习题14
    梳理下我自已对Reactor与及IO多路复用的select\poll\epoll的理解
    Android两个应用同时使用后置摄像录像
    java毕业设计儿童疫苗接种提醒系统小程序服务端Mybatis+系统+数据库+调试部署
    程序员的三重境界:码农,高级码农、程序员!
    容量推荐引擎:基于吞吐量和利用率的预测缩放
  • 原文地址:https://blog.csdn.net/m0_47489229/article/details/127674452