文章目录
OpenCV学习——图像基础与几何变换
0. 版本信息
产品 | 版本 |
---|---|
Python | 3.7 |
Anaconda | 4.8.3 |
Jupyter | 6.0.3 |
OpenCV | 3.4.2 |
1. 导包
import cv2
import numpy as np
print(cv2.__version__)
2. 图像基础
2.1 图片的读取、展示、保存
- 读取图片并展示
# 读取相对路径为./test03.jpg的图片 img = cv2.imread("./test03.jpg", 1) # 展示图片到名为picture的窗口 cv2.imshow("picture", img) # 等待按键,如果按下的是q,那么关闭所有窗口 if cv2.waitKey() == ord("q"): cv2.destroyAllWindows() # cv2.destroyWindow("picture") # 关闭某个名称的窗口
- 保存与压缩图片
# jpg 设置保存图片的质量,有损压缩 img = cv2.imread("test03.jpg", 1) cv2.imwrite("test03_copy_0.jpg", img, [cv2.IMWRITE_JPEG_QUALITY, 0]) cv2.imwrite("test03_copy_10.jpg", img, [cv2.IMWRITE_JPEG_QUALITY, 10]) cv2.imwrite("test03_copy_50.jpg", img, [cv2.IMWRITE_JPEG_QUALITY, 50]) cv2.imwrite("test03_copy_80.jpg", img, [cv2.IMWRITE_JPEG_QUALITY, 80])
# png 无损压缩,透明度,压缩比 0-10 值越低,压缩率越低 img = cv2.imread("test03.jpg", 1) cv2.imwrite("test03_copy_0.png", img, [cv2.IMWRITE_PNG_COMPRESSION, 0]) cv2.imwrite("test03_copy_3.png", img, [cv2.IMWRITE_PNG_COMPRESSION, 3]) cv2.imwrite("test03_copy_5.png", img, [cv2.IMWRITE_PNG_COMPRESSION, 5]) cv2.imwrite("test03_copy_8.png", img, [cv2.IMWRITE_PNG_COMPRESSION, 8]) cv2.imwrite("test03_copy_10.png", img, [cv2.IMWRITE_PNG_COMPRESSION, 10])
2.2 图片的基本信息
- 图片的维度(包含高度、宽度、像素点的三个通道值)
print(img.shape)
(512, 820, 3)
- OpenCV中一个像素点的表示方式(BGR)
# 获取其中的一个像素点 # opencv中表示的方式为 BGR (即第一个是蓝色通道的值,第二个是绿色通道的值,第三个是红色通道的值) print(img[100, 150])
[203 109 36]
- 其他信息
# 每个元素的数据类型 uint8 即0-255 print(img.dtype) # 图像大小 height * width * channels print(img.size)
uint8 1259520
2.3 修改图片像素点的颜色信息
- 修改像素点
# 方式1 修改为黑色 img[90, 160] = [0, 0, 0] print(img[90, 160]) # 方式2 性能更好,但需要一个一个设置 # 红色 img.itemset((90, 170, 0), 0) img.itemset((90, 170, 1), 0) img.itemset((90, 170, 2), 255) print(img[90, 170])
[0 0 0] [ 0 0 255]
- 画一条线
# 画一条线 for i in range(0, 300): img[100, i] = [0, 0, 255] cv2.imshow("picture", img) if cv2.waitKey() == ord("q"): cv2.destroyAllWindows()
2.3 拆分与合并颜色三通道
- 拆分与合并颜色三通道
# 拆分通道 b, g, r = cv2.split(img) # 合并三通道 img = cv2.merge((b, g, r)) # 只有单通道的值,此时是灰度图 print(b)
[[163 163 162 ... 173 173 173] [164 164 163 ... 175 175 175] [165 165 164 ... 174 175 175] ... [ 42 39 39 ... 51 52 52] [ 49 41 38 ... 66 67 66] [ 41 38 38 ... 96 95 95]]
- 对应通道的灰度图
# 单独展示蓝色通道的值(灰度图) cv2.imshow('blue', b) if cv2.waitKey() == ord("q"): cv2.destroyAllWindows() # 获取某个区域红色通道对应的灰度图 red_flower_img = img[180:310, 50:180][:, :, 2] cv2.imshow("red_flower", red_flower_img) if cv2.waitKey() == ord("q"): cv2.destroyAllWindows()
- 修改某块区域为只显示蓝色通道
for i in range(0, 400): for j in range(0, 400): img.itemset((i, j, 1), 0) img.itemset((i, j, 2), 0) cv2.imshow('blue', img) if cv2.waitKey() == ord("q"): cv2.destroyAllWindows()
3. 绘图
3.1 线段、三角形、矩形、圆形、扇形、任意多边形
img = np.zeros((500, 500, 3), np.uint8)
# 画线段
# img, 起点, 终点, 颜色
cv2.line(img, (50, 50), (200, 200), (255, 0, 0))
# img, 起点, 终点, 颜色, 宽度
cv2.line(img, (100, 100), (300, 100), (0, 255, 0), 10)
# img, 起点, 终点, 颜色, 宽度, 线条类型
cv2.line(img, (100, 150), (300, 150), (0, 255, 0), 10, cv2.LINE_AA)
# 画三角形
points = [(400, 300), (300, 360), (240, 240)]
cv2.line(img, points[0], points[1], (0, 0, 255))
cv2.line(img, points[1], points[2], (0, 0, 255))
cv2.line(img, points[2], points[0], (0, 0, 255))
# 画矩形
# img, 左上角, 右下角, 颜色, 是否填充
cv2.rectangle(img, (360, 150), (460, 200), (100, 0, 0), -1)
# 画圆
# img, 圆心, 半径, 颜色, 粗细
cv2.circle(img, (200, 360), (30), (0, 100, 0), 3)
# 扇形
# img, 中心, 轴长, 偏转角度, 起始, 结束, 颜色, 填充
cv2.ellipse(img, (200, 400), (50, 80), 0, 0, 90, (0, 0, 100), -1)
# 任意多边形
points = np.array([[270, 180], [220, 190], [330, 150], [310, 240]])
print(points.shape)
points = points.reshape((-1, 1, 2))
print(points.shape)
print(points)
cv2.polylines(img, [points], True, (255, 255, 255))
cv2.imshow("img", img)
if cv2.waitKey() == ord("q"):
cv2.destroyAllWindows()
3.2 文字、图片
img = cv2.imread("./test03.jpg", 1)
height, width, channels = img.shape
# 画文字
cv2.rectangle(img, (100, 110), (300, 150), (255, 255, 255), 2)
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(img, "Sun Flower", (110, 140), font, 1, (0, 0, 0), 1)
# 复制、画图
img2 = cv2.imread("./test03.jpg", 1)[150:400, 50:300]
height2, width2, channels2 = img2.shape
for i in range(0, height2):
for j in range(0, width2):
img[i, 400 + j] = img2[i, j]
cv2.imshow("img", img)
if cv2.waitKey() == ord("q"):
cv2.destroyAllWindows()
4. 图像的几何变换
4.1 图像截取
flower_img = img[180:310, 50:180]
cv2.imshow("flower", flower_img)
if cv2.waitKey() == ord("q"):
cv2.destroyAllWindows()
4.2 图像缩放
- 方式1
# 获取到高度、宽度的一半的值 img = cv2.imread("./test03.jpg", 1) height, width, channels = img.shape dst_height = int(height / 2) dst_width = int(width / 2) # 进行缩放 dst_img = cv2.resize(img, (dst_width, dst_height)) # 注意先传width,再传height cv2.imshow("dst_img", dst_img) if cv2.waitKey() == ord("q"): cv2.destroyAllWindows()
- 方式2
# 手动实现缩放 img = cv2.imread("./test03.jpg", 1) height, width, channels = img.shape dst_height = int(height / 2) dst_width = int(width / 2) # 缩放 dst_img = np.zeros((dst_height, dst_width, 3), np.uint8) print(dst_img.shape) for i in range(0, dst_height): for j in range(0, dst_width): new_i = int(i * (height / dst_height)) new_j = int(j * (width / dst_width)) dst_img[i, j] = img[new_i, new_j] cv2.imshow("dst_img", dst_img) if cv2.waitKey() == ord("q"): cv2.destroyAllWindows()
- 方式3
# Affine img = cv2.imread("./test03.jpg", 1) height, width, channels = img.shape # 缩放 mat_scale = np.float32([[0.5, 0, 0], [0, 0.5, 0]]) dst_img = cv2.warpAffine(img, mat_scale, (int(width / 2), int(height / 2))) cv2.imshow("dst_img", dst_img) if cv2.waitKey() == ord("q"): cv2.destroyAllWindows()
4.3 图像移动
- 方式1
img = cv2.imread("./test03.jpg", 1) height, width, channels = img.shape # Affine,水平右移100,垂直下移200 matShift = np.float32([[1, 0, 100], [0, 1, 200]]) dst_img = cv2.warpAffine(img, matShift, (width, height)) cv2.imshow("dst_img", dst_img) if cv2.waitKey() == ord("q"): cv2.destroyAllWindows()
- 方式2
# 手动实现移动,右移100 img = cv2.imread("./test03.jpg", 1) height, width, channels = img.shape dst_img = np.zeros(img.shape, np.uint8) for i in range(0, height): for j in range(0, width - 100): dst_img[i, j + 100] = img[i, j] cv2.imshow("dst_img", dst_img) if cv2.waitKey() == ord("q"): cv2.destroyAllWindows()
4.4 图像镜像
img = cv2.imread("./test03.jpg", 1)
height, width, channels = img.shape
dst_img = np.zeros((height * 2, width, channels), np.uint8)
for i in range(0, height):
for j in range(0, width):
dst_img[i, j] = img[i, j] # 原图
dst_img[height * 2 - i - 1, j] = img[i, j] # 反转镜像
cv2.imshow("dst_img", dst_img)
if cv2.waitKey() == ord("q"):
cv2.destroyAllWindows()
4.5 图像旋转
- 平面旋转
img = cv2.imread("./test03.jpg", 1) height, width, channels = img.shape # 旋转矩阵 # 参数:中心点,旋转角度,缩放系数 mat_rotate = cv2.getRotationMatrix2D((width / 2, height / 2), 45, 0.5) dst_img = cv2.warpAffine(img, mat_rotate, (width, height)) cv2.imshow("dst_img", dst_img) if cv2.waitKey() == ord("q"): cv2.destroyAllWindows()
- 空间旋转
img = cv2.imread("./test03.jpg", 1) height, width, channels = img.shape # 左上角、左下角、右上角 mat_src = np.float32([[0, 0], [0, height - 1], [width - 1, 0]]) mat_dst = np.float32([[60, 60], [150, height - 150], [width - 250, 220]]) mat_affine = cv2.getAffineTransform(mat_src, mat_dst) dst_img = cv2.warpAffine(img, mat_affine, (width, height)) cv2.imshow("dst_img", dst_img) if cv2.waitKey() == ord("q"): cv2.destroyAllWindows()