1 图像的放大与缩小
2 图像的翻转
3 图像的旋转
4 仿射变换之图像平移
5 仿射变换之获取变换矩阵
6 透视变换
1 图像的放大与缩小
-
resize(src, dsize[, dst[, fx[, fy[, interpolation]]]])
- src: 要缩放的图片
- dsize: 缩放之后的图片大小, 元组和列表表示均可.
- dst: 可选参数, 缩放之后的输出图片
- fx, fy: x轴和y轴的缩放比, 即宽度和高度的缩放比.
- interpolation: 插值算法, 主要有以下几种:
- INTER_NEAREST, 邻近插值, 速度快, 效果差.
- INTER_LINEAR, 双线性插值, 使用原图中的4个点进行插值. 默认.
- INTER_CUBIC, 三次插值, 原图中的16个点.
- INTER_AREA, 区域插值, 效果最好, 计算时间最长.
import cv2 # 导入OpenCV库,用于图像处理
import numpy as np # 导入NumPy库,用于处理数组操作
# 读取图片文件,将它们分别加载到变量dog和cat中
dog = cv2.imread('./dog.jpeg') # 加载狗的图像
cat = cv2.imread('./cat.jpeg') # 加载猫的图像
# 打印图像的形状,确保正确加载图像,并了解它们的尺寸
print(dog.shape) # 输出:狗的图像尺寸 (360, 499, 3) - 3代表RGB通道
print(cat.shape) # 输出:猫的图像尺寸 (480, 640, 3) - 3代表RGB通道
# 将猫的图像调整为与狗的图像相同的大小
new_cat = cv2.resize(cat, (499, 360)) # 将猫的图像大小缩放至 (499, 360)
# 使用不同的插值方法将狗的图像缩放到800x800像素
# # 1. 最近邻插值(INTER_NEAREST):这是最简单的插值方法,直接选择最近的像素。通常会导致图像有较大的像素块感。
# new_dog1 = cv2.resize(dog, (800, 800), interpolation=cv2.INTER_NEAREST)
# # 2. 双线性插值(INTER_LINEAR):常用的插值方法,考虑周围的像素并计算加权平均值。缩放效果较平滑,适用于图像放大。
# new_dog2 = cv2.resize(dog, (800, 800), interpolation=cv2.INTER_LINEAR)
# # 3. 三次插值(INTER_CUBIC):相比于双线性插值更复杂的插值算法,使用16个周围的像素来计算新的像素值,图像放大时更平滑,但速度较慢。
# new_dog3 = cv2.resize(dog, (800, 800), interpolation=cv2.INTER_CUBIC)
# # 4. 像素区域关系重采样(INTER_AREA):通常用于缩小图像,通过考虑像素区域的平均值来生成新的像素,适合于图像缩小时使用。
# new_dog4 = cv2.resize(dog, (800, 800), interpolation=cv2.INTER_AREA)
# 打印缩放后的猫图像的数据(可以删除此行,除非需要调试)
# print(new_cat) # 这会输出图像的像素矩阵值
# 将狗和猫的图像水平拼接在一起并显示
cv2.imshow('new_cat', np.hstack((dog, new_cat))) # np.hstack水平拼接两个图像
cv2.waitKey(0) # 等待用户按任意键后继续(以显示窗口)
cv2.destroyAllWindows() # 关闭所有打开的窗口
2 图像的翻转
- flip(src, flipCode)
- flipCode =0 表示上下翻转
- flipCode >0 表示左右翻转
- flipCode <0 上下 + 左右
# 翻转
import cv2
import numpy as np
#导入图片
dog = cv2.imread('./dog.jpeg')
new_dog = cv2.flip(dog, flipCode=-1)
cv2.imshow('dog', new_dog)
cv2.waitKey(0)
cv2.destroyAllWindows()
3 图像的旋转
- rotate(img, rotateCode)
- ROTATE_90_CLOCKWISE 90度顺时针
- ROTATE_180 180度
- ROTATE_90_COUNTERCLOCKWISE 90度逆时针
# 旋转
import cv2
import numpy as np
#导入图片
dog = cv2.imread('./dog.jpeg')
new_dog = cv2.rotate(dog, rotateCode=cv2.cv2.ROTATE_90_COUNTERCLOCKWISE)
cv2.imshow('dog', new_dog)
cv2.waitKey(0)
cv2.destroyAllWindows()
4 仿射变换之图像平移
-
仿射变换是图像旋转, 缩放, 平移的总称.具体的做法是通过一个矩阵和和原图片坐标进行计算, 得到新的坐标, 完成变换. 所以关键就是这个矩阵.
-
warpAffine(src, M, dsize, flags, mode, value)
-
M:变换矩阵
-
dsize: 输出图片大小
-
flag: 与resize中的插值算法一致
-
mode: 边界外推法标志
-
value: 填充边界值
-
平移矩阵
- 矩阵中的每个像素由(x,y)组成,(x, y)表示这个像素的坐标. 假设沿x轴平移 t x t_x tx, 沿y轴平移 t y t_y ty, 那么最后得到的坐标为 ( x ^ , y ^ ) = ( x + t x , y + t y ) (\hat x, \hat y) = (x + t_x, y + t_y) (x^,y^)=(x+tx,y+ty), 用矩阵表示就是:
# 仿射变换之平移
import cv2
import numpy as np
#导入图片
dog = cv2.imread('./dog.jpeg')
h, w, ch = dog.shape
M = np.float32([[1, 0, 100], [0, 1, 0]])
# 注意opencv中是先宽度, 再高度
new = cv2.warpAffine(dog, M, (w, h))
cv2.imshow('new', new)
cv2.waitKey(0)
cv2.destroyAllWindows()
5 仿射变换之获取变换矩阵
仿射变换的难点就是计算变换矩阵, OpenCV提供了计算变换矩阵的API
- getRotationMatrix2D(center, angle, scale)
- center 中心点 , 以图片的哪个点作为旋转时的中心点.
- angle 角度: 旋转的角度, 按照逆时针旋转.
- scale 缩放比例: 想把图片进行什么样的缩放.
# 仿射变换之平移
import cv2
import numpy as np
#导入图片
dog = cv2.imread('./dog.jpeg')
h, w, ch = dog.shape
# M = np.float32([[1, 0, 100], [0, 1, 0]])
# 注意旋转的角度为逆时针.
# M = cv2.getRotationMatrix2D((100, 100), 15, 1.0)
# 以图像中心点旋转
M = cv2.getRotationMatrix2D((w/2, h/2), 15, 1.0)
# 注意opencv中是先宽度, 再高度
new = cv2.warpAffine(dog, M, (w, h))
cv2.imshow('new', new)
cv2.waitKey(0)
cv2.destroyAllWindows()
-
getAffineTransform(src[], dst[]) 通过三点可以确定变换后的位置, 相当于解方程, 3个点对应三个方程, 能解出偏移的参数和旋转的角度.
-
src原目标的三个点
-
dst对应变换后的三个点
-
import cv2
import numpy as np
# 导入图片
dog = cv2.imread('./dog.jpeg') # 使用cv2.imread读取图片
# 获取图片的高度(h),宽度(w),以及通道数(ch)
h, w, ch = dog.shape
# 定义原始图片中用于仿射变换的三个顶点坐标
# 这三个点是仿射变换之前的点,指定用于计算仿射变换矩阵
src = np.float32([[20, 10], [30, 10], [20, 30]])
# 定义变换后目标图片中对应的三个顶点坐标
# 这些点是原始图片中的三个点在仿射变换后的位置
dst = np.float32([[10, 15], [36, 20], [28, 10]])
# 计算仿射变换矩阵
# cv2.getAffineTransform会根据src和dst的点计算出2x3的仿射变换矩阵M
M = cv2.getAffineTransform(src, dst)
# 对原图像进行仿射变换
# cv2.warpAffine使用仿射变换矩阵M对图片进行仿射变换,输出图片大小为原图的宽(w)和高(h)
new_dog = cv2.warpAffine(dog, M, (w, h))
# 显示仿射变换后的图片
cv2.imshow('new_dog', new_dog)
# 等待键盘事件
cv2.waitKey(0) # 等待按键事件,0表示无限等待
cv2.destroyAllWindows() # 关闭所有窗口
6 透视变换
透视变换就是将一种坐标系变换成另一种坐标系. 简单来说可以把一张"斜"的图变"正".
-
warpPerspective(img, M, dsize,…)
-
对于透视变换来说, M是一个3 * 3 的矩阵.
-
getPerspectiveTransform(src, dst) 获取透视变换的变换矩阵, 需要4个点, 即图片的4个角.
import cv2
import numpy as np
# 导入图片
img = cv2.imread('./123.png') # 使用cv2.imread读取图片
print(img.shape) # 打印图片的尺寸信息,返回的是(高, 宽, 通道数)
# 定义源图像的四个顶点坐标
# 这些坐标是在原图像中的四个点,用于透视变换
src = np.float32([[100, 1100], [2100, 1100], [0, 4000], [2500, 3900]])
# 定义目标图像的四个顶点坐标
# 这些坐标是透视变换后图像中对应的四个点
dst = np.float32([[0, 0], [2300, 0], [0, 3000], [2300, 3000]])
# 计算透视变换矩阵
# 这个矩阵将源图像的四个点映射到目标图像的四个点
M = cv2.getPerspectiveTransform(src, dst)
# 使用计算得到的透视变换矩阵进行图像变换
# cv2.warpPerspective将原图像按照透视矩阵M进行变换,输出尺寸为(2300, 3000)
new = cv2.warpPerspective(img, M, (2300, 3000))
# 创建用于显示原图的窗口,并调整窗口大小
cv2.namedWindow('img', cv2.WINDOW_NORMAL) # 创建窗口 'img'
cv2.resizeWindow('img', 640, 480) # 将窗口 'img' 调整为640x480
# 创建用于显示透视变换后的图像窗口,并调整窗口大小
cv2.namedWindow('new', cv2.WINDOW_NORMAL) # 创建窗口 'new'
cv2.resizeWindow('new', 640, 480) # 将窗口 'new' 调整为640x480
# 显示原图和透视变换后的图像
cv2.imshow('img', img) # 显示原图
cv2.imshow('new', new) # 显示透视变换后的图像
# 等待键盘事件
cv2.waitKey(0) # 无限等待按键输入,0表示无限等待
cv2.destroyAllWindows() # 关闭所有窗口
设计logo
- 1.引入图片
- 2.设计一个logo图片
- 3.规划一个自己的logo,看看放哪里合适,在添加的位置变成黑色
- 4.利用add方法,把logo和图片叠加在一起
import cv2
import numpy as np
dog = cv2.imread('./dog.jpeg')
# 创建logo
logo = np.zeros((200, 200, 3), np.uint8)
# 绘制logo
logo[20: 120, 20: 120] = [0, 0, 255]
logo[80: 180, 80: 180] = [0, 255, 0]
# 掩码
mask = np.zeros((200, 200), np.uint8)
mask[20: 120, 20: 120] = 255
mask[80: 180, 80: 180] = 255
# cv2.imshow('mask', mask)
m = cv2.bitwise_not(mask)
# cv2.imshow('m', m)
# 选择dog添加logo的位置
roi = dog[0: 200, 0: 200]
# roi与m进行与操作, mask先roi,roi做与运算
tmp = cv2.bitwise_and(roi, roi, mask=m)
# cv2.imshow('tmp', tmp)
dst = cv2.add(tmp, logo)
# cv2.imshow('dst', dst)
# 在dog上还原
dog[: 200, : 200] = dst
# cv2.imshow('logo', logo)
cv2.imshow('dog', dog)
cv2.waitKey(0)
cv2.destroyAllWindows()