图像处理基础操作一(几何变换、平滑处理、形态学操作)

目录

一、图像基础

二、图像基本操作

1、图像数据读取与写入

2、视频数据读取

3、图像颜色通道提取与合并

4、图像边界填充

5、图像融合及类型转换

三、图像的几何变换

1、图像缩放

2、图像旋转

3、图像翻转

4、图像平移

5、图像仿射变换

6、图像透视变换

四、图像阈值化与平滑处理

1、图像阈值化处理

2、图像平滑处理

五、图像形态学操作

1、腐蚀操作

2、膨胀操作

3、开运算

4、闭运算

5、梯度运算

6、顶帽运算

7、黑帽运算


一、图像基础

图像处理:对输入的图像做某种变换,输出仍然是图像,基本不涉及或者很少涉及图像内容的分析。比较典型的有图像变换,图像增强,图像去噪,图像压缩,图像恢复,二值图像处理等等。基于阈值的图像分割也属于图像处理的范畴。一般处理的是单幅图像。

图像分析:对图像的内容进行分析,提取有意义的特征,以便于后续的处理。处理的仍然是单幅图像。

计算机视觉:对图像分析得到的特征进行分析,提取场景的语义表示,让计算机具有人眼和人脑的能力。这时处理的是多幅图像或者序列图像,当然也包括部分单幅图像。

图像都是由像素构成的,即图像中的小方格,这些小方格都有一个明确的位置和被分配的色彩数值,这些小方格的颜色和位置就决定该图像所呈现出来的样子。像素是图像中的最小单位,每一个点阵图像包含了一定量的像素,这些像素决定图像在屏幕上所呈现的大小。

图像通常包括二值图像、灰度图像和彩色图像,具体如下:

  • 二值图像:二值图像中任何一个点非黑即白,要么为白色(像素为255),要么为黑色(像素为0)。将灰度图像转换为二值图像的过程,常通过依次遍历判断实现,如果像素>=127则设置为255,否则设置为0。
  • 灰度图像:灰度图像除了黑和白,还有灰色,它把灰度划分为256个不同的颜色,图像看着也更为清晰。将彩色图像转换为灰度图是图像处理的最基本预处理操作。
  • 彩色图像:彩色图像是RGB图像,RGB表示红、绿、蓝三原色,计算机里所有颜色都是三原色不同比例组成的,即三色通道。

二、图像基本操作

1、图像数据读取与写入

import cv2   # opencv读取的格式是BGR
import numpy as np
#图像显示
def cv_show(name,img):
    cv2.imshow(name,img)   # 图像的显示,也可以创建多个窗口
    cv2.waitKey(0)   # 等待时间,毫秒级,0表示任意键终止
    cv2.destroyAllWindows()   #删除所有窗口
img=cv2.imread('data/cat.jpg',cv2.IMREAD_COLOR)  # 读取彩色图像

cat_new=img[0:100,0:200]  #截取部分图像数据
cv_show('cat_new',cat_new)  #显示截取后的图像

cv2.imwrite('data/cat_new.png',img) #图像的保存
  • img = cv2.imread(文件名,[参数]):参数cv2.IMREAD_UNCHANGED 表示图像不可变,cv2.IMREAD_GRAYSCALE 表示灰度图像, cv2.IMREAD_COLOR 表示读入彩色图像, cv2.COLOR_BGR2RGB 表示图像通道BGR转成RGB;
  • cv2.waitKey(delay):键盘绑定函数,共一个参数,表示等待毫秒数,将等待特定的几毫秒,看键盘是否有输入,返回值为ASCII值。如果其参数为0,则表示无限期的等待键盘输入;参数>0表示等待delay毫秒;参数<0表示等待键盘单击。
  • ROI(Region of Interest)表示感兴趣区域。它是指从被处理图像以方框、圆形、椭圆、不规则多边形等方式勾勒出需要处理的区域。可以通过各种算子(Operator)和函数求得感兴趣ROI区域,并进行图像的下一步处理,被广泛应用于热点地图、人脸识别、图像分割等领域。比如可以通过像素矩阵直接获取ROI区域,如img[200:400, 200:400]。

2、视频数据读取

vc = cv2.VideoCapture('data/test.mp4')
# 检查是否打开正确
if vc.isOpened(): 
    oepn, frame = vc.read()
else:
    open = False
