首页 文章

OpenCV不规则形状的直方图

提问于
浏览
2

我对OpenCV比较陌生 . 我想知道是否有可能获得findcontour找到的轮廓(可以是完美的矩形或不规则形状)的直方图 .

提前致谢 .

编辑:

这正是我想要实现的目标 . 我想分析轮廓区域以检测缺陷(通过分析区域的直方图?)并声明零件缺陷或良好 . 附图像 .

好样品 . (检测到的轮廓以灰色标出)

enter image description here

样品有缺陷 . (左上角有缺陷)

enter image description here

2 回答

  • 1

    您可能会滥用直方图 .

    Contour 的图像应该是二进制值的无色矩阵 which does not represent grayscale-level of pixels, but the boundaries . 同时, histogram 是一个用于分析像素的灰度值如何在2D图像中分布的工具,不是吗?

    那么,为什么要分析二进制值矩阵的 histogram ,这可能无法帮助您分析图像?然而,直方图不是轮廓分析的正确选择 .

    你可以从直方图得到的只是一个双条直方图,因为轮廓矩阵只包含二进制值 . 这可能对分析没有帮助 .

  • 1

    这是另一种方式,使用形态学操作 .

    #include <string>
    #include <iostream>
    #include "opencv2/imgproc/imgproc.hpp"
    #include "opencv2/highgui/highgui.hpp"
    
    cv::Mat make_element(int morph_size, int elem_type)
    {
        cv::Size sz{2*morph_size+1, 2*morph_size+1};
        cv::Point pt{morph_size, morph_size};
        cv::Mat element{getStructuringElement(elem_type, sz, pt)};
        return element;
    }
    
    int main(int argc, char **argv)
    {
        std::string fn{argv[1]};
        cv::Mat src{cv::imread(fn)}, dst, mask[3];
    
        if (!src.data) {
            std::cerr << "No image data :(" << std::endl;
            return -1;
        }
    
        // Clean out noise
        cv::Mat elem1{make_element(5, cv::MORPH_RECT)};
        cv::morphologyEx(src, dst, cv::MORPH_OPEN, elem1);
    
        // Close the hole, then XOR with original
        cv::Mat elem2{make_element(45, cv::MORPH_ELLIPSE)};
        morphologyEx(dst, dst, cv::MORPH_CLOSE, elem2);
        cv::bitwise_xor(src, dst, dst);
    
        // Clean out noise (again)
        cv::Mat elem3{make_element(1, cv::MORPH_RECT)};
        cv::morphologyEx(dst, dst, cv::MORPH_OPEN, elem3);
    
        // Mark the hole
        cv::split(dst, mask);
        cv::bitwise_xor(src, dst, dst, mask[0]);
    
        // Overlay
        cv::split(dst, mask);
        cv::Mat empty{dst.size(), CV_8UC1};
        std::vector<cv::Mat> v{empty, empty, mask[0]};
        cv::merge(v, dst);
        cv::bitwise_or(src, dst, dst);
    
        cv::namedWindow("Defect (ESC to quit)", cv::WINDOW_NORMAL);
        cv::startWindowThread();
        cv::imshow("Defect (ESC to quit)", dst);
        while (true) {
            int k = cv::waitKey(100) & 0xff;
            if (k == 27) {
                break;
            }
        }
        cv::destroyAllWindows();
    
        return 0;
    };
    

    一些额外的阅读:

相关问题