可以检测空心和实心的矩形和菱形
#include "cv.h"
#include "highgui.h"
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "opencv2/imgproc.hpp"
double angle( CvPoint
* pt1
, CvPoint
* pt2
, CvPoint
* 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
;
double angle_line
= (dx1
*dx2
+ dy1
*dy2
)/sqrt((dx1
*dx1
+ dy1
*dy1
)*(dx2
*dx2
+ dy2
*dy2
) + 1e-10);
return acos(angle_line
)*180/3.141592653;
}
CvSeq
* findSquares4( IplImage
* img
, CvMemStorage
* storage
,int minarea
, int maxarea
, int minangle
, int maxangle
)
{
CvSeq
* contours
;
int N
= 6;
CvSize sz
= cvSize( img
->width
& -2, img
->height
& -2 );
IplImage
* timg
= cvCloneImage( img
);
IplImage
* gray
= cvCreateImage( sz
, 8, 1 );
IplImage
* pyr
= cvCreateImage( cvSize(sz
.width
/2, sz
.height
/2), 8, 3 );
IplImage
* tgray
= cvCreateImage( sz
, 8, 1 ); ;
CvSeq
* result
;
double s
, t
;
CvSeq
* squares
= cvCreateSeq( 0, sizeof(CvSeq
), sizeof(CvPoint
), storage
);
cvSetImageROI( timg
, cvRect( 0, 0, sz
.width
, sz
.height
));
cvPyrDown( timg
, pyr
, 7 );
cvPyrUp( pyr
, timg
, 7 );
for( int c
= 0; c
< 3; c
++ )
{
cvSetImageCOI( timg
, c
+1 );
cvCopy( timg
, tgray
, 0 );
for( int l
= 0; l
< N
; l
++ )
{
cvThreshold( tgray
, gray
, (l
+1)*255/N
, 255, CV_THRESH_BINARY
);
cvFindContours( gray
, storage
, &contours
, sizeof(CvContour
),CV_RETR_LIST
, CV_CHAIN_APPROX_SIMPLE
, cvPoint(0,0) );
while( contours
)
{
result
= cvApproxPoly( contours
, sizeof(CvContour
), storage
,CV_POLY_APPROX_DP
, cvContourPerimeter(contours
)*0.02, 0 );
if( result
->total
== 4 && fabs(cvContourArea(result
,CV_WHOLE_SEQ
)) > minarea
&& fabs(cvContourArea(result
,CV_WHOLE_SEQ
)) < maxarea
&& cvCheckContourConvexity(result
) )
{
s
= 0;
for( int i
= 0; i
< 5; i
++ )
{
if( i
>= 2 )
{
t
= fabs(angle( (CvPoint
*)cvGetSeqElem( result
, i
),(CvPoint
*)cvGetSeqElem( result
, i
-2 ),(CvPoint
*)cvGetSeqElem( result
, i
-1 )));
s
= s
> t
? s
: t
;
}
}
if( s
> minangle
&& s
< maxangle
)
for( int i
= 0; i
< 4; i
++ )
cvSeqPush( squares
,(CvPoint
*)cvGetSeqElem( result
, i
));
}
contours
= contours
->h_next
;
}
}
}
cvReleaseImage( &gray
);
cvReleaseImage( &pyr
);
cvReleaseImage( &tgray
);
cvReleaseImage( &timg
);
return squares
;
}
void drawSquares( IplImage
* img
, CvSeq
* squares
,const char* wndname
)
{
CvSeqReader reader
;
IplImage
* cpy
= cvCloneImage( img
);
CvPoint pt
[4];
int i
;
cvStartReadSeq( squares
, &reader
, 0 );
for( i
= 0; i
< squares
->total
; i
+= 4 )
{
CvPoint
* rect
= pt
;
int count
= 4;
memcpy( pt
, reader
.ptr
, squares
->elem_size
);
CV_NEXT_SEQ_ELEM( squares
->elem_size
, reader
);
memcpy( pt
+ 1, reader
.ptr
, squares
->elem_size
);
CV_NEXT_SEQ_ELEM( squares
->elem_size
, reader
);
memcpy( pt
+ 2, reader
.ptr
, squares
->elem_size
);
CV_NEXT_SEQ_ELEM( squares
->elem_size
, reader
);
memcpy( pt
+ 3, reader
.ptr
, squares
->elem_size
);
CV_NEXT_SEQ_ELEM( squares
->elem_size
, reader
);
cvPolyLine( cpy
, &rect
, &count
, 1, 1, CV_RGB(rand()&255,rand()&255,rand()&255), 1, CV_AA
, 0 );
}
cvShowImage( wndname
, cpy
);
cvReleaseImage( &cpy
);
}
int main()
{
CvCapture
* capture
= cvCreateCameraCapture(0);
IplImage
* img0
= 0;
CvMemStorage
* storage
= 0;
int c
;
const char* wndname
= "Square Detection Demo";
storage
= cvCreateMemStorage(0);
cvNamedWindow( wndname
, 1 );
while (true
)
{
img0
= cvQueryFrame(capture
);
drawSquares( img0
, findSquares4( img0
, storage
, 100, 2000, 80, 100), wndname
);
cvClearMemStorage( storage
);
c
= cvWaitKey(10);
if( c
== 27 )
break;
}
cvReleaseImage( &img0
);
cvClearMemStorage( storage
);
cvDestroyWindow( wndname
);
return 0;
}
参考大佬文章:https://blog.csdn.net/qq_15947787/article/details/51085352
出现未定义标识符CV_RGB的解决办法:https://blog.csdn.net/FJY_sunshine/article/details/83054477