二、 OpenCV之腐蚀与膨胀操作

一、腐蚀操作

"""
腐蚀操作是一种基本的形态学操作,其主要目的是消除图像中的边界点,使图像沿着边界向内收缩,同时去除小于指定结构体元素的部分。

在腐蚀操作中,通常会将二值图像中亮度高的部分(通常是白色部分)向内腐蚀。为了进行腐蚀操作,需要一个卷积核(也称为“结构元”),
它决定了腐蚀或膨胀的大小。卷积核可以由cv2.getStructuringElement()函数生成,也可以使用numpy库生成。卷积核的大小决定了形态学处理的面积和强度。
erode(src, kernel, iterations) src: 输入图像, 通常是二值图像 kernel: 结构元素,可以是一个矩阵,椭圆形或者其他形状,可以使用 cv2.getStructuringElement() 来生成一个结构元素 iterations: 腐蚀操作的次数 np.ones((num, num), type) np.ones((5, 5), uint) # 创建一个形状为(5, 5) 的二维数组,所有元素都是1,类型是整数 np.ones(5) # 创建一个长度为5的一维数组, 所有元素都是1 np.ones(3, 4) # 创建一个形状为 (3, 4) 的二维数组,所有元素都是 1 np.hstack((arg1, arg2, 。。。)) 用于在水平方向上将参数堆叠在一起 a = np.array([1, 2, 3]) b = np.array([4, 5, 6]) np.hstack((a, b)) --> [1, 2, 3, 4, 5, 6] c = np.array([[1, 2], [3, 4]]) d = np.array([[5, 6], [7, 8]]) np.hstack((c, d)) -- > [[1,2, 5, 6] [3, 4, 7, 8]]
""" import cv2 import numpy as np def cv_show(name, img): # 显示图片, 也可以创建多个窗口,在窗口上显示图片 cv2.imshow(name, img) # 第一个参数代表图像名称,第二个参数代表图像 # 等待时间,毫秒级, 0 代表任意终止,按任意键关闭 cv2.waitKey(0) # 关闭窗口 cv2.destroyAllWindows() img = cv2.imread("../images/dige.png") kernel = np.ones((5, 5), np.uint8) # print(kernel.shape) # (5, 5) erosion = cv2.erode(img, kernel, iterations=1) res = np.hstack((img, erosion)) cv_show("erosion", res)

 

pie = cv2.imread("../images/pie.png")
kernel = np.ones((20, 20), np.uint8)
erosion_1 = cv2.erode(pie, kernel, iterations=1)
erosion_3 = cv2.erode(pie, kernel, iterations=3)
res = np.hstack((pie, erosion_1, erosion_3))
cv_show("res", res)

二、膨胀操作

"""
在OpenCV库中,膨胀操作(Dilation)是一种图像处理技术,用于增加图像中白色区域(即高亮区域)的大小,或者填充图像中的小孔和裂缝。这个操作通常用于加强图像中的特征,消除小的噪声,以及连接相邻的物体。

膨胀操作可以通过cv2.dilate()函数来实现。与腐蚀操作类似,膨胀操作也需要一个卷积核(也称为结构元素)来定义膨胀的大小和形状。这个核通常是一个正方形的矩阵,其中的值可以是1或0,用于确定哪些像素应该被包含在膨胀操作中。
"""
import cv2
import numpy as np


def cv_show(name, img):
    # 显示图片, 也可以创建多个窗口,在窗口上显示图片
    cv2.imshow(name, img)  # 第一个参数代表图像名称,第二个参数代表图像
    # 等待时间,毫秒级, 0 代表任意终止,按任意键关闭
    cv2.waitKey(0)
    # 关闭窗口
    cv2.destroyAllWindows()


img = cv2.imread("../images/dige.png")
# cv_show("img", img)

# 腐蚀操作
kernel = np.ones((3, 3), np.uint8)
erosion = cv2.erode(img, kernel, iterations=1)
# cv_show("erosion", erosion)

# 膨胀操作
dilate = cv2.dilate(erosion, kernel, iterations=1)
# cv_show("dilate", dilate)
res = np.hstack((img, erosion, dilate))
cv_show("res", res)

