首页 > 其他分享 >opencv 膨胀与腐蚀

opencv 膨胀与腐蚀

时间:2024-07-30 09:28:00浏览次数:12  
标签:title type opencv 腐蚀 dilatation 膨胀 erosion cv 255

腐蚀和膨胀 Erosion/Dilation
erosion/dilation,用白话说,就是让图像亮的区域收缩和扩张.

原理
我们定义一个卷积核矩阵.这个矩阵可以是任何形状的,但通常而言,是矩形或者圆形的.同时要定义一个锚点位置.
用这个卷积核矩阵挨个地划过原始图像矩阵,同时更改锚点位置的像素值.
锚点位置的像素值更改为卷积核矩阵覆盖的有效像素值中的最大值/最小值(分别对应膨胀/腐蚀).
什么叫"有效"像素值呢?就是卷积核中不为0的那些位置.用公式表达的话,即:
在这里插入图片描述
在这里插入图片描述

膨胀和腐蚀,说白了就是个求"卷积核所表示的局部"的最大值最小值的过程.

我们来看一个例子:

import cv2
import numpy as np
def test1():
    img = np.zeros((10,10,1),np.uint8)
    img[3:7,3:7,:] = 255
    img[4:6,4:6,:] = 200
    
    kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
    erosion_dst = cv2.erode(img, kernel1)
    print(erosion_dst)

首先我们创建一个10 x 10的图像,像素如下:

[[  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0 255 255 255 255   0   0   0]
 [  0   0   0 255 200 200 255   0   0   0]
 [  0   0   0 255 200 200 255   0   0   0]
 [  0   0   0 255 255 255 255   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]]

我们创建一个卷积核:

kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))

getStructuringElement api
在这里插入图片描述

三个参数分别为卷积核的形状/大小/锚点位置. 默认锚点在矩阵的中心位置.

形状有三种
在这里插入图片描述

上面代码中我们创建的3 x 3矩形卷积核如下
在这里插入图片描述

用这个卷积核对原始图像做腐蚀后得到的矩阵如下

在这里插入图片描述

即矩阵有如下变化:

[[  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0 255 255 255 255   0   0   0]
 [  0   0   0 255 200 200 255   0   0   0]
 [  0   0   0 255 200 200 255   0   0   0]
 [  0   0   0 255 255 255 255   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]]
 
-->

[[  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0 200 200   0   0   0   0]
 [  0   0   0   0 200 200   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]]

我们考虑第三行第四列img[2,3,:]这个像素.当我们的卷积核矩阵的锚点位置与该像素重合时,我们取周边所有像素的最小值.最小值为0.所以该位置的像素值变为0. 其余位置的像素值同理可求.

我们稍微改一下我们的代码,然后再看一下不同卷积核作用下的不同结果,会理解的更清楚

import cv2
import numpy as np
def test1():
    img = np.zeros((10,10,1),np.uint8)
    img[3:7,3:7,:] = 255
    img[4:6,4:6,:] = 200
    
    kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
    print(kernel1)
    erosion_dst = cv2.erode(img, kernel1)
    print(erosion_dst)

def test2():
    img = np.zeros((10,10,1),np.uint8)
    img[3:7,3:7,:] = 255
    img[4:6,4:6,:] = 200
    img[2,4,:] = 100
    
    kernel1 = cv2.getStructuringElement(cv2.MORPH_RECT,(3,3))
    erosion_dst = cv2.erode(img, kernel1)
    print(erosion_dst)
    
    kernel2 = cv2.getStructuringElement(cv2.MORPH_CROSS,(3,3))
    erosion_dst2 = cv2.erode(img, kernel2)
    print(erosion_dst2)

test2()

我们把原始图像矩阵改为

[[  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0 100   0   0   0   0   0]
 [  0   0   0 255 255 255 255   0   0   0]
 [  0   0   0 255 200 200 255   0   0   0]
 [  0   0   0 255 200 200 255   0   0   0]
 [  0   0   0 255 255 255 255   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]
 [  0   0   0   0   0   0   0   0   0   0]]

