1
+ #include < stdio.h>
2
+ #include < opencv2/opencv.hpp>
3
+
4
+ using namespace std ;
5
+ using namespace cv ;
6
+
7
+ // 计算两个向量pt0->pt1和pt0->pt2的夹角
8
+ double angle (Point pt1, Point pt2, Point pt0) {
9
+ double dx1 = pt1.x - pt0.x ;
10
+ double dy1 = pt1.y - pt0.y ;
11
+ double dx2 = pt2.x - pt0.x ;
12
+ double dy2 = pt2.y - pt0.y ;
13
+ return (dx1*dx2 + dy1*dy2) / sqrt ((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10 );
14
+ }
15
+
16
+ const int N = 5 ;
17
+
18
+ int main () {
19
+ // 读入图片
20
+ Mat src = cv::imread (" F:\\ 2stickies.jpg" );
21
+ // 记录长宽
22
+ int row = src.rows ;
23
+ int col = src.cols ;
24
+ // 存储矩阵
25
+ vector <vector<Point > > squares;
26
+ // 将原图转化为灰度图
27
+ Mat gray (row, col, CV_8UC1);
28
+ cvtColor (src, gray, CV_BGRA2GRAY);
29
+ // 中值滤波,半径为9
30
+ medianBlur (gray, gray, 9 );
31
+ cv::imshow (" median" , gray);
32
+ waitKey (0 );
33
+ // 存储图像的轮廓
34
+ vector <vector<Point > > contours;
35
+ Mat gray0 = gray.clone ();
36
+ for (int l = 0 ; l < N; l++) {
37
+ if (l == 0 ) {
38
+ // 先执行Canny边缘检测
39
+ Canny (gray0, gray, 5 , 50 , 5 );
40
+ // 形态学操作
41
+ dilate (gray, gray, Mat (), Point (-1 , -1 ));
42
+ }
43
+ else {
44
+ gray = gray0 >= (l + 1 ) * 255 / N;
45
+ }
46
+ // 寻找图像的轮廓
47
+ findContours (gray, contours, RETR_LIST, CHAIN_APPROX_SIMPLE);
48
+ // 存储多边形的点
49
+ vector <Point > approx;
50
+ for (size_t i = 0 ; i < contours.size (); i++) {
51
+ approxPolyDP (Mat (contours[i]), approx, arcLength (Mat (contours[i]), true ) * 0.02 , true );
52
+ if (approx.size () == 4 && fabs (contourArea (Mat (approx))) > 1000 &&
53
+ isContourConvex (Mat (approx))) {
54
+ // 找到多边形最大的角
55
+ double maxCosine = 0 ;
56
+ for (int j = 2 ; j < 5 ; j++) {
57
+ double cosine = fabs (angle (approx[j % 4 ], approx[j - 2 ], approx[j - 1 ]));
58
+ maxCosine = max (maxCosine, cosine);
59
+ }
60
+ // 如果余弦值小于0.3,就判断为矩阵
61
+ if (maxCosine < 0.3 ) {
62
+ squares.push_back (approx);
63
+ }
64
+ }
65
+ }
66
+ }
67
+ printf (" %d\n " , squares.size ());
68
+ // 把矩形画在原图上
69
+ for (size_t i = 0 ; i < squares.size (); i++)
70
+ {
71
+ const Point * p = &squares[i][0 ];
72
+ int n = (int )squares[i].size ();
73
+ // dont detect the border
74
+ printf (" %d %d\n " , p->x , p->y );
75
+ if (p->x > 3 && p->y > 3 )
76
+ polylines (src, &p, &n, 1 , true , Scalar (0 , 255 , 0 ), 3 , LINE_AA);
77
+ }
78
+ imshow (" result" , src);
79
+ waitKey (0 );
80
+ return 0 ;
81
+ }
0 commit comments