# Partition() - Finding the number of Clusters

Hi all,

I am evaluating few of the openCV api's for my application, in the process I came through this Partition api. Basically I want to know the number of clusters in the part of image using this api. I have seen this link here explaining the usage, but I cant comprehend.

The thing is I want to find the cluster count in a image using partition api. For example, (for a image like this) I should get the cluster count return value from the Partition function as 6 since there area 6 different coloured clusters are there.

Any help could be really appreciated. Thanks in advance! edit retag close merge delete

Sort by » oldest newest most voted

if you want to partition color data, not points, ofc. you need to adapt the Distance function:

struct ColorDist {
bool operator()(const Vec3b& a, const Vec3b &b) {
return norm(a,b) < 65; // experimental value.
}
};

// ----

resize(m,m,Size(), 0.2, 0.2); // i'm in a hurry ;)
cerr << m.total() << " pixels." << endl;

// pack our pixels into a vector (better idea, anyone ?)
vector<Vec3f> data;
data.insert(data.begin(), m.begin<Vec3b>(), m.end<Vec3b>());

// partition labels:
vector<int> labels;
int k = partition(data, labels, ColorDist());
cerr << k << " clusters." << endl;


alternatively, you could just throw an integer representation of the pixel into a map, and count the uniques directly:

map<int,int> clusters2; // color as key, count as value
for (size_t i=0; i<m.total(); i++)
{
Vec3b v = m.at<Vec3b>(i);
int c = (v << 16) | (v << 8) | (v);
if (clusters2.find(c) != clusters2.end())
clusters2[c] ++;
else
clusters2[c] = 0;
}
cerr << clusters2.size() << " clusters2." << endl;
// 26 clusters.

// now, let's remove the small, noisy ones:
for (map<int,int>::iterator it=clusters2.begin(); it != clusters2.end(); )
{
if (it->second < 50) // throw away all clusters < 50 elements
it = clusters2.erase(it);
else
it++;
}
cerr << clusters2.size() << " clusters2." << endl;
// 6 clusters. ;)


the problem with both methods is, that your image seems to have come a long way. if you take a close look, you'll see a lot of grey, dithered (compression) artefacts around your shapes, which will be unique colors, too ! more

2

Thanks a lot @berak!! As you suggested the code works very well in detecting the unique colours (including the artifacts) but still it depends on the predicate function as rightly mentioned. Very Thanks.!!

For the cluster count, the partition function itself returns an int value which would be suffice for now, I was not able to understand that part in your code both the methods. if possible tell a little bit about those part. Anyways thanks a lot for your help!

1

ah, sure, forgot, that it returns the count already. ;)

I use this message from @berak to build this program :

struct Dist {
bool operator()(const Point& a, const Point &b) {
return sqrt((a.x - b.x)*(a.x - b.x) + (a.y - b.y)*(a.y - b.y)) < 15;
}
};
vector<Point> data;
for (int i = 0; i<m.rows; i++)
for (int j = 0;j<m.cols; j++)
if (m.at<Vec3b>(i,j)!=Vec3b(0,0,0))
data.push_back(Point(j,i));
vector<int> labels;

partition(data, labels, Dist());
Mat cluster(m.rows,m.cols,CV_8UC1);
for (int i=0;i<data.size();i++)
cluster.at<uchar>(data[i])=labels[i];
imwrite("label.bmp",cluster);


I must say that with your image it is much more efficiency to use canny or threshold

more

@LBerger: Thanks for your effort. Yes it is possible to use canny or threshold for this image. But in original scenario, real time images with different objects and textures would be the input. For now, I was interested in the partition api evaluation.

I haven't read last line of your post "there area 6 different coloured clusters are there."

Official site

GitHub

Wiki

Documentation