原理及步骤:

1、旋转角度:图像顺时针或逆时针旋转的角度,以θ表示,需要用户输入;

2、旋转中心:一般以图像中心作为旋转中心,周围像素围绕其旋转;

3、画布大小:由于图像旋转后产生的图像宽和高与原始图像不同,需要先计算好旋转后的画布大小。由于一般处理的图像都是矩形阵列,不考虑特殊形状前提下,我们只需要计算原始图像四个角点坐标围绕中心旋转θ角度后的坐标,取X方向最大最小值之差作为画布宽,Y方向最大最小值之差作为画布高,以此生成一幅空图像;

4、像素赋值:得到画布图像之后,将画布坐标系与原始图像坐标系进行统一,即画布中心与原始图像中心都改正为(0,0)位置,将画布上每个像素进行θ角的反方向旋转,即旋转回原始图像位置,如果旋转后的像素落在原始图像坐标范围内,取该位置最近像素RGB值作为画布上对应像素RGB值;

5、空像素处理:由于旋转后,画布上可能有部分区域在原图没有对应范围,这部分像素为空像素,也可以叫做背景像素,这部分像素可以通过自定义背景色进行赋值。如果输出图片格式为jpg,由于Windows图片浏览工具背景色为白色,建议将背景色输出为白色;

6、背景色透明:如果需要将画布中空像素设置为透明,需要在初始化画布时将画布类型设置为TYPE_INT_ARGB,即png图像对应的格式,输出时也输出为png格式图像即可。

图像旋转java实现:

1、由于java中math三角函数都是以弧度进行计算的,需要将角度转换为弧度。

double angle = theta * Math.PI / 180;

2、计算按照逆时针旋转θ角度后画布大小,即X和Y方向旋转后最大最小值。因为旋转为图像中心,由于中心对称,只需要计算对角线上其中一个坐标,对角线另一个取负即可,之后对四个值进行排序并返回排序后数组。取第一和第二象限两个角点进行计算,先计算原图第一象限角点相对坐标系弧度,第二象限相对坐标系弧度=π-第一象限弧度。

获取X方向旋转后坐标数组:先计算第一象限角点相对中心距离radius,计算该角点弧度angle1,通过反余弦计算得到,再通过计算原图本身弧度加上旋弧度angle后的余弦。

private double[] getX(int i, int j, double angle) {double results[] = new double[4];double radius = Math.sqrt(i * i + j * j);double angle1 = Math.acos(i / radius);results[0] = radius * Math.cos(angle1 + angle);results[1] = radius * Math.cos(Math.PI - angle1 + angle);results[2] = -results[0];results[3] = -results[1];Arrays.sort(results);return results;}

获取Y方向旋转后坐标数组:

private double[] getY(int i, int j, double angle) {double results[] = new double[4];double radius = Math.sqrt(i * i + j * j);double angle1 = Math.asin(j / radius);results[0] = radius * Math.sin(angle1 + angle);results[1] = radius * Math.sin(Math.PI - angle1 + angle);results[2] = -results[0];results[3] = -results[1];Arrays.sort(results);return results;}

3、根据X和Y方向最大最小值作为宽和高生成画布,画布类型根据需要进行设置,需要输出影像背景透明的png图像,类型设置为BufferedImage.TYPE_INT_ARGB,如果原始图像为png格式,也可以直接使用image.getType(),用原始图像格式进行赋值。

int WIDTH = (int) (xCoords[3] - xCoords[0]);int HEIGHT = (int) (yCoords[3] - yCoords[0]);BufferedImage resultImage = new BufferedImage(WIDTH, HEIGHT,                                                 BufferedImage.TYPE_INT_ARGB);

4、对画布每一个像素位置进行逐一计算,计算每个位置按照顺时针旋转θ角后位置,判断该位置是否在原图范围内,在原图范围内,则直接取原图上该位置rgb值对画布对应像素进行赋值,原图范围以外的,通过预先传入的背景色参数进行赋值。由于画布上像素相对坐标系弧度是通过反余弦函数计算的,反余弦取值为(0,π),对于第三四象限的像素,通过判断y坐标是否大于0,大于0则直接计算,小于0,说明该像素位于三四象限,通过计算2π减去反余弦后弧度得到该像素相对坐标系弧度。

