Numpy+PIL实现图片的自由旋转

news2024/12/22 23:53:37

1.内容简介

使用PIL和Numpy编程实现图片的自由旋转。

2.技术要点

(1)用Python PIL库将图片读取为NumPy 数组。
(2)采用旋转后图像幅面放大的图像旋转变换方式,根据旋转角度和原图像尺寸计算图像像素点的旋转变换矩阵。
(3)用旋转变换矩阵计算原图像四个顶点旋转后的像素坐标,用最大坐标减去最小坐标的方式计算旋转后图像新尺寸,创建存储新图像的NumPy数组。
(4)依据反向映射的方式,扫描新图像的像素,通过逆变换的方式确定对应的原图像像素点,将其RGB值赋给新图像的像素点。
(5)将NumPy数组保存为图像输出。

3.代码实现

def rotateImageWithZoom(image_path: str, rotate_angle: float):
    """
    放大图幅的图片旋转
    :param image_path: 图片路径
    :param rotate_angle: 旋转角度,单位:degree,顺时针为正
    :return: 新的图片numpy数组
    """
    img = Image.open(image_path)
    img_mat = np.asarray(img)
    beta = deg2rad(rotate_angle)
    h = img_mat.shape[0]
    w = img_mat.shape[1]
    K1 = np.array([[0, -1, 0.5 * h], [1, 0, 0.5 * w], [0, 0, 1]])
    K2 = np.array([[cos(beta), sin(beta), 0], [-sin(beta), cos(beta), 0], [0, 0, 1]])
    # 坐标变换矩阵
    K = np.matmul(K1, K2)
    # 旋转后左上角像素点位置
    left_up = np.matmul(K, np.array([[0], [0], [1]]))
    # 旋转后左下角像素点位置
    left_down = np.matmul(K, np.array([[h - 1], [0], [1]]))
    # 旋转后右上角像素点位置
    right_up = np.matmul(K, np.array([[0], [w - 1], [1]]))
    # 旋转后右下角像素点位置
    right_down = np.matmul(K, np.array([[h - 1], [w - 1], [1]]))
    # 确定外接矩形尺寸
    x1 = np.array([left_up.reshape((left_up.shape[0],)),
                   left_down.reshape((left_up.shape[0],)),
                   right_up.reshape((left_up.shape[0],)),
                   right_down.reshape((left_up.shape[0],))]).astype(int)
    # 旋转后图像尺寸
    new_h = np.max(x1[:, 0]) - np.min(x1[:, 0])
    new_w = np.max(x1[:, 1]) - np.min(x1[:, 1])
    x_min = np.min(x1[:, 0])
    y_min = np.min(x1[:, 1])
    # 新图像
    new_img_mat = np.ones((new_h, new_w, 3)) * 255
    # 反向映射
    K_inv = np.linalg.inv(K)
    for x in range(new_img_mat.shape[0]):
        for y in range(new_img_mat.shape[1]):
            old_pos = np.matmul(K_inv, np.array([[x + x_min + 1], [y + y_min + 1], [1]])).astype(int)
            if 0 <= old_pos[0] < h and 0 <= old_pos[1] < w:
                new_img_mat[x, y] = img_mat[old_pos[0], old_pos[1]]
    # numpy数组转图片
    new_img_mat = new_img_mat.astype(int)
    new_img = Image.fromarray(new_img_mat.astype(np.uint8))
    new_img.save('photos/rotated_photo_{}.png'.format(rotate_angle))
    plt.imshow(new_img_mat)
    plt.xlabel("${} ^0$".format(rotate_angle))
    plt.show()
    return new_img_mat.astype(int)

4.实现效果

使用方法如下:

if __name__ == '__main__':
    rotateImageWithZoom('photos/takagi.jpeg', -60.3)

原图:
在这里插入图片描述

旋转-60.3°:
在这里插入图片描述
注意:matplotlib绘制图片时x轴是图片高度,y轴是图片宽度,而一般的图片查看器x轴是宽度,y轴是高度。

5.结果分析

旋转后的图片幅面大小发生了明显变化,放大后也可以看出旋转-61.3°的图片变模糊了,原因是旋转变换时每个像素点被视作为没有尺寸的理想点,旋转后的坐标会出现小数(即亚像素坐标),在反向映射时坐标被取整,故存在舍入误差,导致某些像素点丢失。对于0°,90°,180°和-90°这些角度,舍入误差是0,故旋转后除了图幅改变,清晰度没有变化。
结论对图像做旋转变换时,尽量选择特殊角度,以免像素损失,导致图像质量下降,对于非特殊角度,如-10°,-61.3°等旋转后需要去模糊,才能保证清晰度基本不变

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/108756.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL中 java 的 JDBC 编程使用方法及驱动包的下载和使用

