Ask Your Question
1

Clusterization in OpenCV

asked 2012-10-12 15:07:53 -0600

Astor gravatar image

I have a two questions about clusterization in OpenCV. I'm using kmeans clustering.

  • How to get mask of each post-clusterized layer of image? To understand this question I want to show an example. If I clusterize image on 3 clusters and after clusterisation I have this image:

output

(white is first cluster, gray is second and black - third).

So after splitting my aim is to get these three masks:

White: , gray: and black: .

  • What is the fastest way to clusterize only some part of image (I have two images - original image and mask image)? So, for example, if I clusterize image on n clusters after clusterization with mask I want to have n+1 cluster (+1 because of mask).

I'm looking for the fastest solutions of these problems.

Thanks in advance.

edit retag flag offensive close merge delete

1 answer

Sort by ยป oldest newest most voted
4

answered 2012-10-22 15:38:01 -0600

Astor gravatar image

updated 2012-10-22 17:25:50 -0600

I decided to answer my own question. On the first question I found answer by myself, and solution to the second question from my question on StackOverflow. Thanks @remi. So:

  1. It seems that inRange with special parameters will help me to achieve this, but the problem is that in this solution I will have call it k times, so simple iterating with check will do the trick. Also I can use check:

    cv::Mat mask = (labelImage == k)

  2. Here's full code (maybe someone will find it useful):


void kmeansMask(const Mat& src, const Mat& mask, const int k, Mat& dst)
{
    Mat tmp = Mat::zeros(countNonZero(mask), 1, CV_8UC3);
    int counter = 0;
    for (int r = 0; r < mask.rows; ++r)
    {
        for (int c = 0; c < mask.cols; ++c)
        {
            if (mask.at<unsigned char>(r, c))
            {
                tmp.at<cv::Vec3f>(counter++, 0) = src.at<cv::Vec3b>(r, c);
            }
        }
    }

    Mat labels;
    kmeans(tmp, k, labels, TermCriteria(), 1, KMEANS_RANDOM_CENTERS);

    dst = cv::Mat(mask.size(), CV_32S, k);
    counter = 0;
    for (int r = 0; r < mask.rows; ++r)
    {
        for (int c = 0; c < mask.cols; ++c)
        {
            if (mask.at<unsigned char>(r, c))
            {
                dst.at<int>(r, c) = labels.at<int>(counter++, 0);
            }
        }
    }
}
edit flag offensive delete link more

Question Tools

Stats

Asked: 2012-10-12 15:07:53 -0600

Seen: 1,485 times

Last updated: Oct 22 '12