while open:
    ret, frame = vc.read()
    if frame is None:
        break
    if ret == True:
        gray = cv2.cvtColor(frame,  cv2.COLOR_BGR2GRAY)
        cv2.imshow('result', gray)
        if cv2.waitKey(100) & 0xFF == 27:
            break
vc.release()
cv2.destroyAllWindows()
  • cv2.VideoCapture可以捕获摄像头,用数字来控制不同的设备,例如0,1。如果是视频文件,直接指定好路径即可。

3、图像颜色通道提取与合并

def cv_show(name,img):
    cv2.imshow(name,img) 
    cv2.waitKey(0) 
    cv2.destroyAllWindows()
img=cv2.imread('data/cat.jpg',cv2.IMREAD_COLOR)  # 读取彩色图像
b,g,r=cv2.split(img) # 拆分颜色通道
print(r.shape) # (414, 500)
img=cv2.merge((b,g,r)) # 合并颜色通道
print(img.shape) #(414, 500, 3)
# 只保留R

r_img = img.copy()
r_img[:,:,0] = 0
r_img[:,:,1] = 0
cv_show('R',cur_img)

结果为:

注意:OpenCV读取的彩色图像由B、G、R三原色组成,也可以通过下面代码获取不同的通道,b = img[:, :, 0],g = img[:, :, 1],r = img[:, :, 2];opencv和matplotlib读取RGB通道的顺序是不一样的,opencv的顺序是B-G-R,而matplotlib的顺序是R-G-B,下面使用matplotlib读取并显示图片

import cv2   # opencv读取的格式是BGR
import matplotlib.pyplot as plt
import numpy as np

img=cv2.imread('data/cat.jpg',cv2.IMREAD_COLOR)  # 读取彩色图像
b,g,r=cv2.split(img) # 拆分颜色通道
img=cv2.merge((b,g,r)) # 合并颜色通道
# 只保留B
b_img = img.copy()
b_img[:,:,0] = 0
b_img[:,:,1] = 0
plt.subplot(131)
plt.imshow(b_img)
plt.title('Blue')
# 只保留G
g_img = img.copy()
g_img[:,:,0] = 0
g_img[:,:,2] = 0
plt.subplot(132)
plt.imshow(g_img)
plt.title('Green')
# 只保留B
r_img = img.copy()
r_img[:,:,1] = 0
r_img[:,:,2] = 0
plt.subplot(133)
plt.imshow(r_img)
plt.title('Red')

结果为:

4、图像边界填充

import cv2   # opencv读取的格式是BGR
import matplotlib.pyplot as plt
import numpy as np

top_size,bottom_size,left_size,right_size = (50,50,50,50)
replicate = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REPLICATE)
reflect = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_REFLECT_101)
wrap = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_WRAP)
constant = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv2.BORDER_CONSTANT, value=0)
plt.subplot(231), plt.imshow(img, 'gray'), plt.title('ORIGINAL')
plt.subplot(232), plt.imshow(replicate, 'gray'), plt.title('REPLICATE')
plt.subplot(233), plt.imshow(reflect, 'gray'), plt.title('REFLECT')
plt.subplot(234), plt.imshow(reflect101, 'gray'), plt.title('REFLECT_101')
plt.subplot(235), plt.imshow(wrap, 'gray'), plt.title('WRAP')
plt.subplot(236), plt.imshow(constant, 'gray'), plt.title('CONSTANT')
plt.show()

结果为:

  • cv.copyMakeBorder(img,top, bottom, left, right ,borderType):img:需要填充的图像;top:图像上边界需要填充的像素点;bottom:图像下边界需要填充的像素点;left:图像左边界需要填充的像素点;right:图像右边界需要填充的像素点;borderType:图像填充的方法。填充方法主要包括:BORDER_REPLICATE:复制法,也就是复制最边缘像素,BORDER_REFLECT:反射法,对感兴趣的图像中的像素在两边进行复制例如:fedcba|abcdefgh|hgfedcb,BORDER_REFLECT_101:反射法,也就是以最边缘像素为轴,对称,gfedcb|abcdefgh|gfedcba,BORDER_WRAP:外包装法abcdefgh|abcdefgh|abcdefg,BORDER_CONSTANT:常量法,常数值填充,需要在设置一个value值,已显示填充的颜色。

5、图像融合及类型转换

图像融合通常是指将2张或2张以上的图像信息融合到1张图像上,融合的图像含有更多的信息,能够更方便人们观察或计算机处理。通过图像融合可以将两张不清晰的图像融合得到更清晰的图。图像融合是在图像加法的基础上增加了系数和亮度调节量。

