我想使用OpenCV和approxPolyDP函数检测不规则的矩形对象 . 在图像中,我有4个窗口,可以使用approxPolyDP近似为矩形轮廓 . 但是当设置一定的阈值时,我无法检测到所有这些 . 我使用wodth和顶点之间的高度和天使过滤窗口 . 我想有更强大的代码,可以检测所有4个窗口 . 有什么帮助吗?这是我的代码

#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>

 using namespace cv;
 using namespace std;

 Mat src; Mat src_gray;
 int thresh = 5;
 int max_thresh = 60000;
 RNG rng(12345);

 void thresh_callback(int, void* );

 static 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);
 }

 void setLabel(cv::Mat& im, const std::string label, std::vector<cv::Point>& contour)
 {
    int fontface = cv::FONT_HERSHEY_SIMPLEX;
    double scale = 0.4;
    int thickness = 1;
    int baseline = 0;

    cv::Size text = cv::getTextSize(label, fontface, scale, thickness, &baseline);
    cv::Rect r = cv::boundingRect(contour);

    cv::Point pt(r.x + ((r.width - text.width) / 2), r.y + ((r.height + text.height) / 2));
    cv::rectangle(im, pt + cv::Point(0, baseline), pt + cv::Point(text.width, -text.height), CV_RGB(255,255,255), CV_FILLED);
    cv::putText(im, label, pt, fontface, scale, CV_RGB(0,0,0), thickness, 8);
 }


int main()
{

    cv::Mat src = cv::imread("p3.png");
    resize(src, src, Size(640,480), 0, 0, INTER_CUBIC);

     char* source_window = "Source";
     namedWindow( source_window, CV_WINDOW_AUTOSIZE );
     imshow( source_window, src );

     createTrackbar( " Canny thresh:", "Source", &thresh, max_thresh, thresh_callback );
     thresh_callback( 0, 0 );

waitKey(0);
return(0);
}

void thresh_callback(int, void* ) {

    src = imread("p3.png");
    resize(src, src, Size(640,480), 0, 0, INTER_CUBIC);
    //================================
    Mat gray,bw,dil,erd;

    Canny(gray,bw,thresh, thresh*1, 5);
    //Canny( src_gray, canny_output, thresh, thresh*1, 3 );
    dilate(bw,dil,Mat());
    erode(dil,erd,Mat());
    Mat tmp=bw.clone();

    Size kernalSize (15,20);
    Mat element = getStructuringElement (MORPH_RECT, kernalSize, Point(4,4)  );
    morphologyEx( bw, bw, MORPH_CLOSE, element );
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;//novo
    findContours(bw.clone(), contours, CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE);
    vector<Point> approx;
    Mat dst = src.clone();

    for( int i = 0; i< contours.size(); i++ )
    {
        approxPolyDP(Mat(contours[i]), approx, arcLength(Mat(contours[i]), true) * 0.09, true);

        if (approx.size() >= 4.0 && (approx.size() <= 4.1))
        {
            int vtc = approx.size();
            vector<double> cos;
            for(int j = 2; j < vtc + 1; j++)

            cos.push_back(angle(approx[j%vtc], approx[j-2], approx[j-1]));
            sort(cos.begin(), cos.end());
            double mincos = cos.front();
            double maxcos = cos.back();

            if (vtc == 4 && mincos >= -0.6 && maxcos <= 0.6)
            {
                Rect r = boundingRect(contours[i]);
                double ratio = abs(1 - (double)r.width / r.height);
                if (r.height >50 && r.width >20 && r.height < 640 && r.width < 640 && r.height>r.width ) /* constraints on region size */
                                {
                //Rect r = boundingRect(contours[i]);
                //double ratio = abs(1 - (double)r.width / r.height);
                line(dst, approx.at(0), approx.at(1), cvScalar(0,0,255),4);
                line(dst, approx.at(1), approx.at(2), cvScalar(0,0,255),4);
                line(dst, approx.at(2), approx.at(3), cvScalar(0,0,255),4);
                line(dst, approx.at(3), approx.at(0), cvScalar(0,0,255),4);
            }
          }
        }
    }

    }

这里是源图像

source image

并在这里检测到窗口
detected rectangles

这里的图纸/视觉轮廓
contours