OpenCV计算机视觉学习(5)——形态学处理(腐蚀膨胀,开闭运算,礼帽黑帽,边缘检测)
如果需要处理的原图及代码,请移步小编的GitHub地址
传送门:请点击我
如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice
形态学操作简单来说,就是改变物体的形状,下面学习一下,首先本文的目录如下:
- 1,定义结构元素
- 2,腐蚀和膨胀
- 3,开运算和闭运算
- 4,礼帽/顶帽,黑帽算法
- 5,梯度运算
- 6,形态学运算 检测边和角点(1,检测边缘 ; 2,检测拐角)
1,定义结构元素
形态学操作的原理:在特殊领域运算形式——结构元素(Structure Element),在每个像素位置上与二值图像对应的区域进行特定的逻辑运算。运算结构是输出图像的相应像素。运算效果取决于结构元素大小内容以及逻辑运算性质。
结构元素:膨胀和腐蚀操作的最基本组成部分,用于测试输出图像,通常要比待处理的图像小很多,二维平面结构元素由一个数值为0或1的矩阵组成。结构元素的原点指定了图像中需要处理的像素范围,结构元素中数值为1的点决定结构元素的领域像素进行膨胀或腐蚀操作时是否需要参与计算。
形态学处理的核心就是定义结构元素,在OpenCV-Python中,可以使用其自带的 getStructuringElement 函数,也可以直接使用 Numpy 的 ndarray 来定义一个结构元素,形象图如下:
下面代码为上图的十字形,代码如下:
#_*_coding:utf-8_*_
import cv2
import numpy as np def show_element():
element_cross = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))
print(element_cross)
element_ellipse = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))
print(element_ellipse)
element_rect = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
print(element_rect)
'''
[[0 0 1 0 0]
[0 0 1 0 0]
[1 1 1 1 1]
[0 0 1 0 0]
[0 0 1 0 0]] [[0 0 1 0 0]
[1 1 1 1 1]
[1 1 1 1 1]
[1 1 1 1 1]
[0 0 1 0 0]] [[1 1 1 1 1]
[1 1 1 1 1]
[1 1 1 1 1]
[1 1 1 1 1]
[1 1 1 1 1]]''' def define_cross_structure():
NpKernel = np.uint8(np.zeros((5, 5)))
for i in range(5):
NpKernel[2, i] = 1
NpKernel[i, 2] = 1
print("NpKernel", NpKernel)
'''
NpKernel [[0 0 1 0 0]
[0 0 1 0 0]
[1 1 1 1 1]
[0 0 1 0 0]
[0 0 1 0 0]]
'''
上面我们自定义了一个结构元素 kernel,先声明一个矩阵,然后对其进行赋值,这种方法灵活但是略显复杂。OpenCV提供了一个函数 也就是上面展示的,可以获取常用结构元素的性质:矩形(包括线形),椭圆(包括圆形)以及十字形。下面具体学习一下此方法
1.1 定义一些基本符号和关系
1,元素
设有一幅图像X,若点 a 在 X 的区域以内,则称 a 为 X 的元素,记做 a 属于 X,如图 6.1所示。
2,B包含于X
设有两幅图像 B, X。对于 B中所有的元素 ai, 都有 ai 属于 X,则称B包含于 (included in)X ,记做 B 属于 X,如图6.2所示。
3,B击中 X
设有两幅图像B, X。若存在这一一个点,它即是B的元素,又是 X 的元素,则称 B 击中(hit)X,记做 B ↑ X,如图6.3所示。
4,B不击中 X
设有两幅图像B, X。若不存在任何一个点,它既是B的元素,又是 X的元素,即 B和 X的交集是空,则称 B 不击中(miss)X,记做 B ∩ X = Φ;其中 ∩ 是集合运算相交的符号,Φ 表示空集,如图6.4所示。
5,补集
设有一幅图像 X,所有 X 区域以外的点构成的集合称为 X 的补集,记做 Xc,如下图所示。显然,如果B ∩ X = Φ,则 B 在 X的补集内,即 B 属于 Xc。
6,结构元素
设有两幅图像B,X。若X是被处理的对象,而B是用来处理X的,则称B为结构元素(structure element),又被形象的称作刷子。结构元素通常都是一些比较小的图像。
7,对称集
设有一幅图像B,将B中所有元素的坐标取反,即令(x, y)变为(-x, -y),所有这些点构成的新的集合称为B的对称集,记做 Bv,如下图6.6所示。
8,平移
设有一幅图像B,有一个点a(x0, y0),将B平移a后的结果是,把B中所有元素的横坐标加 x0,纵坐标加 y0,即令(x, y)变成(x + x0, y+y0),所有这些点构成新的集合称为B的平移,记做 Ba,如图6.7所示。
1.2 getStructuringElement 方法
getStructuringElement 是OpenCV提供的一个函数,getStructuringElement 的内部并没有什么优化实现,只是封装了一些功能,其原理同样是声明了一个矩阵,然后求形状,指定矩阵的值。而我们只需要直接调用即可。
函数原型如下:
def getStructuringElement(shape, ksize, anchor=None):
参数的意思:
- shape 表示内核的形状,有三种形状可以选择:
——十字形:cv2.getStructuringElement(cv2.MORPH_CROSS,(5,5))
——椭圆:cv2.getStructuringElement(cv2.MORPH_ELLIPSE,(5,5))
——矩形:cv2.getStructuringElement(cv2.MORPH_RECT,(5,5))
- ksize 表示内核的尺寸(n, n)
- anchor 锚点的位置
此函数最终会返回指定形状和尺寸的结构元素。
下面代码实现一下,这里同时展示一下自己写的:
kernel1 = np.ones((3, 3), np.uint8)
kernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) print(kernel1)
print(kernel2)
print(kernel1 == kernel2)
'''
[[1 1 1]
[1 1 1]
[1 1 1]] [[1 1 1]
[1 1 1]
[1 1 1]] [[ True True True]
[ True True True]
[ True True True]]
'''
这里其实再证明一次。
2,腐蚀和膨胀
图像的膨胀(Dilation)和腐蚀(Erosion)是两种基本的形态学运算,主要用来寻找图像中的极大区域和极小区域。其中膨胀类似于“领域扩张”,将图像中的高亮区域或白色部分进行扩张,其运行结果图比原图的高亮区域更大;腐蚀类似于“领域被蚕食”,将图像中的高亮区域或白色部分进行缩减细化,其运行结果图比原图的高亮区域更小。
形态学各种功能实现,都归结为腐蚀 erode 和 膨胀 dilate 的组合,形象理解一下就是腐蚀等于变瘦,膨胀等于变胖,所以下面学习一下腐蚀和膨胀。
注意:腐蚀和膨胀主要针对二值化图像的白色部分。
2.1 腐蚀
腐蚀就是把结构元素B平移a后得到Ba,若Ba包含于X,我们记下这个a点,所有满足上述条件的 a点组成的集合称为X被B腐蚀(Erosion)的结果。
上图 X 是被处理的对象,B是结构元素,不难知道,对于任意一个在阴影部分的点 a,Ba包含于X,所以 X被B腐蚀的结果就是那个阴影部分,阴影部分在 X的范围之内,且比 X小,就像 X 被剥掉了一层似的,这0就是为什么叫腐蚀的原因。
腐蚀的运算符为 “ - ”,其定义如下:
该公式表示图像A用卷积模板B来进行腐蚀处理,通过模板B与图像A进行卷积计算,得到B覆盖区域的像素点最小值,并用这个最小值来替代参考点的像素值。如图所示,将左边的原始图像A腐蚀处理为右边的效果图A-B。
腐蚀:腐蚀会把物体的边界腐蚀掉,卷积核沿着图像滑动,如果卷积核对应的原图的所有像素值为1,那么中心元素就保持原来的值,否则变为零。主要应用在去除白噪声,也可以断开连在一起的物体。
在原图的每一个区域中取最小值,由于是二值化图像,只要有一个点为0,则为0,来达到瘦身的目的。
腐蚀的作用:
- 1,对象大小减少1个像素(3*3)
- 2,平滑对象边缘
- 3,弱化或者分割图像之间的半岛型连接
2.2 膨胀(Dilate)
膨胀可以看做是腐蚀的对偶运算,其定义是:把结构元素B平移 a 后得到 Ba,若Ba击中X,我们记下这个 a 点。所有满足上述条件的 a点组成的集合称为 X被B膨胀的结果。
膨胀的方法是:拿B的中心点和X上的点及X周围的点一个一个的对,如果B上有一个点落在X的范围内,则该点为黑,可以看出X的范围就像X膨胀一圈似的。
图像膨胀的运算符是“⊕”,其定义如下:
这个公式表示用B来对图像A进行膨胀处理,其中B是一个卷积模板或卷积核,其形状可以为正方形或圆形,通过模板B与图像A进行卷及计算,扫描图像中的每一个像素点,用模板元素与二值图像元素做“与”运算,如果都为0,那么目标像素点为0,否则为1。从而计算B覆盖区域的像素点最大值,并用该值替换参考点的像素值实现膨胀。下图是将左边的原始图像A膨胀处理为右边的效果图 A⊕B。
膨胀:卷积核所对应的原图像的像素值只要有一个是1,中心像素值就是1.一般在除噪声,先腐蚀再膨胀,因为腐蚀在去除白噪声的时候也会使图像缩小,所以我们之后要进行膨胀。当然也可以用来将两者物体分开。
膨胀的作用:
- 1,对象大小增加一个像素 (3*3)
- 2,平滑对象边缘
- 3,减少或者填充对象之间的距离
2.3 代码展示
代码如下:
import cv2
import numpy as np def erode_image(img_path):
origin_img = cv2.imread(img_path)
gray_img = cv2.cvtColor(origin_img, cv2.COLOR_BGR2GRAY)
# OpenCV定义的结构元素
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
# 腐蚀图像
eroded = cv2.erode(gray_img, kernel)
# 显示腐蚀后的图像
cv2.imshow('Origin', origin_img)
cv2.imshow('Erode', eroded)
cv2.waitKey(0)
cv2.destroyAllWindows() def dilate_image(img_path):
origin_img = cv2.imread(img_path)
gray_img = cv2.cvtColor(origin_img, cv2.COLOR_BGR2GRAY)
# OpenCV定义的结构元素
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
# 膨胀图像
dilated = cv2.dilate(gray_img, kernel)
# 显示腐蚀后的图像
cv2.imshow('Dilate', dilated)
cv2.waitKey(0)
cv2.destroyAllWindows() if __name__ == '__main__':
img_path = 'origin.jpg'
erode_image(img_path)
dilate_image(img_path)
如上所示,腐蚀和膨胀的处理很简单,只需设置好结构元素,然后分别调用 cv2.erode() 和 cv2.dilate()函数,其中第一个参数为需要处理的图像,第二个是结构元素,返回处理好的图像。
下图从左到右依次是 原图,腐蚀,膨胀(我们可以看出腐蚀是将线条变瘦,膨胀是变胖):
2.4 腐蚀和膨胀的知识点补充
1,可以看做膨胀是将白色区域扩大,腐蚀是将黑色区域扩大。
2,可以不进行灰度处理,对彩色图像进行处理
腐蚀
cv2.erode(src, # 输入图像
kernel, # 卷积核
dst=None,
anchor=None,
iterations=None, # 迭代次数,默认1
borderType=None,
borderValue=None) 膨胀
cv2.dilate(src, # 输入图像
kernel, # 卷积核
dst=None,
anchor=None,
iterations=None, # 迭代次数,默认1
borderType=None,
borderValue=None)
3,开运算和闭运算
开运算和闭运算就是将腐蚀和膨胀按照一定的次序进行处理。但是这两者并不是可逆的,即先开后闭并不能得到原来的图像。
为了获取图像中的主要对象:对一幅二值图连续使用闭运算和开运算,或者消除图像中的噪声,也可以对图像先用开运算后用闭运算,不过这样也会消除一些破碎的对象。
- 开运算:先腐蚀后膨胀,用于移除由图像噪声形成的斑点
- 闭运算:先膨胀后腐蚀,用来连接被误分为许多小块的对象
3.1 开运算
开运算 = 先腐蚀运算,再膨胀运算(看上去把细微连在一起的两块目标分开了)
开运算的效果图如下图所示:
开运算总结:
- (1)开运算能够除去孤立的小点,毛刺和小桥,而总的位置和形状不变。
- (2)开运算是一个基于几何运算的滤波器
- (3)结构元素大小的不同将导致滤波效果的不同
- (4)不同的结构元素的选择导致了不同的分割,即提取出不同的特征。
3.2 闭运算
闭运算=先膨胀运算,再腐蚀运算(看上去将两个细微连接的图封闭在一起)
闭运算的效果如下图所示:
闭运算总结:
- (1)闭运算能够填平小湖(即小孔),弥合小裂缝,而总的位置和形状不变。
- (2)闭运算是通过填充图像的凹角来滤波图像的。
- (3)结构元素大小的不同将导致滤波效果的不同。
- (4)不同结构元素的选择导致了不同的分割。
代码如下:
import cv2
import numpy as np def Open_operation(img_path):
origin_img = cv2.imread(img_path)
gray_img = cv2.cvtColor(origin_img, cv2.COLOR_BGR2GRAY)
# OpenCV定义的结构元素
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 开运算
open = cv2.morphologyEx(gray_img, cv2.MORPH_OPEN, kernel)
# 显示腐蚀后的图像
cv2.imshow('Open', open)
cv2.waitKey(0)
cv2.destroyAllWindows() def Closed_operation(img_path):
origin_img = cv2.imread(img_path)
gray_img = cv2.cvtColor(origin_img, cv2.COLOR_BGR2GRAY)
# OpenCV定义的结构元素
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 闭运算
closed = cv2.morphologyEx(gray_img, cv2.MORPH_CLOSE, kernel)
# 显示腐蚀后的图像
cv2.imshow('Closed', closed)
cv2.waitKey(0)
cv2.destroyAllWindows() def show_origin(origin_path):
# img = cv2.imread(origin_path, )
# 灰度化
img = cv2.imread(origin_path, 0)
cv2.imshow('origin', img)
cv2.waitKey(0)
cv2.destroyAllWindows() if __name__ == '__main__':
# 此图为加了高斯噪声的图片
img_path = 'butterfly_Gaussian.jpg'
show_origin(img_path)
Closed_operation(img_path)
Open_operation(img_path)
效果如下:(分布是原图,开运算的图,闭运算的图)
闭运算用来连接被误分为许多小块的对象,而开运算用于移除由图像噪声形成的斑点。因此,某些情况下可以连续运用这两种运算。如对一幅二值图连续使用闭运算和开运算,将获得图像中的主要读写。同样,如果想消除图像中噪声(即图像中的“小点”),也可以对图像先用开运算后用闭运算,不过这样也会消除一些破碎的对象。
3.3 开运算和闭运算的知识点补充
这里主要补充函数原型
开运算
图像开运算主要使用的函数morphologyEx,它是形态学扩展的一组函数,
其参数cv2.MORPH_OPEN对应开运算。其原型如下:
dst = cv2.morphologyEx(src, cv2.MORPH_OPEN, kernel) 参数dst表示处理的结果,src表示原图像,cv2.MORPH_OPEN表示开运算,kernel表示卷积核 闭运算 图像闭运算主要使用的函数morphologyEx,其原型如下:
dst = cv2.morphologyEx(src, cv2.MORPH_CLOSE, kernel) 参数dst表示处理的结果,src表示原图像, cv2.MORPH_CLOSE表示闭运算,kernel表示卷积核
4,礼帽/顶帽,黑帽算法
礼帽 :原始图像与其进行开运算后的图像进行一个差
黑帽:原始图像与其闭运算后的图像进行一个差
礼帽运算 = 原始图像 - 开运算
黑帽运算 = 闭运算 - 原始图像
代码如下:
import cv2 def hat_algorithm(img_path):
original_img0 = cv2.imread(img_path)
original_img = cv2.imread(img_path, 0) kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) # 定义矩形结构元素
TOPHAT_img = cv2.morphologyEx(original_img, cv2.MORPH_TOPHAT, kernel) # 顶帽运算
BLACKHAT_img = cv2.morphologyEx(original_img, cv2.MORPH_BLACKHAT, kernel) # 黒帽运算 # 显示图像
cv2.imshow("original_img0", original_img0)
cv2.imshow("original_img", original_img)
cv2.imshow("TOPHAT_img", TOPHAT_img)
cv2.imshow("BLACKHAT_img", BLACKHAT_img) cv2.waitKey(0)
cv2.destroyAllWindows() if __name__ == '__main__':
img_path = 'butterfly_Gaussian.jpg'
hat_algorithm(img_path)
效果如下:(依次是原图,灰度图图片(两个类似,是因为我将原图做了灰度化高斯处理,所以灰度化之后和原图类似),顶帽图片,黑帽图片)
该算法可以用于图像识别的预处理,用于图像二值化后取出孤立点,代码如下:
import cv2 def deal_isolated(img_path):
original_img = cv2.imread(img_path, 0)
gray_img = cv2.resize(original_img, None, fx=0.8, fy=0.8,
interpolation=cv2.INTER_CUBIC) # 图形太大了缩小一点 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) # 定义矩形结构元素(核大小为3效果好)
TOPHAT_img = cv2.morphologyEx(gray_img, cv2.MORPH_TOPHAT, kernel) # 顶帽运算
BLACKHAT_img = cv2.morphologyEx(gray_img, cv2.MORPH_BLACKHAT, kernel) # 黒帽运算 bitwiseXor_gray = cv2.bitwise_xor(gray_img, TOPHAT_img) # 显示如下腐蚀后的图像
cv2.imshow("gray_img", gray_img)
cv2.imshow("TOPHAT_img", TOPHAT_img)
cv2.imshow("BLACKHAT_img", BLACKHAT_img)
cv2.imshow("bitwiseXor_gray", bitwiseXor_gray) cv2.waitKey(0)
cv2.destroyAllWindows() if __name__ == '__main__':
img_path = 'lena.jpg'
deal_isolated(img_path)
可以看出,最后效果更加明显了一些:
5,梯度运算
梯度 = 膨胀 - 腐蚀
下面看一个示例:
import cv2
import numpy as np
import matplotlib.pyplot as plt img = cv2.imread('circle.jpg')
kernel = np.ones((7, 7), np.uint8)
# kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7, 7)) erosion = cv2.erode(img, kernel, iterations = 5)
dilation = cv2.dilate(img, kernel, iterations = 3)
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel) result = [img, erosion, dilation, gradient]
titles = ['origin img', 'erosion img', 'dilate img', 'gradient img']
for i in range(4):
plt.subplot(2, 2, i+1), plt.imshow(result[i])
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
效果如下:
6,用形态学运算检测边和角点
这里通过一个较复杂的例子学习如何用形态学算子检测图像中的边缘和拐角(这里只做形态学处理例子,实际使用请参考Canny和Harris等算法:请参考博文:深入学习OpenCV中几种图像边缘检测算子)
6.1 检测边缘
形态学检测边缘的原理很简单,在膨胀时,图像中的物体会向周围“扩张”;腐蚀时,图像的额物体会“收缩”。比较两幅图像,由于其变化的区域只发生在边缘。所以这时将这两幅图像相减,得到的就是图像中的边缘。这里用的依然是参考资料《Opencv2 Computer Vision Application Programming Cookbook》中相关章节的图片:
代码如下:
# coding=utf-8
import cv2
import numpy def detection_edge(img_path):
image = cv2.imread(img_path, 0)
# 构造一个3×3的结构元素
element = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
dilate = cv2.dilate(image, element)
erode = cv2.erode(image, element) # 将两幅图像相减获得边,第一个参数是膨胀后的图像,第二个参数是腐蚀后的图像
# cv2.absdiff参数:(膨胀后的图像,腐蚀后的图像)
result = cv2.absdiff(dilate, erode) # 上面得到的结果是灰度图,将其二值化以便更清楚的观察结果
retval, result = cv2.threshold(result, 40, 255, cv2.THRESH_BINARY)
# 反色,即对二值图每个像素取反
result = cv2.bitwise_not(result)
# 显示图像
cv2.imshow("result", result)
cv2.waitKey(0)
cv2.destroyAllWindows() if __name__ == '__main__':
img_path = "building.jpg"
detection_edge(img_path)
结果如下:
6.2 检测角点(拐角)
与边缘检测不同,拐角的检测过程稍稍有些复杂。但是原理相同,所不同的是先用十字形的结构元素膨胀像素,这种情况下只会在边缘处“扩张”,角点不发生变化。接着用菱形的结构元素腐蚀原图像,导致只有在拐角处才会“收缩”,而直线边缘都未发生变化。
第二步是用X行膨胀原图像,焦点膨胀的比边要多。这样第二次用方块腐蚀时,角点恢复原状,而边要腐蚀的更多。所以当两幅图像相减时,只保留了拐角处,示意图如下(示意图来自参考资料《Opencv2 Computer Vision Application Programming Cookbook》):
代码如下:
# coding=utf-8
import cv2
import numpy def detection_inflexion(img_path):
image = cv2.imread(img_path, 0)
origin = cv2.imread(img_path)
# 构造5×5的结构元素,分别为十字形、菱形、方形和X型
cross = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))
# 菱形结构元素的定义稍麻烦一些
diamond = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
diamond[0, 0] = 0
diamond[0, 1] = 0
diamond[1, 0] = 0
diamond[4, 4] = 0
diamond[4, 3] = 0
diamond[3, 4] = 0
diamond[4, 0] = 0
diamond[4, 1] = 0
diamond[3, 0] = 0
diamond[0, 3] = 0
diamond[0, 4] = 0
diamond[1, 4] = 0
square = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
x = cv2.getStructuringElement(cv2.MORPH_CROSS, (5, 5))
# 使用cross膨胀图像
dilate_cross_img = cv2.dilate(image, cross)
# 使用菱形腐蚀图像
erode_diamond_img = cv2.erode(dilate_cross_img, diamond) # 使用X膨胀原图像
dilate_x_img = cv2.dilate(image, x)
# 使用方形腐蚀图像
erode_square_img = cv2.erode(dilate_x_img, square) # result = result1.copy()
# 将两幅闭运算的图像相减获得角
result = cv2.absdiff(erode_square_img, erode_diamond_img)
# 使用阈值获得二值图
retval, result = cv2.threshold(result, 40, 255, cv2.THRESH_BINARY) # 在原图上用半径为5的圆圈将点标出。
for j in range(result.size):
y = int(j / result.shape[0])
x = int(j % result.shape[0]) if result[x, y] == 255:
cv2.circle(image, (y, x), 5, (255, 0, 0)) cv2.imshow("Result", image)
cv2.waitKey(0)
cv2.destroyAllWindows() if __name__ == '__main__':
img_path = "building.jpg"
detection_inflexion(img_path)
通过上面的代码就能检测出图像的拐角并标出来,效果如下:
当然这个只是一个示例,效果不是很好。
参考文献:https://www.cnblogs.com/ssyfj/p/9276999.html
https://blog.csdn.net/wsp_1138886114/article/details/82917661
https://blog.csdn.net/JohinieLi/article/details/81041276
https://blog.csdn.net/hanshanbuleng/article/details/80657148
1、《Opencv2 Computer Vision Application Programming Cookbook》
2、《OpenCV References Manule》
最初的来源: https://blog.csdn.net/sunny2038/article/details/9137759
https://blog.csdn.net/gbxvip/article/details/50844007
OpenCV计算机视觉学习(5)——形态学处理(腐蚀膨胀,开闭运算,礼帽黑帽,边缘检测)的更多相关文章
- OpenCV探索之路(四):膨胀、腐蚀、开闭运算
腐蚀和膨胀是最基本的形态学运算. 腐蚀和膨胀是针对白色部分(高亮部分)而言的. 膨胀就是对图像高亮部分进行"领域扩张",效果图拥有比原图更大的高亮区域:腐蚀是原图中的高亮区域被蚕食 ...
- OpenCV计算机视觉学习(13)——图像特征点检测(Harris角点检测,sift算法)
如果需要处理的原图及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice 前言 ...
- OpenCV笔记(2)(高斯平滑、腐蚀和膨胀、开闭运算、礼帽和黑帽、Sobel及其他算子)
一.高斯平滑(模糊) def gaussian_blur(image): # 设置ksize来确定模糊效果 img = cv.GaussianBlur(image, (5, 5), 0) cv.ims ...
- OpenCV3编程入门笔记(4)腐蚀、膨胀、开闭运算、漫水填充、金字塔、阈值化、霍夫变换
腐蚀erode.膨胀dilate 腐蚀和膨胀是针对图像中的白色部分(高亮部分)而言的,不是黑色的.除了输入输出图像外,还需传入模板算子element,opencv中有三种可以选择:矩形MORPH_RE ...
- Python 图像处理 OpenCV (10):图像处理形态学之顶帽运算与黑帽运算
前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 「Python ...
- OpenCV计算机视觉学习(10)——图像变换(傅里叶变换,高通滤波,低通滤波)
如果需要处理的原图及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice 在数 ...
- OpenCV计算机视觉学习(2)——图像算术运算 & 掩膜mask操作(数值计算,图像融合,边界填充)
在OpenCV中我们经常会遇到一个名字:Mask(掩膜).很多函数都使用到它,那么这个Mask到底是什么呢,下面我们从图像基本运算开始,一步一步学习掩膜. 1,图像算术运算 图像的算术运算有很多种,比 ...
- OpenCV计算机视觉学习(12)——图像量化处理&图像采样处理(K-Means聚类量化,局部马赛克处理)
如果需要处理的原图及代码,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPractice 准备 ...
- OpenCV计算机视觉学习(1)——图像基本操作(图像视频读取,ROI区域截取,常用cv函数解释)
1,计算机眼中的图像 我们打开经典的 Lena图片,看看计算机是如何看待图片的: 我们点击图中的一个小格子,发现计算机会将其分为R,G,B三种通道.每个通道分别由一堆0~256之间的数字组成,那Ope ...
随机推荐
- cannary
canary是Linux为防止栈溢出的一种保护机制,接着我们分析glibc对canary的实现过程,首先给出跟canary相关的调用栈: security_init() //在elf/rtld.c中 ...
- shell 逻辑判断
|| && 查了 Stack Overflow ||,表示或,从前往后执行,执行第一个真 &&,前者是真才会接着执行 ; 表示接着往下执行,不管前者如何 #!/bin/ ...
- 通俗理解线性回归(Linear Regression)
线性回归, 最简单的机器学习算法, 当你看完这篇文章, 你就会发现, 线性回归是多么的简单. 首先, 什么是线性回归. 简单的说, 就是在坐标系中有很多点, 线性回归的目的就是找到一条线使得这些点都在 ...
- cmd运行SpringBoot的jar中文乱码
问题: 通过以下命令启动springBoot项目后,在项目中查看日志,发现中文乱码 java -jar projectName.jar 解决 启动时添加参数-Dfile.encoding=UTF-8即 ...
- oracle之二redo日志
redo 日志 4.1 redo (重做) log 的功能:数据recovery4.2 redo log 特征: 1)记录数据库的变化(DML.DDL) 2)用于数据块的recover ...
- Windows提示80被占用
情景:使用cmd启动某一服务的时候报错[emerg] 7220#6900: bind() to 0.0.0.0:80 failed (10013: An attempt was made to acc ...
- hystrix(1) 概述
首先我们来讲一下hystrix解决什么问题.在大型分布式系统中经常会存在下面的几类问题: 1.大型分布式系统中,服务之间相互依赖,如果依赖的服务发生异常,那么当前服务也会出现异常,这样将会导致联级的服 ...
- 手把手教你配置git和git仓库
今天是git专题的第二篇,我们来介绍一下git的基本配置,以及建立一个git仓库的基本方法. 首先申明一点,本文不会介绍git的安装.一方面是大部分个人PC的系统当中都是已经装好了git的,另外一方面 ...
- Java审计之命令执行篇
Java审计之命令执行篇 0x00 前言 在Java中能执行命令的类其实并不多,不像php那样各种的命令执行函数.在Java中目前所知的能执行命令的类也就两种,分别是Runtime和 ProcessB ...
- Java Web学习(九)网络协议详解
一.基本概念 概念:协议是网络中计算机或设备之间进行通信的一系列规则的集合. 协议栈/族:在网络中为了完成通信而使用到的多层上的各种协议按照层次顺序的组合. 作用:建立对等层之间的虚拟通信.实现层次之 ...