import cv2   # opencv读取的格式是BGR
import matplotlib.pyplot as plt
import numpy as np

img_cat=cv2.imread('data/cat.jpg')
img_dog=cv2.imread('data/dog.jpg')
print(img_cat.shape)  #(414, 500, 3)
print(img_dog.shape)  #(429, 499, 3)
img_dog = cv2.resize(img_dog, (500, 414))
print(img_dog.shape)  #(414, 500, 3)
  • cv2.resize(img, (500, 414))  :根据给定的维度进行变化 ,img表示需要变化的图片, (500, 414)表示变化的维度,长为414, 宽为500  
  • cv2.resize(img, (0, 0), fx=3, fy=1) : 使得图像x轴变化为原来的三倍,y轴不变,即fx=3, fy=1,表示对图像的x轴进行变化
res = cv2.resize(img, (0, 0), fx=3, fy=1)
plt.imshow(res)

img_cat1 = img_cat+10   #对三个通道像素点进行加10操作
plt.imshow(img_cat1)

img_new=img_cat+img_dog #将两张图片进行相加操作, 如果大于255,就使用256进行约分
plt.imshow(img_new)

img_add=cv2.add(img_cat, img_dog) #使用cv2.add对两个照片进行加和, 如果加和值大于255,就使用255表示
plt.imshow(img_add)

res = cv2.addWeighted(img_cat, 0.4, img_dog, 0.6, 0) #将两个图片进行重叠
plt.imshow(res)
  • cv2.addWeighted(img_cat, 0.4, img_dog, 0.6, 0) 表示将两个图片进行重叠操作,重叠后的像素表示: img_cat*0.4 + img_dog*0.6 + 0 ,0表示重叠的偏置项

图像类型转换:图像类型转换是指将一种类型转换为另一种类型,比如彩色图像转换为灰度图像、BGR图像转换为RGB图像。OpenCV提供了200多种不同类型之间的转换,其中最常用的如下:

  • 图像类型转化:cv2.cvtColor(img, cv2.COLOR_BGR2GRAY);cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
  • 颜色通道转化:cv2.cvtColor(img, cv2.COLOR_BGR2RGB

三、图像的几何变换

1、图像缩放

  • 图像缩放主要调用resize()函数实现:cv2.resize(img, (200,100)) 设置的列数为200,行数为100
  • 获取原始图像像素再乘以缩放系数进行图像变换
img=cv2.imread('data/cat.jpg')
rows,cols=img.shape[:2]
img_new = cv2.resize(img, (int(cols*0.6), int(rows*1.2)))
plt.imshow(img_new)
  • 使用(fx,fy)缩放倍数的方法对图像进行放大或缩小:cv2.resize(img, None, fx=0.3, fy=0.3)

2、图像旋转

  • 图像旋转主要调用getRotationMatrix2D()函数和warpAffine()函数实现
  • cv2.getRotationMatrix2D()函数需要三个参数,旋转中心,旋转角度,旋转后图像的缩放比例
import cv2  
import matplotlib.pyplot as plt
import numpy as np

img=cv2.imread('data/cat.jpg')
rows,cols,channel=img.shape
M=cv2.getRotationMatrix2D((cols/2,rows/2),30,1) #绕图像的中心旋转,参数:旋转中心 旋转度数 scale
img_new=cv2.warpAffine(img,M,(cols,rows)) #参数:原始图像 旋转参数 变换后图像的宽高
plt.imshow(img_new)

3、图像翻转

图像翻转在OpenCV中调用函数flip()实现,cv2.flip(img, flipCode):其中img表示原始图像,flipCode表示翻转方向,如果flipCode为0,则以X轴为对称轴翻转,如果fliipCode>0则以Y轴为对称轴翻转,如果flipCode<0则在X轴、Y轴方向同时翻转。

import cv2  
import matplotlib.pyplot as plt

img=cv2.imread('img/cat.jpg')
src=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)
img1=cv2.flip(src,0) #以X轴为对称轴翻转
img2=cv2.flip(src,1) #以Y轴为对称轴翻转
img3=cv2.flip(src,-1) #X轴Y轴方向同时翻转
#显示图形
titles = ['Source', 'Image1', 'Image2', 'Image3']
images = [src, img1, img2, img3]
for i in range(4):
   plt.subplot(2,2,i+1), plt.imshow(images[i], 'gray')
   plt.title(titles[i])
   plt.xticks([]),plt.yticks([])
