图片基本操作

1
2
3
4
5
6
7
8
9
10
11
12
13
import cv2
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline # 直接展示图片 无需 .show

img = cv2.imread("a.png") # 默认BGR模式

# def show(img):
# 显示图片
cv2.imshow("窗口标题", img)
# 等待时间 0 为一直等 按任意键关闭
cv2.waitKey(0)
cv2.destroyAllWindows()

imread

以某种模式加载图片

1
2
img = cv2.imread("/path/to/img", cv2.IMREAD_***)  # IMREAD_GRAYSCALE等模式
img.shape # 只有两个维度

imwrite

写入图片

1
cv2.imwrite("/path/to/img", img)

视频读取

  • cv2.VideoCapture可以捕获摄像头,用数字来控制不同设备
  • 如果是视频文件,直接指定路径

播放灰度视频

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
vc = cv2.VideoCapture("/path/to/video")
# vc = cv2.VideoCapture(0) 打开视频设备
if vc.isOpened():
open, 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(10) & 0xFF == 27:
break
vc.release()
cv2.destroyAllWindows()

截取部分图像数据

1
2
3
img = cv2.imread("cat.jpg")
cat = img[0:200, 0:200]
cv_show("cat", cat)

颜色通道提取合并

1
2
3
4
5
6
7
b,g,r = cv2.split(img)
img = cv2.merge(b, g, r)

# 只保留R
cur_img = img.copy()
cur_img[:, :, 0] = 0
cur_img[:, :, 1] = 0

边界填充

1
2
3
4
5
6
7
8
9
10
11
top_size, bottom_size, left_size, right_size = (50, 50, 50, 50)

# 复制边缘像素
relicate = 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, borderType=cv2.BORDER_REFLECT)
reflect101 = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_REFLECT_101)
# 用另一侧的像素来填充
wrap = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_WRAP)
# 常数填充,指定value参数,0为黑色
constant = cv2.copyMakeBorder(img, top_size, bottom_size, left_size, right_size, borderType=cv2.BORDER_CONSTANT, value=0)

Pasted image 20231024084136.png

数值计算

数组加法,每个数值都加,uint8溢出自动取模

1
2
img += 256
img[:5, :, 1]

两个array shape 相同时,同样可以相加

1
2
3
4
5
# 溢出自动取模
img1 += img2
img1[:5, :. 1]
# 不溢出,加到最大值255
cv2.add(img1, img2)[:5, :, 0]

图像融合

概念:广播操作

  1. 通过适当复制元素来扩展一个或两个数组,以便在转换之后,两个张量具有相同的形状;
  2. 对生成的数组执行按元素操作。

如果直接相加

1
2
3
img1 + img2 # shape相同正常
# shape 不同
ValueError: operands could not be broadcast(广播机制) with shape (h, w, c) (h, w, c)

resize 后相加

1
2
3
4
5
6
7
8
img1 = cv2.resize(img_dog, (h, w))

co = cv2.resize(img, (0, 0), fx=3, fy=1) # w伸长三倍
# plt.imshow(co, 'gray')
# 权重相加
# res = a*img1 + b*img2 + bias
# a, b权重
res = cv2.addWeighted(img1, 0.4, img2, 0.6, 0)

图像阈值

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

  • src: 输入图,只能输入单通道图像,通常灰度图
  • dst: 输出图
  • thresh: 阈值
  • maxval: 当像素值超过了阈值(或小于阈值,由type决定),所赋予的值
  • type: 二值化操作的类型,包含以下五种类型:
  • THRESH_BINARY 超过阈值部分取最大值,否则取零
  • THRESH_BINARY_INV THRESH_BINARY反转
  • THRESH_TRUNC 截断,大于阈值部分设为阈值,否则不变
  • THRESH_TOZERO 大于阈值部分不变,否则设为0
  • THRESH_TOZERO_INV 反转
    Pasted image 20231025.png

图像平滑处理

均值滤波

平均卷积操作

1
blur = cv2.blur(img, (3, 3))

方框滤波

和均值滤波一样,但可以选择归一化

1
2
3
box = cv2.boxFilter(img, -1, (3, 3), normalize=True) # 与均值滤波相同
box = cv2.boxFilter(img, -1, (3, 3), normalize=False)
# 只相加,不作均值操作,溢出保留最大值

高斯滤波

1
2
3
# 高斯滤波
# 高斯模糊的卷积核里的数值满足高斯分布,中间的权重比较大
aussian = cv2.GaussianBlur(img, (9,9), 1)

中值滤波

1
2
median = cv2.medianBlur(img, 5)
# 一般中值滤波可快速解决噪点问题

多张图片同时显示

1
2
3
4
res = np.hstack((img1, img2, ...))
show(res)
res = np.vstack((img1, img2, ...))
show(res)