opencv基础:形态学击中和击不中

454 阅读2分钟

1. 目标

在本文中,将学习如何使用 Hit-or-Miss 变换(也称为 Hit-and-Miss 变换)在二进制图像中找到匹配的配置或模式。这种变换也是更高级的形态学操作(例如细化或修剪)的基础。

将使用 OpenCV 函数morphologyEx()

2. Hit-or-Miss理论

形态学算子根据图像的形状处理图像。这些运算符将一个或多个结构元应用于输入图像以获得输出图像。两个基本的形态学运算是腐蚀膨胀。这两个操作的组合生成高级形态变换,例如开运算闭运算顶帽变换。要了解更多关于这些和其他基本形态学操作的信息,请参阅之前的文章(腐蚀和膨胀)和(更多形态学变换)。

Hit-or-Miss 变换对于查找二值图像中的模式很有用。特别是,它找到那些邻域与第一个结构元B1B_1的形状相匹配的像素而同时与第二个结构元B2B_2的形状不匹配。在数学上,在图像A上的Hit-or-Mis操作表示如下:

AB=(AB1)(AcB2)A⊛B=(A\ominus B_1) \cap (A^c \ominus B_2)

因此,hit-or-miss 操作包括三个步骤:

  1. 用结构元B1B_1腐蚀图像A.
  2. 用结构元B2B_2腐蚀 图像A的补集 (AcA^{c}).
  3. 取第 1 步和第 2 步交集作为结果。

结构元B1B_1B2B_2可以组合成一个结构元B. 看一个例子:

hitmiss_kernels.png

结构元素(内核)。左:要“hit”的内核B1。中间:“miss”内核B2。右:最终组合内核

在这种情况下,查找的模式是其中中心像素属于背景,而北、南、东、西像素属于前景。邻域中的其余像素可以是任何类型的(在图像上用灰色表示),在匹配的时候忽略它们。现在,将此内核应用于输入图像:

hitmiss_input.png

输入二值图像

hitmiss_output.png

输出二值图像

可以看到在该图像上仅找到一个匹配的位置。

3. 代码

与上一个示例对应的代码如下所示。

可以从这里下载


#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
int main(){
    Mat input_image = (Mat_<uchar>(8, 8) <<
        0, 0, 0, 0, 0, 0, 0, 0,
        0, 255, 255, 255, 0, 0, 0, 255,
        0, 255, 255, 255, 0, 0, 0, 0,
        0, 255, 255, 255, 0, 255, 0, 0,
        0, 0, 255, 0, 0, 0, 0, 0,
        0, 0, 255, 0, 0, 255, 255, 0,
        0, 255, 0, 255, 0, 0, 255, 0,
        0, 255, 255, 255, 0, 0, 0, 0);
    Mat kernel = (Mat_<int>(3, 3) <<
        0, 1, 0,
        1, -1, 1,
        0, 1, 0);
    Mat output_image;
    morphologyEx(input_image, output_image, MORPH_HITMISS, kernel);
    const int rate = 50;
    kernel = (kernel + 1) * 127;
    kernel.convertTo(kernel, CV_8U);
    resize(kernel, kernel, Size(), rate, rate, INTER_NEAREST);
    imshow("kernel", kernel);
    moveWindow("kernel", 0, 0);
    resize(input_image, input_image, Size(), rate, rate, INTER_NEAREST);
    imshow("Original", input_image);
    moveWindow("Original", 0, 200);
    resize(output_image, output_image, Size(), rate, rate, INTER_NEAREST);
    imshow("Hit or Miss", output_image);
    moveWindow("Hit or Miss", 500, 200);
    waitKey(0);
    return 0;
}

如上所见,它就像使用具有操作类型MORPH_HITMISS和所选内核的函数morphologyEx()一样简单。

4. 其他示例

在这里,可以找到将不同内核应用于之前使用的相同输入图像的输出结果:

hitmiss_input.png 原图

hitmiss_example2.png 查找右上角的内核和输出结果

hitmiss_example3.png 查找左端点的内核和输出结果

现在可以试试你自己的模式!

原文地址