1.基本变换——缩放
import cv2
import numpy as np
dog = cv2.imread('./dog.jpeg')
cat = cv2.imread('./cat.jpeg')
print(dog.shape)
print(cat.shape)
new_cat = cv2.resize(cat, (499, 360))
print(new_cat.shape)
cv2.imshow('img', np.hstack((dog, new_cat)))
cv2.waitKey()
cv2.destroyAllWindows()
(360, 499, 3)
(480, 640, 3)
(360, 499, 3)
(1)shape是行、列、深度,而cv2.resize是宽、高。故需要修改顺序。
(2)可以修改插值算法,默认是双线性插值
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, 区域插值, 效果最好, 计算时间最长。
(3)可以通过xy轴(fx fy)比例缩放图片
import cv2
import numpy as np
dog = cv2.imread('./dog.jpeg')
cat = cv2.imread('./cat.jpeg')
# new_dog1 = cv2.resize(dog, (640, 480), interpolation=cv2.INTER_NEAREST)
# new_dog2 = cv2.resize(dog, (640, 480), interpolation=cv2.INTER_LINEAR)# 默认效果
# new_dog3 = cv2.resize(dog, (640, 480), interpolation=cv2.INTER_CUBIC)
# new_dog4 = cv2.resize(dog, (640, 480), interpolation=cv2.INTER_AREA)
new_dog = cv2.resize(dog, dsize=None, fx=1.5, fy=0.5, interpolation=cv2.INTER_AREA)
print(new_dog.shape)
cv2.imshow('new_dog', new_dog)
# cv2.imshow('new_dog1', new_dog1)
# cv2.imshow('new_dog2', new_dog2)
# cv2.imshow('new_dog3', new_dog3)
# cv2.imshow('new_dog4', new_dog4)
cv2.imshow('dog', dog)
cv2.waitKey(0)
cv2.destroyAllWindows()
(180, 748, 3)
2.基本变换——翻转
import cv2
import numpy as np
dog = cv2.imread('./dog.jpeg')
# flipCode=0, 表示上下翻转
# flipCode>0, 表示左右翻转
# flipCode <0, 表示上下左右翻转
new_dog = cv2.flip(dog, -1)
# new_dog = dog[::-1, ::-1]
cv2.imshow('dog', np.hstack((dog, new_dog)))
cv2.waitKey(0)
cv2.destroyAllWindows()
Docstring: flip(src, flipCode[, dst]) -> dst . @brief Flips a 2D array around vertical, horizontal, or both axes.
# flipCode=0, 表示上下翻转
# flipCode>0, 表示左右翻转
# flipCode <0, 表示上下左右翻转
3.基本变换——旋转
import cv2
import numpy as np
dog = cv2.imread('./dog.jpeg')
# - ROTATE_90_CLOCKWISE 90度顺时针
# - ROTATE_180 180度
# - ROTATE_90_COUNTERCLOCKWISE 90度逆时针
new_dog = cv2.rotate(dog, rotateCode=cv2.ROTATE_90_COUNTERCLOCKWISE)
print(dog.shape)
print(new_dog.shape)
cv2.imshow('dog', dog)
cv2.imshow('new_dog', new_dog)
cv2.waitKey(0)
cv2.destroyAllWindows()
ROTATE_90_CLOCKWISE 90度顺时针
ROTATE_180 180度
ROTATE_90_COUNTERCLOCKWISE 90度逆时针
只能是规定方向的旋转。
4.仿射变换——图像平移
import cv2
import numpy as np
dog = cv2.imread('./dog.jpeg')
h, w, ch = dog.shape
# 变换矩阵,最少是float32位
M = np.float32([[1, 0, 100], [0, 1, 100]])
# 平移操作
# 注意opencv中是先宽度, 后高度.
new_dog = cv2.warpAffine(dog,M, dsize=(w, h))
cv2.imshow('dog', dog)
cv2.imshow('new_dog', new_dog)
cv2.waitKey(0)
cv2.destroyAllWindows()
Docstring: warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) -> dst . @brief Applies an affine transformation to an image.
-
warpAffine(src, M, dsize, flags, mode, value)
-
M:变换矩阵
-
dsize: 输出图片大小
-
flag: 与resize中的插值算法一致
-
mode: 边界外推法标志
-
value: 填充边界值平移变换矩阵,
细节还是opencv是先宽后高,imread读的图片是numpy.array,是先高后宽,故需要转化。
5.仿射变换——2D旋转——沿一点逆时针旋转角度
# 在进行旋转操作的时候, 不方便手动计算变换矩阵,
# opencv提供了获取变换矩阵的API.
import cv2
import numpy as np
dog = cv2.imread('./dog.jpeg')
h, w, ch = dog.shape
# 获取变换矩阵
# 规定按照逆时针转动图片
M = cv2.getRotationMatrix2D((w/2, h/2), 45, 1)
print(M)
new_dog = cv2.warpAffine(dog, M, (w, h))
cv2.imshow('dog', dog)
cv2.imshow('new_dog', new_dog)
cv2.waitKey(0)
cv2.destroyAllWindows()
[[ 0.70710678 0.70710678 -54.20236252]
[ -0.70710678 0.70710678 229.14392129]]
(1)可以发现opencv生成的矩阵不是方阵,去掉了齐次扩充的部分,只留下了有信息的部分。
(2)同时出现了,不可拼接的现象。只能分开imshow
(3)注意旋转策略,是基于一点进行逆时针旋转,同时旋转角度为角度制。
6.仿射变换——通过三个点
# 通过三个点来确定变换矩阵
import cv2
import numpy as np
dog = cv2.imread('./dog.jpeg')
h, w, ch = dog.shape
src = np.float32([[100, 100], [200, 100], [200, 300]])
dst = np.float32([[150, 150], [250, 150], [150, 250]])
# 需要原始图片的三个点坐标, 和变换之后的三个对应的坐标
M = cv2.getAffineTransform(src, dst)
print(M)
new_dog = cv2.warpAffine(dog, M, (w, h))
cv2.imshow('dog', dog)
cv2.imshow('new_dog', new_dog)
cv2.waitKey(0)
cv2.destroyAllWindows()
[[ 1. -0.5 100. ]
[ 0. 0.5 100. ]]
问题在如何找到与之对应的三个点。
而且从三个点不能直观看到变换矩阵,故通过cv2.getAffineTransform(src, dst)。
getAffineTransform(src[], dst[]) 通过三点可以确定变换后的位置, 相当于解方程, 3个点对应三个方程, 能解出偏移的参数和旋转的角度.
-
src原目标的三个点
-
dst对应变换后的三个点
7.透视变换
cv2.warpPerspective(src, M, dsize, dst=None, flags=None, borderMode=None, borderValue=None)
参数说明:
src:输入图像
M:变换矩阵
dsize:目标图像shape
flags:插值方式,interpolation方法INTER_LINEAR或INTER_NEAREST
borderMode:边界补偿方式,BORDER_CONSTANT or BORDER_REPLICATE
borderValue:边界补偿大小,常值,默认为0
-
warpPerspective(img, M, dsize,....)
-
对于透视变换来说, M是一个3 * 3 的矩阵.
-
getPerspectiveTransform(src, dst) 获取透视变换的变换矩阵, 需要4个点, 即图片的4个角.
import cv2
import numpy as np
img = cv2.imread('./123.png')
print(img.shape)
# 获取变换矩阵
# src是原图的4个坐标
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)
print(M)
# 透视变换
new_img = cv2.warpPerspective(img, M, (2300, 3000))
cv2.namedWindow('img', cv2.WINDOW_NORMAL)
cv2.resizeWindow('img', 640, 480)
cv2.imshow('img', img)
cv2.namedWindow('new_img', cv2.WINDOW_NORMAL)
cv2.resizeWindow('new_img', 640, 480)
cv2.imshow('new_img', new_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
(4032, 3024, 3)
[[ 1.23647876e+00 4.26371986e-02 -1.70548794e+02]
[ 9.09494702e-17 1.43801235e+00 -1.58181359e+03]
[-1.52727120e-05 9.75196514e-05 1.00000000e+00]]