openCV函数介绍
cv2的getRotationMatrix2D函数,通过将旋转的中心点坐标,旋转的角度,缩放比例作为参数传入即可得到中间旋转矩阵,warpAffine函数将通过这个矩阵,计算出旋转缩放后的图像,以及坐标(坐标单独有函数进行处理)
# 例子
M = cv2.getRotationMatrix2D((w * 0.5, h * 0.5), angle, scale)
new_image = cv2.warpAffine(Image, M, (int(math.ceil(nw)), int(math.ceil(nh))))
一、旋转和缩放介绍
图像旋转根据角度不同,有不同的处理,因为旋转角度小于90°,图像的四角坐标会改变,但顺序不会变化,保持左上-右上-右下-左下的顺序。但假如旋转的角度为90°,180°,或者270°,都不仅会改变坐标的值,而且会改变图像原来四个角坐标的顺序。这个特点在做图像增强处理的时候是要特别注意的,尤其在处理增强后的图像坐标的时候。
下面关于缩放的介绍内容来自中文手册:
http://woshicver.com/FifthSection/4_2_%E5%9B%BE%E5%83%8F%E5%87%A0%E4%BD%95%E5%8F%98%E6%8D%A2/
缩放只是调整图像的大小。为此,OpenCV带有一个函数cv.resize()。图像的大小可以手动指定,也可以指定缩放比例。也可使用不同的插值方法。首选的插值方法是cv.INTER_AREA用于缩小,cv.INTER_CUBIC(慢)和cv.INTER_LINEAR用于缩放。默认情况下,出于所有调整大小的目的,使用的插值方法为cv.INTER_LINEAR。
本次将旋转和缩放合并在一起,有两个重点需要注意:
1.获得旋转和缩放后的图像
2.获得旋转和缩放后的坐标
代码示例
import cv2
import math
import random
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image, ImageFont,ImageDraw
def rotate_bound(Image,total_points_list):
'''图片倾斜,缩放'''
angle = random.choice([random.randint(0,45),90,180,270]) # 获取随机旋转角度
# 随机缩放
scale = 1
if random.randint(0,1)==0: # 不进行缩放
pass
else:
scale=round(random.uniform(0.5,1.5),1) # 缩放因子
w = Image.shape[1]
h = Image.shape[0]
rangle = np.deg2rad(angle)
nw = (abs(np.sin(rangle) * h) + abs(np.cos(rangle) * w)) * scale
nh = (abs(np.cos(rangle) * h) + abs(np.sin(rangle) * w)) * scale
M = cv2.getRotationMatrix2D((w * 0.5, h * 0.5), angle, scale)
nw = max(w, nw)
nh = max(h, nh)
M[0, 2] += (nw - w) / 2
M[1, 2] += (nh - h) / 2
new_image = cv2.warpAffine(Image, M, (int(math.ceil(nw)), int(math.ceil(nh))))
if angle<=45:
# 获取变换后的坐标
total_points_list =get_points(total_points_list,M)
elif angle==90:
total_points_list = get_points(total_points_list, M)
for i in total_points_list:
i[0], i[1],i[2], i[3],i[4], i[5],i[6], i[7] =i[2], i[3],i[4], i[5],i[6], i[7], i[0], i[1]
elif angle==180:
total_points_list = get_points(total_points_list, M)
for i in total_points_list:
i[0], i[1], i[2], i[3], i[4], i[5], i[6], i[7] = i[4], i[5],i[6], i[7],i[0], i[1],i[2], i[3]
elif angle==270:
total_points_list = get_points(total_points_list, M)
for i in total_points_list:
i[0], i[1], i[2], i[3], i[4], i[5], i[6], i[7]= i[6], i[7],i[0], i[1],i[2], i[3],i[4], i[5]
return new_image,total_points_list
def get_points(points_list, M):
'''坐标转换'''
for i in points_list:
i[0], i[1] = [int(i) for i in list(np.dot(M, np.array([i[0], i[1], 1])))]
i[2], i[3] = [int(i) for i in list(np.dot(M, np.array([i[2], i[3], 1])))]
i[4], i[5] = [int(i) for i in list(np.dot(M, np.array([i[4], i[5], 1])))]
i[6], i[7] = [int(i) for i in list(np.dot(M, np.array([i[6], i[7], 1])))]
return points_list
if __name__ == '__main__':
image = cv2.imread('../myimages/1.jpg')
# 图片原来的固有字段的坐标及值
points_list = []
# 这里txt文本的每行格式为 x1,y2,x2,y2,x3,y3,x4,y4,0,'文本内容' 其中前面8个点为该文本内容的顺时针四个点的坐标,第一个为左上角
with open('../myimages/gt_1.txt','r',encoding='utf-8') as f:
for line in f.readlines():
# 获取前8个元素,也就是四点坐标,后面的是文本内容,可以不用变
data_line = line.split(',')
# 将列表中坐标元素变成int
data = [ int(i) if data_line.index(i)<=7 else i for i in data_line]
points_list.append(data)
# 开始旋转
new_image,points_list = rotate_bound(image,points_list)
# 将新的图片写在本地
cv2.imwrite('new_image.jpg',new_image)
# 将新的坐标也写在本地
f = open('new_image.txt', 'w', encoding='utf-8')
for lab in points_list:
line = ",".join(str(i) for i in lab)
f.write(line)
f.write('\n')
f.close()
# 也可以在窗口查看效果
plt.subplot(121), plt.imshow(image), plt.title('Input')
plt.subplot(122), plt.imshow(new_image), plt.title('Output')
plt.show()