编程实现Arnold变换
1.概念
Arnold变换是由Arnold提出的一种变换,也称猫变换、猫映射。目前Arnold变换主要用于图像置乱。该变换可以在其它图像处理前对图像做预处理,例如在数字盲水印嵌入前对水印进行置乱。也可以用于普通的图像加密。
(1).正变换
对于规模为的正方形数字图像来说,我们将图像的所有像素集合看作一个的矩阵。在Arnold变换中,设该矩阵中的任意像素位置为,将像素点按照某种映射变换到另一点。
转换过后,得到如下对应的多项式:
(2)逆变换
相当于改变变换矩阵,得到:
转换为多项式后对应关系:
PS:当变换矩阵为已知的如上的矩阵时此变换被称为狭义的Arnold变换,若变换公式为:
或者为:
那么此变换被称为广义的Arnold变换
2.周期性
Arnold变换具有周期性:
对于数字图像而言,我们仅仅是对图像中像素的位置进行了改变而没有改变其值,如果我们对数字图像迭代地使用Arnold变换,即,将输出作为下一次猫映射的输入,那么迭代一定轮数,图像就会出现置乱的效果。
下图是以的lena灰度图像为例,经过次迭代后,每轮为迭代,图像经过次变换后恢复了原图像:
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();
}
}