小言_互联网的博客

提取接近竖直物体(粗定位)

209人阅读  评论(0)

由于项目的需要提取图像之中的一个接近于竖直的物体,一般的方法是进行图像分割,分割方式使用什么OTSU方式以及hsv方法等等。但是项目中使用的相机是黑白相机,会受到一定的限制。因此想到的是使用线条提取方式。线条提取方式之中最好的方法是使用canny算法,但是这里不能够将接近竖直特征进行提取,因此,此处使用了Prewitt算子进行提取,但是只用这个算法,轮廓提取不出来,就结合了一下canny算子。下面是我的思路,感觉实现过程比较麻烦,但是居然实现了[苦笑]!!!!

本次测试的案例是使用校门口的一个图片,图中存在很多的干扰,如下图所示


  
  1. #include <opencv2/opencv.hpp>
  2. #include <opencv2/highgui/highgui.hpp>
  3. #include <iostream>
  4. #include <opencv2/core.hpp>
  5. #include <opencv2/highgui.hpp>
  6. #include <opencv2/imgproc.hpp>
  7. using namespace cv;
  8. using namespace std;
  9. void getPrewitt_oper(cv::Mat& getPrewitt_horizontal, cv::Mat& getPrewitt_vertical, cv::Mat& getPrewitt_Diagonal1, cv::Mat& getPrewitt_Diagonal2) {
  10. //水平方向
  11. getPrewitt_horizontal = (cv:: Mat_< float>( 3, 3) << -1, -1, -1, 0, 0, 0, 1, 1, 1);
  12. //垂直方向
  13. getPrewitt_vertical = (cv:: Mat_< float>( 3, 3) << -1, 0, 1, -1, 0, 1, -1, 0, 1);
  14. //对角135°
  15. getPrewitt_Diagonal1 = (cv:: Mat_< float>( 3, 3) << 0, 1, 1, -1, 0, 1, -1, -1, 0);
  16. //对角45°
  17. getPrewitt_Diagonal2 = (cv:: Mat_< float>( 3, 3) << -1, -1, 0, -1, 0, 1, 0, 1, 1);
  18. //逆时针反转180°得到卷积核
  19. cv:: flip(getPrewitt_horizontal, getPrewitt_horizontal, -1);
  20. cv:: flip(getPrewitt_vertical, getPrewitt_vertical, -1);
  21. cv:: flip(getPrewitt_Diagonal1, getPrewitt_Diagonal1, -1);
  22. cv:: flip(getPrewitt_Diagonal2, getPrewitt_Diagonal2, -1);
  23. }
  24. void edge_Prewitt(cv::Mat& src, cv::Mat& dst1, cv::Mat& dst2, cv::Mat& dst3, cv::Mat& dst4, cv::Mat& dst, int ddepth, double delta = 0, int borderType = cv::BORDER_DEFAULT) {
  25. //获取Prewitt算子
  26. cv::Mat getPrewitt_horizontal;
  27. cv::Mat getPrewitt_vertical;
  28. cv::Mat getPrewitt_Diagonal1;
  29. cv::Mat getPrewitt_Diagonal2;
  30. getPrewitt_oper(getPrewitt_horizontal, getPrewitt_vertical, getPrewitt_Diagonal1, getPrewitt_Diagonal2);
  31. //卷积得到水平方向边缘
  32. cv:: filter2D(src, dst1, ddepth, getPrewitt_horizontal, cv:: Point( -1, -1), delta, borderType);
  33. //卷积得到4垂直方向边缘
  34. cv:: filter2D(src, dst2, ddepth, getPrewitt_vertical, cv:: Point( -1, -1), delta, borderType);
  35. //卷积得到45°方向边缘
  36. cv:: filter2D(src, dst3, ddepth, getPrewitt_Diagonal1, cv:: Point( -1, -1), delta, borderType);
  37. //卷积得到135°方向边缘
  38. cv:: filter2D(src, dst4, ddepth, getPrewitt_Diagonal2, cv:: Point( -1, -1), delta, borderType);
  39. //边缘强度(近似)
  40. cv:: convertScaleAbs(dst1, dst1); //求绝对值并转为无符号8位图
  41. cv:: convertScaleAbs(dst2, dst2);
  42. cv:: convertScaleAbs(dst3, dst3); //求绝对值并转为无符号8位图
  43. cv:: convertScaleAbs(dst4, dst4);
  44. dst = dst1 + dst2;
  45. }
  46. //数组从大到小排序
  47. void reserve(int x[], int n) {
  48. int i, j, temp;
  49. for (i = 0; i < n - 1; i++) { //一共n个元素,则需要比较n-1次
  50. for (j = 0; j < n - 1 - i; j++) { //每一个元素需要比较的次数
  51. if (x[i] < x[i + j + 1]) {
  52. temp = x[i];
  53. x[i] = x[i + j + 1];
  54. x[i + j + 1] = temp;
  55. }
  56. }
  57. }
  58. }
  59. int main()
  60. {
  61. cv::Mat src = cv:: imread( "楼.jpg");
  62. if (src. empty()) {
  63. return -1;
  64. }
  65. cout << "??" << endl;
  66. if (src. channels() > 1) cv:: cvtColor(src, src, CV_RGB2GRAY);
  67. cv::Mat dst, dst1, dst2, dst3, dst4, dst5;
  68. Mat src1 = cv:: imread( "楼.jpg");
  69. Mat src2 = cv:: imread( "楼.jpg");
  70. //medianBlur(src, src, 5); //均值滤波
  71. GaussianBlur(src, src, Size( 5, 5), 0); //高斯滤波
  72. cout << "??" << endl;
  73. //注意:要采用CV_32F,因为有些地方卷积后为负数,若用8位无符号,则会导致这些地方为0
  74. edge_Prewitt(src, dst1, dst2, dst3, dst4, dst, CV_32F);
  75. cv:: namedWindow( "垂直边缘", CV_WINDOW_NORMAL);
  76. imshow( "垂直边缘", dst2);
  77. cout << "??" << endl;
  78. //获取结构
  79. cv::Mat element1 = cv:: getStructuringElement(cv::MORPH_RECT, cv:: Size( 3, 3));
  80. Mat out1;
  81. //进行形态学开运算操作
  82. morphologyEx(dst2, out1, MORPH_OPEN, element1); //形态学开运算
  83. cv:: namedWindow( "xingtai", CV_WINDOW_NORMAL);
  84. imshow( "xingtai", out1);
  85. //第二次进行形态学操作
  86. edge_Prewitt(dst2, dst1, out1, dst3, dst4, dst, CV_32F);
  87. cv:: namedWindow( "垂直边缘1", CV_WINDOW_NORMAL);
  88. imshow( "垂直边缘1", out1);
  89. cout << "??" << endl;
  90. morphologyEx(out1, out1, MORPH_OPEN, element1); //形态学开运算
  91. cv:: namedWindow( "xingtai1", CV_WINDOW_NORMAL);
  92. imshow( "xingtai1", out1);
  93. //获取结构
  94. cv::Mat element2 = cv:: getStructuringElement(cv::MORPH_ELLIPSE, cv:: Size( 10, 10));
  95. Mat out2;
  96. //进行形态学闭运算操作
  97. morphologyEx(out1, out2, MORPH_CLOSE, element2); //形态学开运算
  98. cv:: namedWindow( "xingtai2", CV_WINDOW_NORMAL);
  99. imshow( "xingtai2", out2);
  100. imwrite( "xingtai2.jpg", out2);
  101. /*
  102. //膨胀运算,将细小缝隙填补上,非必要
  103. Mat kernel = getStructuringElement(0, Size(3, 3));
  104. dilate(out2, dst2, kernel);
  105. cv::namedWindow("膨胀", CV_WINDOW_NORMAL);
  106. imshow("膨胀", dst2);
  107. */
  108. cv:: threshold(out2, dst2, 5, 255, cv::THRESH_BINARY);
  109. cv:: namedWindow( "二值化", CV_WINDOW_NORMAL);
  110. imshow( "二值化", dst2);
  111. cv:: threshold(dst2, dst2, 5, 255, cv::THRESH_BINARY_INV);
  112. cv:: namedWindow( "反二值化", CV_WINDOW_NORMAL);
  113. imshow( "反二值化", dst2);
  114. //进行形态学闭运算操作
  115. morphologyEx(dst2, out2, MORPH_CLOSE, element2); //形态学开运算
  116. cv:: namedWindow( "xingtai3", CV_WINDOW_NORMAL);
  117. imshow( "xingtai3", out2);
  118. imwrite( "xingtai3.jpg", out2);
  119. /*
  120. cv::threshold(dst2, dst2, 5, 255, cv::THRESH_BINARY);
  121. cv::namedWindow("反二值化", CV_WINDOW_NORMAL);
  122. imshow("反二值化", dst2);
  123. imwrite("反二值化.jpg", dst2);
  124. */
  125. /*
  126. //膨胀运算,将细小缝隙填补上,非必要
  127. Mat kernel = getStructuringElement(0, Size(5, 5));
  128. dilate(out2, out2, kernel);
  129. cv::namedWindow("膨胀1", CV_WINDOW_NORMAL);
  130. imshow("膨胀1", out2);*/
  131. Canny(out2, dst2, 5, 10);
  132. cv:: namedWindow( "Canny", CV_WINDOW_NORMAL);
  133. imshow( "Canny", dst2);
  134. imwrite( "Canny.jpg", dst2);
  135. vector<Vec4i> lines;
  136. HoughLinesP(dst2, lines, 1, CV_PI / 180, 50, 200, 30);
  137. int Length[ 100] = { 0}; //存放直线长度
  138. for ( size_t i = 0; i < lines. size(); i++)
  139. {
  140. Vec4i I = lines[i];
  141. double x1 = I[ 0];
  142. double y1 = I[ 1];
  143. double x2 = I[ 2];
  144. double y2 = I[ 3];
  145. //筛选满足条件的点
  146. if ( abs(x1 - x2) + abs(y1 - y2) > 50)
  147. {
  148. Length[i] = sqrt( (x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2));
  149. //将满足条件的点画出
  150. line(src1, Point2d(x1, y1), Point2d(x2, y2), Scalar( 0, 255, 255), 2);
  151. cout << " " << "(" << x1 << "," << y1 << ")" << " " << "(" << x2 << "," << y2 << ")" << endl;
  152. //line(canny, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255), 2);
  153. }
  154. }
  155. Mat imgShow;
  156. imgShow = src1;
  157. resize(imgShow, imgShow, Size(imgShow.cols / 4, imgShow.rows / 4));
  158. imshow( "imgShow", imgShow);
  159. imwrite( "shuchu.png", src1);
  160. reserve(Length, 100);
  161. for ( int i = 0; i < 100; i++) {
  162. cout << "长度"<<Length[i] << endl; //输出排序后的数组元素
  163. }
  164. for ( size_t i = 0; i < lines. size(); i++)
  165. {
  166. Vec4i I = lines[i];
  167. double x1 = I[ 0];
  168. double y1 = I[ 1];
  169. double x2 = I[ 2];
  170. double y2 = I[ 3];
  171. cout << "sdjk" << endl;
  172. cout << int( sqrt((x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2))) << endl;
  173. //筛选满足条件的点
  174. if (( int( sqrt((x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2))) == Length[ 0] ) || ( int( sqrt((x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2))) == Length[ 1]))
  175. {
  176. //将满足条件的点画出
  177. line(src2, Point2d(x1, y1), Point2d(x2, y2), Scalar( 0, 255, 255), 2);
  178. cout << "djfkljsa " << "(" << x1 << "," << y1 << ")" << " " << "(" << x2 << "," << y2 << ")" << endl;
  179. //line(canny, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255), 2);
  180. }
  181. }
  182. imgShow = src2;
  183. resize(imgShow, imgShow, Size(imgShow.cols / 4, imgShow.rows / 4));
  184. imshow( "imgShow2", imgShow);
  185. imwrite( "shuchu2.png", src2);
  186. waitKey( 0);
  187. return 0;
  188. }

