OpenCV不规则形状的直方图

时间:2015-06-01 06:05:38

标签: c++ opencv

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

提前致谢。

编辑:

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

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

enter image description here

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

enter image description here

2 个答案:

答案 0 :(得分:1)

你可能会滥用直方图。

图像的

Contour应该是二进制值,无色矩阵,它不代表灰度级像素,而是边界。 同时,histogram是用于分析像素的灰度值如何在2D图像中分布的工具,不是吗?

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

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

答案 1 :(得分: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;
};

一些额外的阅读: