opencv(c++) 使用minAreaRect 获得最小外接矩形

转载链接:https://www.cnblogs.com/little-monkey/p/7429579.html
一、简介
opencv(c++) 使用minAreaRect 获得最小外接矩形_第1张图片
二、轮廓最小外接矩形的绘制

#include "opencv2/opencv.hpp"
using namespace cv;

void main()
{
    //轮廓最小外接矩形的绘制
    Mat srcImg = imread("E://00.png");
    Mat dstImg = srcImg.clone();
    cvtColor(srcImg, srcImg, CV_BGR2GRAY);
    threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY); //二值化
    imshow("threshold", srcImg);

    vector<vector<Point>> contours;
    vector<Vec4i> hierarcy;
    findContours(srcImg, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
    vector<Rect> boundRect(contours.size());  //定义外接矩形集合
    vector<RotatedRect> box(contours.size()); //定义最小外接矩形集合
    Point2f rect[4];
    for(int i=0; i<contours.size(); i++)
    {
        box[i] = minAreaRect(Mat(contours[i]));  //计算每个轮廓最小外接矩形
        boundRect[i] = boundingRect(Mat(contours[i]));
        circle(dstImg, Point(box[i].center.x, box[i].center.y), 5, Scalar(0, 255, 0), -1, 8);  //绘制最小外接矩形的中心点
        box[i].points(rect);  //把最小外接矩形四个端点复制给rect数组
        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);
        for(int j=0; j<4; j++)
        {
            line(dstImg, rect[j], rect[(j+1)%4], Scalar(0, 0, 255), 2, 8);  //绘制最小外接矩形每条边
        }
    }
    imshow("dst", dstImg);
    waitKey(0);
}

opencv(c++) 使用minAreaRect 获得最小外接矩形_第2张图片
三、粗略计算物体像素长宽

#include "opencv2/opencv.hpp"
#include
using namespace std;
using namespace cv;

void main()
{
    Mat srcImg = imread("E://cup.jpg");
    imshow("src", srcImg);
    Mat dstImg = srcImg.clone();
    medianBlur(srcImg, srcImg, 5);
    GaussianBlur(srcImg, srcImg, Size(3, 3), 0, 0);
    cvtColor(srcImg, srcImg, CV_BGR2GRAY);
    threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY_INV); //INV是因为背景白色,物体黑色,需要反转一下
    imshow("threshold", srcImg);

    vector<vector<Point>> contours;
    vector<Vec4i> hierarcy;

    findContours(srcImg, contours, hierarcy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);
    cout<<"num="<<contours.size()<<endl;
    vector<Rect> boundRect(contours.size());
    vector<RotatedRect> box(contours.size());
    Point2f rect[4];
    for(int i=0; i<contours.size(); i++)
    {
        box[i] = minAreaRect(Mat(contours[i]));
        boundRect[i] = boundingRect(Mat(contours[i]));
        cout<<box[i].angle<<endl;
        cout<<box[i].center<<endl;
        cout<<box[i].size.width<<endl;
        cout<<box[i].size.height<<endl;
        circle(dstImg, Point(box[i].center.x, box[i].center.y), 5, Scalar(0, 255, 0), -1, 8);

        //绘制外接矩形和    最小外接矩形(for循环)
        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);
        box[i].points(rect);//把最小外接矩形四个端点复制给rect数组
        for(int j=0; j<4; j++)
        {
            line(dstImg, rect[j], rect[(j+1)%4], Scalar(0, 0, 255), 2, 8);
        }

        char width[20], height[20];
        sprintf(width, "width=%0.2f", box[i].size.width);
        sprintf(height, "height=%0.2f", box[i].size.height);
        putText(dstImg, width, Point(235, 260), CV_FONT_HERSHEY_COMPLEX_SMALL, 0.85, Scalar(0, 255, 0));
        putText(dstImg, height, Point(235, 285), CV_FONT_HERSHEY_COMPLEX_SMALL, 0.85, Scalar(0, 255, 0));

    }
    imshow("dst", dstImg);
    waitKey(0);
}

