文章目录

  • 前言
  • 一、边界填充
  • 二、图像融合
  • 三、图像阈值
  • 四、图像平滑
  • 1、均值滤波
  • 2、方框滤波
  • 3、高斯滤波
  • 4、中值滤波
  • 五、形态学
  • 1、腐蚀
  • 2、膨胀
  • 3、开运算 & 闭运算
  • 4、梯度运算
  • 5、礼帽 & 黑帽
  • 六、图像梯度
  • 1、Sobel算子
  • 2、Scharr 算子 & Lablacian 算子
  • 七、Canny 边缘检测



前言

本文为11月3日 OpenCV 实战基础学习笔记——图像基本处理,分为七个章节:

  • 边界填充;
  • 图像融合;
  • 图像阈值;
  • 图像平滑;
  • 形态学;
  • 图像梯度;
  • Canny 边缘检测。

一、边界填充

  • BORDER_REPLICATE:复制法:复制最边缘像素;
  • BORDER_REFLECT:反射法,使像素在两边进行复制;
  • BORDER_REFLECT_101:反射法,也就是以最边缘像素为轴,对称;
  • BORDER_WRAP:外包装法;
  • BORDER_CONSTANT:常量法,常数值填充。
top_size, bottom_size, left_size, right_size = (50, 50, 50, 50)

replicate = cv.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv.BORDER_REPLICATE)
reflect = cv.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv.BORDER_REFLECT)
reflect101 = cv.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv.BORDER_REFLECT_101)
wrap = cv.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, cv.BORDER_WRAP)
constant = cv.copyMakeBorder(img, top_size, bottom_size, left_size, right_size,cv.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()

opencv 处理图片使其更加清晰 opencv图像处理入门_opencv 处理图片使其更加清晰

二、图像融合

cat.shape
>>> (414, 500, 3)

dog.shape
>>> (429, 499, 3)

dog = cv.resize(dog, (500, 414))
dog.shape
>>> (414, 500, 3)

res = cv.addWeighted(cat, 0.4, dog, 0.6, 0) # \alpha=0.4, \beta=0.6

plt.imshow(res)

opencv 处理图片使其更加清晰 opencv图像处理入门_opencv 处理图片使其更加清晰_02

三、图像阈值

ret, dst = cv2.threshold(src, thresh, maxval, type)

  • src: 输入图,只能输入单通道图像,通常来说为灰度图
  • dst: 输出图
  • thresh: 阈值
  • maxval: 当像素值超过了阈值(或者小于阈值,根据type来决定),所赋予的值
  • type:二值化操作的类型,包含以下5种类型:
  1. cv2.THRESH_BINARY 超过阈值部分取maxval(最大值),否则取0;
  2. cv2.THRESH_BINARY_INV: THRESH_BINARY的反转;
  3. cv2.THRESH_TRUNC 大于阈值部分设为阈值,否则不变;
  4. cv2.THRESH_TOZERO 大于阈值部分不改变,否则设为0;
  5. cv2.THRESH_TOZERO_INV THRESH_TOZERO的反转。
ret, thresh1 = cv.threshold(img_gray, 127, 255, cv.THRESH_BINARY)
ret, thresh2 = cv.threshold(img_gray, 127, 255, cv.THRESH_BINARY_INV)
ret, thresh3 = cv.threshold(img_gray, 127, 255, cv.THRESH_TRUNC)
ret, thresh4 = cv.threshold(img_gray, 127, 255, cv.THRESH_TOZERO)
ret, thresh5 = cv.threshold(img_gray, 127, 255, cv.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], cmap='gray')
    plt.title(titles[i])
    plt.xticks([])
    plt.yticks([])
plt.show()

opencv 处理图片使其更加清晰 opencv图像处理入门_opencv_03

四、图像平滑

img = cv.imread('lenaNoise.png')
img = cv.cvtColor(img, cv.COLOR_BGR2RGB)

plt.imshow(img)

opencv 处理图片使其更加清晰 opencv图像处理入门_学习_04

1、均值滤波

平均卷积操作。

# 均值滤波:平均卷积操作
blur = cv.blur(img, (3, 3))

cv_show('blur', blur)

opencv 处理图片使其更加清晰 opencv图像处理入门_计算机视觉_05

2、方框滤波

基本和均值一样,可以选择归一化,容易越界。

