Ask Your Question

Revision history [back]

on the given image on the question it seems there is a big closed contour and open contours around it. like this imageimage description as a solution i tried to find edges of open contours and nearest points of closed contour and connect them. as result image :image description

althougt it is not perfect i tested your image and it seems desired result is OK.

i hope it will be useful for you.

#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

using namespace cv;
using namespace std;

/// Global Variables
Point pt0,pt1;
int shift=0; // optional value for drawing scaled
Scalar color = Scalar(0,0,0);

// calculates distance between two points
static double distanceBtwPoints(const cv::Point a, const cv::Point b)
{
    double xDiff = a.x - b.x;
    double yDiff = a.y - b.y;

    return std::sqrt((xDiff * xDiff) + (yDiff * yDiff));
}

static int findNearestPointIndex(const cv::Point pt, const vector<Point> points)
{
    int nearestpointindex = 0;
    double distance;
    double mindistance = 1e+9;

    for ( size_t i = 0; i < points.size(); i++)
    {
        distance = distanceBtwPoints(pt,points[i]);

        if( distance < mindistance )
        {
            mindistance =  distance;
            nearestpointindex = i;
        }
    }
    return nearestpointindex;
}
// draws point vector on given image
int static drawPoints( vector<Point> source_points,int start_index,int end_index, Mat m )
{
    vector<Point> result;
    int c = start_index;
    start_index = min( start_index , end_index );
    end_index = max( end_index, c );

    for ( int i = start_index; i < end_index; i++)
    {
        result.push_back(source_points[i]);
    }
    if( start_index == 0 || result.size() < source_points.size()/2)
    {
        polylines(m,result,false,color,1,LINE_8,shift);
    }

    else
    {
        result.clear();
        for ( int i = 0; i < start_index; i++)
            result.push_back(source_points[i]);
        polylines(m,result,false,color,1,LINE_8,shift);

        result.clear();
        for ( int i = end_index; i < source_points.size(); i++)
        {
            result.push_back(source_points[i]);
            polylines(m,result,false,color,1,LINE_8,shift);
        }
    }
    return 0;
}

bool testPoints(vector<Point> pts)
{
    Point pt = pts[0];
    for ( size_t i = 1; i < pts.size(); i++)
        if( pts[i] == pt ) return false;
    return true;
}

int main( int argc, char** argv )
{
    char* filename = argc >= 2 ? argv[1] : (char*)"test.png";
    Mat img = imread(filename);
    if (img.empty())
        return -1;

    Mat src = img;
    Mat bw;

    cvtColor( src, bw, COLOR_BGR2GRAY );
    bw = bw < 127;

    // Find contours
    vector<vector<Point> > contours;
    vector<Point> contour;
    findContours( bw, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE );


    // assuming the closed contour have biggest size
    contour = contours[0];
    for ( size_t i = 0; i < contours.size(); i++)
    {
        if( contour.size() < contours[i].size() )
            contour = contours[i];
    }

    src = Scalar(255,255,255); // clears source image to redraw

    for ( size_t i = 0; i < contours.size(); i++)
    {
        if( contour != contours[i] && contours[i].size() > 10 )
        {
            pt0 = contours[i][0];

            int ptscount=0;
            for ( size_t j = 0; j <  contours[i].size(); j++)
                if( contours[i][j] == contours[i][j-2] )
                {
                    ptscount++;
                    pt1 = pt0;
                    pt0 = contours[i][j-1];
                }

            if(testPoints(contours[i]) && ptscount > 1 )
                pt0 = contours[i][0];

            // find nearest points of closed contour
            int nearestpointindex_start = findNearestPointIndex(pt0,contour);
            int nearestpointindex_end = findNearestPointIndex(pt1,contour);

            // redrawing
            line(src,pt1,contour[nearestpointindex_end],color,1,LINE_8,shift);
            line(src,pt0,contour[nearestpointindex_start],color,1,LINE_8,shift);

            drawPoints(contours[i],0,contours[i].size(),src);
            drawPoints(contour,nearestpointindex_start,nearestpointindex_end,src);

        }
    }
    imwrite("result.png",src);
    imshow("result", src);
    waitKey(0);
    return 0;
}

on the given image on the question it seems there is a big closed contour and open contours around it. like this imageimage description as a solution i tried to find edges of open contours and nearest points of closed contour and connect them. as result image :image description

althougt it is not perfect i tested your image and it seems desired result is OK.

i hope it will be useful for you.

