openCV-python(二)图像的几何变换-旋转、缩放

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


运行结果:这个是同时进行了旋转和缩放
image.png

你可能感兴趣的:(openCV-python(二)图像的几何变换-旋转、缩放)