OpenCV
基本操作
创建图像
新建
- 灰度图等价于numpy的二维矩阵
注意
dtype
应为np.unit8
img = np.zeros((720,1280), dtype=np.uint8)
- 彩色图像默认通道顺序为BGR,numpy三维矩阵
img = np.zeros((720,1280,3), dtype=np.uint8)
读取
读取图像
- 参数
cv2.IMREAD_GRAYSCALE
读取为灰度,不带参数默认读取为BGR图像img = cv2.imread("./mask.png", cv2.IMREAD_GRAYSCALE)
- 获取彩色图像的长宽:
h, w = img.shape[:2]
读取视频并逐帧访问
- 读入视频
vidcap = cv2.VideoCapture('source.mp4')
- 逐帧访问
success,image = vidcap.read()
- 参考
import cv2 vidcap = cv2.VideoCapture('source.mp4') success,image = vidcap.read() count = 0 while success: cv2.imwrite("frame%d.png" % count, image) # save frame as JPEG file success,image = vidcap.read() print('Read a new frame: ', success) count += 1
写入
写入图片
cv2.imwrite(filename, img)
颜色空间/数据格式
默认数据类型
- OpenCV默认的彩色图像三个通道依次为B、G、R
- 青色:(255, 255, 0)
- 黄色:(0, 255, 255)
- 紫色:(255, 0, 255)
- 灰度转RGB 转换时将会直接将一个通道的数值复制三份
img2 = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB)
- 转HSV色彩空间
从BGR色彩空间转换为HSV,并取出某个特定通道。H:hue色调,S:saturation饱和度,V:value明度
hsv = cv2.cvtColor(self.img, cv2.COLOR_BGR2HSV) h = hsv[:,:,0] s = hsv[:,:,1] v = hsv[:,:,2]
与其它包所使用的数据类型相互转换
skimage与OpenCV image的互相转换
- skimage转OpenCV image分为两个步骤:
- skimage的mask可能是
numpy.bool_
类型的,先将其转换为数值,转换方式为同理处理mask时可以将其它值替换为0/1mask = np.where(sk_imge==True, 255, 0)
np.where
转换后数据类型为numpy.int32
,使用img.astype(np.uint8)
转换为OpenCV的图像数据类型
- skimage的mask可能是
与Matplotlib或者标准RGB格式的之间的转换
- 色彩空间的转换:
cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
显示图像
-
显示图像可以用
imshow('title', img)
-
使用Matplotlib
- 需将BGR格式转为RGB格式,参考
- 灰度图像以灰色而不是伪彩色显示
plt.imshow(img, cmap='Greys_r', interpolation='nearest')
-
鼠标悬浮在像素上时显示对应点的值(使用Matplotlib):
import matplotlib.pyplot as plt
plt.imshow(masked_image)
plt.show()
- 显示一张图片并等待ESC键退出
def display_img(img):
cv2.imshow('image', img)
show_window = True
while show_window:
k = cv2.waitKey(0) & 0xFF
if k == 27:#ESC
cv2.destroyAllWindows()
show_window = False
- 持续显示(视频)
while True:
## get image here
cv2.imshow('image', img)
if cv2.waitKey(25) & 0xFF == 27:
break
缩放图像
- 使用
cv2.resize()
cropped_img = cv2.resize(img[y1:y2,x1:x2], (640,480))
裁剪图像、将处理后的ROI放回原图像
- 直接通过numpy矩阵进行操作
img_range = [[x1,y1],[x2,y2]]
roi = img[img_range[0][1]:img_range[1][1], img_range[0][0]:img_range[1][0], :]
roi_updated = YOUR_CV_FUNC(roi)
img_update = copy.deepcopy(img)
img_update[img_range[0][1]:img_range[1][1], img_range[0][0]:img_range[1][0], :] = roi_updated
拼接图像
- 直接通过numpy矩阵进行操作
- 水平方向拼接
hori = np.concatenate((img1, img2), axis=1)
- 竖直方向拼接
verti = np.concatenate((img1, img2), axis=0)
直方图
- 注意对一个numpy矩阵求最值时返回的类型将为
<class 'numpy.uint16'>
或者是numpy的浮点数类型,需进行类型转换后再作为calcHist
的参数
x_max = int(img.max())
hist = cv2.calcHist([img],[0],None,[x_max],[0,x_max])
y_max = int(hist[1:,].max())
plt.plot(hist[1:,])
plt.xlim([0,x_max])
plt.ylim([0,y_max])
plt.show()
用矩阵进行图像的旋转拉伸位移与点的变换
- 得到一个旋转角度(单位为度)以及旋转的中心-> 得到变换矩阵 -> 调用
warpAffine
进行旋转
rotate_matrix = cv2.getRotationMatrix2D(center=center, angle=angle, scale=1)
rotated_image = cv2.warpAffine(src=img, M=rotate_matrix, dsize=(width, height))
- 找到点在新的空间中的投射
np.dot(a,b)
和a.dot(b)
的结果是一样的
r_mat = cv2.getRotationMatrix2D((100/2, 300/2),-30,1)
# points
points = np.array([[35., 0.],
[175., 0.],
[105., 200.],
[105., 215.],
])
# add ones
ones = np.ones(shape=(len(points), 1))
points_ones = np.hstack([points, ones])
# transform points
transformed_points = np.dot(r_mat, points_ones.T).T