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.
}
};
// ----
Mat m=imread("part.bmp",1);
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[0] << 16) | (v[1] << 8) | (v[2]);
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 !