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

其他例子

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

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

相关推荐
H__Rick2 天前
自动对焦学习-3
人工智能·学习·计算机视觉
计算机科研狗@OUC2 天前
(cvpr26) AIMDepth: Asymmetric Image-Event Mamba for Monocular Depth Estimation
人工智能·深度学习·计算机视觉
qq_366566502 天前
2026最新:5款AI视频口型同步工具实测横评,视频翻译后嘴型对不上的终极解决方案
人工智能·计算机视觉·新媒体运营
梦想三三2 天前
OpenCV银行卡数字识别项目(图像预处理与字符分割)
人工智能·opencv·计算机视觉
双翌视觉2 天前
机器视觉系统为何离不开光学滤光片?
人工智能·数码相机·视觉检测·制造
kaikaile19952 天前
图像稀疏化分解 + 压缩感知(CS)重建 MATLAB
开发语言·计算机视觉·matlab
武子康2 天前
调查研究-180 roboflow/supervision:计算机视觉工程里的“胶水层“,为什么值得关注?
人工智能·opencv·计算机视觉·chatgpt·llm·向量化
YOLO数据集集合2 天前
无人机风电设备智能巡检 风机叶片缺陷目标检测数据集实战 | 表面腐蚀漏油识别 工业视觉质检 深度学习模型训练落地10337期
人工智能·深度学习·目标检测·计算机视觉·无人机
装不满的克莱因瓶2 天前
【工业领域】了解目标检测基本流程——从数据到部署的完整工程化思路
人工智能·python·深度学习·机器学习·计算机视觉·目标跟踪·工业领域