18.opencv 图像变换

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)

18.opencv 图像变换_第1张图片

(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()

18.opencv 图像变换_第2张图片

(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()

18.opencv 图像变换_第3张图片

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: 填充边界值平移变换矩阵, 

18.opencv 图像变换_第4张图片

细节还是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)注意旋转策略,是基于一点进行逆时针旋转,同时旋转角度为角度制。

18.opencv 图像变换_第5张图片

 18.opencv 图像变换_第6张图片

 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. ]]

18.opencv 图像变换_第7张图片

问题在如何找到与之对应的三个点。

 18.opencv 图像变换_第8张图片

而且从三个点不能直观看到变换矩阵,故通过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个角.

18.opencv 图像变换_第9张图片

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]]

你可能感兴趣的:(opencv,opencv)