zoukankan      html  css  js  c++  java
  • 27、【opencv入门】轮廓查找与绘制(5)——最小外接矩形

    一、简介

    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 }

     

  • 相关阅读:
    cookie与session的区别
    基于TCP协议的网络编程
    springboot第一篇:springboot基础
    java中的正则表达式
    NIO
    io基础(字节流、字符流、转换流、缓冲字符流)
    基于UDP协议的网络编程
    es6.3学习笔记
    线程同步和线程通信
    java字符串各种编码
  • 原文地址:https://www.cnblogs.com/Long-w/p/9668580.html
Copyright © 2011-2022 走看看