Detect not regular rectangular object does not work correct

asked 2016-10-10 01:31:15 -0600

astronaut gravatar image

I would like to detect not regular rectangular objects using OpenCV and approxPolyDP function. In the image I have 4 windows that can be approximate as rectangular contour using the approxPolyDP. But Im not able to detect all of them when set up certain threshold. I filter the windows using the wodth and the height and the angel between the vertices. I would like to have more robust code that can detect all 4 windows. Any help?Here my code

#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 ...
(more)
edit retag flag offensive close merge delete

Comments

Some comments : this line is strange

approx.size() >= 4.0 && (approx.size() <= 4.1

approx is a vector(C++) vector.size() is an unsigned int (size)

I don't think your question is good and should be how to detect window in this picture? Try to detect shape with 6 points and check if error is less than a threshold or may be use Hue moment

LBerger gravatar imageLBerger ( 2016-10-10 02:32:41 -0600 )edit

why shape with 6 point? What threshold and why to use Hue moment?

astronaut gravatar imageastronaut ( 2016-10-10 02:36:26 -0600 )edit

About 6 points Don't forget that approximation use contour point and threshold can be adjust using surface ratio or epsilon parameter in approxpolyDP Hue moment and in opencv here

LBerger gravatar imageLBerger ( 2016-10-10 02:55:12 -0600 )edit

so 6 point can be check with if (approx.size() >= 4 && approx.size() <= 6) ?

astronaut gravatar imageastronaut ( 2016-10-10 03:04:44 -0600 )edit

any code examples for shapes with 6 points and checking the Hue moment??

astronaut gravatar imageastronaut ( 2016-10-10 03:45:00 -0600 )edit
LBerger gravatar imageLBerger ( 2016-10-10 04:03:37 -0600 )edit

hue moment is a paper no code there.. actually what is Hue moment for?

astronaut gravatar imageastronaut ( 2016-10-10 07:02:01 -0600 )edit