一、简介
1、最小外接矩形
轮廓最小外接矩形 --- minAreaRect(InputArray points);
1 CV_EXPORTS_W RotatedReect minAreaRect(InputArray points);
points: 输入的二维点集, 可以填Mat类型或std::vector
返回值: RotatedRect类矩形对象, 外接旋转矩形主要成员有center、size、 angle、points
在opencv中,坐标的原点在左上角,与x轴平行的方向为角度为0,逆时针旋转角度为负,顺时针旋转角度为正。而RotatedRect类是以矩形的哪一条边与x轴的夹角作为角度的呢?angle 是水平轴(x轴)逆时针旋转,与碰到的第一个边的夹角,而opencv默认把这个边的边长作为width,angle的取值范围必然是负的 。
二、轮廓最小外接矩形的绘制
1 //轮廓最小外接矩形的绘制 2 #include "opencv2/opencv.hpp" 3 4 using namespace cv; 5 6 int main() 7 { 8 //轮廓最小外接矩形的绘制 9 Mat srcImg = imread("1.png"); 10 Mat dstImg = srcImg.clone(); 11 cvtColor(srcImg, srcImg, CV_BGR2GRAY); 12 threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY); //二值化 13 imshow("threshold", srcImg); 14 15 vector<vector<Point>> contours; 16 vector<Vec4i> hierarcy; 17 findContours(srcImg, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); 18 vector<Rect> boundRect(contours.size()); //定义外接矩形集合 19 vector<RotatedRect> box(contours.size()); //定义最小外接矩形集合 20 Point2f rect[4]; 21 for(int i=0; i<contours.size(); i++) 22 { 23 box[i] = minAreaRect(Mat(contours[i])); //计算每个轮廓最小外接矩形 24 boundRect[i] = boundingRect(Mat(contours[i])); 25 circle(dstImg, Point(box[i].center.x, box[i].center.y), 5, Scalar(0, 255, 0), -1, 8); //绘制最小外接矩形的中心点 26 box[i].points(rect); //把最小外接矩形四个端点复制给rect数组 27 rectangle(dstImg, Point(boundRect[i].x, boundRect[i].y), Point(boundRect[i].x + boundRect[i].width, boundRect[i].y + boundRect[i].height), Scalar(0, 255, 0), 2, 8); 28 for(int j=0; j<4; j++) 29 { 30 line(dstImg, rect[j], rect[(j+1)%4], Scalar(0, 0, 255), 2, 8); //绘制最小外接矩形每条边 31 } 32 } 33 imshow("dst", dstImg); 34 waitKey(0); 35 return 0; 36 }
三、粗略计算物体像素长宽
1 //粗略计算物体的像素长宽 2 #include "opencv2/opencv.hpp" 3 #include<iostream> 4 5 using namespace std; 6 using namespace cv; 7 8 int main() 9 { 10 Mat srcImg = imread("1.jpg"); 11 imshow("src", srcImg); 12 Mat dstImg = srcImg.clone(); 13 medianBlur(srcImg, srcImg, 5); 14 GaussianBlur(srcImg, srcImg, Size(3, 3), 0, 0); 15 cvtColor(srcImg, srcImg, CV_BGR2GRAY); 16 threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY_INV); //INV是因为背景白色,物体黑色,需要反转一下 17 imshow("threshold", srcImg); 18 19 vector<vector<Point>> contours; 20 vector<Vec4i> hierarcy; 21 22 findContours(srcImg, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); 23 cout<<"num="<<contours.size()<<endl; 24 vector<Rect> boundRect(contours.size()); 25 vector<RotatedRect> box(contours.size()); 26 Point2f rect[4]; 27 for(int i=0; i<contours.size(); i++) 28 { 29 box[i] = minAreaRect(Mat(contours[i])); 30 boundRect[i] = boundingRect(Mat(contours[i])); 31 cout<<box[i].angle<<endl; 32 cout<<box[i].center<<endl; 33 cout<<box[i].size.width<<endl; 34 cout<<box[i].size.height<<endl; 35 circle(dstImg, Point(box[i].center.x, box[i].center.y), 5, Scalar(0, 255, 0), -1, 8); 36 37 //绘制外接矩形和 最小外接矩形(for循环) 38 rectangle(dstImg, Point(boundRect[i].x, boundRect[i].y), Point(boundRect[i].x + boundRect[i].width, boundRect[i].y + boundRect[i].height), Scalar(0, 255, 0), 2, 8); 39 box[i].points(rect);//把最小外接矩形四个端点复制给rect数组 40 for(int j=0; j<4; j++) 41 { 42 line(dstImg, rect[j], rect[(j+1)%4], Scalar(0, 0, 255), 2, 8); 43 } 44 45 char width[20], height[20]; 46 sprintf(width, "width=%0.2f", box[i].size.width); 47 sprintf(height, "height=%0.2f", box[i].size.height); 48 putText(dstImg, width, Point(235, 260), CV_FONT_HERSHEY_COMPLEX_SMALL, 0.85, Scalar(0, 255, 0)); 49 putText(dstImg, height, Point(235, 285), CV_FONT_HERSHEY_COMPLEX_SMALL, 0.85, Scalar(0, 255, 0)); 50 51 } 52 imshow("dst", dstImg); 53 waitKey(0); 54 return 0; 55 }
四、倾斜物体矫正提取
1 //倾斜物体的矫正提取 2 #include "opencv2/opencv.hpp" 3 #include<iostream> 4 5 using namespace std; 6 using namespace cv; 7 8 int main() 9 { 10 Mat srcImg = imread("1.jpg"); 11 imshow("src", srcImg); 12 Mat dstImg = srcImg.clone(); 13 GaussianBlur(srcImg, srcImg, Size(3, 3), 0, 0); 14 cvtColor(srcImg, srcImg, CV_BGR2GRAY); 15 Canny(srcImg, srcImg, 100, 200);//因为原图比较复杂,所以需要将canny的值调大,去除不想要的成分 16 //threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY_INV); //二值化也可以实现canny效果,不过在本例中杂絮较多 17 imshow("canny", srcImg); 18 Mat element = getStructuringElement(MORPH_RECT, Size(11, 11), Point(-1, -1)); //定义结构元素 19 dilate(srcImg, srcImg, element); //膨胀 20 imshow("dilate", srcImg); 21 erode(srcImg, srcImg, element); 22 imshow("erode", srcImg); 23 24 vector<vector<Point>> contours; 25 vector<Vec4i> hierarcy; 26 findContours(srcImg, contours, hierarcy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE); 27 vector<Rect> boundRect(contours.size()); 28 vector<RotatedRect> box(contours.size()); 29 Point2f rect[4]; 30 for(int i=0; i<contours.size(); i++) 31 { 32 box[i] = minAreaRect(Mat(contours[i])); 33 boundRect[i] = boundingRect(Mat(contours[i])); 34 35 if(box[i].size.width < 100 || box[i].size.height<100)//筛选 36 continue; 37 rectangle(dstImg, Point(boundRect[i].x, boundRect[i].y), Point(boundRect[i].x + boundRect[i].width, boundRect[i].y + boundRect[i].height), Scalar(0, 255, 0), 2, 8); 38 circle(dstImg, Point(box[i].center.x, box[i].center.y), 5, Scalar(0, 255, 0), -1, 8); 39 box[i].points(rect); 40 for(int j=0; j<4; j++) 41 { 42 line(dstImg, rect[j], rect[(j+1)%4], Scalar(0, 0, 255), 2, 8); 43 } 44 45 float angle; 46 cout<<"angle="<<box[i].angle<<endl; 47 angle = box[i].angle; 48 char width[20], height[20]; 49 sprintf(width, "width=%0.2f", box[i].size.width); 50 sprintf(height, "height=%0.2f", box[i].size.height); 51 putText(dstImg, width, Point(195, 260), CV_FONT_HERSHEY_COMPLEX_SMALL, 0.85, Scalar(0, 255, 0)); 52 putText(dstImg, height, Point(190, 285), CV_FONT_HERSHEY_COMPLEX_SMALL, 0.85, Scalar(0, 255, 0)); 53 imshow("temp", dstImg); 54 55 //利用仿射变换进行旋转 另一种方法,透视变换 56 if (0< abs(angle) && abs(angle)<=45) 57 angle = angle;//负数,顺时针旋转 58 else if (45< abs(angle) && abs(angle)<90) 59 angle = 90 - abs(angle);//正数,逆时针旋转 60 Point2f center = box[i].center; //定义旋转中心坐标 61 double angle0 = angle; 62 double scale = 1; 63 Mat roateM = getRotationMatrix2D(center, angle0, scale); //获得旋转矩阵,顺时针为负,逆时针为正 64 warpAffine(dstImg, dstImg, roateM, dstImg.size()); //仿射变换 65 66 //保存二维码 67 int x0=0, y0=0, w0=0, h0=0; 68 x0 = boundRect[i].x; 69 y0 = boundRect[i].y; 70 w0 = boundRect[i].width; 71 h0 = boundRect[i].height; 72 Mat ROI = dstImg(Rect(x0, y0, w0, h0)); 73 imwrite("F://1.jpg", ROI); 74 } 75 imshow("dst", dstImg); 76 waitKey(0); 77 return 0; 78 }