【OpenCV】 4 图像基本处理(滤波与增强、形态学变化---图像腐蚀、膨胀、开闭运算、顶帽、黑帽)

图像滤波简介

  • 滤波实际上是信号处理得一个概念,图像可以看成一个二维信号,其中像素点的灰度值代表信号的强弱;
  • 高频:图像上变化剧烈的部分;
  • 低频:图像灰度值变化缓慢,平坦的地方;
  • 根据图像高低频,设置高通和低通滤波器。高通滤波器可以检测变化尖锐,明显的地方,低通可以让图像变得平滑,消除噪声;
  • 滤波作用: 高通滤波器用于边缘检测,低通滤波器用于图像平滑去噪
  • 线性滤波:方框滤波/均值滤波/高斯滤波;
  • 非线性滤波:中值滤波/双边滤波;

领域算子:利用给定像素周围的像素值决定此像素的最终输出值的一种算子
在这里插入图片描述

1 线性滤波

1.1 方框滤波cv2.boxFilter(src,depth,ksize,normalize)

函数:cv2.boxFilter(src,depth,ksize,normalize)
src:输入图像;
depth:目标图像深度;
ksize:核大小
normalize:标准化,一般设为1,否则容易溢出
在这里插入图片描述

import cv2
img = cv2.imread('girl2.png', cv2.IMREAD_UNCHANGED)
r = cv2.boxFilter(img, -1, (7, 7), normalize=1)
d = cv2.boxFilter(img, -1, (3, 3), normalize=0) # 不使用Noramlize容易溢出
cv2.namedWindow('img', cv2.WINDOW_NORMAL) # 定义img的窗口可以随意拖动大小
cv2.imshow('img', img), cv2.imshow('r', r), cv2.imshow('d', d)
cv2.waitKey(0);cv2.destroyAllWindows()

1.2 均值滤波cv2.blur(src, ksize)

均值滤波是一种最简单的滤波处理,它取的是卷集合区域内元素的均值;如
在这里插入图片描述

函数:cv2.blur(src, ksize)
src:输入原图
ksize:核大小

# 均值滤波
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('image/opencv.png')
#===== 使用cv2.blur实现均值滤波=====#
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
blur = cv2.blur(img, (3, 3))
# 使用plt显示图像进行对比显示
plt.subplots(121), plt.imshow(img), plt.title('Origin_pic')
plt.subplots(122), plt.imshow(blur), plt.title('Blurred')
plt.xticks([]), plt.yticks([])
plt.show()

1.3 (常用)高斯滤波cv2.Guassianblur(src, ksize, std)

高斯滤波是一种线性平滑滤波,适用于消除高斯噪声。
卷积核权重并不相同,中间像素点权重最高,越远离中心的像素权重越小。其原理是一个2维高斯函数。
比均值滤波效率要慢,但可以有效消除高斯噪声,能保留更多的图像细节。
函数:cv2.Guassianblur(src, ksize, std)
src:输入原图
ksize:高斯核大小
std:标准差,调大后提高远处像素对中心像素的影响程度,滤波结果越平滑

