接着上一节关于图像基本要素的介绍之后,今天主要来介绍二维图像的仿射变换处理。
一、放射变换
放射变换是空间直角坐标系的变换,从一个二维坐标变换到另一个二维坐标,仿射变换是一个线性变换,它保持了图像的“平行性”和“平直性”,即图像中原来的直线和平行线,变换后仍然保持原来的直线和平行线,仿射变换比较常用的有平移(Translation)、缩放(Scale)、旋转(Rotation)和剪切(Shear)。
Java中处理放射变换的类主要是: AffineTransform 类,其实通过这个类,我们可以理解,放射变换最主要就是下面的这个3*3的矩阵
[ m00 m01 m02]
[m10 m11 m12]
[ 0 0 1]
那么如何通过放射变换从一个向量X 如何变换到另一个X'向量,主要也是通过上面的这个矩阵来完成
[ x'] [ m00 m01 m02 ] [ x ] [ m00x + m01y + m02 ] [ y'] = [ m10 m11 m12 ] [ y ] = [ m10x + m11y + m12 ] [ 1 ] [ 0 0 1 ] [ 1 ] [ 1 ] 在这个矩阵中,其中m00和m11是控制x和y方向的缩放变换的,m01和m10是控制裁剪变换的,m02和m12是控制平移变换, 其中旋转矩阵是要做相应的变换,也就是这个3*3的矩阵变换为如下: [ cos(theta) -sin(theta) 0 ] [ sin(theta) cos(theta) 0 ]
[ 0 0 1 ] 其中theta表示旋转的角度值。 二、放射变换Java示例 现在我们将下面的这张图进行一个缩放的处理(图片来源于网络)
下面我们看下代码:
public void affineTest() throws IOException { String SCALE_IMAGE = "D:\\test\\affine.jpeg"; BufferedImage resourceImage = ImageIO.read(new File("D:\\test\\1.jpg")); BufferedImage bufferedImage = new BufferedImage(resourceImage.getWidth() ,resourceImage.getHeight(),BufferedImage.TYPE_INT_ARGB); Graphics2D graphics2D = (Graphics2D) bufferedImage.getGraphics(); AffineTransform affineTransform = new AffineTransform(); affineTransform.setToScale(0.5,0.5); //缩放比例 graphics2D.drawImage(resourceImage,affineTransform,null); FileOutputStream fileOutputStream = new FileOutputStream(new File(SCALE_IMAGE)); ImageIO.write(bufferedImage,"png",fileOutputStream); fileOutputStream.flush(); fileOutputStream.close(); }
其中我们可以看到affineTransform.setToScale(0.5,0.5) 图片的宽和高分别按照原来的1/2,进行等比例缩放,我们看下效果
当然如果参数给的都是1,则和原图没有区别。
下面我们再看看平移参数的使用以及效果
public void streamMapTest() throws IOException { String SCALE_IMAGE = "D:\\test\\affine.jpeg"; BufferedImage resourceImage = ImageIO.read(new File("D:\\test\\1.jpg")); BufferedImage bufferedImage = new BufferedImage(resourceImage.getWidth() ,resourceImage.getHeight(),BufferedImage.TYPE_INT_ARGB); Graphics2D graphics2D = (Graphics2D) bufferedImage.getGraphics(); AffineTransform affineTransform = new AffineTransform(); affineTransform.setToTranslation(100,100); //平移参数 graphics2D.drawImage(resourceImage,affineTransform,null); FileOutputStream fileOutputStream = new FileOutputStream(new File(SCALE_IMAGE)); ImageIO.write(bufferedImage,"png",fileOutputStream); fileOutputStream.flush(); fileOutputStream.close(); }
我们看看效果
可以看出,这个平移是以图片左上角为原点,如果参数为正,则是向右和向下平移,如果参数为负,则是向左和向上平移。
下面来看下旋转的粗合理方式,我们将上面的原图旋转30°看下效果,首先看代码
public void streamMapTest() throws IOException { String SCALE_IMAGE = "D:\\test\\affine.jpeg"; BufferedImage resourceImage = ImageIO.read(new File("D:\\test\\1.jpg")); BufferedImage bufferedImage = new BufferedImage(resourceImage.getWidth() ,resourceImage.getHeight(),BufferedImage.TYPE_INT_ARGB); Graphics2D graphics2D = (Graphics2D) bufferedImage.getGraphics(); AffineTransform affineTransform = new AffineTransform(); affineTransform.setToRotation(Math.PI / 6,0,0); graphics2D.drawImage(resourceImage,affineTransform,null); FileOutputStream fileOutputStream = new FileOutputStream(new File(SCALE_IMAGE)); ImageIO.write(bufferedImage,"png",fileOutputStream); fileOutputStream.flush(); fileOutputStream.close(); }
其中 affineTransform.setToRotation(Math.PI / 6,0,0);这句代码就是设置图像的旋转处理
其中第一个参数,单位是弧度,因此我们按照角度,来处理的时候,一定要进行转化弧度,第二个和第三个参数,指的是
旋转的坐标远点,默认是左上角,也可以自己制定,我们来看看按照0,0点旋转30°后的效果
可以看到原始图片被按照0,0点,顺时针旋转30°。
好了,今天关于Java处理二维图像的仿射变换处理,就介绍到这里,内容如果有不妥之处,欢迎各位大佬指正。