用kernal1时,kernal1如下:
在这里插入图片描述

以第四行,第五列的像素为例,用卷积核的锚点与之对应,此时计算的是其周围八个像素的最小值,最小值为0.
所以我们得到的矩阵为
在这里插入图片描述

当我们用kernal2时,kernal2如下:
在这里插入图片描述

对第四行,第五列的像素,用卷积核的锚点与之对应,此时计算的不再是周围八个像素的最小值,而是其正上方,正下方,正左边,正右边的四个像素的最小值.该值为100.
所以我们得到的矩阵为
在这里插入图片描述

opencv示例
from future import print_function
import cv2 as cv
import numpy as np
import argparse

erosion_size = 0
max_elem = 2
max_kernel_size = 21

title_trackbar_element_type = 'Element:\n 0: Rect \n 1: Cross \n 2: Ellipse'
title_trackbar_kernel_size = 'Kernel size:\n 2n +1'
title_erosion_window = 'Erosion Demo'
title_dilatation_window = 'Dilation Demo'

def erosion(val):
    erosion_size = cv.getTrackbarPos(title_trackbar_kernel_size, title_erosion_window)
    erosion_type = 0
    val_type = cv.getTrackbarPos(title_trackbar_element_type, title_erosion_window)
    if val_type == 0:
        erosion_type = cv.MORPH_RECT
    elif val_type == 1:
        erosion_type = cv.MORPH_CROSS
    elif val_type == 2:
        erosion_type = cv.MORPH_ELLIPSE
    element = cv.getStructuringElement(erosion_type, (2*erosion_size + 1, 2*erosion_size+1), (erosion_size, erosion_size))
    erosion_dst = cv.erode(src, element)
    cv.imshow(title_erosion_window, erosion_dst)
    
def dilatation(val):
    dilatation_size = cv.getTrackbarPos(title_trackbar_kernel_size, title_dilatation_window)
    dilatation_type = 0
    val_type = cv.getTrackbarPos(title_trackbar_element_type, title_dilatation_window)
    if val_type == 0:
        dilatation_type = cv.MORPH_RECT
    elif val_type == 1:
        dilatation_type = cv.MORPH_CROSS
    elif val_type == 2:
        dilatation_type = cv.MORPH_ELLIPSE
    element = cv.getStructuringElement(dilatation_type, (2*dilatation_size + 1, 2*dilatation_size+1), (dilatation_size, dilatation_size))
    dilatation_dst = cv.dilate(src, element)
    cv.imshow(title_dilatation_window, dilatation_dst)

src = cv.imread("/home/sc/disk/keepgoing/opencv_test/j.png")
cv.namedWindow(title_erosion_window)
cv.createTrackbar(title_trackbar_element_type, title_erosion_window , 0, max_elem, erosion)
cv.createTrackbar(title_trackbar_kernel_size, title_erosion_window , 0, max_kernel_size, erosion)

cv.namedWindow(title_dilatation_window)
cv.createTrackbar(title_trackbar_element_type, title_dilatation_window , 0, max_elem, dilatation)
cv.createTrackbar(title_trackbar_kernel_size, title_dilatation_window , 0, max_kernel_size, dilatation)

erosion(0)
dilatation(0)
cv.waitKey()

通过createTrackbar在窗口上创建两个bar,方便我们看不同种类不同大小的卷积核的影响.

cv.createTrackbar(title_trackbar_element_type, title_erosion_window , 0, max_elem, erosion)
cv.createTrackbar(title_trackbar_kernel_size, title_erosion_window , 0, max_kernel_size, erosion)

原始图片:
在这里插入图片描述

处理效果:
在这里插入图片描述

标签:title,type,opencv,腐蚀,dilatation,膨胀,erosion,cv,255
From: https://blog.csdn.net/m0_37302966/article/details/140763357