#(重点)高斯滤波
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('image/median.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
#======高斯滤波======#
# 参数1:img;参数2:高斯核大小;参数3:标准差
blur = cv2.GaussianBlur(img, (7, 7), 7)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.xticks([]), plt.yticks([]) # 不显示x,y坐标
plt.subplot(122),plt.imshow(blur),plt.title('Blurred')
plt.show()

2 非线性滤波

2.1 中值滤波cv2.medianBlur(img,ksize)

中值滤波是一种非线性滤波,是用像素点邻域灰度值的中值代替该点的灰度值
中值滤波可以去除椒盐噪声和斑点噪声
函数:cv2.medianBlur(img,ksize)
img:输入原图
ksize:核大小

# 中值滤波
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('image/median.png')
median = cv2.medianBlur(img, (3,3))
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.subplot(122),plt.imshow(median),plt.title('median')
plt.show()

2.2 双边滤波cv2.bilateralFilter(src=image, d,sigmaColor, sigmaSpace)

双边滤波是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折中处理,同时考虑空间与信息和灰度相似性,达到保边去噪的目的,具有简单、非迭代、局部处理的特点。
函数:cv2.bilateralFilter(src=image, d,sigmaColor, sigmaSpace)
src:输入原图
d:像素的邻域直径
sigmaColor:灰度值相似性高斯函数标准差
sigmaSpace:空间高斯函数标准差
参数说明:
关于2个sigma参数:
简单起见,可以令2个sigma的值相等;
若很小(小于10),几乎没有什么效果;
若很大(大于150),效果会很强,使图像显得非常卡通化;

关于参数d:
过大的滤波器(d>5)执行效率低,对于实时应用,建议取d=5;
对于需要过滤严重噪声的离线应用,可取d=9;
d>0时,由d指定邻域直径;
d<=0时,d会自动由sigmaSpace的值确定,且d与sigmaSpace成正比;

import cv2
from matplotlib import pyplot as plt
img = cv2.imread('image/bilateral.png')
img = cv2.cvtColor(img,cv.COLOR_BGR2RGB)
blur = cv2.bilateralFilter(img,-1,15,10)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.subplot(122),plt.imshow(blur),plt.title('Blurred')
plt.show()

在这里插入图片描述

2.3 直方图均衡化目的

直方图均衡化是将原图像通过某种变换,得到一幅灰度直方图为均匀分布的新图像的方法。
直方图均衡化方法的基本思想是对在图像中像素个数多的灰度级进行展宽,而对像素个数少的灰度级进行缩减。从而达到清晰图像的目的。

2.3.1 灰度直方图均衡化cv2.equalizeHist(img)

函数:cv2.equalizeHist(img)
说明: 此处的img输入为灰度图,即单通道
步骤:
统计直方图中每个灰度级出现的次数;
计算累计归一化直方图;
重新计算像素点的像素值

# 直方图均衡化
import cv2
img = cv2.imread('./image/dark.png', 0)
img_equal = cv2.equalizeHist(img)
cv2.imshow('img_equal', img_equal)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

2.3.2 彩色直方图均衡化(先cv2.split(img)分解通道、再cv2.merge((b, g, r)))

import cv2
import numpy as np
img = cv2.imread("./image/dark1.jpg")
cv2.imshow("src", img)
# 彩色图像均衡化,需要分解通道 对每一个通道均衡化
(b, g, r) = cv2.split(img) # b.shape: (640, 574)
bH = cv2.equalizeHist(b)
gH = cv2.equalizeHist(g)
rH = cv2.equalizeHist(r)
# 合并每一个通道
result = cv2.merge((bH, gH, rH))
cv2.imshow("dst", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

2.4 Gamma变化

目的: Gamma变换就是用来图像增强,其提升了暗部细节,通过非线性变换,让图像从暴光强度的线性响应变得更接近人眼感受的响应,即将漂白(相机曝光)或过暗(曝光不足)的图片,进行矫正。

Gamma变换是对输入图像灰度值进行的非线性操作,使输出图像灰度值与输入图像灰度值呈指数关系:
说明: Vin输入为0-1之间,因此输入时需要先进行归一化,然后取指数
在这里插入图片描述

import cv2
import numpy as np
img=cv2.imread('./image/dark1.jpg')
def adjust_gamma(image, gamma=1.0):
    invGamma = 1.0/gamma
    table = []
    for i in range(256):
        table.append(((i / 255.0) ** invGamma) * 255)
    table = np.array(table).astype("uint8")
    print(table)
    return cv2.LUT(image, table)

img_gamma = adjust_gamma(img, 0.8)  # 小于1变暗,大于1变亮
#print(img_gamma)
cv2.imshow("img",img)
cv2.imshow("img_gamma",img_gamma)

cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

3 形态学操作(腐蚀、膨胀、开闭运算、黑帽、顶帽)

3.1 图像腐蚀cv2.erode(src,kernel, anchor, iterations)

函数:cv2.erode(src, kernel, anchor=None, iterations)
src:原图
kernel:腐蚀操作内核,默认为3x3,可以使用下列opencv封装定义kernel的api,可定义形状,大小
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7,7))
-------cv2.MORPH_CROSS十字形,cv2.MORPH_RECT矩形,cv2.MORPH_ELLIPSE椭圆形
anchor:内核中心点,默认(-1,-1)即中心

