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";
Mat mSource= imread(FileName_S,0),
mAlphaMat,mForegroundMask,mResult;
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);
//Extract the Foreground Mask too
inRange(mSource, 255, 255, mForegroundMask);
//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);
imshow("Alpha Mask + Dilate", mAlphaMat);
//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
//Credits: http://answers.opencv.org/question/56095/draw-lines-from-centroid-of-contour-at-given-angle-till-edge-of-contour/#56254
Moments Moments = moments(mForegroundMask);
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();
}
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 :
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?
Please add some sample Image for your desired output!
Done! thank you.
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.