plt.show()

4、图像平移

图像平移首先定义平移矩阵M,再调用warpAffine()函数实现平移,核心函数如下:M = np.float32([[1, 0, x], [0, 1, y]]),
 cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))

# encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 读取图片
img = cv2.imread('img/cat.jpg')
image = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 图像向下平移
M = np.float32([[1, 0, 0], [0, 1, 100]])
img1 = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))
#图像向上平移
M = np.float32([[1, 0, 0], [0, 1, -100]])
img2 = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))
#图像向右平移
M = np.float32([[1, 0, 100], [0, 1, 0]])
img3 = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))
#图像向左平移
M = np.float32([[1, 0, -100], [0, 1, 0]])
img4 = cv2.warpAffine(image, M, (image.shape[1], image.shape[0]))

# 显示图形
titles = ['Image1', 'Image2', 'Image3', 'Image4']
images = [img1, img2, img3, img4]
for i in range(4):
    plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()  

5、图像仿射变换

  • 图像仿射变换又称为图像仿射映射,是指在几何中,一个向量空间进行一次线性变换并接上一个平移,变换为另一个向量空间。通常图像的旋转加上拉升就是图像仿射变换,仿射变换需要一个M矩阵实现,但是由于仿射变换比较复杂,很难找到这个M矩阵.
  • OpenCV提供了根据变换前后三个点的对应关系来自动求解M的函数——cv2.getAffineTransform(pos1,pos2),其中pos1和pos2表示变换前后的对应位置关系,输出的结果为仿射矩阵M,接着使用函数cv2.warpAffine()实现图像仿射变换。
  • 图像仿射变换的函数原型如:M = cv2.getAffineTransform(pos1,pos2),pos1表示变换前的位置,pos2表示变换后的位置;cv2.warpAffine(src, M, (cols, rows)),src表示原始图像,M表示仿射变换矩阵,(rows,cols)表示变换后的图像大小,rows表示行数,cols表示列数
#encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt

#读取图片
src = cv2.imread('img/cat.jpg')
#获取图像大小
rows, cols = src.shape[:2]
#设置图像仿射变换矩阵
pos1 = np.float32([[50,50], [200,50], [50,200]])
pos2 = np.float32([[10,100], [200,50], [100,250]])
M = cv2.getAffineTransform(pos1, pos2)
#图像仿射变换
img_new = cv2.warpAffine(src, M, (cols, rows))

#显示图像
images=[src,img_new]
for i in range(2):
   plt.subplot(1,2,i+1)
   plt.imshow(images[i])
plt.show()

6、图像透视变换

  • 图像透视变换(Perspective Transformation)的本质是将图像投影到一个新的视平面,OpenCV通过函数cv2.getPerspectiveTransform(pos1,pos2)构造矩阵M,其中pos1和pos2分别表示变换前后的4个点对应位置。得到M后在通过函数cv2.warpPerspective(src,M,(cols,rows))进行透视变换。
  • 图像透视变换的函数原型如下:M = cv2.getPerspectiveTransform(pos1, pos2),pos1表示透视变换前的4个点对应位置,pos2表示透视变换后的4个点对应位置;cv2.warpPerspective(src,M,(cols,rows)),src表示原始图像,M表示透视变换矩阵,(rows,cols)表示变换后的图像大小,rows表示行数,cols表示列数。
#encoding:utf-8
import cv2
import numpy as np
import matplotlib.pyplot as plt

#读取图片
src = cv2.imread('img/cat.jpg')
#获取图像大小
rows, cols = src.shape[:2]
#设置图像透视变换矩阵
pos1 = np.float32([[114, 82], [287, 156], [8, 322], [216, 333]])
pos2 = np.float32([[0, 0], [188, 0], [0, 262], [188, 262]])
M = cv2.getPerspectiveTransform(pos1, pos2)
#图像透视变换
img_new= cv2.warpPerspective(src, M, (190, 272))
#显示图像
images=[src,img_new]
for i in range(2):
   plt.subplot(1,2,i+1)
   plt.imshow(images[i])
plt.show()

四、图像阈值化与平滑处理

1、图像阈值化处理

图像的二值化或阈值化(Binarization)旨在提取图像中的目标物体,将背景以及噪声区分开来。通常会设定一个阈值T,通过T将图像的像素划分为两类:大于T的像素群和小于T的像素群。

