Home How to draw a rectangle containing an object in Android (Java, OpenCV)
Reply: 0

How to draw a rectangle containing an object in Android (Java, OpenCV)

user5367
1#
user5367 Published in July 22, 2018, 8:34 pm

Basically, I want to achieve this, and so far, I've written the following Java code...

    // Display the camera frame
    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
        // The object's width and height are set to 0
        objectWidth = objectHeight = 0;

        // frame is captured as a coloured image
        frame = inputFrame.rgba();

        /** Since the Canny algorithm only works on greyscale images and the captured image is
         *  coloured, we transform the captured cam image into a greyscale one
         */
        Imgproc.cvtColor(frame, grey, Imgproc.COLOR_RGB2GRAY);

        // Calculating borders of image using the Canny algorithm
        Imgproc.Canny(grey, canny, 180, 210);

        /** To avoid background noise (given by the camera) that makes the system too sensitive
         *  small variations, the image is blurred to a small extent. Blurring is one of the
         *  required steps before any image transformation because this eliminates small details
         *  that are of no use. Blur is a low-pass filter.
         */
        Imgproc.GaussianBlur(canny, canny, new Size(5, 5), 5);

        // Calculate the contours
        Imgproc.findContours(canny, contours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);

        /** The contours come in different sequences
         *  1 sequence for each connected component.
         *  Taking the assumption only 1 object is in view, if we have more than 1 connected
         *  component, this'll be considered part of the details of the object.
         *
         *  For this, we put all contours together in a single sequence
         *  If there is at least 1 contour, I can continue processing
         */
        for (MatOfPoint mat : contours) {
            // Retrieve and store all contours in one giant map
            mat.copyTo(allContours);
        }

        MatOfPoint2f allCon = new MatOfPoint2f(allContours.toArray());

        // Calculating the minimal rectangle to contain the contours
        RotatedRect box = Imgproc.minAreaRect(allCon);

        // Getting the vertices of the rectangle
        Point[] vertices = initialiseWithDefaultPointInstances(4);
        box.points(vertices);

        // Now the vertices are in possession, temporal smoothing can be performed.
            for (int i = 0; i < 4; i++) {
                // Smooth coordinate x of the vertex
                vertices[i].x = alpha * lastVertices[i].x + (1.0 - alpha) * vertices[i].x;
                // Smooth coordinate y of the vertex
                vertices[i].y = alpha * lastVertices[i].y + (1.0 - alpha) * vertices[i].y;
                // Assign the present smoothed values as lastVertices for the next smooth
                lastVertices[i] = vertices[i];
            }

        /** With the vertices, the object size is calculated.
         *  The object size is calculated through pythagoras theorm. In addition, it gives
         *  the distance between 2 points in a bi-dimensional space.
         *
         *  For a rectangle, considering any vertex V, its two sizes (width and height) can
         *  be calculated by calculating the distance of V from the previous vertex and
         *  calculating the distance of V from the next vertex. This is the reason why I
         *  calculate the distance between vertici[0]/vertici[3] and vertici[0]/vertici[1]
         */
        objectWidth = (int) (conversionFactor * Math.sqrt((vertices[0].x - vertices[3].x) * (vertices[0].x - vertices[3].x) + (vertices[0].y - vertices[3].y) * (vertices[0].y - vertices[3].y)));
        objectHeight = (int) (conversionFactor * Math.sqrt((vertices[0].x - vertices[1].x) * (vertices[0].x - vertices[1].x) + (vertices[0].y - vertices[1].y) * (vertices[0].y - vertices[1].y)));

        /** Draw the rectangle containing the contours. The line method draws a line from 1
         *  point to the next, and accepts only integer coordinates; for this reason, 2
         *  temporary Points have been created and why I used Math.round method.
         */
        Point pt1 = new Point();
        Point pt2 = new Point();
        for (int i = 0; i < 4; i++) {
            pt1.x = Math.round(vertices[i].x);
            pt1.y = Math.round(vertices[i].y);
            pt2.x = Math.round(vertices[(i + 1) % 4].x);
            pt2.y = Math.round(vertices[(i + 1) % 4].y);
            Imgproc.line(frame, pt1, pt2, red, 3);
        }

        //If the width and height are non-zero, then print the object size on-screen
        if (objectWidth != 0 && objectHeight != 0) {
            String text;
            text = String.format("%d x %d", objectWidth, objectHeight);
            widthValue.setText(text);
        }


        // This function must return
        return frame;
    }

    // Initialising an array of points
    public static Point[] initialiseWithDefaultPointInstances(int length) {
        Point[] array = new Point[length];
        for (int i = 0; i < length; i++) {
            array[i] = new Point();
        }
        return array;
    }

What I want to achieve is drawing a rectangle on-screen that contains the object's contours (edges). If anyone knows the answer to my question, please feel free to comment below, as I have been stuck on this for a couple of hours

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.310086 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO