0

I'm trying to separate the background (green field and light green towel) from the objects using OpenCV so I segmented the following image manually: enter image description here

By bordering the objects in red and coloring blue the connected components which should not be taken into consideration as you can see in the bottom right of the image: enter image description here

After threasholding on 254 the channels R and B, I got the following:

  1. Channel Red

Channel red

  1. Channel Blue Channel Blue

If I fulfill the all contours of red channel using

findContours( bordersRed, contoursRedChannel, hierarchyRedChannel, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, cv::Point(0, 0) );
for (int index = 0; index < contoursRedChannel.size(); index ++)
    {
        drawContours( bordersRed, contoursRedChannel, index, colorForMask, CV_FILLED, 8, hierarchyRedChannel, 0, cv::Point() );
    }

the bottom right corner will be like:

enter image description here

But what I need is to ignore the contours that contains only blue points in order to have something like:

enter image description here

so I have to combine the red with blue channels to get it but don't know how yet. Any advice would be appreciated.

Thanks.

Maystro
  • 2,907
  • 8
  • 36
  • 71

1 Answers1

1

You can do that using floodFill, assuming you know a point inside the shape you want to fill.

Result starting from your "Channel red":

enter image description here

Code:

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

int main()
{
    // Your image
    Mat1b img = imread("path_to_image", IMREAD_GRAYSCALE);

    // Assume you know a point inside the shape
    Point seed(930, 370); 

    // Apply floodfill
    floodFill(img, seed, Scalar(255));

    // Show image
    imshow("Result", img);
    waitKey();

    return 0;
}

UPDATE

Once you fill the contours in both masks with drawContours(... CV_FILLED), you can simply XOR the two mask:

enter image description here

Code:

#include <opencv2\opencv.hpp>
#include <vector>
#include <algorithm>

using namespace std;
using namespace cv;

int main()
{
    // Load the two mask
    Mat1b channel_red_mask = imread("channel_red.png", IMREAD_GRAYSCALE);
    Mat1b channel_blue_mask = imread("channel_blue.png", IMREAD_GRAYSCALE);

    // Use just the bottom right part
    Rect roi(Point(800, 270), Point(channel_red_mask.cols, channel_red_mask.rows));
    channel_red_mask = channel_red_mask(roi).clone();
    channel_blue_mask = channel_blue_mask(roi).clone();


    // Fill all contours, in both masks
    {
        vector<vector<Point>> contours;
        findContours(channel_red_mask.clone(), contours, RETR_LIST, CHAIN_APPROX_SIMPLE);
        for (int i = 0; i < contours.size(); ++i)
        {
            drawContours(channel_red_mask, contours, i, Scalar(255), CV_FILLED);
        }
    }
    {
        vector<vector<Point>> contours;
        findContours(channel_blue_mask.clone(), contours, RETR_LIST, CHAIN_APPROX_SIMPLE);
        for (int i = 0; i < contours.size(); ++i)
        {
            drawContours(channel_blue_mask, contours, i, Scalar(255), CV_FILLED);
        }
    }

    // XOR the masks
    Mat1b xored = channel_red_mask ^ channel_blue_mask;

    imshow("XOR", xored);
    waitKey();

    return 0;
}
Miki
  • 40,887
  • 13
  • 123
  • 202
  • Thanks for your answer.. it seems to me the question was not clear enough so I've updated it now. Please check it – Maystro Nov 19 '15 at 20:53