Java 图像处理(二)

接着上一节关于图像基本要素的介绍之后,今天主要来介绍二维图像的仿射变换处理。

一、放射变换

 

放射变换是空间直角坐标系的变换,从一个二维坐标变换到另一个二维坐标,仿射变换是一个线性变换,它保持了图像的“平行性”和“平直性”,即图像中原来的直线和平行线,变换后仍然保持原来的直线和平行线,仿射变换比较常用的有平移(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处理二维图像的仿射变换处理,就介绍到这里,内容如果有不妥之处,欢迎各位大佬指正。

 

 

 

 












 
posted @ 2022-07-03 11:31  开放GIS  阅读(391)  评论(0编辑  收藏  举报