灰度转换处理后的图像中,每个像素都只有一个灰度值,其大小表示明暗程度。二值化处理可以将图像中的像素划分为两类颜色,当灰度Gray小于阈值T时,其像素设置为0,表示黑色;当灰度Gray大于或等于阈值T时,其Y值为255,表示白色。

二值化处理广泛应用于各行各业,比如生物学中的细胞图分割、交通领域的车牌设别等。在文化应用领域中,通过二值化处理将所需民族文物图像转换为黑白两色图,从而为后面的图像识别提供更好的支撑作用。

OpenCV中提供了阈值函数threshold()实现二值化处理:retval, dst = cv2.threshold(src, thresh, maxval, type)

  • dst: 输出图
  • src: 输入图,只能输入单通道图像,通常来说为灰度图
  • thresh: 阈值
  • maxval: 最大值,当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
  • type:二值化操作的类型

二值化操作的类型主要包含以下5种类型:

  • cv2.THRESH_BINARY :二进制阈值化,超过阈值部分取maxval(最大值),否则取0
  • cv2.THRESH_BINARY_INV: 反二进制阈值化,超过阈值部分取0,否则取maxval(最大值)
  • cv2.THRESH_TRUNC :截断阈值化,大于阈值部分设为阈值,否则不变
  • cv2.THRESH_TOZERO :阈值化为0,大于等于阈值部分不改变,否则设为0
  • cv2.THRESH_TOZERO_INV :反阈值化为0,大于等于阈值部分设为0,否则不变
import cv2  
import matplotlib.pyplot as plt
import numpy as np
img=cv2.imread('data/cat.jpg')
img_gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh1 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY)
ret, thresh2 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_BINARY_INV)
ret, thresh3 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TRUNC)
ret, thresh4 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO)
ret, thresh5 = cv2.threshold(img_gray, 127, 255, cv2.THRESH_TOZERO_INV)

titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [img, thresh1, thresh2, thresh3, thresh4, thresh5]

for i in range(6):
    plt.subplot(2, 3, i + 1), plt.imshow(images[i], 'gray')
    plt.title(titles[i])
    plt.xticks([]), plt.yticks([])
plt.show()

cv2.threshold()函数中的参数img_gray表示灰度图,参数127表示对像素值进行分类的阈值,参数255表示像素值高于阈值时应该被赋予的新像素值,最后一个参数对应不同的阈值处理方法。结果如下图:

2、图像平滑处理

图像增强:图像增强是对图像进行处理,使其比原始图像更适合于特定的应用,它需要与实际应用相结合。对于图像的某些特征如边缘、轮廓、对比度等,图像增强是进行强调或锐化,以便于显示、观察或进一步分析与处理。图像增强的方法是因应用不同而不同,研究内容包括:

图像平滑:图像平滑是一种区域增强的算法,平滑算法有邻域平均法、中值滤波、边界保持类滤波等。在图像产生、传输和复制过程中,常常会因为多方面原因而被噪声干扰或出现数据丢失,降低了图像的质量(某一像素,如果它与周围像素点相比有明显的不同,则该点被噪声所感染)。这就需要对图像进行一定的增强处理以减小这些缺陷带来的影响。

邻域平均法:图像简单平滑是指通过邻域简单平均对图像进行平滑处理的方法,用这种方法在一定程度上消除原始图像中的噪声、降低原始图像对比度的作用。它利用卷积运算对图像邻域的像素灰度进行平均,从而达到减小图像中噪声影响、降低图像对比度的目的。邻域平均法主要缺点是在降低噪声的同时使图像变得模糊,特别在边缘和细节处,而且邻域越大,在去噪能力增强的同时模糊程度越严重。

滤波器:在图像简单平滑中,算法利用卷积模板逐一处理图像中每个像素,这一过程可以形象地比作对原始图像的像素一一进行过滤整理,在图像处理中把邻域像素逐一处理的算法过程称为滤波器。平滑线性滤波器的工作原理是利用模板对邻域内像素灰度进行加权平均,也称为均值滤波器

为图像增加噪声如下

# -*- coding:utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("img/cat.jpg", cv2.IMREAD_UNCHANGED)
rows, cols, chn = img.shape
# 为图片增加噪声
for i in range(5000):
    x = np.random.randint(0, rows)
    y = np.random.randint(0, cols)
    img[x, y, :] = 255