文章目录1.简介2.JDBC 的使用2.1 先安装对应数据库的驱动包~~2.2 把安装好的 jar 驱动包导入到项目中~~2.2.1 在项目中创建目录&#xff0c;把 jar 包拷贝进来。2.2.2 右键创建的目录3.编写数据库代码插入一个记录4.查看插入记录后的数据表5.如何编写代码实现查找操作1.简介 实…

数据库实验2 数据库安全性定义与检查

前言&#xff1a;记得验收时问了一个问题吧&#xff0c;就是用户和角色的区别是什么 实验2.1自主存取控制实验 1.实验目的 掌握自主存取控制权限的定义和维护方法。 2.实验内容和要求 定义用户、角色,分配权限给用户、角色,回收权限,以相应的用户名登录数据库验证权限分配…

分享巧记Linux命令的方法

最近有些学弟经常私信问我说&#xff0c;他们自己是Linux方面的小白&#xff0c;对于Linux的命令了解十分的少&#xff0c;虽然每次跟着我推荐的学习视频教程可以进行操作&#xff0c;但是离开了视频&#xff0c;就又是两眼抓瞎&#xff0c;什么也想不起来。不知道怎么样通过命…

【数据结构】队列与Queue接口

目录 一、队列 二、 Java里的Queue接口 1、概述 2、常用方法 1.入队 2.出队 3.获取队首元素 4、判空 三、单链表实现队列 1、准备字段 2、实现入队 3、实现出队 4、实现获取队首元素 5、实现判空 四、循环队列的实现 1、前言 2、字段准备 3、实现入队 4、实现…

一致性哈希

一、简介 这个算法是一种特殊的哈希算法&#xff0c;目的是解决分布式缓存的问题。 普通哈希算法在分布式存储具有较大的局限性&#xff0c;简单的讲就是难以扩展。 一致性哈希相对而言具有较好的容错性和可扩展性&#xff0c;更加适合现在的分布式存储。 二、经典哈希版本 …

SpringBoot+Vue项目实践课程教学管理平台

文末获取源码 开发语言&#xff1a;Java 使用框架&#xff1a;spring boot 前端技术&#xff1a;JavaScript、Vue.js 、css3 开发工具&#xff1a;IDEA/MyEclipse/Eclipse、Visual Studio Code 数据库&#xff1a;MySQL 5.7/8.0 数据库管理工具&#xff1a;phpstudy/Navicat JD…

✿✿✿JavaScript --- JSON

目录 1.JSON的简介 2.JSON的语法规则 3.JSON 字符串转换为 JavaScript 对象 4.常用的JSON相关的函数 5.JSON对象的遍历 6.补充&#xff1a;JS中的this关键字 1.JSON的简介 JSON&#xff08; JavaScript Object Notation &#xff09; 是用于存储和传输数据的格式&#xf…

Android studio配置大内存,编译速度更快!

本文使用的是windows 10系统&#xff0c;Android studio 版本是Android Studio Chipmunk | 2021.2.1&#xff08;松鼠&#xff09; 目录为什么要配置大内存&#xff1f;默认内存是多少&#xff1f;如何扩大内存配置&#xff1f;这个配置保存在哪个文件&#xff1f;文件在哪里&a…

二叉树10:二叉树的最小深度

主要是我自己刷题的一些记录过程。如果有错可以指出哦&#xff0c;大家一起进步。 转载代码随想录 原文链接&#xff1a; 代码随想录 leetcode链接&#xff1a;111. 二叉树的最小深度 题目&#xff1a; 给定一个二叉树&#xff0c;找出其最小深度。 最小深度是从根节点到最近…

Asp.Net Core实现最基本的Http服务

概述 和.NetFramework时代不同&#xff0c;Core是可以自承载的&#xff0c;也就说开发好的Web项目&#xff0c;可以打包成exe直接运行的&#xff0c;而不必放到IIS这样的环境中。接下来&#xff0c;我们写点代码&#xff0c;体验一下Asp.Net Core自带的Http功能。 初体验 所谓…

嵌入式微功耗RTU的功能与特点介绍、技术参数详情