pie = cv2.imread("../images/pie.png")
kernel = np.ones((30, 30), np.uint8)
dilate_1 = cv2.dilate(pie, kernel, iterations=1)
dilate_3 = cv2.dilate(pie, kernel, iterations=3)
res = np.hstack((pie, dilate_1, dilate_3))
cv_show("res", res)

 

三、开运算与闭运算

"""
开运算,先腐蚀再膨胀
闭运算, 先膨胀再腐蚀
cv2.MORPH_OPEN: 开运算
cv2.MORPH_CLOSE: 闭运算
"""

import cv2
import numpy as np


def cv_show(name, img):
    # 显示图片, 也可以创建多个窗口,在窗口上显示图片
    cv2.imshow(name, img)  # 第一个参数代表图像名称,第二个参数代表图像
    # 等待时间,毫秒级, 0 代表任意终止,按任意键关闭
    cv2.waitKey(0)
    # 关闭窗口
    cv2.destroyAllWindows()


img = cv2.imread("../images/dige.png")
# 开运算,先腐蚀再膨胀, 先把图片的毛刺去掉,然后再恢复成原来的宽度
kernel = np.ones((5, 5), np.uint8)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
res = np.hstack((img, opening))
cv_show("opening", res)

# 闭运算, 先膨胀再腐蚀, 先进行膨胀,毛刺更多,再腐蚀就腐蚀不掉了
img = cv2.imread("../images/dige.png")
kernel = np.ones((5, 5), np.uint8)
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
res = np.hstack((img, closing))
cv_show("opening", res)

四、梯度计算

"""
在OpenCV中,图像梯度指的是图像灰度值变化的速度或速率。对于图像的边缘部分,其两侧灰度值相差较大,因此梯度值也较大。通过计算图像梯度,可以突出图像的边缘信息。
梯度计算 == 膨胀 - 腐蚀 cv2.MORPH_GRADIENT: 梯度计算, 图像的减法操作 """ import cv2 import numpy as np def cv_show(name, img): # 显示图片, 也可以创建多个窗口,在窗口上显示图片 cv2.imshow(name, img) # 第一个参数代表图像名称,第二个参数代表图像 # 等待时间,毫秒级, 0 代表任意终止,按任意键关闭 cv2.waitKey(0) # 关闭窗口 cv2.destroyAllWindows() pie = cv2.imread("../images/pie.png") kernel = np.ones((7, 7), np.uint8) dilate = cv2.dilate(pie, kernel, iterations=5) erosion = cv2.erode(pie, kernel, iterations=5) # 梯度计算 == 膨胀操作 - 腐蚀操作 gradient = cv2.morphologyEx(pie, cv2.MORPH_GRADIENT, kernel) res = np.hstack((dilate, erosion, gradient)) cv_show("gradient", res)

五、礼帽与黑帽

"""
礼帽: 原始输入 - 开运算
黑帽: 闭运算 - 原始输入
cv2.MORPH_TOPHAT: 礼帽
cv2.MORPH_BLACKHAT: 黑帽
"""
import cv2
import numpy as np


def cv_show(name, img):
    # 显示图片, 也可以创建多个窗口,在窗口上显示图片
    cv2.imshow(name, img)  # 第一个参数代表图像名称,第二个参数代表图像
    # 等待时间,毫秒级, 0 代表任意终止,按任意键关闭
    cv2.waitKey(0)
    # 关闭窗口
    cv2.destroyAllWindows()

img = cv2.imread("../images/dige.png")
cv_show("image", img)

# 礼帽  ( 原始输入 - 开运算(先腐蚀没有刺了, 再膨胀)  == 就剩刺了)
kernel = np.ones((7, 7), np.uint8)
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
cv_show("tophat", tophat)

# 黑帽  (闭运算(先膨胀更多刺了,再腐蚀) - 原始输入 == 原始的小轮廓)
img = cv2.imread("../images/dige.png")
blackhat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)
cv_show("blackhat", blackhat)

六、图像梯度算子

6.1 sobel算子

 