plt.imshow(img)
plt.show()

(1)均值滤波

均值滤波是指任意一点的像素值,都是周围N*M个像素值的均值。Python调用OpenCV实现均值滤波的核心函数如下:
result = cv2.blur(原始图像,核大小)其中,核大小是以(宽度,高度)表示的元祖形式。常见的形式包括:核大小(3,3)和(5,5)。核如果设置为(1,1)处理结果就是原图,核中每个权重值相同,称为均值。核越大图像会变的越模糊。

# -*- coding:utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("img/cat.jpg", cv2.IMREAD_UNCHANGED)
rows, cols, chn = img.shape
# 为图片增加噪声
for i in range(5000):
    x = np.random.randint(0, rows)
    y = np.random.randint(0, cols)
    img[x, y, :] = 255
source = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 均值滤波
result = cv2.blur(source, (5, 5))
# 显示图形
titles = ['Source Image', 'Blur Image']
images = [source, result]
for i in range(2):
   plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
   plt.title(titles[i])
   plt.xticks([]), plt.yticks([])
plt.show()

(2)方框滤波

方框滤波和均值滤波核基本一致,区别是需不需要均一化处理。OpenCV调用boxFilter()函数实现方框滤波。函数如下:
result = cv2.boxFilter(原始图像, 目标图像深度, 核大小, normalize属性),其中,目标图像深度是int类型,通常用“-1”表示与原始图像一致;核大小主要包括(3,3)和(5,5)normalize属性表示是否对目标图像进行归一化处理。当normalize为true时需要执行均值化处理,当normalize为false时,不进行均值化处理,实际上为求周围各像素的和,很容易发生溢出,溢出时均为白色,对应像素值为255。

# -*- coding:utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("img/cat.jpg", cv2.IMREAD_UNCHANGED)
rows, cols, chn = img.shape
# 为图片增加噪声
for i in range(5000):
    x = np.random.randint(0, rows)
    y = np.random.randint(0, cols)
    img[x, y, :] = 255
source = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 方框滤波
result = cv2.boxFilter(source, -1, (5,5), normalize=True)
#result = cv2.boxFilter(source, -1, (5,5), normalize=False)
# 显示图形
titles = ['Source Image', 'BoxFilter Image']
images = [source, result]
for i in range(2):
   plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
   plt.title(titles[i])
   plt.xticks([]), plt.yticks([])
plt.show()

(3)高斯滤波

为了克服简单局部平均法造成图像模糊的弊端,目前已提出许多保持边缘、细节的局部平滑算法。它们的出发点都集中在如何选择邻域的大小、形状和方向、参数加平均及邻域各店的权重系数等。

图像高斯平滑也是邻域平均的思想对图像进行平滑的一种方法,在图像高斯平滑中,对图像进行平均时,不同位置的像素被赋予了不同的权重。高斯平滑与简单平滑不同,它在对邻域内像素进行平均时,给予不同位置的像素不同的权值,高斯滤波让临近的像素具有更高的重要度,对周围像素计算加权平均值,较近的像素具有较大的权重值。

Python中OpenCV主要调用GaussianBlur函数:dst = cv2.GaussianBlur(src, ksize, sigmaX) 其中,src表示原始图像,ksize表示核大小,sigmaX表示X方向方差。注意,核大小(N, N)必须是奇数,X方向方差主要控制权重。

# -*- coding:utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("data/cat.jpg", cv2.IMREAD_UNCHANGED)
rows, cols, chn = img.shape
# 为图片增加噪声
for i in range(5000):
    x = np.random.randint(0, rows)
    y = np.random.randint(0, cols)
    img[x, y, :] = 255
source = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
#高斯滤波
result = cv2.GaussianBlur(source, (3,3), 0)
# 显示图形
titles = ['Source Image', 'GaussianBlur Image']
images = [source, result]
for i in range(2):
   plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
   plt.title(titles[i])
   plt.xticks([]), plt.yticks([])
plt.show()

(4)中值滤波

在使用邻域平均法去噪的同时也使得边界变得模糊,而中值滤波是非线性的图像处理方法,在去噪的同时可以兼顾到边界信息的保留。选一个含有奇数点的窗口W,将这个窗口在图像上扫描,把窗口中所含的像素点按灰度级的升或降序排列,取位于中间的灰度值来代替该点的灰度值。

