编程实现Arnold变换

1.概念

Arnold变换是由Arnold提出的一种变换,也称猫变换、猫映射。目前Arnold变换主要用于图像置乱。该变换可以在其它图像处理前对图像做预处理,例如在数字盲水印嵌入前对水印进行置乱。也可以用于普通的图像加密。

(1).正变换

这里写图片描述

对于规模为NXNNXN正方形数字图像来说,我们将图像的所有像素集合看作一个NXNNXN的矩阵。在Arnold变换中,设该矩阵中的任意像素位置为(x,y)(x,y),将像素点(x,y)(x,y)按照某种映射变换到另一点(x,y)(x',y')

转换过后,得到如下对应的多项式:

这里写图片描述

(2)逆变换

相当于改变变换矩阵,得到:

这里写图片描述

转换为多项式后对应关系:

这里写图片描述

PS:当变换矩阵为已知的如上的矩阵时此变换被称为狭义的Arnold变换,若变换公式为:

这里写图片描述

或者为:

这里写图片描述

那么此变换被称为广义的Arnold变换
2.周期性

Arnold变换具有周期性

对于数字图像而言,我们仅仅是对图像中像素的位置进行了改变而没有改变其值,如果我们对数字图像迭代地使用Arnold变换,即,将输出作为下一次猫映射的输入,那么迭代一定轮数,图像就会出现置乱的效果。

下图是以256X256256X256的lena灰度图像为例,经过192192次迭代后,每轮为迭代,图像经过192192次变换后恢复了原图像:

这里写图片描述

3.Java代码

 public static void arnoldTransform(File srcImageFile, File desImageFile, int period) { 
    	
   	 BufferedImage srcImage = null;  
     try {  
       	 srcImage = ImageIO.read(srcImageFile);  
     } catch (IOException e) {  
    	 e.printStackTrace();  
     }   
     int width = srcImage.getWidth();  
     int height = srcImage.getHeight(); 
     
     BufferedImage desImage = null;
     if (width != height) {  
    	 System.out.println("此图像不符合要求N x N!"); 
     } 
     else {  
	     int[][] imageMatrix = new int[height][width];  
	     //获取图像每个像素的RGB值
	     for(int i = 0; i < height; i++) {  
	    	 for (int j = 0; j < width; j++) {  
	    		 imageMatrix[i][j] = srcImage.getRGB(i, j);  
	         }  
	     }  
	     int N = width;  
	     int[][] srcMatrix = imageMatrix;  
	     int[][] desMatrix = new int[N][N];  
	     desImage = new BufferedImage(width, height, srcImage.getType());      
	     for (int n = 0; n < period; n++) {  
	    	 if (n != 0) {  
	    		 srcMatrix = desMatrix;  
	             desMatrix = new int[N][N];  
	         }  
		     for (int i = 0; i < N; i++) {  
		    	 for (int j = 0; j < N; j++) {  
		    		 desMatrix[(i + j) % N][(i + 2 * j) % N] = srcMatrix[i][j];  
		         }  
		     }  
	     }       
	     for (int i = 0; i < N; i++) {  
	         for (int j = 0; j < N; j++) {  
	             desImage.setRGB(i, j, desMatrix[i][j]);  
	         }  
	     		}  
     }  
     try {  
          ImageIO.write(desImage, "jpg", desImageFile);  
     } catch (IOException e) {  
          e.printStackTrace();  
     }  
 
   }