一、目标图片:
二、分割目的:
分割识别图中的纸盒区域
三、实现思路及步骤:
1.使用双边变换进行滤波操作,保留并增强边缘信息
2.使用canny算子检测边缘信息,使用开运算去除小噪点
使用多边形逼近,画出边缘轮廓,对轮廓进行筛选操作
使用矩形直角、平行等特征构建向量模型筛选轮廓,使用直线连接矩形的四个角点位置,画出矩形位置
注:识别效果一般;采用mask-rcnn机器学习方法重新进行纸箱模型分割,效果有着显著提升,可以进我的个人主页查看,博客连接网址:https://blog.csdn.net/weixin_38341864/article/details/88819668
四、完整代码实例:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229#include <opencv2opencv.hpp> #include <iostream> #include <math.h> #include <string.h> using namespace std; using namespace cv; #define PI 3.1415 int thresh = 280, N = 1; //轮廓提取参数调节 float EpsilonThd = 0.05; float MaxRegion = 200000, MinRegion = 8000; float SharpeThd = 2.5; float AngleMaxThd = 105; float AngleMinThd = 75; float AngleParaThd = 10; float EqualThd = 10; //两点是否为同一点的距离阈值 void findSquares(const Mat& image, vector<vector<Point>>& squares); double AngleCal(Point pt1, Point pt2, Point pt0); void RemoveInvalid(vector<vector<Point>> &corner); //移除无效轮廓 bool CompareCorner(vector<Point> corner1, vector<Point> corner2); //判断角点是否为同一个点 void drawSquares(Mat& image, const vector<vector<Point> >& squares); float getDistance(Point2f a, Point2f b) { return sqrt(pow(a.x - b.x, 2) + pow(a.y - b.y, 2)); } int main() { Mat image = imread("D:\photoclub\2\5_1.jpg"); if (!image.data) { cout << "打开图片有误" << endl; return -1; } Mat image_gray; vector<vector<Point>> squares; cvtColor(image, image_gray, COLOR_BGR2GRAY); imshow("SorceImage", image_gray); findSquares(image_gray, squares); RemoveInvalid(squares); drawSquares(image, squares); imshow("Result", image); waitKey(); return 0; } // helper function: // finds a cosine of angle between vectors // from pt0->pt1 and from pt0->pt2 double AngleCal(Point pt1, Point pt2, Point pt0) { double dx1 = pt1.x - pt0.x; double dy1 = pt1.y - pt0.y; double dx2 = pt2.x - pt0.x; double dy2 = pt2.y - pt0.y; return (dx1*dx2 + dy1 * dy2) / sqrt((dx1*dx1 + dy1 * dy1)*(dx2*dx2 + dy2 * dy2) + 1e-10); } void findSquares(const Mat& image, vector<vector<Point>>& squares) { /*找到长方形的函数 image 输入待查找长方形的图片 squares 输出长方形点集*/ int index = 0; RNG rng = theRNG(); squares.clear(); vector<vector<Point> > contours; for (int con = 0; con < 1; con++) { Mat timg, cimg; image.convertTo(cimg, CV_8U, 0.5 + 0.5*con, 0);//cimg改变 imshow("Image" + to_string(con), cimg); for (int th = 0; th < 3; th++) { bilateralFilter(cimg, timg, -1, 3 + th * 3, 15);//双边 Mat gray; for (int l = 0; l < N; l++) { if (l == 0) { Canny(timg, gray, 5, thresh, 5);//canny imshow("canny" + to_string(th),gray); Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5)); dilate(gray, gray, kernel, Point(-1, -1));//膨胀 } else { gray = timg >= (l + 1) * 255 / N;//***GRAY->timg } int kernel_length = timg.cols;//invalid findContours(gray, contours, RETR_LIST, CHAIN_APPROX_NONE);//找轮廓 Mat display; cvtColor(timg, display, COLOR_GRAY2BGR); vector<Point> approx; for (size_t i = 0; i < contours.size(); i++) { approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true)*EpsilonThd, true); //多边形拟合 Scalar color = { (double)rng(256),(double)rng(256) ,(double)rng(256) };//随机颜色 drawContours(display, contours, i, color, 1); RotatedRect rect = minAreaRect(contours[i]); //矩形特征 double sharpe = rect.size.width / rect.size.height; //矩形长比高 if (approx.size() == 4 &&//容器大小 fabs(contourArea(Mat(approx))) > MinRegion &&//面积范围 fabs(contourArea(Mat(approx))) < MaxRegion &&//面积范围 sharpe < SharpeThd && //长宽比范围 sharpe > 1.0 / SharpeThd &&//长宽比范围 isContourConvex(Mat(approx))) { float maxAngle = 90, minAngle = 90; float rect_angle[3]; for (int j = 2; j < 5; j++) { float angle = acos(AngleCal(approx[j % 4], approx[j - 2], approx[j - 1])) * 180 / PI; rect_angle[j - 2] = angle; maxAngle = MAX(maxAngle, angle); minAngle = MIN(minAngle, angle); } float paral = (abs(180 - rect_angle[1] - rect_angle[0]) + abs(180 - rect_angle[1] - rect_angle[2])) / 2; if (maxAngle < AngleMaxThd && minAngle > AngleMinThd && paral < AngleParaThd) squares.push_back(approx); } } imshow("轮廓"+to_string(index), display); index++; } } } } void RemoveInvalid(vector<vector<Point>> &corner) { if (corner.size() == 0) return; for (int i = 1; i < corner.size(); i++) { vector<Point> temp = corner[i]; for (int j = 0; j < i; j++) { vector<Point> temp2 = corner[j]; if (CompareCorner(temp, temp2)) { corner.erase(corner.begin() + i); i--; break; } } } } bool CompareCorner(vector<Point> corner1, vector<Point> corner2) { bool is_equal = false; for (int i = 0; i < corner1.size(); i++) { Point temp = corner1[i]; for (int j = 0; j < corner2.size(); j++) { Point temp2 = corner2[j]; if (getDistance((Point2f)temp, (Point2f)temp2) < EqualThd) { is_equal = true; break; } } if (!is_equal) break; } return is_equal; } void drawSquares(Mat& image, const vector<vector<Point> >& squares) { /*在已经找到长方形的图片上画出长方形 image 待圈出长方形的图片 squares 找到的长方形点集*/ for (size_t i = 0; i < squares.size(); i++) { const Point* p = &squares[i][0]; int n = (int)squares[i].size(); if (p->x > 3 && p->y > 3) polylines(image, &p, &n, 1, true, Scalar(0, 255, 0), 2, LINE_AA); } }
最后
以上就是标致音响最近收集整理的关于C++和opencv实现图像分割(二)的全部内容,更多相关C++和opencv实现图像分割(二)内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复