OpenCV主要调用medianBlur()函数实现中值滤波。图像平滑里中值滤波的效果最好dst = cv2.medianBlur(src, ksize) 其中,src表示源文件,ksize表示核大小。核必须是大于1的奇数,如3、5、7等。

# -*- coding:utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("img/cat.jpg", cv2.IMREAD_UNCHANGED)
rows, cols, chn = img.shape
# 为图片增加噪声
for i in range(5000):
    x = np.random.randint(0, rows)
    y = np.random.randint(0, cols)
    img[x, y, :] = 255
source = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
#中值滤波
result = cv2.medianBlur(img, 5)  # 中值滤波
# 显示图形
titles = ['Source Image', 'MedianBlur Image']
images = [source, result]
for i in range(2):
   plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
   plt.title(titles[i])
   plt.xticks([]), plt.yticks([])
plt.show()

注:常用的窗口还有方形、十字形、圆形和环形。不同形状的窗口产生不同的滤波效果,方形和圆形窗口适合外轮廓线较长的物体图像,而十字形窗口对有尖顶角状的图像效果好。中值滤波对于消除孤立点和线段的干扰十分有用,但对消除高斯噪声的影响效果不佳。对于一些细节较多的复杂图像,可以多次使用不同的中值滤波。

五、图像形态学操作

1、腐蚀操作

图像的腐蚀(Erosion)操作主要用来寻找图像中的极小区域,类似于“领域被蚕食”,将图像中的高亮区域或白色部分进行缩减细化,其运行结果图比原图的高亮区域更小。其主要包括两个输入对象:二值图像和卷积核。卷积核是腐蚀中的关键数组,采用numpy库可以成。卷积核的中心点逐个像素扫描原始图像。被扫描到的原始图像中的像素点,只有当卷积核对应的元素值均为1时,其值才为1,否则其值修改为0。图像被腐蚀后,去除了噪声,但是会压缩图像。

图像腐蚀主要使用的函数为erode,其原型为:dst = cv2.erode(src, kernel, iterations) 参数dst表示处理的结果,src表示原图像,kernel表示卷积核,iterations表示迭代次数,迭代次数默认是1,表示进行一次腐蚀,也可以根据需要进行多次迭代,进行多次腐蚀。

# -*- coding:utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("data/dige.png")
kernel = np.ones((3,3),np.uint8) #表示3*3的卷积核
erosion = cv2.erode(img,kernel,iterations = 1)  #图像腐蚀操作
# 显示图形
titles = ['Source Image', 'Erosion Image']
images = [img, erosion]
for i in range(2):
   plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
   plt.title(titles[i])
   plt.xticks([]), plt.yticks([])
plt.show()

2、膨胀操作

图像膨胀是腐蚀操作的逆操作,图像的膨胀(Dilation)操作主要用来寻找图像中的极大区域,类似于“领域扩张”,将图像中的高亮区域或白色部分进行扩张,其运行结果图比原图的高亮区域更大,主要用于去噪。其主要包括两个输入对象:二值图像和卷积核。卷积核的中心点逐个像素扫描原始图像,被扫描到的原始图像中的像素点,当卷积核对应的元素值只要有一个为1时,其值就为1,否则为0。

图像膨胀主要使用的函数为dilate,其原型为:dst = cv2.dilate(src, kernel, iterations) 参数dst表示处理的结果,src表示原图像,kernel表示卷积核,iterations表示迭代次数,迭代次数默认是1,表示进行一次膨胀,也可以根据需要进行多次迭代,进行多次膨胀。通常进行1次膨胀即可。

# -*- coding:utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("data/dige.png")
kernel = np.ones((3,3),np.uint8) #表示3*3的卷积核
dilate = cv2.dilate(img,kernel,iterations = 2)  #图像膨胀操作
# 显示图形
titles = ['Source Image', 'Dilate Image']
images = [img, dilate]
for i in range(2):
   plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
   plt.title(titles[i])
   plt.xticks([]), plt.yticks([])
plt.show()

3、开运算

图像开运算是图像依次经过腐蚀、膨胀处理后的过程。图像被腐蚀后,去除了噪声,但是也压缩了图像;接着对腐蚀过的图像进行膨胀处理,可以去除噪声,并保留原有图像。

图像开运算主要使用的函数morphologyEx,它是形态学扩展的一组函数,其参数cv2.MORPH_OPEN对应开运算。其原型如下:dst = cv2.morphologyEx(src, cv2.MORPH_OPEN, kernel) 参数dst表示处理的结果,src表示原图像,cv2.MORPH_OPEN表示开运算,kernel表示卷积核。