调试过程:本次在进行调试过程之中进行了两次垂直检测迭代,进一步去排除水平线的干扰.使用形态学操作去除图片之中的空洞等等.

第一次进行垂直检测,注意这个地方只能够用特定的算子进行垂直检测,别的算子没有这个效果. 

为了减少图片之中白色空洞的干扰,使用开操作.

重复上述操作,进一步排除水平线的干扰.

接下来是进行闭操作,将图中的白色线条尽可能连在一起,上图之中的楼左侧的线有一些断开了.

闭操作的缺陷是会产生小白点点.如下二值化过程

再进行一次反二值化,因为我不会用别的算子结合霍夫直线检测检测出来直线,只能转回去进行操作. 

形态学操作,去除白点

 canny一下检测出来轮廓

显示全部直线

 直线提取,我的方式是提取最长的两段直线。

 在上述操作完成之后,得到了物体的粗定位直线。

但是上面的算法还是存在相应的问题,换了一个别的图像可能就检测的不准。发现问题就是出在了二值化的过程。

为了修正上方的算法的失败,使用提取外部轮廓的方式进行求取,将代码改了改。
 


  
  1. #include <opencv2/opencv.hpp>
  2. #include <opencv2/highgui/highgui.hpp>
  3. #include <iostream>
  4. #include <opencv2/core.hpp>
  5. #include <opencv2/highgui.hpp>
  6. #include <opencv2/imgproc.hpp>
  7. using namespace cv;
  8. using namespace std;
  9. void getPrewitt_oper(cv::Mat& getPrewitt_horizontal, cv::Mat& getPrewitt_vertical, cv::Mat& getPrewitt_Diagonal1, cv::Mat& getPrewitt_Diagonal2) {
  10. //水平方向
  11. getPrewitt_horizontal = (cv:: Mat_< float>( 3, 3) << -1, -1, -1, 0, 0, 0, 1, 1, 1);
  12. //垂直方向
  13. getPrewitt_vertical = (cv:: Mat_< float>( 3, 3) << -1, 0, 1, -1, 0, 1, -1, 0, 1);
  14. //对角135°
  15. getPrewitt_Diagonal1 = (cv:: Mat_< float>( 3, 3) << 0, 1, 1, -1, 0, 1, -1, -1, 0);
  16. //对角45°
  17. getPrewitt_Diagonal2 = (cv:: Mat_< float>( 3, 3) << -1, -1, 0, -1, 0, 1, 0, 1, 1);
  18. //逆时针反转180°得到卷积核
  19. cv:: flip(getPrewitt_horizontal, getPrewitt_horizontal, -1);
  20. cv:: flip(getPrewitt_vertical, getPrewitt_vertical, -1);
  21. cv:: flip(getPrewitt_Diagonal1, getPrewitt_Diagonal1, -1);
  22. cv:: flip(getPrewitt_Diagonal2, getPrewitt_Diagonal2, -1);
  23. }
  24. void edge_Prewitt(cv::Mat& src, cv::Mat& dst1, cv::Mat& dst2, cv::Mat& dst3, cv::Mat& dst4, cv::Mat& dst, int ddepth, double delta = 0, int borderType = cv::BORDER_DEFAULT) {
  25. //获取Prewitt算子
  26. cv::Mat getPrewitt_horizontal;
  27. cv::Mat getPrewitt_vertical;
  28. cv::Mat getPrewitt_Diagonal1;
  29. cv::Mat getPrewitt_Diagonal2;
  30. getPrewitt_oper(getPrewitt_horizontal, getPrewitt_vertical, getPrewitt_Diagonal1, getPrewitt_Diagonal2);
  31. //卷积得到水平方向边缘
  32. cv:: filter2D(src, dst1, ddepth, getPrewitt_horizontal, cv:: Point( -1, -1), delta, borderType);
  33. //卷积得到4垂直方向边缘
  34. cv:: filter2D(src, dst2, ddepth, getPrewitt_vertical, cv:: Point( -1, -1), delta, borderType);
  35. //卷积得到45°方向边缘
  36. cv:: filter2D(src, dst3, ddepth, getPrewitt_Diagonal1, cv:: Point( -1, -1), delta, borderType);
  37. //卷积得到135°方向边缘
  38. cv:: filter2D(src, dst4, ddepth, getPrewitt_Diagonal2, cv:: Point( -1, -1), delta, borderType);
  39. //边缘强度(近似)
  40. cv:: convertScaleAbs(dst1, dst1); //求绝对值并转为无符号8位图
  41. cv:: convertScaleAbs(dst2, dst2);
  42. cv:: convertScaleAbs(dst3, dst3); //求绝对值并转为无符号8位图
  43. cv:: convertScaleAbs(dst4, dst4);
  44. dst = dst1 + dst2;
  45. }
  46. //数组从大到小排序
  47. void reserve(int x[], int n) {
  48. int i, j, temp;
  49. for (i = 0; i < n - 1; i++) { //一共n个元素,则需要比较n-1次
  50. for (j = 0; j < n - 1 - i; j++) { //每一个元素需要比较的次数
  51. if (x[i] < x[i + j + 1]) {
  52. temp = x[i];
  53. x[i] = x[i + j + 1];
  54. x[i + j + 1] = temp;
  55. }
  56. }
  57. }
  58. }
  59. int main()
  60. {
  61. cv::Mat src = cv:: imread( "楼.jpg");
  62. if (src. empty()) {
  63. return -1;
  64. }
  65. cout << "??" << endl;
  66. if (src. channels() > 1) cv:: cvtColor(src, src, CV_RGB2GRAY);
  67. cv::Mat dst, dst1, dst2, dst3, dst4, dst5;
  68. Mat src1 = cv:: imread( "楼.jpg");
  69. Mat src2 = cv:: imread( "楼.jpg");
  70. //medianBlur(src, src, 5); //均值滤波
  71. GaussianBlur(src, src, Size( 5, 5), 0); //高斯滤波
  72. cout << "??" << endl;
  73. //注意:要采用CV_32F,因为有些地方卷积后为负数,若用8位无符号,则会导致这些地方为0
  74. edge_Prewitt(src, dst1, dst2, dst3, dst4, dst, CV_32F);
  75. cv:: namedWindow( "垂直边缘", CV_WINDOW_NORMAL);
  76. imshow( "垂直边缘", dst2);
  77. cout << "??" << endl;
  78. /*
  79. Mat shdjk;
  80. cv::threshold(dst2, shdjk, 25, 255, cv::THRESH_BINARY);
  81. cv::namedWindow("二值化1212", CV_WINDOW_NORMAL);
  82. imshow("二值化1212", shdjk);
  83. */
  84. //获取结构
  85. cv::Mat element1 = cv:: getStructuringElement(cv::MORPH_RECT, cv:: Size( 3, 3));
  86. Mat out1;
  87. //进行形态学开运算操作
  88. morphologyEx(dst2, out1, MORPH_OPEN, element1); //形态学开运算
  89. cv:: namedWindow( "xingtai", CV_WINDOW_NORMAL);
  90. imshow( "xingtai", out1);
  91. Mat out2;
  92. //第二次进行形态学操作
  93. edge_Prewitt(out1, dst1, out1, dst3, dst4, dst, CV_32F);
  94. cv:: namedWindow( "垂直边缘1", CV_WINDOW_NORMAL);
  95. imshow( "垂直边缘1", out1);
  96. cout << "??" << endl;
  97. /*
  98. morphologyEx(out1, out1, MORPH_OPEN, element1);//形态学开运算
  99. cv::namedWindow("xingtai1", CV_WINDOW_NORMAL);
  100. imshow("xingtai1", out1);
  101. //获取结构
  102. cv::Mat element2 = cv::getStructuringElement(cv::MORPH_ELLIPSE, cv::Size(10, 10));
  103. //进行形态学闭运算操作
  104. morphologyEx(out1, out2, MORPH_CLOSE, element2);//形态学闭合运算
  105. cv::namedWindow("xingtai2", CV_WINDOW_NORMAL);
  106. imshow("xingtai2", out2);
  107. imwrite("xingtai2.jpg", out2);
  108. waitKey(0);
  109. */
  110. std::vector<std::vector<cv::Point>> contours;
  111. std::vector<cv::Vec4i> hierarchy;
  112. findContours(out1, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
  113. double maxArea = 0;
  114. int index = 0;
  115. vector<cv::Point> maxContour;
  116. for ( size_t i = 0; i < contours. size(); i++)
  117. {
  118. double area = cv:: contourArea(contours[i]);
  119. if (area > maxArea)
  120. {
  121. maxArea = area;
  122. maxContour = contours[i];
  123. index = i;
  124. }
  125. }
  126. drawContours(src1, contours, index, Scalar( 255)); // 参数
  127. cv:: namedWindow( "test", CV_WINDOW_NORMAL);
  128. imshow( "test", src1);
  129. waitKey( 0);
  130. /*
  131. Mat shdjk;
  132. cv::threshold(out1, shdjk, 10, 255, cv::THRESH_BINARY);
  133. cv::namedWindow("二值化1212", CV_WINDOW_NORMAL);
  134. imshow("二值化1212", shdjk);
  135. std::vector<std::vector<cv::Point>> contours;
  136. std::vector<cv::Vec4i> hierarchy;
  137. cv::findContours(shdjk, contours, hierarchy, cv::RETR_EXTERNAL, cv::CHAIN_APPROX_NONE); //只找最外层轮廓
  138. std::vector<std::vector<cv::Point>> approxCurves(contours.size());
  139. for (int i = 0; i < contours.size(); ++i) { //绘制逼近后的轮廓
  140. double epsilon = 0.1 * cv::arcLength(contours[i], true);
  141. cv::approxPolyDP(contours[i], approxCurves[i], epsilon, true);
  142. cv::drawContours(src1, approxCurves, i, cv::Scalar(0, 255, 0), 2);
  143. }
  144. cv::namedWindow("success", CV_WINDOW_NORMAL);
  145. imshow("success", src1);
  146. cv::waitKey();
  147. */
  148. //
  149. /*
  150. Mat dhfjua;
  151. cv::threshold(out2, dhfjua, 15, 255, cv::THRESH_BINARY);
  152. cv::namedWindow("二值化000", CV_WINDOW_NORMAL);
  153. imshow("二值化000", dhfjua);
  154. */
  155. /*
  156. //膨胀运算,将细小缝隙填补上,非必要
  157. Mat kernel = getStructuringElement(0, Size(3, 3));
  158. dilate(out2, dst2, kernel);
  159. cv::namedWindow("膨胀", CV_WINDOW_NORMAL);
  160. imshow("膨胀", dst2);
  161. */
  162. /*0
  163. cv::threshold(out2, dst2, 5, 255, cv::THRESH_BINARY);
  164. cv::namedWindow("二值化", CV_WINDOW_NORMAL);
  165. imshow("二值化", dst2);
  166. cv::threshold(dst2, dst2, 5, 255, cv::THRESH_BINARY_INV);
  167. cv::namedWindow("反二值化", CV_WINDOW_NORMAL);
  168. imshow("反二值化", dst2);
  169. */
  170. /*
  171. Mat out3;
  172. //进行形态学闭运算操作
  173. morphologyEx(dst2, out3, MORPH_CLOSE, element2);//形态学开运算
  174. cv::namedWindow("xingtai3", CV_WINDOW_NORMAL);
  175. imshow("xingtai3", out3);
  176. imwrite("xingtai3.jpg", out3);
  177. */
  178. waitKey( 0);
  179. vector<Vec4i> lines;
  180. HoughLinesP(src1, lines, 1, CV_PI / 180, 100, 400, 30);
  181. int Length[ 1000] = { 0 }; //存放直线长度
  182. for ( size_t i = 0; i < lines. size(); i++)
  183. {
  184. Vec4i I = lines[i];
  185. double x1 = I[ 0];
  186. double y1 = I[ 1];
  187. double x2 = I[ 2];
  188. double y2 = I[ 3];
  189. //筛选满足条件的点
  190. if ( abs(x1 - x2) + abs(y1 - y2) > 50)
  191. {
  192. Length[i] = sqrt((x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2));
  193. //将满足条件的点画出
  194. line(src1, Point2d(x1, y1), Point2d(x2, y2), Scalar( 0, 255, 255), 2);
  195. cout << " " << "(" << x1 << "," << y1 << ")" << " " << "(" << x2 << "," << y2 << ")" << endl;
  196. //line(canny, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255), 2);
  197. }
  198. }
  199. Mat imgShow;
  200. imgShow = src1;
  201. resize(imgShow, imgShow, Size(imgShow.cols / 4, imgShow.rows / 4));
  202. imshow( "imgShow", imgShow);
  203. imwrite( "shuchu.png", src1);
  204. reserve(Length, 1000);
  205. for ( int i = 0; i < 1000; i++) {
  206. cout << "长度" << Length[i] << endl; //输出排序后的数组元素
  207. }
  208. for ( size_t i = 0; i < lines. size(); i++)
  209. {
  210. Vec4i I = lines[i];
  211. double x1 = I[ 0];
  212. double y1 = I[ 1];
  213. double x2 = I[ 2];
  214. double y2 = I[ 3];
  215. cout << "sdjk" << endl;
  216. cout << int( sqrt((x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2))) << endl;
  217. //筛选满足条件的点
  218. if (( int( sqrt((x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2))) == Length[ 0]) || ( int( sqrt((x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2))) == Length[ 1]))
  219. {
  220. //将满足条件的点画出
  221. line(src2, Point2d(x1, y1), Point2d(x2, y2), Scalar( 0, 255, 255), 2);
  222. cout << "djfkljsa " << "(" << x1 << "," << y1 << ")" << " " << "(" << x2 << "," << y2 << ")" << endl;
  223. //line(canny, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255), 2);
  224. }
  225. }
  226. imgShow = src2;
  227. resize(imgShow, imgShow, Size(imgShow.cols / 4, imgShow.rows / 4));
  228. imshow( "imgShow2", imgShow);
  229. imwrite( "shuchu2.png", src2);
  230. waitKey( 0);
  231. return 0;
  232. }

效果还是不好,问题就是出在了相应的一个二值化的过程,因此,想到使用区域增长算法改进


  
  1. #include <iostream>
  2. #include <string>
  3. #include <list>
  4. #include <vector>
  5. #include <map>
  6. #include <stack>
  7. #include <opencv2/core/core.hpp>
  8. #include <opencv2/highgui/highgui.hpp>
  9. #include <opencv2/imgproc/imgproc.hpp>
  10. using namespace std;
  11. using namespace cv;
  12. //------------------------------【两步法新改进版】----------------------------------------------
  13. // 对二值图像进行连通区域标记,从1开始标号
  14. void Two_PassNew(const Mat &bwImg, Mat &labImg)
  15. {
  16. assert(bwImg. type() == CV_8UC1);
  17. labImg. create(bwImg. size(), CV_32SC1); //bwImg.convertTo( labImg, CV_32SC1 );
  18. labImg = Scalar( 0);
  19. labImg. setTo( Scalar( 1), bwImg);
  20. assert(labImg. isContinuous());
  21. const int Rows = bwImg.rows - 1, Cols = bwImg.cols - 1;
  22. int label = 1;
  23. vector< int> labelSet;
  24. labelSet. push_back( 0);
  25. labelSet. push_back( 1);
  26. //the first pass
  27. int *data_prev = ( int*)labImg.data; //0-th row : int* data_prev = labImg.ptr<int>(i-1);
  28. int *data_cur = ( int*)(labImg.data + labImg.step); //1-st row : int* data_cur = labImg.ptr<int>(i);
  29. for ( int i = 1; i < Rows; i++)
  30. {
  31. data_cur++;
  32. data_prev++;
  33. for ( int j = 1; j < Cols; j++, data_cur++, data_prev++)
  34. {
  35. if (*data_cur != 1)
  36. continue;
  37. int left = *(data_cur - 1);
  38. int up = *data_prev;
  39. int neighborLabels[ 2];
  40. int cnt = 0;
  41. if (left > 1)
  42. neighborLabels[cnt++] = left;
  43. if (up > 1)
  44. neighborLabels[cnt++] = up;
  45. if (!cnt)
  46. {
  47. labelSet. push_back(++label);
  48. labelSet[label] = label;
  49. *data_cur = label;
  50. continue;
  51. }
  52. int smallestLabel = neighborLabels[ 0];
  53. if (cnt == 2 && neighborLabels[ 1] < smallestLabel)
  54. smallestLabel = neighborLabels[ 1];
  55. *data_cur = smallestLabel;
  56. // 保存最小等价表
  57. for ( int k = 0; k < cnt; k++)
  58. {
  59. int tempLabel = neighborLabels[k];
  60. int& oldSmallestLabel = labelSet[tempLabel]; //这里的&不是取地址符号,而是引用符号
  61. if (oldSmallestLabel > smallestLabel)
  62. {
  63. labelSet[oldSmallestLabel] = smallestLabel;
  64. oldSmallestLabel = smallestLabel;
  65. }
  66. else if (oldSmallestLabel < smallestLabel)
  67. labelSet[smallestLabel] = oldSmallestLabel;
  68. }
  69. }
  70. data_cur++;
  71. data_prev++;
  72. }
  73. //更新等价队列表,将最小标号给重复区域
  74. for ( size_t i = 2; i < labelSet. size(); i++)
  75. {
  76. int curLabel = labelSet[i];
  77. int prelabel = labelSet[curLabel];
  78. while (prelabel != curLabel)
  79. {
  80. curLabel = prelabel;
  81. prelabel = labelSet[prelabel];
  82. }
  83. labelSet[i] = curLabel;
  84. }
  85. //second pass
  86. data_cur = ( int*)labImg.data;
  87. for ( int i = 0; i < Rows; i++)
  88. {
  89. for ( int j = 0; j < bwImg.cols - 1; j++, data_cur++)
  90. *data_cur = labelSet[*data_cur];
  91. data_cur++;
  92. }
  93. }
  94. //-------------------------------【老版两步法】-------------------------------------------
  95. void Two_PassOld(const cv::Mat& _binImg, cv::Mat& _lableImg)
  96. {
  97. //connected component analysis (4-component)
  98. //use two-pass algorithm
  99. //1. first pass: label each foreground pixel with a label
  100. //2. second pass: visit each labeled pixel and merge neighbor label
  101. //
  102. //foreground pixel: _binImg(x,y) = 1
  103. //background pixel: _binImg(x,y) = 0
  104. if (_binImg. empty() || _binImg. type() != CV_8UC1)
  105. {
  106. return;
  107. }
  108. // 1. first pass
  109. _lableImg. release();
  110. _binImg. convertTo(_lableImg, CV_32SC1);
  111. int label = 1; // start by 2
  112. std::vector< int> labelSet;
  113. labelSet. push_back( 0); //background: 0
  114. labelSet. push_back( 1); //foreground: 1
  115. int rows = _binImg.rows - 1;
  116. int cols = _binImg.cols - 1;
  117. for ( int i = 1; i < rows; i++)
  118. {
  119. int* data_preRow = _lableImg. ptr< int>(i - 1);
  120. int* data_curRow = _lableImg. ptr< int>(i);
  121. for ( int j = 1; j < cols; j++)
  122. {
  123. if (data_curRow[j] == 1)
  124. {
  125. std::vector< int> neighborLabels;
  126. neighborLabels. reserve( 2); //reserve(n) 预分配n个元素的存储空间
  127. int leftPixel = data_curRow[j - 1];
  128. int upPixel = data_preRow[j];
  129. if (leftPixel > 1)
  130. {
  131. neighborLabels. push_back(leftPixel);
  132. }
  133. if (upPixel > 1)
  134. {
  135. neighborLabels. push_back(upPixel);
  136. }
  137. if (neighborLabels. empty())
  138. {
  139. labelSet. push_back(++label); //assign to a new label
  140. data_curRow[j] = label;
  141. labelSet[label] = label;
  142. }
  143. else
  144. {
  145. std:: sort(neighborLabels. begin(), neighborLabels. end());
  146. int smallestLabel = neighborLabels[ 0];
  147. data_curRow[j] = smallestLabel;
  148. //save equivalence
  149. for ( size_t k = 1; k < neighborLabels. size(); k++)
  150. {
  151. int tempLabel = neighborLabels[k];
  152. int& oldSmallestLabel = labelSet[tempLabel];
  153. if (oldSmallestLabel > smallestLabel)
  154. {
  155. labelSet[oldSmallestLabel] = smallestLabel;
  156. oldSmallestLabel = smallestLabel;
  157. }
  158. else if (oldSmallestLabel < smallestLabel)
  159. {
  160. labelSet[smallestLabel] = oldSmallestLabel;
  161. }
  162. }
  163. }
  164. }
  165. }
  166. }
  167. //update equivalent labels
  168. //assigned with the smallest label in each equivalent label set
  169. for ( size_t i = 2; i < labelSet. size(); i++)
  170. {
  171. int curLabel = labelSet[i];
  172. int prelabel = labelSet[curLabel];
  173. while (prelabel != curLabel)
  174. {
  175. curLabel = prelabel;
  176. prelabel = labelSet[prelabel];
  177. }
  178. labelSet[i] = curLabel;
  179. }
  180. //2. second pass
  181. for ( int i = 0; i < rows; i++)
  182. {
  183. int *data = _lableImg. ptr< int>(i);
  184. for ( int j = 0; j < cols; j++)
  185. {
  186. int& pixelLabel = data[j];
  187. pixelLabel = labelSet[pixelLabel];
  188. }
  189. }
  190. }
  191. //---------------------------------【种子填充法老版】-------------------------------
  192. void SeedFillOld(const cv::Mat& binImg, cv::Mat& lableImg) //种子填充法
  193. {
  194. // 4邻接方法
  195. if (binImg. empty() ||
  196. binImg. type() != CV_8UC1)
  197. {
  198. return;
  199. }
  200. lableImg. release();
  201. binImg. convertTo(lableImg, CV_32SC1);
  202. int label = 1;
  203. int rows = binImg.rows - 1;
  204. int cols = binImg.cols - 1;
  205. for ( int i = 1; i < rows - 1; i++)
  206. {
  207. int* data = lableImg. ptr< int>(i);
  208. for ( int j = 1; j < cols - 1; j++)
  209. {
  210. if (data[j] == 1)
  211. {
  212. std::stack<std::pair< int, int>> neighborPixels;
  213. neighborPixels. push(std:: pair< int, int>(i, j)); // 像素位置: <i,j>
  214. ++label; // 没有重复的团,开始新的标签
  215. while (!neighborPixels. empty())
  216. {
  217. std::pair< int, int> curPixel = neighborPixels. top(); //如果与上一行中一个团有重合区域,则将上一行的那个团的标号赋给它
  218. int curX = curPixel.first;
  219. int curY = curPixel.second;
  220. lableImg. at< int>(curX, curY) = label;
  221. neighborPixels. pop();
  222. if (lableImg. at< int>(curX, curY - 1) == 1)
  223. { //左边
  224. neighborPixels. push(std:: pair< int, int>(curX, curY - 1));
  225. }
  226. if (lableImg. at< int>(curX, curY + 1) == 1)
  227. { // 右边
  228. neighborPixels. push(std:: pair< int, int>(curX, curY + 1));
  229. }
  230. if (lableImg. at< int>(curX - 1, curY) == 1)
  231. { // 上边
  232. neighborPixels. push(std:: pair< int, int>(curX - 1, curY));
  233. }
  234. if (lableImg. at< int>(curX + 1, curY) == 1)
  235. { // 下边
  236. neighborPixels. push(std:: pair< int, int>(curX + 1, curY));
  237. }
  238. }
  239. }
  240. }
  241. }
  242. }
  243. //-------------------------------------------【种子填充法新版】---------------------------
  244. void SeedFillNew(const cv::Mat& _binImg, cv::Mat& _lableImg)
  245. {
  246. // connected component analysis(4-component)
  247. // use seed filling algorithm
  248. // 1. begin with a forgeground pixel and push its forground neighbors into a stack;
  249. // 2. pop the pop pixel on the stack and label it with the same label until the stack is empty
  250. //
  251. // forground pixel: _binImg(x,y)=1
  252. // background pixel: _binImg(x,y) = 0
  253. if (_binImg. empty() ||
  254. _binImg. type() != CV_8UC1)
  255. {
  256. return;
  257. }
  258. _lableImg. release();
  259. _binImg. convertTo(_lableImg, CV_32SC1);
  260. int label = 0; //start by 1
  261. int rows = _binImg.rows;
  262. int cols = _binImg.cols;
  263. Mat mask(rows, cols, CV_8UC1);
  264. mask. setTo( 0);
  265. int *lableptr;
  266. for ( int i = 0; i < rows; i++)
  267. {
  268. int* data = _lableImg. ptr< int>(i);
  269. uchar *masKptr = mask. ptr<uchar>(i);
  270. for ( int j = 0; j < cols; j++)
  271. {
  272. if (data[j] == 255 && mask. at<uchar>(i, j) != 1)
  273. {
  274. mask. at<uchar>(i, j) = 1;
  275. std::stack<std::pair< int, int>> neighborPixels;
  276. neighborPixels. push(std:: pair< int, int>(i, j)); // pixel position: <i,j>
  277. ++label; //begin with a new label
  278. while (!neighborPixels. empty())
  279. {
  280. //get the top pixel on the stack and label it with the same label
  281. std::pair< int, int> curPixel = neighborPixels. top();
  282. int curY = curPixel.first;
  283. int curX = curPixel.second;
  284. _lableImg. at< int>(curY, curX) = label;
  285. //pop the top pixel
  286. neighborPixels. pop();
  287. //push the 4-neighbors(foreground pixels)
  288. if (curX - 1 >= 0)
  289. {
  290. if (_lableImg. at< int>(curY, curX - 1) == 255 && mask. at<uchar>(curY, curX - 1) != 1) //leftpixel
  291. {
  292. neighborPixels. push(std:: pair< int, int>(curY, curX - 1));
  293. mask. at<uchar>(curY, curX - 1) = 1;
  294. }
  295. }
  296. if (curX + 1 <= cols - 1)
  297. {
  298. if (_lableImg. at< int>(curY, curX + 1) == 255 && mask. at<uchar>(curY, curX + 1) != 1)
  299. // right pixel
  300. {
  301. neighborPixels. push(std:: pair< int, int>(curY, curX + 1));
  302. mask. at<uchar>(curY, curX + 1) = 1;
  303. }
  304. }
  305. if (curY - 1 >= 0)
  306. {
  307. if (_lableImg. at< int>(curY - 1, curX) == 255 && mask. at<uchar>(curY - 1, curX) != 1)
  308. // up pixel
  309. {
  310. neighborPixels. push(std:: pair< int, int>(curY - 1, curX));
  311. mask. at<uchar>(curY - 1, curX) = 1;
  312. }
  313. }
  314. if (curY + 1 <= rows - 1)
  315. {
  316. if (_lableImg. at< int>(curY + 1, curX) == 255 && mask. at<uchar>(curY + 1, curX) != 1)
  317. //down pixel
  318. {
  319. neighborPixels. push(std:: pair< int, int>(curY + 1, curX));
  320. mask. at<uchar>(curY + 1, curX) = 1;
  321. }
  322. }
  323. }
  324. }
  325. }
  326. }
  327. }
  328. //---------------------------------【颜色标记程序】-----------------------------------
  329. //彩色显示
  330. cv::Scalar GetRandomColor()
  331. {
  332. uchar r = 255 * ( rand() / ( 1.0 + RAND_MAX));
  333. uchar g = 255 * ( rand() / ( 1.0 + RAND_MAX));
  334. uchar b = 255 * ( rand() / ( 1.0 + RAND_MAX));
  335. return cv:: Scalar(b, g, r);
  336. }
  337. void LabelColor(const cv::Mat& labelImg, cv::Mat& colorLabelImg)
  338. {
  339. int num = 0;
  340. if (labelImg. empty() ||
  341. labelImg. type() != CV_32SC1)
  342. {
  343. return;
  344. }
  345. std::map< int, cv::Scalar> colors;
  346. int rows = labelImg.rows;
  347. int cols = labelImg.cols;
  348. colorLabelImg. release();
  349. colorLabelImg. create(rows, cols, CV_8UC3);
  350. colorLabelImg = cv::Scalar:: all( 0);
  351. for ( int i = 0; i < rows; i++)
  352. {
  353. const int* data_src = ( int*)labelImg. ptr< int>(i);
  354. uchar* data_dst = colorLabelImg. ptr<uchar>(i);
  355. for ( int j = 0; j < cols; j++)
  356. {
  357. int pixelValue = data_src[j];
  358. if (pixelValue > 1)
  359. {
  360. if (colors. count(pixelValue) <= 0)
  361. {
  362. colors[pixelValue] = GetRandomColor();
  363. num++;
  364. }
  365. cv::Scalar color = colors[pixelValue];
  366. *data_dst++ = color[ 0];
  367. *data_dst++ = color[ 1];
  368. *data_dst++ = color[ 2];
  369. }
  370. else
  371. {
  372. data_dst++;
  373. data_dst++;
  374. data_dst++;
  375. }
  376. }
  377. }
  378. printf( "color num : %d \n", num);
  379. }
  380. //------------------------------------------【测试主程序】-------------------------------------
  381. int main()
  382. {
  383. cv::Mat binImage = cv:: imread( "sda.jpg", 0);
  384. //cv::threshold(binImage, binImage, 50, 1, CV_THRESH_BINARY);
  385. cv::Mat labelImg;
  386. double time;
  387. time = getTickCount();
  388. SeedFillNew(binImage, labelImg);
  389. time = 1000 * (( double) getTickCount() - time) / getTickFrequency();
  390. cout << std::fixed << time << "ms" << endl;
  391. //彩色显示
  392. /*
  393. cv::Mat colorLabelImg;
  394. LabelColor(labelImg, colorLabelImg);
  395. cv::imshow("colorImg", colorLabelImg);
  396. */
  397. //灰度显示
  398. cv::Mat grayImg;
  399. labelImg *= 10;
  400. labelImg. convertTo(grayImg, CV_8UC1);
  401. cv:: imshow( "labelImg", grayImg);
  402. double minval, maxval;
  403. minMaxLoc(labelImg, &minval, &maxval);
  404. cout << "minval" << minval << endl;
  405. cout << "maxval" << maxval << endl;
  406. cv:: waitKey( 0);
  407. return 0;
  408. }

终于知道是啥原因了,我在进行Prewitt算子对边缘进行粗定位检测过后,没有进行去噪处理,一定要把图像转换为二值图像,就方便多了。并且还要记住,霍夫检测的直线像素是255白线才可以,经过长时间的试错终于解决了。输入原图像如下所示,我这里使用的去噪对比了四种,但是下面这种是最好的。Opencv 非局部降噪_51CTO博客_opencv降噪Opencv 非局部降噪,opencv自带的非局部降噪算法:CV_EXPORTS_WvoidfastNlMeansDenoising(InputArraysrc,OutputArraydst,floath=3,inttemplateWindowSize=7,intsearchWindowSize=21);h是过滤强度,templateWindowSize是分块大小,searchWindowSize是搜索区域大小。应用实例intmain(){MatI..https://blog.51cto.com/u_15458280/4843576

 


  
  1. #include<opencv2/opencv.hpp>
  2. #include<iostream>
  3. using namespace std;
  4. using namespace cv;
  5. //数组从大到小排序
  6. void reserve(int x[], int n) {
  7. int i, j, temp;
  8. for (i = 0; i < n - 1; i++) { //一共n个元素,则需要比较n-1次
  9. for (j = 0; j < n - 1 - i; j++) { //每一个元素需要比较的次数
  10. if (x[i] < x[i + j + 1]) {
  11. temp = x[i];
  12. x[i] = x[i + j + 1];
  13. x[i + j + 1] = temp;
  14. }
  15. }
  16. }
  17. }
  18. void add_salt_pepper_noise(Mat &image) {
  19. RNG rng(12345);
  20. int h = image.rows;
  21. int w = image.cols;
  22. int nums = 10000;
  23. for ( int i = 0; i < nums; i++) {
  24. int x = rng. uniform( 0, w);
  25. int y = rng. uniform( 0, h);
  26. if (i % 2 == 1) {
  27. image. at<Vec3b>(y, x) = Vec3b( 255, 255, 255);
  28. }
  29. else {
  30. image. at<Vec3b>(y, x) = Vec3b( 0, 0, 0);
  31. }
  32. }
  33. imshow( "salt pepper", image);
  34. }
  35. void gaussian_noise(Mat &image) {
  36. Mat noise = Mat:: zeros(image. size(), image. type());
  37. randn(noise, ( 15, 15, 15), ( 30, 30, 30));
  38. Mat dst;
  39. add(image, noise, dst);
  40. imshow( "gaussian noise", dst);
  41. dst. copyTo(image);
  42. }
  43. Mat convertTo3Channels(const Mat& binImg)
  44. {
  45. Mat three_channel = Mat:: zeros(binImg.rows, binImg.cols, CV_8UC3);
  46. vector<Mat> channels;
  47. for ( int i = 0; i < 3; i++)
  48. {
  49. channels. push_back(binImg);
  50. }
  51. merge(channels, three_channel);
  52. return three_channel;
  53. }
  54. int main(int argc, char*argv[])
  55. {
  56. //加载图像
  57. Mat img, gray_image, dst;
  58. img = imread( "垂直边缘.jpg");
  59. Mat img1 = imread( "垂直边缘.jpg");
  60. //判断图像是否导入成功
  61. if (img. empty())
  62. {
  63. cout << "加载失败" << endl;
  64. return -1;
  65. }
  66. //显示图像
  67. namedWindow( "original image", WINDOW_AUTOSIZE);
  68. imshow( "original image", img);
  69. //转换灰度图像
  70. cvtColor(img, gray_image, COLOR_BGR2GRAY);
  71. //获取灰度图像宽度和高度
  72. int width = gray_image.cols;
  73. int height = gray_image.rows;
  74. //遍历像素值(单通道)
  75. for ( int row = 0; row < height; row++)
  76. {
  77. for ( int col = 0; col < width; col++)
  78. {
  79. int gray = gray_image. at<uchar>(row, col);
  80. gray_image. at<uchar>(row, col) = 255 - gray; //图像取反
  81. };
  82. };
  83. namedWindow( "inv_gray_image", WINDOW_AUTOSIZE);
  84. imshow( "inv_gray_image", gray_image);
  85. Mat sh;
  86. fastNlMeansDenoising(gray_image, sh, 21, 7, 21);
  87. namedWindow( "inv_gray_image1", WINDOW_AUTOSIZE);
  88. imshow( "inv_gray_image1", sh);
  89. waitKey( 50);
  90. //Mat s;
  91. //获取灰度图像宽度和高度
  92. width = sh.cols;
  93. height = sh.rows;
  94. //遍历像素值(单通道)
  95. for ( int row = 0; row < height; row++)
  96. {
  97. for ( int col = 0; col < width; col++)
  98. {
  99. int gray = sh. at<uchar>(row, col);
  100. sh. at<uchar>(row, col) = 255 - gray; //图像取反
  101. };
  102. };
  103. namedWindow( "inv_gray_image2", WINDOW_AUTOSIZE);
  104. imshow( "inv_gray_image2", sh);
  105. cv:: threshold(sh, sh, 50, 255, cv::THRESH_BINARY);
  106. cv:: namedWindow( "二值化", CV_WINDOW_NORMAL);
  107. imshow( "二值化", sh);
  108. vector<Vec4i> lines;
  109. HoughLinesP(sh, lines, 1, CV_PI / 180, 50, 100, 5);
  110. int Length[ 100] = { 0 }; //存放直线长度
  111. for ( size_t i = 0; i < lines. size(); i++)
  112. {
  113. Vec4i I = lines[i];
  114. double x1 = I[ 0];
  115. double y1 = I[ 1];
  116. double x2 = I[ 2];
  117. double y2 = I[ 3];
  118. //筛选满足条件的点
  119. if ( abs(x1 - x2) + abs(y1 - y2) > 50)
  120. {
  121. Length[i] = sqrt((x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2));
  122. //将满足条件的点画出
  123. line(img, Point2d(x1, y1), Point2d(x2, y2), Scalar( 0, 255, 255), 2);
  124. cout << " " << "(" << x1 << "," << y1 << ")" << " " << "(" << x2 << "," << y2 << ")" << endl;
  125. //line(canny, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255), 2);
  126. }
  127. }
  128. Mat imgShow;
  129. imgShow = img;
  130. resize(imgShow, imgShow, Size(imgShow.cols / 4, imgShow.rows / 4));
  131. imshow( "imgShow", imgShow);
  132. imwrite( "shuchu.png", imgShow);
  133. reserve(Length, 100);
  134. for ( int i = 0; i < 100; i++) {
  135. cout << "长度" << Length[i] << endl; //输出排序后的数组元素
  136. }
  137. for ( size_t i = 0; i < lines. size(); i++)
  138. {
  139. Vec4i I = lines[i];
  140. double x1 = I[ 0];
  141. double y1 = I[ 1];
  142. double x2 = I[ 2];
  143. double y2 = I[ 3];
  144. cout << "sdjk" << endl;
  145. cout << int( sqrt((x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2))) << endl;
  146. //筛选满足条件的点
  147. if (( int( sqrt((x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2))) == Length[ 0]) || ( int( sqrt((x1 - x2)*(x1 - x2) + (y1 - y2) * (y1 - y2))) == Length[ 1]))
  148. {
  149. //将满足条件的点画出
  150. line(img1, Point2d(x1, y1), Point2d(x2, y2), Scalar( 0, 255, 255), 2);
  151. cout << "djfkljsa " << "(" << x1 << "," << y1 << ")" << " " << "(" << x2 << "," << y2 << ")" << endl;
  152. //line(canny, Point2d(x1, y1), Point2d(x2, y2), Scalar(0, 255, 255), 2);
  153. }
  154. }
  155. imgShow = img1;
  156. resize(imgShow, imgShow, Size(imgShow.cols / 4, imgShow.rows / 4));
  157. imshow( "imgShow2", imgShow);
  158. imwrite( "shuchu2.png", imgShow);
  159. waitKey( 0);
  160. return 0;
  161. };

结果图如下所示:

 ​​​​​​​

 终于弄出来了,去干饭。


转载:https://blog.csdn.net/m0_47489229/article/details/128948195
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场