首页 > 编程知识 正文

像旋转函数,数字像处理旋转矩阵

时间:2023-05-03 16:52:59 阅读:236812 作者:535

今天在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(); // 把水平镜像后的像素矩阵设置回 bufImage bufImage.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五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。