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和所选的内核一样简单。

其他例子

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

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

相关推荐
陈嘿萌11 小时前
ACM MM 2026|告别密集交互!ProtoHGF-Net:基于原型超图的RGBT目标检测新范式
图像处理·人工智能·深度学习·目标检测·计算机视觉·学术研究与理论基础
指针向南12 小时前
PDF 转 HTML 免费5种方法,体积0.5%到368%
图像处理·人工智能·计算机视觉·pdf
陕西亿鑫鸿物联技术有限公司14 小时前
传统安防利旧升级实战:如何基于边缘计算接入海康大华IPC构建AI分析系统?
深度学习·计算机视觉·边缘计算·物联网架构·流媒体技术
拜小白14 小时前
【论文解读】Ray-casting MLC:用几何感知光线投射做自训练房间布局估计
深度学习·计算机视觉·全景图
MarkHD1 天前
超分辨率与图像放大:从ESRGAN的纹理重建到UltimateSDUpscale的4K分块实战
人工智能·深度学习·计算机视觉
微尘hjx1 天前
【StrongSort 03】多轨迹算法StrongSort改进点
人工智能·算法·yolo·视觉检测·ultralytics·strongsort·轨迹算法
硅谷秋水2 天前
Agentic World Action Models(AW-0)贡献与不足分析
人工智能·机器学习·计算机视觉·语言模型·机器人
拜小白2 天前
【论文解读】OmniSRNet:畸变感知学习——从单张全向图像恢复房间结构
深度学习·计算机视觉·全景图
工业机器人视觉检测设备2 天前
云汇智能铝制机盖视觉检测设备落地 筑牢汽车零部件装配质量防线
自动化·视觉检测·自动化设备·检测设备
何以解忧唯有撸码2 天前
c# + YOLODotNet+OpenCVSharp 实现物品轨迹追踪
计算机视觉·c#·winform·yolov8·opencvsharp