# Split a Mat into parts, based on each containing three colors?

I am looking at speeding up an alpha matting algorithm. To do this I need to cut a mat of this image: into the smallest possible sections, where each section contains all three of the possible colors. (the alpha matting algorithm requires all three to compute the matte).

It will not always be the same image, how can i automatically chop up a Mat into submats based on all three colors being present?

So what I have now is: But the matte algorithm fails where there is only black and gray, or only white and gray. I need every color inside every section. I guess something like this would work for this image: But every image will be different, so I will need to work it out based on color.

thank you.

edit retag close merge delete

I don't understand what you want exactly.

split is to split channels (BGR).

if you want only white pixels in img then use a mask :

Mat maskWhite = img == 255;
Mat maskGray = img == 127;


Hi, thanks for your reply. Perhaps split is the wrong word. I need to create sub mats from the image, or ROI. Each one as small as possible, while containing some white, some black, and some gray pixels.So rather than creating ROI with even spacing, i need to work out how best to cut the image up, giving me the maximum number of pieces, each containing all three colors. Does that make more sense?

Is it necessary for All your Squares to be in the same size?

It is not an opencv problem but an image processing problem. I don't think you can ignore this page where you find some source codes to solve this problem

Nope! the only specification is that every color is present.

Sort by » oldest newest most voted Hi,

I think it is better to fit a Triangle than a Square for your use case.Hope this gives you some rough idea! We can partition the Alpha mask based on these initial cuts. I will add the later part in sometime.

#include <iostream>
#include "opencv2/opencv.hpp"

using namespace cv;
using namespace std;

void Erode(InputArray mSrc, OutputArray mDst, int erosion_size, int erosion_elem)
{
int erosion_type = 0;
if (erosion_elem == 0){ erosion_type = MORPH_RECT; }
else if (erosion_elem == 1){ erosion_type = MORPH_CROSS; }
else if (erosion_elem == 2) { erosion_type = MORPH_ELLIPSE; }

//![kernel]
Mat element = getStructuringElement(erosion_type,
Size(2 * erosion_size + 1, 2 * erosion_size + 1),
Point(erosion_size, erosion_size));

/// Apply the erosion operation
erode(mSrc, mDst, element);
}

void Dilate(InputArray mSrc, OutputArray mDst, int dilate_size, int dilate_elem)
{
int dilate_type = 0;
if (dilate_elem == 0){ dilate_type = MORPH_RECT; }
else if (dilate_elem == 1){ dilate_type = MORPH_CROSS; }
else if (dilate_elem == 2) { dilate_type = MORPH_ELLIPSE; }

//![kernel]
Mat element = getStructuringElement(dilate_type,
Size(2 * dilate_size + 1, 2 * dilate_size + 1),
Point(dilate_size, dilate_size));

/// Apply the erosion operation
dilate(mSrc, mDst, element);
}

int main(int argc, char* argv[])
{
string FileName_S = "Input.png";

if (mSource.empty())
{
cout << "[Error] Invalid Input Image!";
return 0;
}

//Source Image
imshow("Input Image", mSource); //Extract the Alpha Mask that we are interested in
inRange(mSource, 128, 128, mAlphaMat);

//Choose the Size of the Intersection Area
const int SIZE_WIDTH = 5;

//Grow the White region by Dilating the Alpha Mask
Dilate(mAlphaMat, mAlphaMat, SIZE_WIDTH, 1); //Just for Visualisation purpose
mSource.copyTo(mResult, mAlphaMat);
cvtColor(mResult, mResult, COLOR_GRAY2BGR);

//Find the Centre of the Foreground Mask to Start Partition in a Circle
Point Centre(int(Moments.m10 / Moments.m00), int(Moments.m01 / Moments.m00));
Rect bounds(0, 0, mResult.cols, mResult.rows);

for (int Angle = 0; Angle<360; Angle += 20)
{
//Find another point in the circle with some offset! We just need the direction!
Point Point2(Centre.x + sin(Angle*CV_PI / 180) * 500, Centre.y + cos(Angle*CV_PI / 180) * 500);

//Iterate through the Line till the Image Boundary
LineIterator Line_Itr(mResult, Centre, Point2, 8);

//Draw the Line at each step till it reaches Image Boundary
while (bounds.contains(Line_Itr.pos()) && (Line_Itr.pos().x>0 &&Line_Itr.pos().y>0))
{
mResult.at<Vec3b>(Line_Itr.pos()) = Vec3b(0, 255, 0);
Line_Itr++;
}
}

imshow("Result", mResult); waitKey();

}

more

Thank you! After more thought, I actually need to stick with squares, so i can process each as a separate Mat, then re-assemble into one. I will definitely use this as a starting point tho. Thank you again!

Official site

GitHub

Wiki

Documentation