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

其他例子

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

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

相关推荐
视觉工程师07065 小时前
GRR & CRR怎么测
视觉检测
YOLO数据集集合9 小时前
无人机低空影像语义分割数据集 | 语义分割 遥感影像 无人机低空 地物分类 Potsdam Vaihingen LoveDA 9080期
人工智能·深度学习·yolo·目标检测·计算机视觉·语义分割·无人机数据集
硅谷秋水11 小时前
GE-Act 2.0:面向机器人操作的“世界-动作”模型预训练与扩展
机器学习·计算机视觉·语言模型·机器人
AI Blog14 小时前
YOLO数据集 | 第05期:无人机检测、电力巡检、阀门识别
深度学习·目标检测·计算机视觉·yolo数据集
Evand J21 小时前
【MATLAB例程|图像滤波降噪13】局部噪声方差自适应滤波(LNR)图像降噪与效果展示。附完整例程的下载链接
图像处理·计算机视觉·matlab·滤波·代码·降噪
VisionDataLab1 天前
多SKU混产视觉换型瓶颈根治:免重教、免重调的德成嵌入式视觉配方架构与工程落地
自动化·视觉检测
巡山小钻风来也1 天前
【工业异常检测】PatchCore 完整训练实战指南|Anomalib1.x 从原理、数据集、训练到部署
视觉检测
星野云联AIoT技术洞察1 天前
RK3588 边缘 AI 盒子适合什么工业视觉场景
计算机视觉·边缘计算·rk3588·语音识别·图像识别·边缘网关·边缘计算盒子
这张生成的图像能检测吗1 天前
(论文速读)Cylinder3D:面向室外 LiDAR 分割的柱面划分与非对称 3D 卷积
计算机视觉·点云·3d视觉·三维感知
贾伟康1 天前
【HarmonyOS 7新能力|028】Core Vision Kit工程封装:把接入逻辑放进可维护的分层结构
计算机视觉·harmonyos·arkts·端侧ai·harmonyos 7