Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Obtaining list of unique pixel values in OpenCV Mat

Is there an equivalent of np.unique() or bincount() for an OpenCV Mat? I am working with C++ so can't just convert to a numpy array.

like image 810
eagle34 Avatar asked Jul 12 '14 20:07

eagle34


2 Answers

No, there is not! You can code your own, though:

std::vector<float> unique(const cv::Mat& input, bool sort = false)

Find the unique elements of a single channel cv::Mat.

Parameters:

input: It will be treated as if it was 1-D.

sort: Sorts the unique values (optional).

The implementation of such function is pretty straight forward, however, the following only works with single channel CV_32F:

#include <algorithm>
#include <vector>

std::vector<float> unique(const cv::Mat& input, bool sort = false)
{
    if (input.channels() > 1 || input.type() != CV_32F) 
    {
        std::cerr << "unique !!! Only works with CV_32F 1-channel Mat" << std::endl;
        return std::vector<float>();
    }

    std::vector<float> out;
    for (int y = 0; y < input.rows; ++y)
    {
        const float* row_ptr = input.ptr<float>(y);
        for (int x = 0; x < input.cols; ++x)
        {
            float value = row_ptr[x];

            if ( std::find(out.begin(), out.end(), value) == out.end() )
                out.push_back(value);
        }
    }

    if (sort)
        std::sort(out.begin(), out.end());

    return out;
}

Example:

float data[][3] = {
  {  9.0,   3.0,  7.0 },
  {  3.0,   9.0,  3.0 },
  {  1.0,   3.0,  5.0 },
  { 90.0, 30.0,  70.0 },
  { 30.0, 90.0,  50.0 }
};

cv::Mat mat(3, 5, CV_32F, &data);

std::vector<float> unik = unique(mat, true);

for (unsigned int i = 0; i < unik.size(); i++)
    std::cout << unik[i] << " ";
std::cout << std::endl;

Outputs:

1 3 5 7 9 30 50 70 90 
like image 136
karlphillip Avatar answered Nov 12 '22 21:11

karlphillip


You could try to build a histogram with number of bins equal to number of possible pixel values.

like image 28
morynicz Avatar answered Nov 12 '22 20:11

morynicz