box = cv.boxFilter(img, -1, (3, 3), normalize=True)

cv_show('box', box)

opencv 处理图片使其更加清晰 opencv图像处理入门_学习_06

3、高斯滤波

卷积核中的数值满足高斯分布,相当于更重视中间的。

gaussian = cv.GaussianBlur(img, (5, 5), 1)

cv_show('gaussian', gaussian)

opencv 处理图片使其更加清晰 opencv图像处理入门_计算机视觉_07

4、中值滤波

相当于用中值代替。

medium = cv.medianBlur(img, 5)

cv_show('medium', medium)

opencv 处理图片使其更加清晰 opencv图像处理入门_边缘检测_08

五、形态学

img = cv.imread('dige.png')

cv_show('img', img)

opencv 处理图片使其更加清晰 opencv图像处理入门_边缘检测_09

1、腐蚀

kernel = np.ones((5, 5), np.uint8)
erosion = cv.erode(img, kernel, iterations=1)

cv_show('erosion', erosion)

opencv 处理图片使其更加清晰 opencv图像处理入门_学习_10

2、膨胀

kernel = np.ones((3, 3), np.uint8)
dige_dilate = cv.dilate(erosion, kernel, iterations=1)

cv_show('dilate', dige_dilate)

opencv 处理图片使其更加清晰 opencv图像处理入门_opencv_11

3、开运算 & 闭运算

  • 开运算:先腐蚀,再膨胀;
kernel = np.ones((5, 5), np.uint8)
opening = cv.morphologyEx(img, cv.MORPH_OPEN, kernel)

cv_show("opening", opening)

opencv 处理图片使其更加清晰 opencv图像处理入门_计算机视觉_12

  • 闭运算:先膨胀,再腐蚀。
closing = cv.morphologyEx(img, cv.MORPH_CLOSE, kernel)

cv_show("closing", closing)

opencv 处理图片使其更加清晰 opencv图像处理入门_opencv 处理图片使其更加清晰_13

4、梯度运算

梯度 = 膨胀 - 腐蚀。

pie = cv.imread('pie.png')
kernel = np.ones((7, 7), np.uint8)

dilate = cv.dilate(pie, kernel, iterations=5)
erosion = cv.erode(pie, kernel, iterations=5)

res = np.hstack((dilate, erosion))

cv_show('res', res)

opencv 处理图片使其更加清晰 opencv图像处理入门_opencv_14

gradient = cv.morphologyEx(pie, cv.MORPH_GRADIENT, kernel)

cv_show('gradient', gradient)

opencv 处理图片使其更加清晰 opencv图像处理入门_学习_15

5、礼帽 & 黑帽

  • 礼帽:原始输入 - 开运算结果;
img = cv.imread('dige.png')
tophat = cv.morphologyEx(img, cv.MORPH_TOPHAT, kernel)

cv_show('tophat', tophat)

opencv 处理图片使其更加清晰 opencv图像处理入门_opencv 处理图片使其更加清晰_16

  • 黑帽:闭运算 - 原始输入。
blackhat = cv.morphologyEx(img, cv.MORPH_BLACKHAT, kernel)

cv_show('blackhat', blackhat)

opencv 处理图片使其更加清晰 opencv图像处理入门_opencv_17

六、图像梯度

1、Sobel算子

dst = cv2.Sobel(src, ddepth, dx, dy, ksize)

  • ddepth:图像的深度;
  • dx和dy分别表示水平和竖直方向;
  • ksize是Sobel算子的大小.
pie_sobel_x = cv.Sobel(pie, cv.CV_64F, 1, 0, ksize=3) # 1, 0: 只算水平方向
cv_show('pie_sobel_x', pie_sobel_x)

opencv 处理图片使其更加清晰 opencv图像处理入门_计算机视觉_18

# 白到黑是正数,黑到白是负数,所有的负数会被截断成 0,所以要取绝对值
pie_sobel_x = cv.convertScaleAbs(pie_sobel_x)
cv_show('pie_sobel_x', pie_sobel_x)

opencv 处理图片使其更加清晰 opencv图像处理入门_学习_19

# 分别计算 G_x 和 G_y,再求和
pie_sobel_y = cv.Sobel(pie, cv.CV_64F, 0, 1, ksize=3) # 0, 1: 只算竖直方向
pie_sobel_y = cv.convertScaleAbs(pie_sobel_y)
cv_show('pie_sobel_y', pie_sobel_y)

