Ask Your Question
0

OpenCV4Android - Resize a Contour but retain center?

asked 2016-05-31 16:16:51 -0600

Mytheral gravatar image

updated 2016-06-01 15:15:32 -0600

So let's say that I have the contour of an object but I want to shave off the outer 5 pixels from the contour what would be the best way to do that?

Is there a way to scale a contour? Some form of erosion? A distance transform? or would it have to be done more manually?

I've seen this: http://answers.opencv.org/question/44...

The problem with the above approach is that it does not retain it's center and I would then have to run another contour to "get" the inner segment I want.

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
2

answered 2016-06-01 23:20:38 -0600

updated 2016-06-02 09:26:27 -0600

i have an answer posted before : dilating image before finding contours.

We can do eroding image before finding contours to get opposite effect.

additionally i tried another two ways :

  • drawing contours thicker and finding contours again.( works slower )

  • a trial implementation to relocate contour points ( it works faster but it still need to be improved )

the code and results are as follows ( i hope this information will be helpful )

Performans comparison
***************************
0.00119661  seconds (dilating image before finding contours ) 0
0.0071249   seconds (drawing contours thicker and finding contours again)  4
0.000708922 seconds (new trial method)  0
0.00113688  seconds (eroding image before finding contours ) 1
0.0046207   seconds (drawing contours thicker with Scalar(0) and finding contours again)  2

input image:

image description

Output images:

image description

image description

image description

image description

image description

#include <opencv2/opencv.hpp>
#include <ctime>
using namespace cv;
using namespace std;

vector<vector<Point> > getExpandedContours(Mat binary_img, int pixels, int method)
{
    if (method == 0)
    {
        dilate(binary_img, binary_img, Mat(), Point(-1, -1), pixels);
    }

    vector<vector<Point> > contours;

    findContours(binary_img, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);

    if (method == 1)
    {
        for (int i = 0; i < contours.size(); i++)
        {
            drawContours(binary_img, contours, i, Scalar(255), pixels * 2);
        }

        findContours(binary_img, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
    }

    if (method == 2)
    {
        int erosion_value = pixels;
        int free_man_cc = -1;
        vector<Point> contour;
        for (int j = 0; j < contours.size(); j++)
        {
            contour = contours[j];
            int xdiff = 0;
            int ydiff = 0;

            for (int i = 0; i < contour.size() - 1; i++)
            {
                Point pt;

                if ((contour[i].y > contour[i + 1].y) & (contour[i].x == contour[i + 1].x))
                {
                    free_man_cc = 0;
                    xdiff = -1 * erosion_value;
                    ydiff = -1 * erosion_value;
                }

                if ((contour[i].y > contour[i + 1].y) & (contour[i].x < contour[i + 1].x))
                {
                    free_man_cc = 1;
                    xdiff = -1 * erosion_value;
                    ydiff = -1 * erosion_value;
                }

                if ((contour[i].y == contour[i + 1].y) & (contour[i].x < contour[i + 1].x))
                {
                    free_man_cc = 2;
                    xdiff = erosion_value;
                    ydiff = -1 * erosion_value;
                }

                if ((contour[i].y < contour[i + 1].y) & (contour[i].x < contour[i + 1].x))
                {
                    free_man_cc = 3;
                    xdiff = erosion_value;
                    ydiff = -1 * erosion_value;
                }

                if ((contour[i].y < contour[i + 1].y) & (contour[i].x == contour[i + 1].x))
                {
                    free_man_cc = 4;
                    xdiff = erosion_value;
                    ydiff = erosion_value;
                }

                if ((contour[i].y < contour[i + 1].y) & (contour[i].x > contour[i + 1].x))
                {
                    free_man_cc = 5;
                    xdiff = erosion_value;
                    ydiff = erosion_value;
                }

                if ((contour[i].y == contour[i + 1].y) & (contour[i].x > contour[i + 1].x))
                {
                    free_man_cc = 6;
                    xdiff = -1 * erosion_value;
                    ydiff = erosion_value;
                }

                if ((contour[i].y > contour[i + 1].y) & (contour[i].x > contour[i + 1].x))
                {
                    free_man_cc = 7;
                    xdiff = -1 * erosion_value;
                    ydiff = erosion_value;
                }
                contours[j][i].x = contour[i].x - xdiff;
                contours[j][i].y = contour[i].y - ydiff;
            }
        }
    }
    return contours;
}

vector<vector<Point> > getShrinkedContours(Mat binary_img, int pixels, int method)
{
    if (method == 0)
    {
        erode(binary_img, binary_img, Mat(), Point(-1, -1), pixels);
    }

    vector<vector<Point> > contours;

    findContours(binary_img.clone(), contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);

    if (method == 1)
    {
        for (int i = 0; i < contours.size(); i++)
        {
            drawContours(binary_img, contours, i, Scalar(0), pixels * 2);
        }

        findContours(binary_img, contours, RETR_EXTERNAL, CHAIN_APPROX_NONE);
    }

    return contours;
}

int main(int argc, const char * argv[])
{
    Mat img = imread("d:/test.png");
    Mat img0 = img.clone();
    Mat ...
(more)
edit flag offensive delete link more

Question Tools

1 follower

Stats

Asked: 2016-05-31 16:16:51 -0600

Seen: 1,950 times

Last updated: Jun 02 '16