平升电子嵌入式微功耗RTU&#xff0c;可灵活嵌入至各类仪表、传感器和工业设备中&#xff0c;定时采集设备数据并通过4G/5G/NB-IoT远传至监管软件&#xff0c;实现设备联网。 嵌入式微功耗RTU设计小巧、方便集成&#xff0c;微功耗运行&#xff0c;支持标准水资源/水文/环保/M…

Biotin-PEG-AC,Biotin-PEG-Acrylate,生物素PEG丙烯酸酯线性杂双功能PEG试剂

英文名称&#xff1a;Biotin-PEG-AC&#xff0c;Biotin-PEG-Acrylate 中文名称&#xff1a;生物素-聚乙二醇-丙烯酸酯 生物素-聚乙二醇-丙烯酸酯是一种含有生物素和丙烯酸酯的线性杂双功能聚乙二醇试剂。它是一种有用的带有PEG间隔基的交联或生物结合试剂。生物素能与亲和素和…

智创万物,数赢未来——如何助推数智时代的发展浪潮

数智化核心特征 可视化 消费者的行为可以看得见&#xff0c;生产者的行为也可以看得见。产业互联网或者消费互联网非常重要的一点就是要对消费者行为和生产者行为的可视化&#xff0c;其背后是数字化的力量。 可量化 可量化意味着企业家可以对管理流程进行改造&#xff0c;…

echarts的legend——图例样式的配置

认识图例&#xff1a; 以上几张图表中&#xff0c;红色圆圈部分即图例 echarts图表中的图例&#xff0c;有形状&#xff0c;颜色&#xff0c;位置等等各种样式的不同配置。 echarts官网配置项手册里有非常详细的内容&#xff0c;我们挑几种常用的看看&#xff0c;加深对legend属…

深度学习——物体检测算法:R-CNN,SSD,YOLO(笔记)

一&#xff0c;R-CNN 1.区域卷积神经网络R-CNN 首先从输入图像中提取若干个锚框&#xff0c;并标注好它们的类别和偏移量。然后用卷积神经网络对每一个锚框进行前向传播抽取特征。最后用每个提议区域的特征来预测类别和边界框。 ①使用启发式搜索算法来选择锚框 ②使用预训练…

【第一周学习——认识 O(N*logN) 的排序[ 归并排序 、堆排序、快速排序 ]

前言&#xff1a; &#x1f44f;作者简介&#xff1a;我是笑霸final&#xff0c;一名热爱技术的在校学生。 &#x1f4dd;个人主页&#xff1a;个人主页1 || 笑霸final的主页2 &#x1f4d5;系列专栏&#xff1a;《数据结构与算法》 &#x1f4e7;如果文章知识点有错误的地方&a…

力扣(LeetCode)187. 重复的DNA序列(C++)

哈希表 直观思考&#xff0c;由于限定了答案长度 101010 &#xff0c;只需要一次遍历字符串&#xff0c;统计所有长度为 101010 的子串的出现次数(哈希表) &#xff0c;最后遍历哈希表&#xff0c;维护答案&#xff0c;记录出现 222 次(及以上)的字符串 。 class Solution { …

【BBuf的CUDA笔记】二,解析 OneFlow BatchNorm 相关算子实现

0x1. 前言 在ResNet中&#xff08;https://github.com/pytorch/vision/blob/main/torchvision/models/resnet.py&#xff09;&#xff0c;关于BatchNorm的调用一共有两种模式&#xff0c;第一种是ReLU接在BN之后&#xff1a; out self.bn1(out) out self.relu(out)另外一种…

MicFunPred——最新16S rRNA扩增子数据功能预测数据库

近年来&#xff0c;基于扩增子测序进行物种的功能预测是研究微生物群落功能的主要方面&#xff0c;目前最常用的软件包括Tax4Fun以及PICRUSt2。关于这两款软件的使用方法详可参见凌波微课|扩增子研究第十六讲&#xff1a;扩增子测序结果中的物种功能预测。 Tax4Fun使用最近邻匹…

2022年终总结-两年Androider的成长之路

金句分享 生活金句 1.可难道我们生命中做的每一件事不都是为了被爱得更多一点吗 2.这不只是一种对承诺的恐惧&#xff0c;也不是我缺乏关心和爱的能力&#xff0c;因为我做得到&#xff0c;只不过&#xff0c;老老实实讲。我想 我宁愿为了某件我擅长的事&#xff0c;我能表现…