"""
图像梯度Sobel算子是计算机视觉领域的一种重要处理方法,主要用于获取数字图像的一阶梯度,常用于边缘检测。是一个离散性查分算子
通过计算图像亮度函数的梯度之近似值来工作。在图像的任何一点使用次算子,都会产生对应的梯度矢量或是其法矢量

sobel算子由两个 3X3的卷积核构成,分别用于计算中心像素邻域的灰度加权差,这两个卷积核分为垂直方向和竖直方向。

当进行边缘检测时,Sobel算子会把图像中每一个像素的上下左右四领域灰度值加权差,在边缘处达到极值从而检测边缘。此外,
在计算法线时,也可以用于计算法线的横向偏移和纵向偏移

cv2.Sobel(src, ddepth, dx, dy, ksize)
ddepth: 图像的深度
dx, dy分别表示水平和竖直方向
ksize是Sobel算子的大小

cv2.addWeighted(src1, alpha, src2, beta, gamma)
src1: 图像1
alpha: 图像1权重
src2: 图像2
beta: 图像2权重
gamma: 添加到加权总和上的标量值
"""
import cv2
import numpy as np


def cv_show(name, img):
    cv2.imshow(name, img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


img = cv2.imread("../images/pie.png")
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
res = np.hstack((img, sobelx))
cv_show("sobelx", res)

# 白到黑是正数,黑到白是负数, 所有的负数都会被截断成0, 所以要取绝对值,所以上图右侧都变成黑色
sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
sobelx_abs = cv2.convertScaleAbs(sobelx)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)
sobely_abs = cv2.convertScaleAbs(sobely)
res = np.hstack((img, sobelx_abs, sobely_abs))
cv_show("sobel_abs", res)

# 分别计算x和y,再求和
sobelx_y = cv2.addWeighted(sobelx_abs, 0.5, sobely_abs, 0.5, 0)
# 不建议直接计算,直接将权重设置为 1,效果不是不如 x + y
sobelx__y = cv2.Sobel(img, cv2.CV_64F, 1, 1, ksize=3)
sobelx__y = cv2.convertScaleAbs(sobelx__y)
res = np.hstack((img, sobelx_y, sobelx__y))
cv_show("sobel_x_y", res)

 

import cv2
import numpy as np


def cv_show(name, img):
    cv2.imshow(name, img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


img = cv2.imread("../images/lena.jpg", cv2.IMREAD_GRAYSCALE)


sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)
sobely = cv2.convertScaleAbs(sobely)
res = np.hstack((img, sobelx, sobely))
cv_show("res", res)

 

sobelx_y = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)  # 直接 x + y
sobelx__y = cv2.Sobel(img, cv2.CV_64F, 1, 1, ksize=3)    # 直接相加
sobelx__y = cv2.convertScaleAbs(sobelx__y)
res = np.hstack((img, sobelx_y, sobelx__y))
cv_show("res_x_y", res)

6.2 Scharr算子与laplacian算子

 

 

"""
Scharr算子


"""
import cv2
import numpy as np


def cv_show(name, img):
    cv2.imshow(name, img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


img = cv2.imread("../images/lena.jpg", cv2.IMREAD_GRAYSCALE)

sobelx = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)
sobely = cv2.Sobel(img, cv2.CV_64F, 0, 1, ksize=3)
sobely = cv2.convertScaleAbs(sobely)
sobelxy = cv2.addWeighted(sobelx, 0.5, sobely, 0.5, 0)

scharrx = cv2.Scharr(img, cv2.CV_64F, 1, 0)
scharrx = cv2.convertScaleAbs(scharrx)
scharry = cv2.Sobel(img, cv2.CV_64F, 0, 1)
scharry = cv2.convertScaleAbs(scharry)
scharrxy = cv2.addWeighted(scharrx, 0.5, scharry, 0.5, 0)

laplacian = cv2.Laplacian(img, cv2.CV_64F)
laplacian = cv2.convertScaleAbs(laplacian)

res = np.hstack((sobelxy, scharrxy, laplacian))
cv_show("res", res)

 

 

posted on 2024-03-11 15:37  软饭攻城狮  阅读(29)  评论(0编辑  收藏  举报

导航