OpenCV - 简单图像处理

2024-04-15

OpenCV是常用图像处理工具。图像处理(Image Processing)是用计算机对图像进行分析,以获取所需结果的过程,又称为影像处理。图像处理一般是指数字图像处理。数字图像是用工业相机、摄像机、扫描仪等设备经过拍摄得到的一个大的二维数组,该数组的元素称为像素,其值称为灰度值。

1. 图像模糊

1.1 均值滤波

  • 均值滤波是指通过将图像与低通滤波器内核进行卷积来实现图像模糊,这对于消除噪声很有用。它实际上从图像中消除了高频部分(如噪声、边缘)。因此,在此操作中会使边缘有些楼糊 (利用一些模糊技术也可以不模糊边缘)。
  • 一个5像素×5像素的核模板其实就是一个均值滤波器。OpenCV 有一个专门的均值滤波槽板供用户使用,即归一化卷积模板。所有的滤波模板都是使用卷积框覆盖区域的所有像素点与模板相乘后得到的值作为中心像素的值的。
  • OpenCV可以使用cv2.blur(img, (3, 3))函数实现图像的均值滤波。
  • 第一个参数img是图像对象,第二个参数(3,3)是滤波核(滤波核为奇数)。

1.2 中值滤波

  • 中值滤波模板使用卷积框中像素的中值代替中心值,从而达到去噪声的目的。这个模板一般用于去除椒盐噪声。均值滤波用计算得到的一个新值来取代中心像素的值,而中值滤波用中心像素周围(也可以是它本身)的值来取代中心像素的值,卷积核的大小也是奇数。
  • OpenCV可以使用cv2.medianBlur(img, 3)函数实现图像的中值滤波。
  • 第一个参数 img 是图像对象,第二个参数是滤波核(3为简写方式,与均值滤波中(3,3)表达的含义相同)。

1.3 高斯滤波

  • 现在把卷积模板中的值换一下,不全是 1,换成一组符合高斯分布的数值放在模板中。例如,中间的数值最大,越靠近两边数值越小,构造一个小的高斯包,可以使用函数cv2.GaussianBlur()。
  • 对于高斯模板,需要制定的是高斯核的高和宽(奇数),以及沿x方向与y方向的标准差(如果只给出x,则y=x;如果将x和y都设置为 0,那么函数会自己计算。高斯核可以有效去除图像的高斯噪声)。
  • OpenCV可以使用 cv2.GaussianBlur(source, (3, 3), 0)函数实现图像的高斯滤波。
  • 第一个参数source为图像对象,第二个参数(3, 3)为滤波核,第三个参数0为高斯核标准差。

