利用opencv检测出矩形1

利用opencv检测出矩形

//#include "stdafx.h"  
#include <opencv2/opencv.hpp>
#include <iostream>
#include <windows.h>
using namespace cv;
using namespace std;


int* findRectInfo(std::vector<cv::Point> rect)
    {
    int rectInfo[4] = {0};
    int x[4]= {0},y[4]= {0};
    int maxX = 0,maxY = 0,minX = 2000,minY = 2000;
    //get the rect points
    for(int i=0;i<4;i++)
    {
        x[i] = rect[i].x;
        y[i] = rect[i].y;

        if(maxX<x[i])
            maxX = x[i];
        if(maxY<y[i])
            maxY = y[i];
        if(minX>x[i])
            minX = x[i];
        if(minY>y[i])
            minY = y[i];
    }
    rectInfo[0] = minY;
    rectInfo[1] = minX;
    rectInfo[2] = maxY - minY;
    rectInfo[3] = maxX - minX;
    cout<<"minY="<<minY<<endl;
    cout<<"minX="<<minX<<endl;
    cout<<"maxY - minY="<<maxY - minY<<endl;
    cout<<"maxX - minX="<<maxX - minX<<endl;
    return rectInfo;// 得到矩形的左上角的坐标和矩形的边长
}

double angle(Point pt1, Point pt2, Point 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;
    return (dx1*dx2 + dy1*dy2) / sqrt((dx1*dx1 + dy1*dy1)*(dx2*dx2 + dy2*dy2) + 1e-10);
}//勾股定理验证是否满足直角的关系


int main(int argc, char* argv[])
{
    VideoCapture cap;
    cap.open(0);
    if (!cap.isOpened())
    {
        return -1;
    }
    double w = 320, h = 320;
    cap.set(CV_CAP_PROP_FRAME_WIDTH, w);
    cap.set(CV_CAP_PROP_FRAME_HEIGHT, h);
    namedWindow("Video");
    bool stop = false;

    Mat frame1,frame2,frame3;
    //IplImage* image;
    CvMemStorage* storage = NULL;


    while (!stop)
    {
        cap>> frame1;

        //image = &IplImage(frame);
        //IplImage *img1 = cvCreateImage(cvGetSize(image), IPL_DEPTH_8U, 1);
        cvtColor(frame1, frame2, CV_BGR2GRAY);


        GaussianBlur(frame2, frame3, cv::Size(5, 5), 0, 0);
        //cvShowImage("AV", img1);


        // Quantize the gray scale to 30 levels
        int gbins = 16;
        int histSize[] = { gbins };
        // gray scale varies from 0 to 256
        float granges[] = { 0,256 };
        const float* ranges[] = { granges };
        cv::MatND hist;
        // we compute the histogram from the 0-th and 1-st channels
        int channels[] = { 0 };

        //calculate hist
        calcHist(&frame2, 1, channels, cv::Mat(), // do not use mask
            hist, 1, histSize, ranges,
            true, // the histogram is uniform
            false);
        //find the max value of hist
        double maxVal = 0;
        minMaxLoc(hist, 0, &maxVal, 0, 0);

        int scale = 20;
        cv::Mat histImg;
        histImg.create(500, gbins*scale, CV_8UC3);

        //show gray scale of hist image
        for (int g = 0; g<gbins; g++) {
            float binVal = hist.at<float>(g, 0);
            int intensity = cvRound(binVal * 255);
            rectangle(histImg, cv::Point(g*scale, 0),
                cv::Point((g + 1)*scale - 1, binVal / maxVal * 400),
                CV_RGB(0, 0, 0),
                CV_FILLED);
        }
        imshow("histImg", histImg);

        // processing
        Mat hsvRe;
        threshold(frame3, hsvRe, 150, 255, cv::THRESH_BINARY);//阈值设定函数  形式:void cvThreshold( const CvArr* src, CvArr* dst, double threshold, double max_value, int threshold_type );

        vector<vector<Point>> contours;  //contours指所有轮廓
        vector<Vec4i> hierarchy;
        // find 
        findContours(hsvRe, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);//找出图片中的所有轮廓
        // draw 
        //Mat result(hsvRe.size(), CV_8U, Scalar(0));
        //drawContours(result, contours, -1, Scalar(255), 2);

        //namedWindow("contours");
        //imshow("contours", result);




        imshow("Video1", frame1);
        imshow("Video2", frame2);
        imshow("Video3", hsvRe);

//.......................识别矩形.................................................//.

vector<Point> approx;
vector<vector<Point>> squares;
for (size_t i = 0; i < contours.size(); i++)//表示所有的轮廓
{
    approxPolyDP(Mat(contours[i]), approx, 
                 arcLength(Mat(contours[i]), true)*0.02, true);

    if (approx.size() == 4 &&
        fabs(contourArea(Mat(approx))) > 1000 &&
        isContourConvex(Mat(approx)))
    {
        double maxCosine = 0;

        for( int j = 2; j < 5; j++ )
        {
            double cosine = fabs(angle(approx[j%4],approx[j-2], approx[j-1]));
            maxCosine = MAX(maxCosine, cosine);
        }

        if( maxCosine < 0.1 )
            squares.push_back(approx);
    }
}


//...........................get rect from image...........................................

    std::vector<int> compression_params;
    compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);
    compression_params.push_back(9);
    Mat image(3210,3210,CV_8UC3,Scalar(0));

 for(int i=0;i<squares.size();i++)
    {
        int rect[4],*tmp;
        tmp = findRectInfo(squares[i]);
        cout<<i<<endl;
        for(int j=0;j<4;j++)
        {
            rect[j] = *(tmp+j);
        }
         cv::Rect roi(rect[1],rect[0],rect[3],rect[2]);
         cout<<"w:"<<roi.width<<endl;
         cout<<"w:"<<roi.height<<endl;
        //cv::Mat roi_of_image = image(roi);
    }

        /*char * filename = new char[100];
        sprintf(filename,"F:\\Temp\\%i.png",i);
        imshow("Video4", roi_of_image);
        cv::imwrite(filename,roi_of_image,compression_params);*/
   /* }*/

    //...............................

        //storage = cvCreateMemStorage(0);
        //cvNamedWindow(wndname, 1);
        // find and draw the squares

        //cvReleaseImage(&image);
        //cvClearMemStorage(storage);

        if (waitKey(27) >= 0)//Esc键退出
            stop = true;
    }
    return 0;
}
 这个程序是自己在网上各种查阅和拼凑在一起能检测出矩形的程序。

猜你喜欢

转载自blog.csdn.net/qq_31376113/article/details/50897539