for (int i = 0; i < WIDTH; i++) {for (int j = 0; j < HEIGHT; j++) {int x = i - WIDTH / 2;int y = HEIGHT / 2 - j;double radius = Math.sqrt(x * x + y * y);double angle1;if (y > 0) {angle1 = Math.acos(x / radius);} else {angle1 = 2 * Math.PI - Math.acos(x / radius);}x = (int) (radius * Math.cos(angle1 - angle));y = (int) (radius * Math.sin(angle1 - angle));if (x < (width / 2) & x > -(width / 2) & y < (height / 2) & y > -(height / 2)) {int rgb = image.getRGB(x + width / 2, height / 2 - y);resultImage.setRGB(i, j, rgb);}else {int rgb = ((0 & 0xff) << 24) | ((backgroundColor.getRed() & 0xff) << 16) | ((backgroundColor.getGreen() & 0xff) << 8)| ((backgroundColor.getBlue() & 0xff));resultImage.setRGB(i, j, rgb);}}}

5、完整的程序实现及测试

public class ImageRotate {/*** 创建任意角度的旋转图像* @param image* @param theta* @param backgroundColor* @return*/public BufferedImage rotateImage(BufferedImage image, double theta,Color backgroundColor) {int width = image.getWidth();int height = image.getHeight();double angle = theta * Math.PI / 180; // 度转弧度double[] xCoords = getX(width / 2, height / 2, angle);double[] yCoords = getY(width / 2, height / 2, angle);int WIDTH = (int) (xCoords[3] - xCoords[0]);int HEIGHT = (int) (yCoords[3] - yCoords[0]);BufferedImage resultImage = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB);for (int i = 0; i < WIDTH; i++) {for (int j = 0; j < HEIGHT; j++) {int x = i - WIDTH / 2;int y = HEIGHT / 2 - j;double radius = Math.sqrt(x * x + y * y);double angle1;if (y > 0) {angle1 = Math.acos(x / radius);} else {angle1 = 2 * Math.PI - Math.acos(x / radius);}x = (int) (radius * Math.cos(angle1 - angle));y = (int) (radius * Math.sin(angle1 - angle));if (x < (width / 2) & x > -(width / 2) & y < (height / 2) & y > -(height / 2)) {int rgb = image.getRGB(x + width / 2, height / 2 - y);resultImage.setRGB(i, j, rgb);}else {int rgb = ((0 & 0xff) << 24) | ((backgroundColor.getRed() & 0xff) << 16) | ((backgroundColor.getGreen() & 0xff) << 8)| ((backgroundColor.getBlue() & 0xff));resultImage.setRGB(i, j, rgb);}}}return resultImage;}// 获取四个角点旋转后Y方向坐标private double[] getY(int i, int j, double angle) {double results[] = new double[4];double radius = Math.sqrt(i * i + j * j);double angle1 = Math.asin(j / radius);results[0] = radius * Math.sin(angle1 + angle);results[1] = radius * Math.sin(Math.PI - angle1 + angle);results[2] = -results[0];results[3] = -results[1];Arrays.sort(results);return results;}// 获取四个角点旋转后X方向坐标private double[] getX(int i, int j, double angle) {double results[] = new double[4];double radius = Math.sqrt(i * i + j * j);double angle1 = Math.acos(i / radius);results[0] = radius * Math.cos(angle1 + angle);results[1] = radius * Math.cos(Math.PI - angle1 + angle);results[2] = -results[0];results[3] = -results[1];Arrays.sort(results);return results;}public static void main(String[] args) throws Exception {File input = new File("C:/Users/admin/Desktop/1.jpg");File output = new File("C:/Users/admin/Desktop/2.png");BufferedImage image = ImageIO.read(input);Color bgColor = new Color(255, 255, 255);BufferedImage result = new ImageRotate().rotateImage(image, 45,bgColor);ImageIO.write(result, "png", output);}
}

测试图像:

旋转45度后生成的png图像:

java图像处理之实现任意角度图像旋转相关推荐

  1. unity物体自身轴旋转_unity3D实现物体任意角度自旋转