import cv2
import numpy as np 
import matplotlib.pyplot as plt
img = cv2.imread('./image/morphology.png')
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
kernel = np.ones((3,3),np.uint8)
# kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7,7))  # opencv封装的函数,可以定义kernel的形状和大小,推荐
erosion = cv2.erode(img,kernel,iterations = 1)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.subplot(122),plt.imshow(erosion),plt.title('erosion')
plt.show()

3.2 图像膨胀cv2.dilate(src, kernel,anchor,iterations)

函数:cv2.dilate(src, kernel,anchor,iterations)
src:原图
kernel:膨胀操作内核

import cv2 
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('./image/morphology.png')
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
#kernel = np.ones((3,),np.uint8)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (7,7))

dilation = cv2.dilate(img,kernel,iterations = 1)
kernel1 = np.ones((7,7),np.uint8)
opening = cv2.morphologyEx(dilation,cv2.MORPH_OPEN,kernel1)
plt.subplot(121),plt.imshow(opening),plt.title('opening')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(dilation),plt.title('dilation')
plt.show()

3.3 开运算(先腐蚀,再膨胀,将两目标分开)

3.3.1 开运算原理cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel)

在这里插入图片描述
开运算总结:
1.开运算能够除去孤立的小点,毛刺和小桥, 而总的位置和形状不变。
2.开运算是一个基于几何运算的滤波器。
3.结构元素大小的不同将导致滤波效果的不同。
4.不同的结构元素的选择导致了不同的分割,即提取出不同的特征。

3.3.2开运算代码示例

import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('./image/open.png')
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9,9))
opening = cv2.morphologyEx(img,cv2.MORPH_OPEN,kernel) # 进行开运算
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.subplot(122),plt.imshow(opening),plt.title('opening')
plt.show()

在这里插入图片描述

3.4 闭运算(先膨胀,再腐蚀,将两目标封闭)

3.4.1 闭运算原理cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel)

在这里插入图片描述
闭运算总结:

  1. 闭运算能够填平小湖(即小孔),弥合小裂缝,而总的位置和形状不变。
  2. 闭运算是通过填充图像的凹角来滤波图像的。
  3. 结构元素大小的不同将导致滤波效果的不同。
  4. 不同结构元素的选择导致了不同的分割。

3.4.2闭运算代码示例

import cv2 
import numpy as np
img = cv2.imread('./image/close.png')
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
kernel = np.ones((7,7),np.uint8)
closing = cv2.morphologyEx(img,cv2.MORPH_CLOSE,kernel)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.subplot(122),plt.imshow(closing),plt.title('closing')
plt.show()

在这里插入图片描述

3.5 形态学梯度 cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)

图像膨胀和腐蚀之间的区别,结果即对象的轮廓。

import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread('./image/morphology.png')
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
kernel = np.ones((3,3), np.uint8)
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
plt.subplots(121), plt.imshow(img), plt.title('Original')
plt.subplots(122), plt.imshow(gradient), plt.title('Gradient')
plt.show()

在这里插入图片描述

3.6 顶帽cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel)

原图像与开运算图的区别(差值),突出原图像中比周围亮的区域

# 顶帽, 输入图像和图像开运算之差
import cv2 
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('./image/morphology.png')
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
kernel = np.ones((9,9),np.uint8)
tophat = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.subplot(122),plt.imshow(tophat),plt.title('tophat')
plt.show()

3.7 黑帽cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel)

闭操作图像-原图像,突出原图中比周围暗的区域

# 黑帽
import cv2 
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('./image/morphology.png')
img = cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
kernel = np.ones((9,9),np.uint8)
tophat = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT,kernel)
plt.subplot(121),plt.imshow(img),plt.title('Original')
plt.show()

猜你喜欢

转载自blog.csdn.net/weixin_44994302/article/details/121387894