1. 目标
在本文中,将学习如何使用 Hit-or-Miss 变换(也称为 Hit-and-Miss 变换)在二进制图像中找到匹配的配置或模式。这种变换也是更高级的形态学操作(例如细化或修剪)的基础。
将使用 OpenCV 函数morphologyEx()。
2. Hit-or-Miss理论
形态学算子根据图像的形状处理图像。这些运算符将一个或多个结构元应用于输入图像以获得输出图像。两个基本的形态学运算是腐蚀和膨胀。这两个操作的组合生成高级形态变换,例如开运算、闭运算或顶帽变换。要了解更多关于这些和其他基本形态学操作的信息,请参阅之前的文章(腐蚀和膨胀)和(更多形态学变换)。
Hit-or-Miss 变换对于查找二值图像中的模式很有用。特别是,它找到那些邻域与第一个结构元的形状相匹配的像素而同时与第二个结构元的形状不匹配。在数学上,在图像A上的Hit-or-Mis操作表示如下:
因此,hit-or-miss 操作包括三个步骤:
- 用结构元腐蚀图像A.
- 用结构元腐蚀 图像A的补集 ().
- 取第 1 步和第 2 步交集作为结果。
结构元和可以组合成一个结构元B. 看一个例子:
结构元素(内核)。左:要“hit”的内核B1。中间:“miss”内核B2。右:最终组合内核
在这种情况下,查找的模式是其中中心像素属于背景,而北、南、东、西像素属于前景。邻域中的其余像素可以是任何类型的(在图像上用灰色表示),在匹配的时候忽略它们。现在,将此内核应用于输入图像:
输入二值图像
输出二值图像
可以看到在该图像上仅找到一个匹配的位置。
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. 其他示例
在这里,可以找到将不同内核应用于之前使用的相同输入图像的输出结果:
原图
查找右上角的内核和输出结果
查找左端点的内核和输出结果
现在可以试试你自己的模式!