According to stackflow’s answer: Obtaining list of unique pixel values in OpenCV Mat, we can get the unique value list of OpeCV Mat, but the speed is too slow. Is there a faster way?
Thank you
According to stackflow’s answer: Obtaining list of unique pixel values in OpenCV Mat, we can get the unique value list of OpeCV Mat, but the speed is too slow. Is there a faster way?
Thank you
please clarify. why do you want to do this?
use a std::set
or a std::map
to collect pixel values, not vector
(so you dont need to iterate in the most inner loop)
Yes! Using std::set
really speeds things up
std::vector<float> unique1(const cv::Mat& input, bool sort = false)
{
if (input.channels() > 1 || input.type() != CV_8U)
{
std::cerr << "unique !!! Only works with CV_8U 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;
}
to
std::set<int> Unique2(const cv::Mat& input)
{
if (input.channels() > 1 || input.type() != CV_8U)
{
std::cerr << "unique !!! Only works with CV_8U 1-channel Mat" << std::endl;
return std::set<int>();
}
std::set<int> out;
for (int y = 0; y < input.rows; y++)
{
for (int x = 0; x < input.cols; x++)
{
int value = input.at<uchar>(y, x);
std::set<int>::iterator iter;
if ((iter = out.find(value)) == out.end())
{
out.insert(value);
}
}
}
return out;
}
Test code:
#include <vector>
#include "opencv2/opencv.hpp"
int main()
{
cv::Mat1b gt(6087, 18744);
cv::randu(gt, 0, 2);
std::vector<int> vUnique = unique1(gt, true);
std::set<int> setUnique = unique2(gt);
return 0;
}