使用numpy处理图片——镜像翻转和旋转
在《使用numpy处理图片——基础操作》一文中,我们介绍了如何使用numpy修改图片的透明度。本文我们将介绍镜像翻转和旋转。
镜像翻转
上下翻转

from PIL import Image
import numpy as np
img = Image.open('example.png')
data = np.array(img)# axis=0 is vertical, axis=1 is horizontal
verticalData = np.flip(data, axis=0)
verticalImg = Image.fromarray(verticalData)
verticalImg.save('vertical.png')

左右翻转

from PIL import Image
import numpy as np
img = Image.open('example.png')
data = np.array(img)# axis=0 is vertical, axis=1 is horizontal
horizontalData = np.flip(data, axis=1)
horizontalImg = Image.fromarray(horizontalData)
horizontalImg.save('horizontal.png')

旋转
上面的翻转,又可以称之为镜像翻转。因为得到的图片,只有通过镜子去查看,才是正常的字。

而一般情况下,我们需要的是旋转,即得到的文字还是可以正确识别的。

向左旋转90度
向左旋转90需要通过两个步骤完成:
- 转置
- 上下镜像翻转

def flip_left_90(arr):return np.flip(arr.transpose((1,0,2)), axis=0)
需要解释下transpose传递元组的意思
If specified, it must be a tuple or list which contains a permutation of [0,1,…,N-1] where N is the number of axes of a. The i’th axis of the returned array will correspond to the axis numbered axes[i] of the input. If not specified, defaults to range(a.ndim)[::-1], which reverses the order of the axes.
这句话的意思是,传递的元组要包含该数组所有的维度的值。转换的方法就是对应项相互转置。比如数组最开始时的维度表示是(0,1,2),如果给transpose传递了(1,0,2)。就意味着0维度和1维度转置,2维度保持不变。这个对我们处理图片特别重要,因为2维度保存的是RGBA信息。这个信息不能转置,否则就会导致颜色错乱。

旋转180度
旋转180度有两种方法:
- 两次90度左转。
- 上下镜像翻转后左右镜像翻转。(顺序无所谓)

def flip_180_with_flip_left_90(arr):return flip_left_90(flip_left_90(arr))

def flip_180_with_axis(arr):return np.flip(np.flip(arr, axis=1), axis=0)

向右旋转90度
向右旋转90度,也是向左旋转270度。可以拆解为:
- 3次向左旋转
- 1次180度旋转外加1次90度向左旋转
- 1次90度向左旋转外加1次180度旋转
def flip_right_90_with_left_90(arr):return flip_left_90(flip_left_90(flip_left_90(arr)))def flip_right_90_with_axis_left_90(arr):return flip_left_90(flip_180_with_axis(arr))def flip_right_90_with_left_90_axis(arr):return flip_180_with_axis(flip_left_90(arr))