    本文实例为大家分享了unity3D实现物体任意角度自旋转的具体代码,供大家参考,具体内容如下 主要涉及函数: Input.GetAxis("Mouse x") 可取得鼠标横向(x轴 ...

  2. JAVA对图片的任意角度旋转,以及镜像操作

    package relevantTest; /*  * 该代码实现了对图像的水平镜像变换,垂直镜像变换,任意角度旋转,jtf的实时监控,以及对图像的缩放变换,以及按钮的若隐若现效果.  * 在对图像进 ...

  3. 利用opencv对图像和检测框做任意角度的旋转

    一.钢筋比赛中的数据扩充  #coding:utf-8 #数据集扩增 import cv2 import math import numpy as np import xml.etree.Elemen ...

  4. unity物体自身轴旋转_unity3D中物体实现任意角度自旋转

    主要涉及函数: Input.GetAxis("Mouse x") 可取得鼠标横向(x轴)移动增量 Input.GetAxis("Mouse y") 可取得鼠标竖 ...

  5. Android xml布局view进行任意角度的旋转

    代码实现: layout.setOritation(int Degree); 注意这里是错的,应该是:layout.setRotation(int Degree); XML实现: 设置android: ...

  6. 图形图像处理-之-任意角度的高质量的快速的图像旋转 上篇 纯软件的任意角度的快速旋转

    (2009.03.09  可以到这里下载旋转算法的完整的可以编译的项目源代码:  http://blog.csdn.net/housisong/archive/2009/03/09/3970925.a ...

  7. c++实现图像旋转任意角度

    图形图像处理-之-任意角度的高质量的快速的图像旋转 上篇 纯软件的任意角度的快速旋转                                 HouSisong@GMail.com   200 ...

  8. C# 使用 GDI+ 实现添加中心旋转(任意角度)的文字

    这篇文章是 GDI+ 总结系列的第三篇,如果对 GDI+ 的基础使用不熟悉的朋友可以先看第一篇文章<C# 使用 GDI+ 画图>. 需求 需求是要实现给图片添加任意角度旋转的文字,文字的旋 ...

  9. 任意角度旋转图片的ground truth目标检测框

    任意角度旋转图片的ground truth目标检测框 (感谢前辈)转自:https://zhuanlan.zhihu.com/p/72129125 因为检测一个物体的时候需要对目标进行多个任意角度的旋 ...

最新文章

  1. StringBuffer的delete方法与deleteCharAt方法的区别。
  2. mysql怎么防止误操作_MySQL数据库防止人为误操作的实例讲解
  3. 使用Spring Cloud Function框架进行面向函数的编程
  4. SNMP监控一些常用OID的总结
  5. 对象的内置属性和js的对象之父Object()
  6. 一文整理四六级考前必背知识点【精简版】
  7. .NET Core TDD前传: 编写易于测试的代码 -- 缝
  8. Python学习1 基础语法 数据类型 计算机基础
  9. android Listview2 笔记
  10. 一、开始动手开发网球平台
  11. 3d激光雷达开发(ransac的思想)
  12. JavaScript延时函数
  13. 升级到IE11,IE11调试F12 空白没法调试
  14. html p标签嵌套a,HTML标签嵌套规则详细归纳适合新手朋友
  15. php安全漏洞怎么修复,thinkphp漏洞如何修复
  16. 银行硬件维护维修工单小程序开发制作
  17. 汇编语言||存储单元,存储字长,存储字,存储容量的理解
  18. 罗斯福国家森林树木类型识别
  19. android内置sd卡挂载过程,Android获取机身存储、内置SD卡与外置TF卡路径
  20. Python_删除TXT文件中不想要的内容

热门文章

  1. 深度学习在自然语言处理的应用(Version 0.76)
  2. 13行代码AC_2017年省赛C组蓝桥杯第一题 贪吃蛇长度(考查文件读取)
  3. 解题报告——蓝桥杯 试题 基础练习 2n皇后问题(附n皇后代码)
  4. js带开关的时钟_昌利JS系列混凝土搅拌机衬板配件
  5. decimal 类型数据怎么引用_Java基本数据类型和引用类型
  6. oracle with 查询,oracle with 语句实现递归查询
  7. Mysql数据库(二)——mysql数据库管理
  8. 编译MiniGUI 程序
  9. php rdkafka实例,kafka 消息队列 php-rdkafka扩展示例
  10. esxi安装openwrt_双软路由安装——ROS安装、上网、DNS缓存、常用设置(小白教程)...