【问题标题】:Obtaining list of unique pixel values in OpenCV Mat获取 OpenCV Mat 中唯一像素值的列表
【发布时间】:2014-09-03 05:06:01
【问题描述】:

对于 OpenCV Mat,是否有 np.unique()bincount() 的等价物?我正在使用 C++,所以不能只转换为 numpy 数组。

【问题讨论】:

    标签: c++ arrays opencv matrix computer-vision


    【解决方案1】:

    这是使用标准库实现的另一个建议。

    opencv-unique.cpp

    #include <opencv2/opencv.hpp>
    #include <vector>
    #include <iostream>
    #include <algorithm>
    #include <cstdint>
    
    /**
     * @brief Find unique elements of an OpenCV image
     *
     * @tparam type is the C++ type to access the image elements.
     * @param in is the OpenCV single-channel image to find the unique values. Note: This
     * modifies the image. Make a copy with .clone(), if you need the image afterwards.
     *
     * @returns vector of unique elements
     */
    template<typename type>
    std::vector<type> unique(cv::Mat in) {
        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);
    }
    
    int main() {
        cv::Mat img = (cv::Mat_<uint16_t>(3, 4) << 1, 5, 3, 4, 3, 1, 5, 5, 1, 3, 4, 3);
    
        std::cout << "unique values: ";
        auto u = unique<uint16_t>(img);
        for (auto v : u)
            std::cout << v << " ";
        std::cout << std::endl;
    
        return 0;
    }
    

    编译并执行产量:

    $ g++ -Wall opencv-unique.cpp -o unique -lopencv_core -I /usr/include/opencv4 && ./unique
    unique values: 1 3 4 5
    

    以上版本适用于单通道图像。您可以将其扩展到多通道图像(以获得独特的颜色),例如 this

    【讨论】:

      【解决方案2】:

      您可以尝试构建一个直方图,其中 bin 的数量等于可能的像素值的数量。

      【讨论】:

        【解决方案3】:

        不,没有!您可以自己编写代码:

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

        查找单通道 cv::Mat 的独特元素。

        参数:

        输入:将被视为一维。

        sort:对唯一值进行排序(可选)。

        这种功能的实现非常简单,但是,以下仅适用于单通道 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;
        }
        

        示例:

        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;
        

        输出:

        1 3 5 7 9 30 50 70 90 
        

        【讨论】:

        • 你为什么不用std::set
        • @Shai 最初似乎是个好主意,从性能的角度来看它可能更快,因为它保证存储唯一值。它使我放置在代码中的std::find() 变得无用,如果您的cv::Mat 是单通道并且您需要存储一个整数,它会很棒。 然而,如果您需要存储cv::Vec3b(一个像素)或其他复杂的数据类型,std::vector 可能更适合这项工作。 std::set 以特定顺序存储值,并且可能希望以不同的方式重新组织这些值,因此答案为 std::vector
        • 我对@9​​87654333@ 不感兴趣。根据您在存储/订购的角度需要多大的灵活性,std::set 可能就足够了,而且可能是一个更快的解决方案。我并不太担心这些答案的表现,因为它是一个与问题无关的主题。一开始我尽量不讲太多细节。
        猜你喜欢
        • 2019-05-04
        • 2011-12-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多