OpenCV的查找命中或未命中

返回:OpenCV系列文章目录(持续更新中......)

上一篇:OpenCV4.9更多形态转换

下一篇:OpenCV系列文章目录(持续更新中......)

目标

在本教程中,您将学习如何使用 Hit-or-Miss 转换(也称为 Hit-and-Miss 转换)在二进制映像中查找给定配置或模式。这种变换也是更高级的形态操作(如疏伐或修剪)的基础。

我们将使用OpenCV函数 morphologyEx() .

命中或未命中理论

形态学运算符根据图像的形状处理图像。这些运算符将一个或多个结构化元素 应用于输入图像以获取输出图像。两种基本的形态操作是侵蚀扩张 。这两种操作的组合会产生高级形态转换,例如打开关闭顶帽 转换。要了解有关这些和其他基本形态操作的更多信息,请参阅前面的教程(侵蚀和扩张)和(更多形态转换)。

命中或未命中变换对于查找二进制图像中的模式非常有用。特别是,它找到那些邻域与第一个结构元素B1的形状匹配,但同时与第二个结构元素 B2 的形状不匹配的像素。从数学上讲,应用于图像A的运算可以表示如下:

因此,命中或未命中操作包括三个步骤:

  1. 使用结构元素B1侵蚀图像 A。
  2. 侵蚀图像A(AC)的补码与结构元素(B2)。
  3. AND 来自步骤 1 和步骤 2。

结构元素 B1和 B2 可以组合成一个元素B。让我们看一个例子:

在本例中,我们正在寻找一种模式,其中中心像素属于背景,而北、南、东、西像素属于前景。附近的其余像素可以是任何类型的,我们不关心它们。现在,让我们将此内核应用于输入图像:

您可以看到该图案仅在图像中的一个位置找到。

代码

与上一个示例对应的代码如下所示。
您也可以从这里下载

C++:

cpp 复制代码
#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;
}

Java:

java 复制代码
import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgproc.Imgproc;
 
class HitMissRun{
 
 public void run() {
 Mat input_image = new Mat( 8, 8, CvType.CV_8UC1 );
 int row = 0, col = 0;
 input_image.put(row ,col,
 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 = new Mat( 3, 3, CvType.CV_16S );
 kernel.put(row ,col,
 0, 1, 0,
 1, -1, 1,
 0, 1, 0 );
 
 Mat output_image = new Mat();
 Imgproc.morphologyEx(input_image, output_image, Imgproc.MORPH_HITMISS, kernel);
 
 int rate = 50;
 Core.add(kernel, new Scalar(1), kernel);
 Core.multiply(kernel, new Scalar(127), kernel);
 kernel.convertTo(kernel, CvType.CV_8U);
 
 Imgproc.resize(kernel, kernel, new Size(), rate, rate, Imgproc.INTER_NEAREST);
 HighGui.imshow("kernel", kernel);
 HighGui.moveWindow("kernel", 0, 0);
 
 Imgproc.resize(input_image, input_image, new Size(), rate, rate, Imgproc.INTER_NEAREST);
 HighGui.imshow("Original", input_image);
 HighGui.moveWindow("Original", 0, 200);
 
 Imgproc.resize(output_image, output_image, new Size(), rate, rate, Imgproc.INTER_NEAREST);
 HighGui.imshow("Hit or Miss", output_image);
 HighGui.moveWindow("Hit or Miss", 500, 200);
 
 HighGui.waitKey(0);
 System.exit(0);
 }
}
 
public class HitMiss
{
 public static void main(String[] args) {
 // load the native OpenCV library
 System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
 new HitMissRun().run();
 }
}

Python:

python 复制代码
import cv2 as cv
import numpy as np
 
input_image = np.array((
 [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]), dtype="uint8")
 
kernel = np.array((
 [0, 1, 0],
 [1, -1, 1],
 [0, 1, 0]), dtype="int")
 
output_image = cv.morphologyEx(input_image, cv.MORPH_HITMISS, kernel)
 
rate = 50
kernel = (kernel + 1) * 127
kernel = np.uint8(kernel)
 
kernel = cv.resize(kernel, None, fx = rate, fy = rate, interpolation = cv.INTER_NEAREST)
cv.imshow("kernel", kernel)
cv.moveWindow("kernel", 0, 0)
 
input_image = cv.resize(input_image, None, fx = rate, fy = rate, interpolation = cv.INTER_NEAREST)
cv.imshow("Original", input_image)
cv.moveWindow("Original", 0, 200)
 
output_image = cv.resize(output_image, None , fx = rate, fy = rate, interpolation = cv.INTER_NEAREST)
cv.imshow("Hit or Miss", output_image)
cv.moveWindow("Hit or Miss", 500, 200)
 
cv.waitKey(0)
cv.destroyAllWindows()

正如你所看到的,它就像使用函数morphologyEx() 和操作类型MORPH_HITMISS和所选的内核一样简单。

其他例子

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

现在试试你自己的模式吧!

相关推荐
做cv的小昊11 小时前
结合代码读3DGS论文(10)——ICLR 2025 3DGS加速&压缩新工作Sort-Free 3DGS论文及代码解读
论文阅读·人工智能·游戏·计算机视觉·3d·图形渲染·3dgs
棱镜研途14 小时前
EI会议分享 | 2026年图像处理与模式识别国际会议(IC-IPPR 2026)【SPIE出版】
图像处理·人工智能·深度学习·目标检测·计算机·计算机视觉·视觉检测
不懒不懒14 小时前
【实战案例:基于特征匹配的指纹识别系统开发】
人工智能·opencv·计算机视觉
困死,根本不会16 小时前
OpenCV视觉舵机控制系统:从坐标检测到串口控制完整实现
人工智能·opencv·计算机视觉
Fleshy数模16 小时前
基于OpenCV实现指纹识别与验证:原理与实战
人工智能·opencv·计算机视觉
CoovallyAIHub17 小时前
AAAI 2026 | 华中科大联合清华等提出Anomagic:跨模态提示零样本异常生成+万级AnomVerse数据集(附代码)
深度学习·算法·计算机视觉
cv2016_DL18 小时前
MLLM逆袭传统检测器!Rex-Omni:用Next Point Prediction实现高精度通用目标检测
人工智能·目标检测·计算机视觉
光羽隹衡18 小时前
计算机视觉——Opencv(摄像头实时风格迁移)
人工智能·opencv·计算机视觉
CoovallyAIHub20 小时前
编码智能体做 CV 任务,实际能力到哪一步了?——五项视觉任务实测解读
深度学习·算法·计算机视觉
听风吹等浪起20 小时前
ResNet模型进阶改进方案完整集合——计算机视觉从业者的结构化性能增强工具箱
人工智能·计算机视觉