opencv 处理图片使其更加清晰 opencv图像处理入门_opencv 处理图片使其更加清晰_20

pie_sobel_xy = cv.addWeighted(pie_sobel_x, 0.5, pie_sobel_y, 0.5, 0)
cv_show('pie_sobel_xy', pie_sobel_xy)

opencv 处理图片使其更加清晰 opencv图像处理入门_学习_21

# 不建议直接计算,会有重影
pie_sobel_xy_2 = cv.Sobel(pie, cv.CV_64F, 1, 1, ksize=3)
pie_sobel_xy_2 = cv.convertScaleAbs(pie_sobel_xy_2)
cv_show('pie_sobel_xy_2', pie_sobel_xy_2)

opencv 处理图片使其更加清晰 opencv图像处理入门_opencv_22

lena = cv.imread('lena.jpg', cv.IMREAD_GRAYSCALE)
cv_show('lena', lena)

lena_sobel_x = cv.Sobel(lena, cv.CV_64F, 1, 0, ksize=3)
lena_sobel_x = cv.convertScaleAbs(lena_sobel_x)

lena_sobel_y = cv.Sobel(lena, cv.CV_64F, 0, 1, ksize=3)
lena_sobel_y = cv.convertScaleAbs(lena_sobel_y)

lena_sobel_xy = cv.addWeighted(lena_sobel_x, 0.5, lena_sobel_y, 0.5, 0)
cv_show('lena_sobel_xy', lena_sobel_xy)

opencv 处理图片使其更加清晰 opencv图像处理入门_opencv 处理图片使其更加清晰_23


opencv 处理图片使其更加清晰 opencv图像处理入门_opencv 处理图片使其更加清晰_24

2、Scharr 算子 & Lablacian 算子

opencv 处理图片使其更加清晰 opencv图像处理入门_计算机视觉_25

opencv 处理图片使其更加清晰 opencv图像处理入门_opencv 处理图片使其更加清晰_26

# 不同算子的差异
lena_scharr_x = cv.Scharr(lena, cv.CV_64F, 1, 0)
lena_scharr_x = cv.convertScaleAbs(lena_scharr_x)

lena_scharr_y = cv.Scharr(lena, cv.CV_64F, 0, 1)
lena_scharr_y = cv.convertScaleAbs(lena_scharr_y)

lena_scharr_xy = cv.addWeighted(lena_scharr_x, 0.5, lena_scharr_y, 0.5, 0)

lena_lap = cv.Laplacian(lena, cv.CV_64F)
lena_lap = cv.convertScaleAbs(lena_lap)

res = np.hstack((lena_scharr_xy, lena_lap))
cv_show('res', res)

opencv 处理图片使其更加清晰 opencv图像处理入门_opencv_27

七、Canny 边缘检测

步骤:

  1. 高斯滤波,平滑图像;
  2. opencv 处理图片使其更加清晰 opencv图像处理入门_opencv 处理图片使其更加清晰_28

  3. 计算每个像素点的梯度强度和方向;
  4. opencv 处理图片使其更加清晰 opencv图像处理入门_边缘检测_29

  5. 非极大值抑制,消除边缘检测带来的杂散响应;
  6. opencv 处理图片使其更加清晰 opencv图像处理入门_opencv 处理图片使其更加清晰_30

  7. 双阈值检测,确定真实和潜在的边缘;
  8. opencv 处理图片使其更加清晰 opencv图像处理入门_opencv_31

  9. 抑制孤立的弱边缘完成最终检测。
v1 = cv.Canny(lena, 80, 150) # min value 和 max value
v2 = cv.Canny(lena, 50, 100)

res = np.hstack((v1, v2))
cv_show('res', res)

opencv 处理图片使其更加清晰 opencv图像处理入门_opencv 处理图片使其更加清晰_32

car = cv.imread('car.png', cv.IMREAD_GRAYSCALE)

v1 = cv.Canny(car, 120, 250) # min value 和 max value
v2 = cv.Canny(car, 50, 100)

res = np.hstack((v1, v2))
cv_show('res', res)

opencv 处理图片使其更加清晰 opencv图像处理入门_opencv 处理图片使其更加清晰_33