影醉阏轩窗

衣带渐宽终不悔,为伊消得人憔悴。
扩大
缩小

《图像处理实例》 之 拟合求交点

 


 

 

要求:找出下面图像中三个点的坐标

出处不说明,主要方法介绍

 


 

 

 

代码:

  1 #include<opencv2/opencv.hpp>
  2 #include<iostream>
  3 
  4 using namespace cv;
  5 using namespace std;
  6 vector<RotatedRect> Rects;
  7 int main(int argc, char** argv) {
  8     
  9     Mat inputImage = imread("laser.png");
 10     Mat gaussImage1, guassImage2;
 11     cvtColor(inputImage, inputImage, COLOR_BGR2GRAY);
 12     //------------------------防止光照和斑点的干扰--------------------//
 13     GaussianBlur(inputImage, gaussImage1, Size(3, 3), 0, 0, 4);
 14     GaussianBlur(inputImage, guassImage2, Size(5, 5), 0, 0, 4);
 15     absdiff(gaussImage1, guassImage2, inputImage);
 16     threshold(inputImage, inputImage, 5, 255, THRESH_BINARY);
 17     Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
 18     morphologyEx(inputImage, inputImage, MORPH_CLOSE, kernel);
 19     morphologyEx(inputImage, inputImage, MORPH_OPEN, kernel);
 20     //----------------------查找最合适的两条线--=------------------------//
 21     //***********先用轮廓检测
 22     //***********最小外接矩形
 23     //***********找到最合适的两个外接矩形,其中这两个矩形的长宽中一个值为最大的//
 24     vector<vector<Point>> contours;
 25     vector<Vec4i> hierarchy;
 26     findContours(inputImage, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(-1, -1));
 27     
 28     for (size_t i = 0; i < contours.size(); i++)//找合适的轮廓
 29     {
 30         RotatedRect Rect;
 31         double minLH;
 32         Rects.push_back(minAreaRect(contours[i]));
 33         if (Rects.size() == 3)
 34         {
 35             vector<double> num;
 36             for (size_t i = 0; i < 3; i++)
 37             {
 38                 num.push_back(max(Rects[i].size.height, Rects[i].size.width));
 39             }
 40             minLH = min(min(num[0], num[1]), num[2]);
 41             vector<RotatedRect>::iterator it = Rects.begin();
 42             for (size_t i = 0; i < 3; i++,it++)
 43             {
 44                 if (minLH == num[i]) Rects.erase(it);
 45                 break;
 46             }
 47         }
 48     }
 49     Mat showImage1 = Mat::zeros(inputImage.size(), CV_8UC3);
 50     vector<Vec4f> lines;
 51     for (size_t i = 0; i < contours.size(); i++)//拟合合适的直线
 52     {
 53         RotatedRect Rect = minAreaRect(contours[i]);
 54         double maxHL = max(Rect.size.height, Rect.size.width);
 55         double maxHLR = max(Rects[0].size.height, Rects[0].size.width);
 56         double maxHLL = max(Rects[1].size.height, Rects[1].size.width);
 57         Vec4f line;
 58         if (maxHL == maxHLR || maxHL == maxHLL)
 59         {
 60             drawContours(showImage1, contours, static_cast<int>(i), Scalar(255, 0, 0), 1);
 61             fitLine(contours[i], line, cv::DIST_L2, 0, 1e-2, 1e-2);
 62             lines.push_back(line);
 63         }
 64     }
 65     Mat showImage = Mat::zeros(inputImage.size(), CV_8UC3);
 66     //获取点斜式的点和斜率  
 67     Point point0;
 68     point0.x = lines[0][2];
 69     point0.y = lines[0][3];
 70 
 71     double k = lines[0][1] / lines[0][0];
 72 
 73     //计算直线的端点(y = k(x - x0) + y0)  
 74     Point point1, point2;
 75     point1.x = 0;
 76     point1.y = k * (0 - point0.x) + point0.y;
 77     point2.x = 640;
 78     point2.y = k * (640 - point0.x) + point0.y;
 79     double b0 = point0.y - k *  point0.x;
 80     line(showImage, point1, point2, cv::Scalar(0, 255, 0), 1, 8, 0);
 81 
 82     //获取点斜式的点和斜率  
 83     Point point3;
 84     point3.x = lines[1][2];
 85     point3.y = lines[1][3];
 86 
 87     double k1 = lines[1][1] / lines[1][0];
 88 
 89     //计算直线的端点(y = k(x - x0) + y0)  
 90     Point point4, point5;
 91     point4.x = 100;
 92     point4.y = k1 * (100 - point3.x) + point3.y;
 93     double b1 = point3.y - k1 *  point3.x;
 94     line(showImage, point3, point4, cv::Scalar(0, 0, 255), 1, 8, 0);
 95 
 96     //----求直线交点
 97     Point2f center;
 98     center.x = (b1 - b0) / (k - k1);
 99     center.y = k1 * center.x + b1;
100     char countText[50];//定义数组长度的时候千万多比实际使用多一点,不然就一直崩溃!!!
101     sprintf(countText, "Corn x is : %d", static_cast<int>(center.x));
102     putText(showImage, countText, Point(30, 30), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(0, 255, 255), 2, 6);
103     char countText1[50];//定义数组长度的时候千万多比实际使用多一点,不然就一直崩溃!!!
104     sprintf(countText1, "Corn y is : %d", static_cast<int>(center.y));
105     putText(showImage, countText1, Point(30, 100), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(0, 255, 255), 2, 6);
106     //----------------------拟合中间的直线,然后进行两条直线的焦点-----------------//
107     //*******y = tan(angle)*x +b
108     //*******先求k 和 b
109     //*******直接利用交点公式计算 x = (b[1]-b[0])/(k[1]-k[0]) , y = k[1] * x + b[1]
110 /*
111     double k[2], b[2];
112     Point center;
113     k[0] = tan(Rects[0].angle);
114     k[1] = tan(Rects[1].angle);
115     b[0] = Rects[0].center.y - k[0] * Rects[0].center.x;
116     b[1] = Rects[1].center.y - k[1] * Rects[1].center.x;
117     CV_Assert(abs(k[1] - k[0]) == 0);
118     center.x = (b[1] - b[0]) / (k[1] - k[0]);
119     center.y = k[1] * center.x + b[1];
120 */
121     /*
122     Mat showImage;
123     showImage.create(inputImage.size(), inputImage.type());
124     vector<Vec4i> lines;
125     HoughLinesP(inputImage, lines, 1, CV_PI / 180, 50, 10, 5);
126     for (size_t i = 0; i < lines.size(); i++)
127     {
128         Vec4i l;
129         l = lines[i];
130         line(showImage, Point(l[0], l[1]), Point(l[2], l[3]), Scalar(100, 255, 200), 1, LINE_AA);
131     }
132     */
133     waitKey(0);
134 }

 


 

 

 

 

  1 #include <opencv2/opencv.hpp>  
  2 #include <opencv2/core/core.hpp>  
  3 #include <iostream>  
  4 #include <vector>  
  5 using namespace std;
  6 using namespace cv;
  7 int count_Judge[2] = {0,0};
  8 /**
  9 * @brief 对输入图像进行细化
 10 * @param src为输入图像,用cvThreshold函数处理过的8位灰度图像格式,元素中只有0与1,1代表有元素,0代表为空白
 11 * @param maxIterations限制迭代次数,如果不进行限制,默认为-1,代表不限制迭代次数,直到获得最终结果
 12 * @return 为对src细化后的输出图像,格式与src格式相同,元素中只有0与1,1代表有元素,0代表为空白
 13 */
 14 Mat thinImage(const cv::Mat & src, const int maxIterations = -1)
 15 {
 16     assert(src.type() == CV_8UC1);
 17     cv::Mat dst;
 18     int width = src.cols;
 19     int height = src.rows;
 20     src.copyTo(dst);
 21     int count = 0;  //记录迭代次数  
 22     while (true)
 23     {
 24         count++;
 25         if (maxIterations != -1 && count > maxIterations) //限制次数并且迭代次数到达  
 26             break;
 27         std::vector<uchar *> mFlag; //用于标记需要删除的点  
 28                                     //对点标记  
 29         for (int i = 0; i < height; ++i)
 30         {
 31             uchar * p = dst.ptr<uchar>(i);
 32             for (int j = 0; j < width; ++j)
 33             {
 34                 //如果满足四个条件,进行标记  
 35                 //  p9 p2 p3  
 36                 //  p8 p1 p4  
 37                 //  p7 p6 p5  
 38                 uchar p1 = p[j];
 39                 if (p1 != 1) continue;
 40                 uchar p4 = (j == width - 1) ? 0 : *(p + j + 1);
 41                 uchar p8 = (j == 0) ? 0 : *(p + j - 1);
 42                 uchar p2 = (i == 0) ? 0 : *(p - dst.step + j);
 43                 uchar p3 = (i == 0 || j == width - 1) ? 0 : *(p - dst.step + j + 1);
 44                 uchar p9 = (i == 0 || j == 0) ? 0 : *(p - dst.step + j - 1);
 45                 uchar p6 = (i == height - 1) ? 0 : *(p + dst.step + j);
 46                 uchar p5 = (i == height - 1 || j == width - 1) ? 0 : *(p + dst.step + j + 1);
 47                 uchar p7 = (i == height - 1 || j == 0) ? 0 : *(p + dst.step + j - 1);
 48                 if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) >= 2 && (p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) <= 6)
 49                 {
 50                     int ap = 0;
 51                     if (p2 == 0 && p3 == 1) ++ap;
 52                     if (p3 == 0 && p4 == 1) ++ap;
 53                     if (p4 == 0 && p5 == 1) ++ap;
 54                     if (p5 == 0 && p6 == 1) ++ap;
 55                     if (p6 == 0 && p7 == 1) ++ap;
 56                     if (p7 == 0 && p8 == 1) ++ap;
 57                     if (p8 == 0 && p9 == 1) ++ap;
 58                     if (p9 == 0 && p2 == 1) ++ap;
 59 
 60                     if (ap == 1 && p2 * p4 * p6 == 0 && p4 * p6 * p8 == 0)
 61                     {
 62                         //标记  
 63                         mFlag.push_back(p + j);
 64                     }
 65                 }
 66             }
 67         }
 68 
 69         //将标记的点删除  
 70         for (std::vector<uchar *>::iterator i = mFlag.begin(); i != mFlag.end(); ++i)
 71         {
 72             **i = 0;
 73         }
 74 
 75         //直到没有点满足,算法结束  
 76         if (mFlag.empty())
 77         {
 78             break;
 79         }
 80         else
 81         {
 82             mFlag.clear();//将mFlag清空  
 83         }
 84 
 85         //对点标记  
 86         for (int i = 0; i < height; ++i)
 87         {
 88             uchar * p = dst.ptr<uchar>(i);
 89             for (int j = 0; j < width; ++j)
 90             {
 91                 //如果满足四个条件,进行标记  
 92                 //  p9 p2 p3  
 93                 //  p8 p1 p4  
 94                 //  p7 p6 p5  
 95                 uchar p1 = p[j];
 96                 if (p1 != 1) continue;
 97                 uchar p4 = (j == width - 1) ? 0 : *(p + j + 1);
 98                 uchar p8 = (j == 0) ? 0 : *(p + j - 1);
 99                 uchar p2 = (i == 0) ? 0 : *(p - dst.step + j);
100                 uchar p3 = (i == 0 || j == width - 1) ? 0 : *(p - dst.step + j + 1);
101                 uchar p9 = (i == 0 || j == 0) ? 0 : *(p - dst.step + j - 1);
102                 uchar p6 = (i == height - 1) ? 0 : *(p + dst.step + j);
103                 uchar p5 = (i == height - 1 || j == width - 1) ? 0 : *(p + dst.step + j + 1);
104                 uchar p7 = (i == height - 1 || j == 0) ? 0 : *(p + dst.step + j - 1);
105 
106                 if ((p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) >= 2 && (p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9) <= 6)
107                 {
108                     int ap = 0;
109                     if (p2 == 0 && p3 == 1) ++ap;
110                     if (p3 == 0 && p4 == 1) ++ap;
111                     if (p4 == 0 && p5 == 1) ++ap;
112                     if (p5 == 0 && p6 == 1) ++ap;
113                     if (p6 == 0 && p7 == 1) ++ap;
114                     if (p7 == 0 && p8 == 1) ++ap;
115                     if (p8 == 0 && p9 == 1) ++ap;
116                     if (p9 == 0 && p2 == 1) ++ap;
117 
118                     if (ap == 1 && p2 * p4 * p8 == 0 && p2 * p6 * p8 == 0)
119                     {
120                         //标记  
121                         mFlag.push_back(p + j);
122                     }
123                 }
124             }
125         }
126 
127         //将标记的点删除  
128         for (std::vector<uchar *>::iterator i = mFlag.begin(); i != mFlag.end(); ++i)
129         {
130             **i = 0;
131         }
132 
133         //直到没有点满足,算法结束  
134         if (mFlag.empty())
135         {
136             break;
137         }
138         else
139         {
140             mFlag.clear();//将mFlag清空  
141         }
142     }
143     return dst;
144 }
145 void FindLine(InputArray _src, vector<Point2f>& lines, uchar method, uchar angle, double& b);
146 
147 int main(int argc, char*argv[]) {
148 
149     Mat inputImage = cv::imread("1.png");
150     Mat src;
151     cvtColor(inputImage, src, COLOR_BGR2GRAY);
152     if (src.empty())
153     {
154         std::cout << "读取文件失败!" << std::endl;
155         return -1;
156     }
157 
158     //将原图像转换为二值图像  
159     threshold(src, src, 0, 1, THRESH_BINARY | THRESH_OTSU);
160     //图像细化  
161     src = thinImage(src);
162     //显示图像  
163     src = src * 255;
164     Mat kernel = getStructuringElement(MORPH_RECT, Size(2, 1));
165     morphologyEx(src, src, MORPH_OPEN, kernel);
166     vector<Point2f> lines2;
167     double b2;
168     FindLine(src, lines2, 2, 0, b2);
169 
170 
171     vector<Point2f> lines;
172     double b;
173     FindLine(src, lines, 0, 0, b);
174 
175 
176     vector<Point2f> lines1;
177     double b1;
178     FindLine(src, lines1, 1, 0, b1);
179 
180 
181     Mat showImage;
182     cvtColor(src, showImage, COLOR_GRAY2BGR);
183     line(showImage, lines2[0], lines2[1], Scalar(0, 0, 255), 1);
184     line(showImage, lines[0], lines[1], Scalar(0, 0, 255), 1);
185     line(showImage, lines1[0], lines1[1], Scalar(0, 0, 255), 1);
186 
187     waitKey(0);
188 }
189 //---------------------------------------有角度,通过寻找一个点换算直线--------------------------------------------//
190 //-------@_src   : input a image that Binary
191 //-------@lines  : output lines message, y = kx + b ,lines[0] stand for k ,lines[1] stand for b
192 //-------@method : if method == 0 return left lines, method == 1 return right lines, else return horizon lines
193 //                   default method == 0
194 //-------@angle     : if angle == true angle = 60 degree, else angle = 45 degree.default angle == true
195 void FindLine(InputArray _src, vector<Point2f>& lines, uchar method, uchar angle, double& b)
196 {
197     Mat src = _src.getMat();
198     CV_Assert(src.depth() != 1);
199     double k = 0;//y = kx + b 
200     Point2f aimPoint[3];//aimPoint[0]/aimPoint[1]存储查询的点,防止误判, aimPoint[3]:直线另一个点
201     if (method == 0)
202     {
203         
204         for (size_t i = 0; i < src.rows; i++)
205         {
206             for (size_t j = 0; j < src.cols; j++)
207             {
208                 //Point2f tempPoint(j, i);
209                 //aimPoint = src.at<uchar>(i, j) > 0 ? tempPoint : aimPoint;
210                 if (src.at<uchar>(i, j) > 0)
211                 {
212                     aimPoint[0] = aimPoint[1];
213                     aimPoint[1] = Point2f(j, i);
214                     
215                     break;
216                 }
217                 
218             }
219         }
220     }
221     else if (method == 1)
222     {
223         char flag[2] = { 0 ,0 };
224         for (size_t i = 0; i < src.rows; i++)
225         {
226             for (size_t j = 0; j < src.cols; j++)
227             {
228                 if (src.at<uchar>(i, src.cols - j - 1) > 0)
229                 {
230                     aimPoint[0] = aimPoint[1];
231                     aimPoint[1] = Point2f(src.cols - j - 1, i);
232                     break;
233                 }
234             }
235         }
236     }
237     else
238     {
239         int count[2];
240         int a = 0, b = 0;
241         for (size_t i = 0; i < src.rows; i++)
242         {
243             for (size_t j = 0; j < src.cols; j++)
244             {
245                 if (src.at<uchar>(i, j) > 0)
246                 {
247                     count[0]++;
248                 }
249                 //count[0] = src.at<uchar>(i, j) > 0 ? count[0]++ : count[0];
250             }
251             if (count[0] > count[1])
252             {
253                 aimPoint[1] = Point2f(0, i);
254                 aimPoint[0] = Point2f(0, i);
255                 count[1] = count[0];
256             }
257             count[0] = 0;
258         }
259     }
260     //------------防止误判
261     //if (abs(aimPoint[0].x - aimPoint[1].x) > 3) aimPoint[1] = aimPoint[0];
262     count_Judge[0] = 0;
263     count_Judge[1] = 0;
264     for (size_t i = 0; i < src.cols; i++)
265     {
266         count_Judge[0] += src.at<uchar>(aimPoint[0].y, i) > 0 ? 1 : 0;
267     }
268     for (size_t i = 0; i < src.cols; i++)
269     {
270         count_Judge[1] += src.at<uchar>(aimPoint[0].y, i) > 0 ? 1 : 0;
271     }
272     if (count_Judge[0] >= count_Judge[1] || abs(aimPoint[0].y - aimPoint[1].y) > 2) aimPoint[1] = aimPoint[0];
273     lines.push_back(aimPoint[1]);
274     if (angle == 0)
275     {
276         if (method == 0)
277         {
278             b = aimPoint[1].y - sqrt(3) * aimPoint[1].x / 3;
279             aimPoint[2] = Point2f(0, sqrt(3) * 0 + b);
280         }
281         else if (method == 1)
282         {
283             b = aimPoint[1].y + sqrt(3)*aimPoint[1].x / 3;
284             aimPoint[2] = Point2f(src.cols, (b / sqrt(3)) / 3);
285         }
286         else
287         {
288             b = aimPoint[1].y;
289             aimPoint[2] = Point2f(src.cols, b);
290         }
291     }
292     else if (angle == 1)
293     {
294         if (method == 0)
295         {
296             b = aimPoint[1].y - aimPoint[1].x;
297             aimPoint[2] = Point2f(0, 0 + b);
298         }
299         else if (method == 1)
300         {
301             b = aimPoint[1].y + aimPoint[1].x;
302             aimPoint[2] = Point2f(src.cols, b / (1));
303         }
304         else
305         {
306             b = aimPoint[1].y;
307             aimPoint[2] = Point2f(src.cols, b);
308         }
309     }
310     else if (angle == 1)
311     {
312         if (method == 0)
313         {
314             b = aimPoint[1].y - sqrt(3)*aimPoint[1].x;
315             aimPoint[2] = Point2f(0, sqrt(3) * 0 + b);
316         }
317         else if (method == 1)
318         {
319             b = aimPoint[1].y + sqrt(3)*aimPoint[1].x;
320             aimPoint[2] = Point2f(src.cols, b / sqrt(3));
321         }
322         else
323         {
324             b = aimPoint[1].y;
325             aimPoint[2] = Point2f(src.cols, b);
326         }
327     }
328     lines.push_back(aimPoint[2]);
329 }

 

 

 

posted on 2017-08-17 14:16  影醉阏轩窗  阅读(1161)  评论(0编辑  收藏  举报

导航

/* 线条鼠标集合 */ /* 鼠标点击求赞文字特效 */ //带头像评论