# -*- coding:utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("data/dige.png")
kernel = np.ones((5,5),np.uint8) 
#  开运算:先腐蚀,再膨胀
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
# 显示图形
titles = ['Source Image', 'Opening Image']
images = [img, opening]
for i in range(2):
   plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
   plt.title(titles[i])
   plt.xticks([]), plt.yticks([])
plt.show()

4、闭运算

图像闭运算是图像依次经过膨胀、腐蚀处理后的过程。图像先膨胀,后腐蚀,它有助于关闭前景物体内部的小孔,或物体上的小黑点。

图像闭运算主要使用的函数morphologyEx,其原型如下:dst = cv2.morphologyEx(src, cv2.MORPH_CLOSE, kernel) 参数dst表示处理的结果,src表示原图像, cv2.MORPH_CLOSE表示闭运算,kernel表示卷积核。

# -*- coding:utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("data/dige.png")
kernel = np.ones((5,5),np.uint8) 
#  闭运算:先膨胀,再腐蚀
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
# 显示图形
titles = ['Source Image', 'Closing Image']
images = [img, closing]
for i in range(2):
   plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
   plt.title(titles[i])
   plt.xticks([]), plt.yticks([])
plt.show()

5、梯度运算

图像梯度运算是膨胀图像减去腐蚀图像的结果,得到图像的轮廓,其中二值图像1表示白色点,0表示黑色点。梯度运算(img) = 膨胀(img) - 腐蚀(img) 

图像梯度运算主要使用的函数morphologyEx,参数为cv2.MORPH_GRADIENT。其原型如下:dst = cv2.morphologyEx(src, cv2.MORPH_GRADIENT, kernel) 参数dst表示处理的结果,src表示原图像, cv2.MORPH_GRADIENT表示梯度运算,kernel表示卷积核。

# -*- coding:utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("data/dige.png")
kernel = np.ones((5,5),np.uint8) 
#  梯度运算
gradient = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
# 显示图形
titles = ['Source Image', 'Gradient Image']
images = [img, gradient]
for i in range(2):
   plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
   plt.title(titles[i])
   plt.xticks([]), plt.yticks([])
plt.show()

6、顶帽运算

图像顶帽(图像礼帽)运算是原始图像减去图像开运算的结果,得到图像的噪声。顶帽运算(img) = 原始图像(img) - 开运算(img)

图像开运算主要使用的函数morphologyEx,它是形态学扩展的一组函数,其参数cv2.MORPH_TOPHAT对应开运算。其原型如下:dst = cv2.morphologyEx(src, cv2.MORPH_TOPHAT, kernel) 参数dst表示处理的结果,src表示原图像,cv2.MORPH_TOPHAT表示顶帽运算,kernel表示卷积核。

# -*- coding:utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("data/dige.png")
kernel = np.ones((5,5),np.uint8) 
# 图像顶帽运算
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
# 显示图形
titles = ['Source Image', 'Tophat Image']
images = [img, tophat]
for i in range(2):
   plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
   plt.title(titles[i])
   plt.xticks([]), plt.yticks([])
plt.show()

7、黑帽运算

图像黑帽运算是图像闭运算操作减去原始图像的结果,得到图像内部的小孔,或者前景色中的小黑点。黑帽运算(img) = 闭运算图像(img) - 原始图像(img)

图像开运算主要使用的函数morphologyEx,它是形态学扩展的一组函数,其参数cv2.MORPH_BLACKHAT对应开运算。其原型如下:dst = cv2.morphologyEx(src, cv2.MORPH_BLACKHAT, kernel) 参数dst表示处理的结果,src表示原图像,cv2.MORPH_BLACKHAT表示黑帽运算,kernel表示卷积核。

# -*- coding:utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt

img = cv2.imread("data/dige.png")
kernel = np.ones((5,5),np.uint8) 
# 图像黑帽运算
blackhat  = cv2.morphologyEx(img,cv2.MORPH_BLACKHAT, kernel)
# 显示图形
titles = ['Source Image', 'Blackhat Image']
images = [img, blackhat]
for i in range(2):
   plt.subplot(1, 2, i + 1), plt.imshow(images[i], 'gray')
   plt.title(titles[i])
   plt.xticks([]), plt.yticks([])
plt.show()

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Asia-Lee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值