相关文章

  • 从opencv视频文件夹中读取并提取关键点
    我的文件夹中有一个视频列表(每个视频10秒),我试图循环遍历每个动作视频以提取关键点并将它们保存为json文件。path="pathtovideofolder"forfileinos.listdir(path):cap=cv2.VideoCapture(path+file)whilecap.isOpened():try:ret,frame=cap.......
  • Python OpenCV - 显示坏像素检查测试
    我想找到显示器中存在的每个坏像素。坏像素可能是颜色不正确的像素,或者像素只是黑色。显示屏的尺寸为160x320像素。所以如果显示效果好的话,必须有160*320=51200像素。如果显示器没有51200像素,那就是坏的。另外,我想知道每个坏像素的位置。一旦拍摄的图像太大,我将共享一个......
  • 基于opencv的特征值分类
    opencv可以很方便对图像求hog特征值,然后使用SVM进行分离,最终达到特定物体识别的功能。下面的示例#include<opencv2/opencv.hpp>#include"opencv2/core/core.hpp"#include"opencv2/highgui/highgui.hpp"#include<opencv2/imgproc/imgproc.hpp>#include<opencv2/cor......
  • 如何在 OpenCV 中检测部分被遮挡的圆形标记?
    我正在开发一个项目,涉及使用OpenCV检测地图上的圆形标记(图钉)。标记有时部分连接到街道,这使得使用标准轮廓过滤方法很难检测到它们。我尝试了几种方法来改进检测,包括:形态操作:我使用了cv2.morphologyEx、cv2.erode和cv2.dilate具有不同的内核大小。然而,这些方法要......
  • 有没有办法在Python中使用OpenCV在边界框后面画一条线?
    我正在为我的本科论文编写一个应用程序,该应用程序从根本上允许使用OpenCV库跟踪视频源中的多个对象。为了进一步发展这个想法,我希望能够在屏幕上画一条线,显示边界框在我正在跟踪的对象周围的历史记录。我注意到没有排序用于执行此操作的内置函数,因此任何有关制作此类内容的......
  • OpenCV aruco 标记检测不起作用
    我想在OpenCV中检测图像中的aruco标记。我的OpenCV版本是4.8.0。看起来它已被其他一些功能取代,我找不到任何指南。感谢您的帮助!#programtodetectarucomarkerswithopencv24.8.0versionimportcv2importnumpyasnp#dictionaryofarucomarkersaruco_dict=......
  • OpenCV 计算图像上的三角形
    我们如何计算该图像中的三角形:首先,我们需要消除颜色噪声。然后我们可以尝试cv2.Canny和cv2.findCountours。但是cv2.findCountours如何区分各个交叉形状?我尝试了这个:img=cv2.fastNlMeansDenoisingColored(img,None,6,6)kernel=cv2.getStructurin......
  • Python 和 OpenCV:如何裁剪半成形边界框
    我有一个为无网格表创建网格线的脚本:脚本之前:脚本之后:是否有一种简单的方法,使用OpenCV来裁剪“脚本之后”图像,使其仅包含四边边界框?示例输出:编辑:我目前正在研究一种解决方案,该解决方案可以找到垂直/水平方向的第一条/最后一条......
  • Opencv学习项目4——手部跟踪
    主要是使用opencv和mediapipe库来实现手部跟踪,首先我们先介绍一下mediapipe库mediapipe库介绍MediaPipe是一个由Google开发的开源框架,用于构建基于机器学习的应用程序,特别是涉及实时数据处理和传感的应用。它提供了一套工具和库,使开发者可以轻松地构建复杂的多媒体处理......
  • vs2022 QT Opencv用到的一些代码
     MyFirstQT.cpp#include"MyFirstQT.h"#include"ui_MyFirstQT.h"#include<QFileDialog>#include<QMessageBox>#include<QPixmap>#include<opencv2/opencv.hpp>#include<QDebug>#include<opencv2/imgp......