Amrmsmb
Amrmsmb

Reputation: 1

How to detect whole rectangle in a frame

I am using OpenCV4Android version 2.4.11 and I am trying to detect the rectangles in frames retrieved from Camera. I referred to some questions in this website and they were so helpful. but the issue i am facing currently is when i try to detect an object with light color in the middle as shown in the original image below the detection algorithm in this case does not detect the object as whole, rather it detects the dark parts of it as shown in image in the section titled "processed" below.

the code posted below indicates the steps i followed and the threshold values i used to detect the objects in the frames.

please let me know why the object as a whole is not getting detected and what can i do to detect the whole object not only parts of it

code:

    //step 1
    this.mMatGray = new Mat();
    Imgproc.cvtColor(this.mMatInputFrame, this.mMatGray, Imgproc.COLOR_BGR2GRAY);
    //step 2
    this.mMatEdges = new Mat();
    Imgproc.blur(this.mMatGray, this.mMatEdges, new Size(7, 7));//7,7
    //step 3
    Imgproc.Canny(this.mMatEdges, this.mMatEdges, 128, 128*2, 5, true);//..,..,2,900,7,true
    //step 4
    dilated = new Mat();
    Mat dilateElement = Imgproc.getStructuringElement(Imgproc.MORPH_DILATE, new Size(3, 3));
    Imgproc.dilate(mMatEdges, dilated, dilateElement);

     ArrayList<MatOfPoint> contours = new ArrayList<>();
    hierachy = new Mat();
    Imgproc.findContours(dilated, contours, hierachy, Imgproc.RETR_LIST, Imgproc.CHAIN_APPROX_SIMPLE);

    MatOfPoint2f approxCurve = new MatOfPoint2f();
    if (contours.size() > 0) {
        for (int i = 0; i < contours.size(); i++) {

            MatOfPoint2f contour2f = new MatOfPoint2f(contours.get(i).toArray());
            double approxDistance = Imgproc.arcLength(contour2f, true) * .02;//.02
            Imgproc.approxPolyDP(contour2f, approxCurve, approxDistance, true);
            MatOfPoint points = new MatOfPoint(approxCurve.toArray());

            if (points.total() >= 4 && Imgproc.isContourConvex(points) && Math.abs(Imgproc.contourArea(points)) >= 40000 && Math.abs(Imgproc.contourArea(points)) <= 150000) {
                Rect boundingRect = Imgproc.boundingRect(points);
                RotatedRect minAreaRect = Imgproc.minAreaRect(contour2f);
                Point[] rectPoints = new Point[4];
                minAreaRect.points(rectPoints);
                Rect minAreaAsRect = minAreaRect.boundingRect();

                //to draw the minAreaRect
                for( int j = 0; j < 4; j++ ) {
                    Core.line(mMatInputFrame, rectPoints[j], rectPoints[(j+1)%4], new Scalar(255,0,0));
                }
                Core.putText(mMatInputFrame, "MinAreaRect", new Point(10, 30), 1,1 , new Scalar(255,0,0),2);
                Core.putText(mMatInputFrame, "Width: " + minAreaAsRect.width , new Point(minAreaAsRect.tl().x, minAreaAsRect.tl().y-100), 1,1 , new Scalar(255,0,0),2);
                Core.putText(mMatInputFrame, "Height: " + minAreaAsRect.height, new Point(minAreaAsRect.tl().x, minAreaAsRect.tl().y-80), 1,1 , new Scalar(255,0,0),2);
                Core.putText(mMatInputFrame, "Area: " + minAreaAsRect.area(), new Point(minAreaAsRect.tl().x, minAreaAsRect.tl().y-60), 1,1 , new Scalar(255,0,0),2);

                //drawing the contour
                Imgproc.drawContours(mMatInputFrame,  contours, i, new Scalar(0,0,0),2);

                //drawing the boundingRect
                Core.rectangle(mMatInputFrame, boundingRect.tl(), boundingRect.br(), new Scalar(0, 255, 0), 1, 1, 0);
                Core.putText(mMatInputFrame, "BoundingRect", new Point(10, 60), 1,1 , new Scalar(0,255,0),2);
                Core.putText(mMatInputFrame, "Width: " + boundingRect.width , new Point(boundingRect.br().x-100, boundingRect.tl().y-100), 1,1 , new Scalar(0,255,0),2);
                Core.putText(mMatInputFrame, "Height: " + boundingRect.height, new Point(boundingRect.br().x-100, boundingRect.tl().y-80), 1,1 , new Scalar(0,255,0),2);
                Core.putText(mMatInputFrame, "Area: " + Imgproc.contourArea(points), new Point(boundingRect.br().x-100, boundingRect.tl().y-60), 1,1 , new Scalar(0,255,0),2);
            }
        }
    }

original image:

enter image description here

processed image:

enter image description here

Upvotes: 2

Views: 865

Answers (1)

MD. Nazmul Kibria
MD. Nazmul Kibria

Reputation: 1090

I have implemented in c++. API's are same so you can easily port for android. I have used Opencv 2.4.8 . Please check the implementation. Hope the code says what is done:

#include <iostream>
#include <string>
#include "opencv/highgui.h"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/objdetect/objdetect.hpp"

using namespace std;
using namespace cv;


Mat GetKernel(int erosion_size)
{
       Mat element = getStructuringElement(cv::MORPH_CROSS,
              cv::Size(2 * erosion_size + 1, 2 * erosion_size + 1),
              cv::Point(erosion_size, erosion_size) );

       return element;
}
int main()
{
    Mat img = imread("C:/Users/dell2/Desktop/j6B3A.png",0);//loading gray scale image
    Mat imgC = imread("C:/Users/dell2/Desktop/j6B3A.png",1);
    GaussianBlur(img,img,Size(7,7),1.5,1.5);

    Mat dimg;
    adaptiveThreshold(img,dimg,255,ADAPTIVE_THRESH_GAUSSIAN_C,THRESH_BINARY,17,1);



       dilate(dimg,img,GetKernel(2)); 
       erode(img,dimg,GetKernel(2)); 
       erode(dimg,img,GetKernel(1)); 


       dimg = img;

    //*
     vector<vector<Point>> contours; // Vector for storing contour
    vector<Vec4i> hierarchy;

    findContours( dimg, contours, hierarchy,CV_RETR_TREE , CV_CHAIN_APPROX_NONE ); // Find the contours in the image

     double largest_area = 0;
     int largest_contour_index = 0;
     Rect bounding_rect;

     for( int i = 0; i< contours.size(); i++ ) // iterate through each contour. 
      {
       double a=contourArea( contours[i],false);  //  Find the area of contour
       if(a>largest_area){
       largest_area=a;
       largest_contour_index=i;                //Store the index of largest contour
       bounding_rect=boundingRect(contours[i]); // Find the bounding rectangle for biggest contour
       }

      }

     drawContours( imgC, contours, largest_contour_index, Scalar(255,0,0), 2, 8, hierarchy, 0, Point() );
    rectangle(imgC, bounding_rect,  Scalar(0,255,0),2, 8,0);  
 /**/

    //imshow("display",dimg);
    imshow("display2",imgC);
    waitKey(0);
    return 0;
}

Output produced:

enter image description here

You can fine tune the threshold if necessary.

Upvotes: 2

Related Questions