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

  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
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
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  影醉阏轩窗  阅读(771)  评论(0编辑  收藏

### 导航

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