代码
from PIL import Image
import numpy as np
img = Image.open('example.png')
data = np.array(img)# axis=0 is vertical, axis=1 is horizontal
verticalData = np.flip(data, axis=0)
verticalImg = Image.fromarray(verticalData)
verticalImg.save('vertical.png')horizontalData = np.flip(data, axis=1)
horizontalImg = Image.fromarray(horizontalData)
horizontalImg.save('horizontal.png')def flip_180_with_flip_left_90(arr):return flip_left_90(flip_left_90(arr))def flip_180_with_axis(arr):return np.flip(np.flip(arr, axis=1), axis=0)def flip_left_90(arr):return np.flip(arr.transpose((1,0,2)), axis=0)def flip_right_90_with_left_90(arr):return flip_left_90(flip_left_90(flip_left_90(arr)))def flip_right_90_with_axis_left_90(arr):return flip_left_90(flip_180_with_axis(arr))def flip_right_90_with_left_90_axis(arr):return flip_180_with_axis(flip_left_90(arr))left90Data = flip_left_90(data)
left90Img = Image.fromarray(left90Data)
left90Img.save('flipleft90.png')right90DataFromLeft90 = flip_right_90_with_left_90(data)
right90ImgFromLeft90 = Image.fromarray(right90DataFromLeft90)
right90ImgFromLeft90.save('flipright90fromleft90.png')right90DataFromAxisLeft90 = flip_right_90_with_axis_left_90(data)
right90ImgFromAxisLeft90 = Image.fromarray(right90DataFromAxisLeft90)
right90ImgFromAxisLeft90.save('flipright90fromamxisleft90.png')right90DataFromLeft90Axis = flip_right_90_with_left_90_axis(data)
right90ImgFromLeft90Axis = Image.fromarray(right90DataFromLeft90Axis)
right90ImgFromLeft90Axis.save('flipright90fromleft90amxis.png')left180DataFromLeft90 = flip_180_with_flip_left_90(data)
left180ImgFromLeft90 = Image.fromarray(left180DataFromLeft90)
left180ImgFromLeft90.save('flip180fromleft90.png')left180DataFromAxis = flip_180_with_axis(data)
left180ImgFromAxis = Image.fromarray(left180DataFromAxis)
left180ImgFromAxis.save('flip180fromaxis.png')
参考资料
- https://flat2010.github.io/2017/05/31/Numpy%E6%95%B0%E7%BB%84%E8%A7%A3%E6%83%91/
- https://numpy.org/doc/stable/reference/generated/numpy.transpose.html
相关文章:
使用numpy处理图片——镜像翻转和旋转
在《使用numpy处理图片——基础操作》一文中,我们介绍了如何使用numpy修改图片的透明度。本文我们将介绍镜像翻转和旋转。 镜像翻转 上下翻转 from PIL import Image import numpy as np img Image.open(example.png) data np.array(img)# axis0 is vertical, a…...
HTML5 article标签,<time>...</time>标签和pubdate属性的运用
1、<article>...</article>标签的运用 article标签代表文档、页面或应用程序中独立的、完整的、可以独自被外部引用的内容。它可以是一篇博客或报竟杂志中的文章、一篇论坛帖子、一段用户评论或一个独立的插件,或者其他任何独立的内容。把文章正文放在h…...
Amazing OpenAI API:把非 OpenAI 模型都按 OpenAI API 调用
分享一个有趣的小工具,10MB 身材的小工具,能够将各种不同的模型 API 转换为开箱即用的 OpenAI API 格式。 让许多依赖 OpenAI API 的软件能够借助开发者能够接触到的,非 OpenAI 的 API 私有部署和使用起来。 写在前面 这个小工具软件写于两…...
RK3568平台开发系列讲解(驱动篇)pinctrl 函数操作集结构体讲解
🚀返回专栏总目录 文章目录 一、pinctrl_ops二、pinmux_ops三、pinconf_ops沉淀、分享、成长,让自己和他人都能有所收获!😄 pinctrl_ops:提供有关属于引脚组的引脚的信息。pinmux_ops:选择连接到该引脚的功能。pinconf_ops:设置引脚属性(上拉,下拉,开漏,强度等)。…...
vue购物车案例,v-model 之 lazy、number、trim,与后端交互
购物车案例 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><script src"./js/vue.js"></script> </head> <body> <div id"d1"&…...
云原生Kubernetes: Kubeadm部署K8S 1.29版本 单Master架构
目录 一、实验 1.环境 2.K8S master节点环境准备 3.K8S master节点安装kubelet、kubeadm、kubectl 3.K8S node节点环境准备与软件安装 4.K8S master节点部署服务 5.K8S node节点部署 6.K8S master节点查看集群 7.容器网络(CNI)部署 8.K8S 集群…...
C++协程操作
什么是C++协程 C++中的协程是一种用户态轻量级线程,它拥有自己的上下文和栈,并且协程的切换和调度由用户定义,不需要陷入内核。如同一个进程可以拥有多个线程,一个线程也可以拥有多个协程。协程的优点在于极高的执行效率,因为协程切换不需要陷入内核,而是由用户程序定义切…...
计算机配件杂谈-鼠标
目录 基础知识鼠标的发展鼠标的左右手鼠标的显示样式鼠标的移动和可见性移动可见性 现在的我们的生活工作都基本上离不开电脑了,不管是你平时玩玩游戏,上班工作等等; 今天将关于鼠标的一些小的技巧分享出来,共勉! 基础…...
用Python来制作一个微信聊天机器人
1. 效果展示 通过本地搭建一个flask服务器来接收信息,这里我简单使用展示,就没有对接收的信息进行处理了。 信息接收展示 发送信息展示 这里就直接使用python发送一个post请求即可,可以发送文字或者图片 代码展示 接收信息 #!/usr/bin/e…...
2024年第九届机器学习技术国际会议(ICMLT 2024) 即将召开
2024年第九届机器学习技术国际会议(ICMLT 2024)将于2024年5月24-26日在挪威奥斯陆举行。ICMLT 2024旨在讨论机器学习技术领域的最新研究技术现状和前沿趋势,为来自世界各地的科学家、工程师、实业家、学者和其他专业人士提供一个互动和交流的…...
算法训练day9Leetcode232用栈实现队列225用队列实现栈
今天学习的文章和视频链接 https://programmercarl.com/%E6%A0%88%E4%B8%8E%E9%98%9F%E5%88%97%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html 栈与队列理论基础 见我的博客 https://blog.csdn.net/qq_36372352/article/details/135470438?spm1001.2014.3001.5501 232用栈实现…...
linux驱动(四):platform
本文主要探讨x210驱动的平台设备类型(platform)以及misc设备。 驱动模型 设备驱动模型:总线(bus type)、设备(device)和驱动(driver) 总线:虚拟总线用于挂接驱动驱动和设备 总线、设备、驱动关系:/sys/bus下的子目录…...
Guava:Cache强大的本地缓存框架
Guava Cache是一款非常优秀的本地缓存框架。 一、 经典配置 Guava Cache 的数据结构跟 JDK1.7 的 ConcurrentHashMap 类似,提供了基于时间、容量、引用三种回收策略,以及自动加载、访问统计等功能。 基本的配置 Testpublic void testLoadingCache() th…...
#{}和${}的区别?
#{}是占位符,预编译处理;${}是拼接符,字符串替换,没有预编译处理。Mybatis在处理#{}时,#{}传入参数是以字符串传入,会将SQL中的#{}替换为?号,调用PreparedStatement的set方法来赋值。Mybatis在…...
string的模拟实现
string的模拟实现 msvc和g下的string内存比较成员变量构造函数与析构函数拷贝构造函数赋值拷贝c_str、size和capacity函数以及重载[]、clear、expand_capacity迭代器与遍历reservepush_back、append、insert字符串比较运算符erase<<流提取 >>流插入resizefindsubst…...
算法练习:查找二维数组中的目标值
题目: 编写一个高效的算法来搜索矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性:每行的元素从左到右升序排列。每列的元素从上到下升序排列。 实现: 1. main方法 public static void main(String[] args) {int[][] matrix {{1…...
考研自命题资料、考题如何找
这篇文章是抖音和b站上上传的同名视频的原文稿件,感兴趣的csdn用户可以关注我的抖音和b站账号(GeekPower极客力量)。同时这篇文章也为视频观众提供方便,可以更加冷静地分析和思考。文章同时在知乎发表。 去年我发布了一个视频&am…...
MySQL 存储引擎和索引类型介绍
1. 引言 MySQL 是一个流行的关系型数据库管理系统,提供多种存储引擎以满足不同的业务需求。本文将介绍几种常见的 MySQL 存储引擎和索引类型比较,并给出相应的示例。 2. 存储引擎概述 2.1 InnoDB 存储引擎 InnoDB 是 MySQL 的默认存储引擎࿰…...
element-ui table height 属性导致界面卡死
问题: 项目上,有个点击按钮弹出抽屉的交互, 此时界面卡死 原因分析: 一些场景下(父组件使用动态单位/弹窗、抽屉中使用), element-ui 的 table 会循环计算高度值, 导致界面卡死 github 上的一些 issues 和解决方案: Issues ElemeFE/element GitHub 官方讲是升…...
Vue2.v-指令
v-if 在双引号中写判断条件。 <div v-if"score>90">A</div> <div v-else-if"score>80">B</div> <div v-else>C</div>v-on: :冒号后面跟着事件。 为了简化,可以直接用代替v-on:。 事件名“内联语…...
Hack The Box注册失败?别慌,可能是你的‘上网姿势’不对(附最新可用方案)
Hack The Box注册问题排查与解决方案全指南 注册Hack The Box时遇到各种报错提示是许多技术爱好者共同的困扰。作为全球知名的网络安全实战平台,其注册流程确实存在一些技术门槛需要跨越。本文将系统性地分析注册失败的深层原因,并提供多种经过验证的解决…...
隐写术:把秘密藏在你眼皮底下
你有没有想过,秘密不一定非要“加密”,还可以“藏起来”?这就是隐写术的思想——让别人根本不知道这里藏了信息。早在公元前5世纪,一位希腊人为了把情报传回祖国,把文字写在刮去蜡的木板上,再用新蜡覆盖。收…...
3分钟掌握Windows与Office智能激活:KMS_VL_ALL_AIO终极解决方案
3分钟掌握Windows与Office智能激活:KMS_VL_ALL_AIO终极解决方案 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO 还在为Windows和Office的激活问题烦恼吗?KMS_VL_ALL_AIO作…...
【Sora 2视频集成终极指南】:ChatGPT原生调用、API对接、帧级控制与多模态工作流落地实录(2024官方SDK首曝)
更多请点击: https://intelliparadigm.com 第一章:ChatGPT Sora 2视频集成功能详解 ChatGPT Sora 2 并非官方发布的模型名称,而是社区对 OpenAI 视频生成能力演进方向的一种泛称。当前(截至 2024 年中),O…...
Codex客户端Mac低版本安装解决方法
Codex客户端Mac低版本安装解决方法 关键词:Codex客户端安装、Mac系统版本过低、无法安装Codex、Mac兼容性问题解决、Codex客户端下载、Mac软件安装失败 在实际开发环境里,很多工具对 macOS 版本都有最低要求限制。最近在本地尝试安装 Codex 客户端时&am…...
计算机毕业设计:Python医疗文本挖掘与可视化决策平台 Flask框架 随机森林 机器学习 疾病数据 智慧医疗 深度学习(建议收藏)✅
博主介绍:✌全网粉丝10W,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业项目实战6年之久,选择我们就是选择放心、选择安心毕业✌ > 🍅想要获取完整文章或者源码,或者代做,拉到文章底部即可与…...
保姆级教程:用易语言和大漠插件给游戏做字库,实现自动化文字识别(附模块源码)
零基础实战:易语言与大漠插件游戏字库制作全指南 游戏自动化开发中,文字识别是绕不开的核心技术。想象一下,当你的程序能自动读取任务提示、NPC对话或物品名称时,整个自动化流程就拥有了"眼睛"。本文将彻底拆解大漠插件…...
【音频精修】Melodyne 核心工具实战:从音高微调到节奏重塑
1. Melodyne入门:音频精修的瑞士军刀 第一次打开Melodyne时,我完全被它那些密密麻麻的音符块吓到了。这玩意儿看起来比钢琴卷帘窗还复杂,但用顺手后才发现,它简直是拯救车祸现场录音的神器。作为业内公认的音高校正标杆࿰…...
如何快速提升英雄联盟游戏体验:League-Toolkit智能工具完全指南
如何快速提升英雄联盟游戏体验:League-Toolkit智能工具完全指南 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power 🚀. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 英雄联盟作为全球最…...
SQL中标签的精确清理
在处理字符串数据时,尤其是在处理带有特定标签的数据时,常常会遇到一些棘手的问题。比如,我们想要从一组标签中移除特定标签(如 ‘وسم’),但在移除过程中可能会遇到意外的逗号或者空格问题。在本文中,我们将探讨如何在SQL中通过精确的语句来清理标签,同时解决这些常…...