#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

using namespace cv;
using namespace std;

/// Global Variables
Point pt0,pt1;
int shift=0; // optional value for drawing scaled
Scalar color = Scalar(0,0,0);

// calculates distance between two points
static double distanceBtwPoints(const cv::Point a, const cv::Point b)
{
    double xDiff = a.x - b.x;
    double yDiff = a.y - b.y;

    return std::sqrt((xDiff * xDiff) + (yDiff * yDiff));
}

static int findNearestPointIndex(const cv::Point pt, const vector<Point> points)
{
    int nearestpointindex = 0;
    double distance;
    double mindistance = 1e+9;

    for ( size_t i = 0; i < points.size(); i++)
    {
        distance = distanceBtwPoints(pt,points[i]);

        if( distance < mindistance )
        {
            mindistance =  distance;
            nearestpointindex = i;
        }
    }
    return nearestpointindex;
}
// draws point vector on given image
int static drawPoints( vector<Point> source_points,int start_index,int end_index, Mat m )
{
    vector<Point> result;
    int c = start_index;
    start_index = min( start_index , end_index );
    end_index = max( end_index, c );

    for ( int i = start_index; i < end_index; i++)
    {
        result.push_back(source_points[i]);
    }
    if( start_index == 0 || result.size() < source_points.size()/2)
    {
        polylines(m,result,false,color,1,LINE_8,shift);
    }

    else
    {
        result.clear();
        for ( int i = 0; i < start_index; i++)
            result.push_back(source_points[i]);
        polylines(m,result,false,color,1,LINE_8,shift);

        result.clear();
        for ( int i = end_index; i < source_points.size(); i++)
        {
            result.push_back(source_points[i]);
            polylines(m,result,false,color,1,LINE_8,shift);
        }
    }
    return 0;
}

bool testPoints(vector<Point> pts)
{
    Point pt = pts[0];
    for ( size_t i = 1; i < pts.size(); i++)
        if( pts[i] == pt ) return false;
    return true;
}

int main( int argc, char** argv )
{
    char* filename = argc >= 2 ? argv[1] : (char*)"test.png";
    Mat img = imread(filename);
    if (img.empty())
        return -1;

    Mat src = img;
    Mat bw;

    cvtColor( src, bw, COLOR_BGR2GRAY );
    bw = bw < 127;

    // Find contours
    vector<vector<Point> > contours;
    vector<Point> contour;
    findContours( bw, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE );


    // assuming the closed contour have biggest size
    contour = contours[0];
    for ( size_t i = 0; i < contours.size(); i++)
    {
        if( contour.size() < contours[i].size() )
            contour = contours[i];
    }

    src = Scalar(255,255,255); // clears source image to redraw

    for ( size_t i = 0; i < contours.size(); i++)
    {
        if( contour != contours[i] && contours[i].size() > 10 )
        {
            pt0 = contours[i][0];

            int ptscount=0;
            for ( size_t j = 0; j <  contours[i].size(); j++)
                if( contours[i][j] == contours[i][j-2] )
                {
                    ptscount++;
                    pt1 = pt0;
                    pt0 = contours[i][j-1];
                }

            if(testPoints(contours[i]) && ptscount > 1 )
                pt0 = contours[i][0];

            // find nearest points of closed contour
            int nearestpointindex_start = findNearestPointIndex(pt0,contour);
            int nearestpointindex_end = findNearestPointIndex(pt1,contour);

            // redrawing
            line(src,pt1,contour[nearestpointindex_end],color,1,LINE_8,shift);
            line(src,pt0,contour[nearestpointindex_start],color,1,LINE_8,shift);

            drawPoints(contours[i],0,contours[i].size(),src);
            drawPoints(contour,nearestpointindex_start,nearestpointindex_end,src);

        }
    }
    imwrite("result.png",src);
    imshow("result", src);
    waitKey(0);
    return 0;
}

Second trial code gives this result image

image description

IMHO this code is easier to implement but results is different.

#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

using namespace cv;
using namespace std;

// calculates distance between two points
static double distanceBtwPoints(const cv::Point a, const cv::Point b)
{
    double xDiff = a.x - b.x;
    double yDiff = a.y - b.y;

    return std::sqrt((xDiff * xDiff) + (yDiff * yDiff));
}

