Last active
May 29, 2023 19:20
-
-
Save JohnWayne1986/e1aee3154d14aa3597ad0e69479838e8 to your computer and use it in GitHub Desktop.
This demonstrates how to get the unique pixel values from OpenCV images.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <opencv2/opencv.hpp> | |
#include <vector> | |
#include <iostream> | |
#include <algorithm> | |
#include <cstdint> | |
/** | |
* @brief Functor to find unique elements of an OpenCV image | |
* | |
* @tparam type is the element type. For single-channel images this can be e. g. uint8_t. For | |
* multi-channel images this should be some kind of cv::Vec, like cv::Vec3b. | |
* | |
* @param in is the OpenCV image to find the unique values. Note: This functor | |
* modifies the image. Make a copy with .clone(), if you need the image afterwards. | |
* | |
* @returns vector of unique elements | |
*/ | |
template<typename type> | |
struct UniqueFunctor { | |
cv::Mat in; | |
std::vector<type> operator()() { | |
assert(in.channels() == 1 && "This implementation is only for single-channel images"); | |
auto begin = in.begin<type>(), end = in.end<type>(); | |
auto last = std::unique(begin, end); // remove adjacent duplicates to reduce size | |
std::sort(begin, last); // sort remaining elements | |
last = std::unique(begin, last); // remove duplicates | |
return std::vector<type>(begin, last); | |
} | |
}; | |
template<typename type, int cn> | |
struct UniqueFunctor<cv::Vec<type, cn>> { | |
cv::Mat in; | |
using vec_type = cv::Vec<type, cn>; | |
std::vector<vec_type> operator()() { | |
auto compare = [] (vec_type const& v1, vec_type const& v2) { | |
return std::lexicographical_compare(&v1[0], &v1[cn], &v2[0], &v2[cn]); | |
}; | |
auto begin = in.begin<vec_type>(), end = in.end<vec_type>(); | |
auto last = std::unique(begin, end); // remove adjacent duplicates to reduce size | |
std::sort(begin, last, compare); // sort remaining elements | |
last = std::unique(begin, last); // remove duplicates | |
return std::vector<vec_type>(begin, last); | |
} | |
}; | |
template<typename full_type> | |
void print_unique(cv::Mat img) { | |
std::cout << "unique values: "; | |
auto unique = UniqueFunctor<full_type>{img}(); | |
for (auto v : unique) | |
std::cout << v << " "; | |
std::cout << std::endl; | |
} | |
int main() { | |
cv::Mat img; | |
// single-channel test | |
img = (cv::Mat_<uint16_t>(3, 4) << 1, 5, 3, 4, 3, 1, 5, 5, 1, 3, 4, 3); | |
print_unique<uint16_t>(img); | |
// multi-channel test | |
img = (cv::Mat_<cv::Vec3b>(2, 3) << cv::Vec3b{0, 0, 1}, cv::Vec3b{0, 1, 1}, cv::Vec3b{0, 1, 0}, | |
cv::Vec3b{0, 1, 0}, cv::Vec3b{0, 0, 1}, cv::Vec3b{0, 1, 1}); | |
print_unique<cv::Vec3b>(img); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Compilation and output: