今天在Leetcode上看到一个旋转图片的算法,想出几种解决方案之后,便将其实际应用于真实图片的操作,在此将过程分享出来,希望对你有所帮助!

本篇博客只涉及90度及其倍数的角度旋转。


0x01.图片旋转算法概述

  • 给定一个 n × n 的二维矩阵表示一个图像,将图像顺时针旋转 90 度。
  • 例如:
    给定 matrix =
[[1,2,3],[4,5,6],[7,8,9]
],

使其变为:

[[7,4,1],[8,5,2],[9,6,3]
]

0x02.图片旋转算法的三种思路

  • 算法的要求简单理解就是,最上面第一行变成最右边第一列,最上面第二行变成最右边第二列,以此类推。

思路一:引入中间矩阵

  • 这种算法是最容易想到的,只需要引入一个中间矩阵,临时存储每次旋转后的结果即可。

  • 具体每一个元素转换的关系式举个例子就可以发现。

  • 实现代码:

    public void rotate(int[][] matrix) {int n = matrix.length;int[][] matrix_new = new int[n][n];for (int i = 0; i < n; ++i) {for (int j = 0; j < n; ++j) {matrix_new[j][n - i - 1] = matrix[i][j];}}for (int i = 0; i < n; ++i) {for (int j = 0; j < n; ++j) {matrix[i][j] = matrix_new[i][j];}}}

思路二:原地旋转-四个元素轮换

  • 这一思路来源是:如果不适用辅助的矩阵,那么在原地操作一个元素后,必然会覆盖旋转后替代的第二个元素,要想这个元素不被能保留下来,最好的办法是同时对第二个元素也进行旋转,以此类推,完成一次循环,用临时变量保存中间的值,这样旋转一次就没有造成元素的丢失。
  • 具体每一个元素转换的关系式举个例子就可以发现。
  • 实现代码:
    public void rotate2(int[][] matrix) {int n = matrix.length;for (int i = 0; i < n / 2; ++i) {for (int j = 0; j < (n + 1) / 2; ++j) {int temp = matrix[i][j];matrix[i][j] = matrix[n - j - 1][i];matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1];matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];matrix[j][n - i - 1] = temp;}}}

思路三:原地旋转-两次翻转

  • 这应该是最妙的一种方法,对矩阵进行水平轴翻转,再进行主对角线翻转,即可得到旋转后的矩阵。
  • 具体的数学证明略。
  • 实现代码:
    public void rotate(int[][] matrix) {int n = matrix.length;// 水平翻转for (int i = 0; i < n / 2; ++i) {for (int j = 0; j < n; ++j) {int temp = matrix[i][j];matrix[i][j] = matrix[n - i - 1][j];matrix[n - i - 1][j] = temp;}}// 主对角线翻转for (int i = 0; i < n; ++i) {for (int j = 0; j < i; ++j) {int temp = matrix[i][j];matrix[i][j] = matrix[j][i];matrix[j][i] = temp;}}}

0x03.实际应用

  • 使用javax.imageio.ImageIO;, java.awt.image.BufferedImage;完成对图片的操作。
  • 具体代码:(采用第三种思路)
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;public class Rotate {//输入图片路径private static final String INPUT_FILE_PATH="D:\\ATFWUSOSO\\AT-淡蓝简约AT.png";//输出图片路径private static final String OUTPUT_FILE_PATH="new.png";//图片格式private static final String IMAGE_TYPE="PNG";private static int width;private static int height;//操作二维数组private static int[][] newBufImage;//bufImage导出/写入的rgb一维数组private static int[] rgbs;//一维数组转换成二维数组private static void oneToTwo(){int k=0;for(int i=0;i<width;i++){for(int j=0;j<height;j++){newBufImage[i][j]=rgbs[k++];}}}//二维数组转换成一维数组private static void twoToOne(){int k=0;for(int i=0;i<width;i++){for(int j=0;j<height;j++){rgbs[k++]=newBufImage[i][j];}}}public static void rotate(int[][] matrix) {int n = matrix.length;// 水平翻转for (int i = 0; i < n / 2; ++i) {for (int j = 0; j < n; ++j) {int temp = matrix[i][j];matrix[i][j] = matrix[n - i - 1][j];matrix[n - i - 1][j] = temp;}}// 主对角线翻转for (int i = 0; i < n; ++i) {for (int j = 0; j < i; ++j) {int temp = matrix[i][j];matrix[i][j] = matrix[j][i];matrix[j][i] = temp;}}}public static void main(String[] args) throws IOException{//读取图片BufferedImage bufImage = ImageIO.read(new File(INPUT_FILE_PATH));//获取宽高width=bufImage.getWidth();height=bufImage.getHeight();//获取rgb数组rgbs=bufImage.getRGB(0,0,width,height,null,0,width);newBufImage=new int[width][height];//转换成二维数组执行算法oneToTwo();rotate(newBufImage);twoToOne();// 把水平镜像后的像素矩阵设置回 bufImagebufImage.setRGB(0, 0, width, height, rgbs, 0, width);// 把修改过的 bufImage 保存到本地ImageIO.write(bufImage, IMAGE_TYPE, new File(OUTPUT_FILE_PATH));}public static void rotate1(int[][] matrix) {int n = matrix.length;int[][] matrix_new = new int[n][n];for (int i = 0; i < n; ++i) {for (int j = 0; j < n; ++j) {matrix_new[j][n - i - 1] = matrix[i][j];}}for (int i = 0; i < n; ++i) {for (int j = 0; j < n; ++j) {matrix[i][j] = matrix_new[i][j];}}}public void static rotate2(int[][] matrix) {int n = matrix.length;for (int i = 0; i < n / 2; ++i) {for (int j = 0; j < (n + 1) / 2; ++j) {int temp = matrix[i][j];matrix[i][j] = matrix[n - j - 1][i];matrix[n - j - 1][i] = matrix[n - i - 1][n - j - 1];matrix[n - i - 1][n - j - 1] = matrix[j][n - i - 1];matrix[j][n - i - 1] = temp;}}}}
  • 说明:

    • 为了直接使用上述算法,所以进行了一维数组和二维数组的相互转换
    • 可以执行多次达到旋转多次的效果,不过最好使用不同的算法。

旋转图像算法-实际应用相关推荐

  1. 用matlab实现任意点图片的旋转_(实验二) --- 图像旋转变换---matlab实现

    =摘要= 图像处理老师的课很"抽像",很会"跳"....刚讲了一点"RBG转灰度图",就马上进军图像的几何变换了,同时也带来了一个新的实验( ...

  2. 图像算法二:【图像几何变换】平移、镜像、转置、缩放、旋转、插值

    作为一个强大的科学计算软件,MATLAB广泛运用于较多领域,以其简单的编程风格著称.这篇文章便通过matlab语言来讲述如何进行图像的各种几何变换. 图像几何变换又称为图像空间变换,它是将一幅图像中的 ...

  3. 图像算法研究---索引图像旋转缩放锯齿问题

    所谓索引图像 ,就是一种把像素值直接作为RGB调色板下标的图像,把像素值直接映射成调色板中的数值.索引图像最多只包含256种颜色,这256中颜色分别对应0-255个值,也就是256种索引值,一般的真彩 ...

  4. 利用OpenCV实现旋转文本图像矫正的原理及OpenCV代码

    图像处理开发需求.图像处理接私活挣零花钱,请加微信/QQ 2487872782 图像处理开发资料.图像处理技术交流请加QQ群,群号 271891601 对图像进行旋转矫正,关键是要获取旋转角度是多少! ...

  5. 图像算法九:【图像特征提取】特征降维、PCA人脸特征抽取、局部二进制

    PCA数学理论: 关于PCA的理论,资料很多,公式也一大把,本人功底有限,理论方面这里就不列出了.下面主要从应用的角度大概来讲讲具体怎么实现数据集的降维. 把原始数据中每个样本用一个向量表示,然后把所 ...

  6. 图像算法八:【图像分割】边缘检测(Roberts,Sobel,canny)、霍夫变换(hough)、阈值分割、区域分割

    1.我们主要学习以下四种差分算子 Roberts算子 Sobel算子 Prewitt算子 canny算子 % Matlab图像边缘检测梯度算子–Roberts.Prewitt.Sobel.LOG.Ca ...

  7. 图像算法七:【形态学图像处理】二值运算、膨胀、腐蚀

    二值图像腐蚀函数 [算法说明]:二值图像腐蚀操作属于图像形态学的范畴,形态学运算是只针对二值图像进行,并依据数学形态学(Mathermatical Morphogy)集合论方法发展起来的数字图像处理方 ...

  8. 图像算法六:【彩色图像处理】彩色模型、彩图处理

    颜色模型(颜色空间)就是描述用一组数值来描述颜色的数学模型.在彩色图像处理中,选择合适的彩色模型是很重要的.从应用的角度来看,彩色模型可分为两类: 一.面向硬件设备的彩色模型 1.RGB模型 最典型. ...

  9. 图像算法五:【图像小波变换】多分辨率重构、Gabor滤波器、Haar小波

    matlab设计: 与单纯运用某种自适应算法相比,基于小波分解的自适应滤波算法在收敛速度和稳定性上都有了很大的提高 小波变换: 示意:尺度越大,采用越大的时间窗,尺度越小,采用越短的时间窗,即尺度与频 ...

最新文章

  1. 【组队学习】【26期】编程实践(Django网站开发)
  2. 刚刚,YOLOv4重磅更新!快来一睹论文真容吧!
  3. 从ICLR提交论文看机器学习的趋势和风口
  4. 阎崇年:《袁崇焕传》自序
  5. 查看cananl是否启动_振动筛无法启动的3大原因及8大注意事项
  6. es的聚合mysql聚合速度_Elasticsearch(8) --- 聚合查询(Metric聚合)
  7. 写给想转行机器学习深度学习的同学
  8. python程序多线程_Python-多线程编程
  9. elasticsearch-jdbc实现MySQL同步到ElasticSearch深入详解
  10. 【OpenCV 例程200篇】74. 图像的抗混叠
  11. ibm邮件怎么撤回_怎么申请邮箱?163邮箱如何注册使用?
  12. python 学堂在线_最新网课答案2020学堂在线Python 交互式程序设计导论
  13. Zookeeper与Kafka集群搭建
  14. linux 端口映射设置
  15. QQ密技68招(超强)
  16. office 365与Visio共存
  17. CXF框架介绍及Spring集成
  18. 51单片机单片机基础知识
  19. 034 Rust死灵书之为Vec实现Drain
  20. Kettle carte部署与运行

热门文章

  1. PHP调用快递100电子面单接口API接口
  2. 8086汇编基础 mov word ptr 字数据赋值
  3. web前端开发常用浏览器介绍及运行配置
  4. 运维工程师面试的经历及面试相关问题
  5. ntp服务器源码c语言,基于NTP服务器+ Ethernet智能手表(智能表源码+ Ethernet源码+3D打印)...
  6. hctf2016 web 部分WriteUp.md
  7. 不为彼岸,只为大海-----海贼王
  8. oracle 监听程序服务无法启动,ORA-12500: TNS: 监听程序无法启动专用服务器进程
  9. 西门子plc的上升沿和下降沿是什么意思?
  10. 【数字人民币】DCEP接入参考文档1-运作模式介绍