static int findNearestPointIndex(const cv::Point pt, const vector<Point> points)
{
    int nearestpointindex = 0;
    double distance;
    double mindistance = 1e+9;

    for ( size_t i = 0; i < points.size(); i++)
    {
        distance = distanceBtwPoints(pt,points[i]);

        if( distance < mindistance )
        {
            mindistance =  distance;
            nearestpointindex = i;
        }
    }
    return nearestpointindex;
}

int main( int argc, char** argv )
{
    Point pt0;
    int shift=0; // optional value for drawing scaled
    Scalar color = Scalar(0,0,0);

    char* filename = argc >= 2 ? argv[1] : (char*)"test.png";
    Mat img = imread(filename);
    if (img.empty())
        return -1;

    Mat src = img;
    Mat bw;

    cvtColor( src, bw, COLOR_BGR2GRAY );
    bw = bw < 127;

    // Find contours
    vector<vector<Point> > contours;
    vector<Point> contour;
    findContours( bw, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE );

    // assuming the closed contour have biggest size
    contour = contours[0];
    for ( size_t i = 0; i < contours.size(); i++)
    {
        if( contour.size() < contours[i].size() )
            contour = contours[i];
    }

    for ( size_t i = 0; i < contours.size(); i++)
    {
        if( contour != contours[i] && contours[i].size() > 10 )
        {
            for ( size_t j = 0; j <  contours[i].size(); j++)
            {
                pt0 = contours[i][j];
                line(src,pt0,contour[findNearestPointIndex(pt0,contour)],color,1,LINE_8,shift);
            }
        }
    }

    cvtColor( src, src, COLOR_BGR2GRAY );
    src = src < 127;
    vector<vector<Point> > contours1;
    findContours( src, contours1, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE );

    src = 255; // clears source image to redraw
    for ( size_t i = 0; i < contours1.size(); i++)
    {
        drawContours(src,contours1,i,color);
    }

    Mat m_xor(src.size(),CV_8UC1,255);
    polylines(m_xor,contour,false,color,1,LINE_8);

    m_xor = 255 - (src ^ m_xor) ;

    imwrite("result.png",m_xor);
    imshow("result", m_xor);
    waitKey(0);
    return 0;
}

on the given image on the question it seems there is a big closed contour and open contours around it. like this imageimage description as a solution i tried to find edges of open contours and nearest points of closed contour and connect them. as result image :image description

althougt it is not perfect i tested your image and it seems desired result is OK.

i hope it will be useful for you.

#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

using namespace cv;
using namespace std;

/// Global Variables
Point pt0,pt1;
int shift=0; // optional value for drawing scaled
Scalar color = Scalar(0,0,0);

// calculates distance between two points
static double distanceBtwPoints(const cv::Point a, const cv::Point b)
{
    double xDiff = a.x - b.x;
    double yDiff = a.y - b.y;

    return std::sqrt((xDiff * xDiff) + (yDiff * yDiff));
}

static int findNearestPointIndex(const cv::Point pt, const vector<Point> points)
{
    int nearestpointindex = 0;
    double distance;
    double mindistance = 1e+9;

    for ( size_t i = 0; i < points.size(); i++)
    {
        distance = distanceBtwPoints(pt,points[i]);

        if( distance < mindistance )
        {
            mindistance =  distance;
            nearestpointindex = i;
        }
    }
    return nearestpointindex;
}
// draws point vector on given image
int static drawPoints( vector<Point> source_points,int start_index,int end_index, Mat m )
{
    vector<Point> result;
    int c = start_index;
    start_index = min( start_index , end_index );
    end_index = max( end_index, c );

    for ( int i = start_index; i < end_index; i++)
    {
        result.push_back(source_points[i]);
    }
    if( start_index == 0 || result.size() < source_points.size()/2)
    {
        polylines(m,result,false,color,1,LINE_8,shift);
    }

    else
    {
        result.clear();
        for ( int i = 0; i < start_index; i++)
            result.push_back(source_points[i]);
        polylines(m,result,false,color,1,LINE_8,shift);

        result.clear();
        for ( int i = end_index; i < source_points.size(); i++)
        {
            result.push_back(source_points[i]);
            polylines(m,result,false,color,1,LINE_8,shift);
        }
    }
    return 0;
}

bool testPoints(vector<Point> pts)
{
    Point pt = pts[0];
    for ( size_t i = 1; i < pts.size(); i++)
        if( pts[i] == pt ) return false;
    return true;
}