实验

  1. 导入模块

     import cv2
     import matplotlib.pyplot as plt
     import matplotlib as mpl
     mpl.rcParams['font.sans-serif']=['SimHei'] # 指定默认字体为黑体
     mpl.rcParams['axes.unicode_minus'] = False # 正常显示负号
    
  2. 均值滤波

     img = cv2.imread("picture/rabbit.png", 0) # 直接读为灰度图
     blur = cv2.blur(img, (5, 5))# 模板大小为5*5
     # 显示图像
     plt.subplot(1, 2, 1)
     plt.imshow(img, 'gray')
     plt.title('zaosheng')
     plt.subplot(1, 2, 2)
     plt.imshow(blur, 'gray')
     plt.title('blur')
     plt.show()
    

    i1

  3. 中值滤波

     img = cv2.imread("picture/rabbit.png", 0)# 直接读为灰度图
     dst = cv2.medianBlur(img, (5))# 卷积核大小为5
     # 显示图像
     plt.subplot(1, 2, 1)
     plt.imshow(img, gray)
     plt.title(zaosheng)
     plt.subplot(1, 2, 2)
     plt.imshow(dst, 'gray')
     plt.title("medianBlur")
     plt.show()
    

    i2

  4. 高斯滤波

     img =cv2.imread("picture/rabbit.png", 0)# 直接读为灰度图像
     m_dst = cv2.medianBlur(img,  (5))
     g_dst = cv2.GaussianBlur(img, (5, 5), 0)# 高斯核为5*5
     # 显示图像
     plt.subplot(1, 3, 1), plt.imshow(img, 'gray')
     plt.title("zaosheng")
     plt.subplot(1, 3, 2), plt.imshow(g_dst, 'gray')
     plt.title("GaussianBlurn”)
     plt.subplot(1, 3, 3), plt.imshow(m_dst, 'gray')
     plt.title('mediaBlur')
     plt.show()
    

    i3

2. 图像锐化

  • 图像锐化(Image Sharpening)是补偿图像的轮廓,以及增强图像的边缘和灰度跳变的部分使图像变得清晰的操作,分为空间域处理和频域处理两类。
  • 图像锐化的目的是突出图像上地物的边缘、轮廓,或者某些线性目标要素的特征。这种滤波方法增强了地物边缘与周围像元之间的反差,因此也称为边缘增强。

实验

  1. 导入模块

     import cv2 as cv
     import numpy as np
     import matplotlib.pyplot as plt
     import matplotlib as mpl
     mpl.rcParams['font.sans-serif'] = ['SimHei']
    
  2. 读取图像

    img = cv.imread("picture/rabbit.jpg", 0) # 灰度图
    plt.imshow(img, "gray")
    plt.title("灰度图")
    plt.show()
    

    i4

  3. 图像锐化

     img_f = np.copy(img)
     img_f = img_f.astype("float")
    
     row, column = img.shape
     gradient = np.zeros((row, column))
     for x in range(row - 1):
         for y in range(column - 1):
             gx = abs(img_f[x + 1, y] - img_f[xy]) # 通过相邻像相减计算图像梯度
             gy = 	abs(img_f[x, y + 1] - img_f[x, y]) # 通过相邻像素相减计算图像梯度
             gradient[x, y] = gx + gy
     plt.imshow(gradient, "gray")
     plt.title("梯度图")
     plt.show()
    

    i5

     sharp = img_f + gradient  # 叠加原图与梯度图,实现图像锐化
     # 将小于0的像素设置为0, 将大于255 的像素设置为255
     sharp = np.where(sharp < 0, 0, np.where(sharp > 255, 255, sharp))
     plt.imshow(sharp, "gray")
     plt.title("锐化图")
     plt.show()
    

    i6

  4. 对比图像

     # 修改图像类型
     gradient = gradient.astype("uint8")
     sharp = sharp.astype("uint8")
     # 显示图像
     plt.subplot(1, 3, 1)
     plt.imshow(img, "gray")
     plt.title("灰度图")
    
     plt.subplot(1, 3, 2)
     plt.imshow(gradient, "gray")
     plt.title("梯度图")
    
     plt.subplot(1, 3, 3)
     plt.imshow(sharp, "gray")
     plt.title("锐化图")
     plt.show()
    

    i7

总结

  • 图像模糊常用于图像去噪、弱化边界的情景,常见的模糊方法有均值滤波、中值滤波高斯滤波。
  • 通过图像锐化可以更清晰地显示图像轮廓,从而查看图像细节。

3. 图像绘制

  • 图像处理需要执行绘图操作标注图像中检测物的具体位置,以及注明图像内容。在实际取景过程中,内存大小、拍摄角度等因素会影响图像呈现效果,所以需要对图像的尺寸、角度进行修改。
  • 使用 OpenCV 可以绘制不同的几何图形,可以使用的方法包括 cv.line()、cv.circle()、cv.rectangle()、cv.ellipse()、cvputText()等。在上述方法中有如下一些常见的参数。
  • img:要绘制图形的图像。
  • color:图形的颜色。对于 BGR,将其作为元组传递,如(255,0,0)。对于灰度,只需传递标量值即可。
  • 厚度:线或圆形等的粗细。如果向闭合图形(如圆形) 传递-1,它将填充图形。默认厚度为1
  • lineType:线的类型,包括 8 连接线、抗锯齿线等,在默认情况下为 8连接线。cv.LINE_AA表示抗锯齿的线条,非常适合作为曲线。

实验

  1. 导入模块

     import cv2
     import numpy as np
     import matplotlib.pyplot as plt
    
  2. 绘制线

     img = np.zeros((512, 512, 3), np.uint8)
     print(img.dtype)
     cv2.line(img, # 目标图像
                         (0, 0),  # 起点
                         (256, 256) , # 终点
                         (255, 0, 0), # 颜色
                         5)# 粗细
     img_line = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
     plt.imshow(img_line)
     plt.show()
    

    i8

  3. 绘制矩形

     img = np.zeros((512, 512, 3), np.uint8)
     cv2.rectangle(img, # 目标图像
                                 (128, 128), # 顶点
                                 (256, 256), # 相对的顶点
                                 (0, 255, 0), # 颜色
                                 3)# 粗细
     img_rectangle = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
     plt.imshow(img_rectangle)
     plt.show()
    

    i9

  4. 绘制圆形

     img = np.zeros((512, 512, 3), np.uint8)
     cv2.circle(img, # 目标图像
                             (256, 256),  # 圆心
                             256, #半径
                             (0, 0, 255),  # 颜色
                             -1)  # 填充
     img2 = cv2.cvtColor(img,  cv2.COLOR_BGR2RGB)
     plt.imshow(img2)
     plt.show()
    

    i10

  5. 绘制椭圆形

     img = np.zeros((512, 512, 3), np.uint8)
     cv2.ellipse(img,  # 目标图像
                             (256, 256), # 中心
                             (256, 128), # 长轴、短轴
                             0, # 逆时针旋转角度
                             0, # 开始角度
                             360, # 结束角度
                             (0, 0, 255), # 颜色
                             -1) # 填充
     cv2.ellipse(img, (256, 256), (256, 128), 45, 0, 360, (0, 255, 0), -1)
     cv2.ellipse(img, (256, 256), (256, 128), 90, 0, 360, (255, 0, 0), -1)
    
     img2 = cv2.cvtColor(img,  cv2.COLOR_BGR2RGB)
     plt.imshow(img2)
     plt.show()
    

    i11

  6. 绘制多边形

     img = np.zeros((512, 512, 3), np.uint8)
     pts = np.array([[50, 50], [400100], [462462], [100400]],np.int64)
     print(pts)
     print(pts.shape)
     pts = pts.reshape((-1, 1, 2))
     print(pts)
     print(pts.shape)
     cv2.polylines(img, # 目标图像
                                 [pts], # 顶点
                                 True, # 是否闭合
                                 (0, 0, 255) ,# 颜色
                                 3)  #粗细
     img2 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
     plt.imshow(img2)
     plt.show()
    

    i12

  7. 添加文字

     img =np.zeros((512, 512, 3), np.uint8)
     font = cv2.FONT_HERSHEY_SIMPLEX
     cv2.putText(img, # 目标图像
                             "OpenCV", # 文字
                             (10, 300), # 文本框左下角
                             font, # 文宇字体
                             4, # 文字大小
                             (255, 255, 255), # 文宇颜色
                             3,# 文宇粗细
                             cv2.LINE_AA # 文字线型
     )
     img2 = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
     plt.imshow(img2)
     plt.show()
    

    i13

4. 图像的几何变换

4.1 缩放

  • 缩放操作只是调整图像的大小,使用矩阵进行计算和修改。OpenCV 使用 cv2.resize(img,(scale))函数对图像进行缩放。第一个参数img为图像对象,第二个参数(scale)为缩放尺寸或比例。

4.2 平移

  • 平移是指物体位置的移动。
  • OpenCV 使用cv2.warpAffine(img,M,(width,height))函数对图像进行平移。第一个参数img为图像对象,第二个参数M为变换矩阵,第三个参数(width,height)为变换后的图像大小。

4.3 旋转

  • OpenCV 提供了可缩放的和可调整的旋转中心,可以在任意位置旋转图像。
  • OpenCV 使用cv2.getRotationMatrix2D((x,y),45,1)函数处理变换矩阵。第一个参数(x,y)为旋转中心,第二个参数 45为旋转角度(逆时针 ),第三个参数1为缩放比例。
  • 经过上述处理后,使用cv2.warpAffine()函数进行旋转操作。

实验

  1. 缩放

     # 导入模块
     import cv2
     from matplotlib import pyplot as plt
    
     # 读取图像
     img = cv2.imread('images/rabbit.jpg')
     print(img.shape)
     width, height = img.shape[:2]
    
     img_original = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    
     # 1.通过 dsize 设置输出图像的大小
     img_dsize = cv2.resize(img,  # 输入图像
                                                 (4 *width, 2*height), # 输出图像的大小
                                                 )
     img_dsize = cv2.cvtColor(img_dsize, cv2.COLOR_BGR2RGB)
    
     # 2.通过 fx和fy 设置输出图像的大小
     img_fx_fy = cv2.resize(img,# 输入图像
                                                     None ,   # 输出图像的大小
                                                     fx=1/2,  # y轴缩放因子
                                                     fy=1/4,  # x轴缩放因子
                                                     )
     img_fx_fy = cv2.cvtColor(img_fx_fy, cv2.COLOR_BGR2RGB)
     plt.imshow(img_fx_fy)
     plt.show()
    

    i14

  2. 平移

     #导入模块
     import cv2
     import numpy as np
     from matplotlib import pyplot as plt
    
     # 读取图像
     img = cv2.imread('images/rabbit.jpg')
     print(img.shape)
     width,height = img.shape[:2]
    
     # 平移前的图像
     img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # 颜色通道从BGR转换为RGB
    
     # 2*3变换矩阵:100表示水平方向上的平移距离,50表示垂直方向上的平移距离
     M = np.float64([[1, 0, 100], [0, 1,50]])
     # 平移
     img2 = cv2.warpAffine(img,  # 变换前的图像
                                                 M,# 变换矩阵
                                                 (width, height))  # 变换后的图像大小
     img2_rgb = cv2.cvtColor(img2, cv2.COLOR_BGR2RGB)# 颜色通道从BGR 转换为RGB
     plt.imshow(img2_rgb)
     plt.show()
    

    i15

  3. 旋转

     # 导入模块
     import cv2
     from matplotlib import pyplot as plt
    
     # 读取图像
     img = cv2.imread('images/lena.jpg')
     print(img.shape)
     Width, height = img.shape[:2]
    
     # 旋转前的图像
     img_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    
     # 2*3变换矩阵
     M = cv2.getRotationMatrix2D((width/2, height/2),  # 旋转中心
                                                                 45,		# 旋转角度
                                                                 1)    # 缩放比例
     print(M)
    
     #旋转
     img_rotate = cv2.warpAffine(img,	# 输入图像
                                                             M,     # 变换矩阵
                                                             (width, height))   # 变换后的图像大小
     img_rotate = cv2.cvtColor(img_rotate, cv2.COLOR_BGR2RGB)
     plt.imshow(img_rotate)
     plt.show()
    

    i16

总结

  • OpenCV自带多种绘图方式,可以绘制直线、矩形、圆形、圆形,以及添加文字。
  • OpenCV 支持图像变换操作,可以对图像进行缩放、平移、旋转、仿射变换。
  • OpenCV是一个功能强大的图像处理库,使用BGR通道方式读取图像。