Josh
Josh

Reputation: 1429

OpenCV: Computing superpixel centroids

Background:

I have computed SLIC superpixels of an image using gSLICr, which gives a "per-pixel map" of image superpixels as indices (0 to the number of superpixels-1).

This map is a pointer to an integer const array (const int*) containing the indices.

I now want to compute the centroids of each superpixel using OpenCV.

Coming from a Matlab background, I would do this by using regionprops:

segments = vl_slic(myImage, regionSize, regularizer);
stats = regionprops(segments, 'Centroid');
centroids = cat(1, stats.Centroid);

I don't know how this is done using OpenCV.

Questions:

(i) How do I convert a const int* array to a cv::Mat?

(ii) How do I compute the superpixel centroids from the matrix in (i)?

Upvotes: 0

Views: 1387

Answers (1)

David Stutz
David Stutz

Reputation: 2618

As the first questions seems to be answered, I will focus on you second question. I used the following code to compute the mean coordinates (i.e. spatial centroids) of each superpixel:

/** \brief Compute the mean coordinates of each superpixel (i.e. spatial centroids).
 * \param[in] labels a matrix of type CV_32SC1 holding the labels for each pixel
 * \param[out] means the spatial centroids (or means in y and x axes) of the superpixels
 */
void getMeans(const cv::Mat &labels, std::vector<cv::Vec2f> &means) {

    // Count superpixels or get highest superpixel index:
    int superpixels = 0;
    for (int i = 0; i < labels.rows; ++i) {
        for (int j = 0; j < labels.cols; ++j) {
            if (labels.at<int>(i, j) > superpixels) {
                superpixels = labels.at<int>(i, j);
            }
        }
    }

    superpixels++;

    // Setup means as zero vectors.
    means.clear();
    means.resize(superpixels);
    for (int k = 0; k < superpixels; k++)
    {
        means[k] = cv::Vec2f(0, 0);
    }

    std::vector<int> counts(superpixels, 0);

    // Sum y and x coordinates for each superpixel:
    for (int i = 0; i < labels.rows; ++i) {
        for (int j = 0; j < labels.cols; ++j) {
            means[labels.at<int>(i, j)][0] += i; // for computing mean i (i.e. row or y axis)
            means[labels.at<int>(i, j)][1] += j; // for computing the mean j (i.e. column or x axis)

            counts[labels.at<int>(i, j)]++;
        }
    }

    // Obtain averages by dividing by the size (=number of pixels) of the superpixels.
    for (int k = 0; k < superpixels; ++k) {
        means[k] /= counts[k];
    }
}

// Do something with the means ...

If you also need the mean color, the method would require the image as an argument, but the remaining code can easily be adapted for computing the mean colors.

Upvotes: 0

Related Questions