int main( int argc, char** argv )
{
    char* filename = argc >= 2 ? argv[1] : (char*)"test.png";
    Mat img = imread(filename);
    if (img.empty())
        return -1;

    Mat src = img;
    Mat bw;

    cvtColor( src, bw, COLOR_BGR2GRAY );
    bw = bw < 127;

    // Find contours
    vector<vector<Point> > contours;
    vector<Point> contour;
    findContours( bw, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE );


    // assuming the closed contour have biggest size
area
    contour = contours[0];
    for ( size_t i = 0; i < contours.size(); i++)
    {
        if( contour.size() < contours[i].size() contourArea(contour) < contourArea(contours[i]) )
            contour = contours[i];
    }

    src = Scalar(255,255,255); // clears source image to redraw

    for ( size_t i = 0; i < contours.size(); i++)
    {
        if( contour != contours[i] && contours[i].size() > 10 )
        {
            pt0 = contours[i][0];

            int ptscount=0;
            for ( size_t j = 0; j <  contours[i].size(); j++)
                if( contours[i][j] == contours[i][j-2] )
                {
                    ptscount++;
                    pt1 = pt0;
                    pt0 = contours[i][j-1];
                }

            if(testPoints(contours[i]) && ptscount > 1 )
                pt0 = contours[i][0];

            // find nearest points of closed contour
            int nearestpointindex_start = findNearestPointIndex(pt0,contour);
            int nearestpointindex_end = findNearestPointIndex(pt1,contour);

            // redrawing
            line(src,pt1,contour[nearestpointindex_end],color,1,LINE_8,shift);
            line(src,pt0,contour[nearestpointindex_start],color,1,LINE_8,shift);

            drawPoints(contours[i],0,contours[i].size(),src);
            drawPoints(contour,nearestpointindex_start,nearestpointindex_end,src);

        }
    }
    imwrite("result.png",src);
    imshow("result", src);
    waitKey(0);
    return 0;
}

Second trial code gives this result image

image description

IMHO this code is easier to implement but results is different.

#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>

using namespace cv;
using namespace std;

// calculates distance between two points
static double distanceBtwPoints(const cv::Point a, const cv::Point b)
{
    double xDiff = a.x - b.x;
    double yDiff = a.y - b.y;

    return std::sqrt((xDiff * xDiff) + (yDiff * yDiff));
}

static int findNearestPointIndex(const cv::Point pt, const vector<Point> points)
{
    int nearestpointindex = 0;
    double distance;
    double mindistance = 1e+9;

    for ( size_t i = 0; i < points.size(); i++)
    {
        distance = distanceBtwPoints(pt,points[i]);

        if( distance < mindistance )
        {
            mindistance =  distance;
            nearestpointindex = i;
        }
    }
    return nearestpointindex;
}

int main( int argc, char** argv )
{
    Point pt0;
    int shift=0; // optional value for drawing scaled
    Scalar color = Scalar(0,0,0);

    char* filename = argc >= 2 ? argv[1] : (char*)"test.png";
    Mat img = imread(filename);
    if (img.empty())
        return -1;

    Mat src = img;
    Mat bw;

    cvtColor( src, bw, COLOR_BGR2GRAY );
    bw = bw < 127;

    // Find contours
    vector<vector<Point> > contours;
    vector<Point> contour;
    findContours( bw, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE );

    // assuming the closed contour have biggest size
area
    contour = contours[0];
    for ( size_t i = 0; i < contours.size(); i++)
    {
        if( contour.size() < contours[i].size() contourArea(contour) < contourArea(contours[i]) )
            contour = contours[i];
    }

    for ( size_t i = 0; i < contours.size(); i++)
    {
        if( contour != contours[i] && contours[i].size() > 10 )
        {
            for ( size_t j = 0; j <  contours[i].size(); j++)
            {
                pt0 = contours[i][j];
                line(src,pt0,contour[findNearestPointIndex(pt0,contour)],color,1,LINE_8,shift);
            }
        }
    }

    cvtColor( src, src, COLOR_BGR2GRAY );
    src = src < 127;
    vector<vector<Point> > contours1;
    findContours( src, contours1, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE );

    src = 255; // clears source image to redraw
    for ( size_t i = 0; i < contours1.size(); i++)
    {
        drawContours(src,contours1,i,color);
    }

    Mat m_xor(src.size(),CV_8UC1,255);
    polylines(m_xor,contour,false,color,1,LINE_8);

    m_xor = 255 - (src ^ m_xor) ;

    imwrite("result.png",m_xor);
    imshow("result", m_xor);
    waitKey(0);
    return 0;
}