opencv(c++) 使用minAreaRect 获得最小外接矩形_第3张图片
四、倾斜物体矫正提取

#include "opencv2/opencv.hpp"
#include
using namespace std;
using namespace cv;

void main()
{
    Mat srcImg = imread("E://qrcode.jpg");
    imshow("src", srcImg);
    Mat dstImg = srcImg.clone();
    GaussianBlur(srcImg, srcImg, Size(3, 3), 0, 0);
    cvtColor(srcImg, srcImg, CV_BGR2GRAY);
    Canny(srcImg, srcImg, 100, 200);//因为原图比较复杂,所以需要将canny的值调大,去除不想要的成分
    //threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY_INV); //二值化也可以实现canny效果,不过在本例中杂絮较多
    imshow("canny", srcImg);
    Mat element = getStructuringElement(MORPH_RECT, Size(11, 11), Point(-1, -1)); //定义结构元素
    dilate(srcImg, srcImg, element); //膨胀
    imshow("dilate", srcImg);
    erode(srcImg, srcImg, element);
    imshow("erode", srcImg);

    vector<vector<Point>> contours;
    vector<Vec4i> hierarcy;
    findContours(srcImg, contours, hierarcy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE);
    vector<Rect> boundRect(contours.size());
    vector<RotatedRect> box(contours.size());
    Point2f rect[4];
    for(int i=0; i<contours.size(); i++)
    {
        box[i] = minAreaRect(Mat(contours[i]));
        boundRect[i] = boundingRect(Mat(contours[i]));

        if(box[i].size.width < 100 || box[i].size.height<100)//筛选
            continue;
        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);
        circle(dstImg, Point(box[i].center.x, box[i].center.y), 5, Scalar(0, 255, 0), -1, 8);
        box[i].points(rect);
        for(int j=0; j<4; j++)
        {
            line(dstImg, rect[j], rect[(j+1)%4], Scalar(0, 0, 255), 2, 8);
        }

        float angle;
        cout<<"angle="<<box[i].angle<<endl;
        angle = box[i].angle;
        char width[20], height[20];
        sprintf(width, "width=%0.2f", box[i].size.width);
        sprintf(height, "height=%0.2f", box[i].size.height);
        putText(dstImg, width, Point(195, 260), CV_FONT_HERSHEY_COMPLEX_SMALL, 0.85, Scalar(0, 255, 0));
        putText(dstImg, height, Point(190, 285), CV_FONT_HERSHEY_COMPLEX_SMALL, 0.85, Scalar(0, 255, 0));
        imshow("temp", dstImg);

        //利用仿射变换进行旋转        另一种方法,透视变换
        if (0< abs(angle) && abs(angle)<=45)
            angle = angle;//负数,顺时针旋转
        else if (45< abs(angle) && abs(angle)<90)
            angle = 90 -  abs(angle);//正数,逆时针旋转
        Point2f center = box[i].center;  //定义旋转中心坐标
        double angle0 = angle;
        double scale = 1;
        Mat roateM = getRotationMatrix2D(center, angle0, scale);  //获得旋转矩阵,顺时针为负,逆时针为正
        warpAffine(dstImg, dstImg, roateM, dstImg.size()); //仿射变换

        //保存二维码
        int x0=0, y0=0, w0=0, h0=0;
        x0 = boundRect[i].x;
        y0 = boundRect[i].y;
        w0 = boundRect[i].width;
        h0 = boundRect[i].height;
        Mat ROI = dstImg(Rect(x0, y0, w0, h0));
        imwrite("F://1.jpg", ROI);
    }
    imshow("dst", dstImg);
    waitKey(0);
}

opencv(c++) 使用minAreaRect 获得最小外接矩形_第4张图片
opencv(c++) 使用minAreaRect 获得最小外接矩形_第5张图片
opencv(c++) 使用minAreaRect 获得最小外接矩形_第6张图片
opencv(c++) 使用minAreaRect 获得最小外接矩形_第7张图片

你可能感兴趣的:(opencv,c++,计算机视觉)