🍍原文: 图像加密笔记之 Arnold 变换及 Matlab 代码实现
🍍写在前面: 在原文的基础上补全了代码。注意,Matlab 貌似是从 1 开始计数的,而非 0!
1 核心代码
A r n o l d \mathsf{Arnold} Arnold 变换的置乱代码如下:
img_new=zeros(h,w) % h和w分别是原始图像的高度和宽度
for i=1:n % n是置乱的轮数for y=1:hfor x=1:w xx=mod((x-1)+b*(y-1),N)+1; % a和b是可自行指定的参数yy=mod(a*(x-1)+(a*b+1)*(y-1),N)+1; img_new(yy,xx)=img(y,x); endendimg=img_new;
end
A r n o l d \mathsf{Arnold} Arnold 变换的还原代码如下:
img=img_new; % img_new是置乱后的图像
for i=1:nfor y=1:hfor x=1:w xx=mod((a*b+1)*(x-1)-b*(y-1),N)+1;yy=mod(-a*(x-1)+(y-1),N)+1;img_new(yy,xx)=img(y,x);endendimg=img_new;
end
简而言之,置乱就是根据公式重新设置每个像素的位置,还原就是根据公式恢复每个像素原本的位置。
2 完整代码
补全后的代码如下,代码说明见后文:
close all
X = imread('white_bear.jpg');
I = rgb2gray(X);
[h, w]=size(I);N = h; % 等于图片长度和宽度
a = 2; % 设置参数
b = 3; % 设置参数
n = 5; % n为置乱轮数% 置乱--------------------------------------------------
imagesArray = zeros(h, w, 3, n);
img = I;
img_new = zeros(h,w);
for i=1:nfor y=1:hfor x=1:w xx=mod((x-1)+b*(y-1),N)+1;yy=mod(a*(x-1)+(a*b+1)*(y-1),N)+1; img_new(yy,xx)=img(y,x);endendimg = cat(3, img_new, img_new, img_new);imagesArray(:,:,:,i) = img;
endfigure('Name','置乱前后的图像')
subplot(2,3,1);imshow(I);title('原始图像','FontSize',12);for i=1:ntitleStr = ['置乱次数=', num2str(i)];subplot(2,3,1+i);imshow(uint8(imagesArray(:,:,:,i)));title(titleStr,'FontSize',12);
end% 还原--------------------------------------------------
imagesNewArray = zeros(h, w, 3, n);
imagesNewArray(:, :, :, 1) = imagesArray(:, :, :, n);
img = imagesArray(:, :, :, n);for i=2:n+1for y=1:hfor x=1:w xx=mod((a*b+1)*(x-1)-b*(y-1),N)+1;yy=mod(-a*(x-1)+(y-1),N)+1; img_new(yy,xx)=img(y,x); endendimg = cat(3, img_new, img_new, img_new);imagesNewArray(:,:,:,i) = img;
endfigure('Name','还原前后的图像')
for i=1:n+1titleStr = ['还原次数=', num2str(i-1)];subplot(2,3,i);imshow(uint8(imagesNewArray(:,:,:,i)));title(titleStr,'FontSize',12);
end
2.1 初始设置
close all
X = imread('white_bear.jpg');
I = rgb2gray(X);
[h, w]=size(I);N = h; % 等于图片长度和宽度
a = 2; % 设置参数
b = 3; % 设置参数
n = 5; % n为置乱轮数
imread()
:读取原始图像。请根据自己的需求填写图像名;rgb2gray()
:将原始图像转换为灰度图像;size()
:获取原始图像的高度 h \mathsf{h} h 和宽度 w \mathsf{w} w;N = h
:由于我的原始图像比例为 1 : 1 \mathsf{1:1} 1:1,因此填高度或宽度都行。
2.2 置乱操作
我在核心代码的基础上加入了一个数组和画图的代码。
img = I;
img_new = zeros(h, w);
imagesArray = zeros(h, w, 3, n);
- i m g \mathsf{img} img 变量用于存放原始图像;
- i m g _ n e w \mathsf{img\_new} img_new 的大小必须与 i m g \mathsf{img} img 的一致,否则无法赋值;
- i m a g e s A r r a y \mathsf{imagesArray} imagesArray 数组的大小为 n \mathsf{n} n,所存放的变量大小为 h × w × 3 \mathsf{h\times w\times 3} h×w×3;
i m a g e s A r r a y \mathsf{imagesArray} imagesArray 数组用于存储第 i i i 轮的置乱结果,即第 i i i 轮生成的 i m g _ n e w \mathsf{img\_new} img_new,它的大小是 h × w \mathsf{h\times w} h×w。后文会解释为什么还需要一个 3 \mathsf{3} 3。
for i=1:nfor y=1:hfor x=1:w xx=mod((x-1)+b*(y-1),N)+1;yy=mod(a*(x-1)+(a*b+1)*(y-1),N)+1; img_new(yy,xx)=img(y,x);endendimg = cat(3, img_new, img_new, img_new); % 将灰度图像的通道数变为3imagesArray(:, :, :, i) = img;
end
上述代码中,只有倒数第二行、第三行和核心代码的不一样。
cat(3,...)
:在第 3 \mathsf{3} 3 个维度上将 3 \mathsf{3} 3 个 i m g _ n e w \mathsf{img\_new} img_new 拼接起来;imagesArray(:, :, :, i)
:将 i m g \mathsf{img} img 存入 i m a g e s A r r a y \mathsf{imagesArray} imagesArray 数组中;
说明:由于画图代码中的 i m s h o w \mathsf{imshow} imshow 函数要求输入值的大小为 M × N × 3 \mathsf{M\times N\times 3} M×N×3,因此我们需要把 i m g _ n e w \mathsf{img\_new} img_new 这一灰度图像的通道数变为 3 \mathsf{3} 3,即把 3 \mathsf{3} 3 个 i m g _ n e w \mathsf{img\_new} img_new 拼接起来。其中, i m g _ n e w \mathsf{img\_new} img_new 的大小是 M × N × 1 ( M = h , N = w ) \mathsf{M\times N\times 1\ (M=h,N=w)} M×N×1 (M=h,N=w)。
figure('Name','置乱前后的图像')
subplot(2,3,1);imshow(I);title('原始图像','FontSize',12);for i=1:ntitleStr = ['置乱次数=', num2str(i)];subplot(2,3,1+i);imshow(uint8(imagesArray(:,:,:,i)));title(titleStr,'FontSize',12);
end
- f o r \mathsf{for} for 循环前:绘制原始图像;
- f o r \mathsf{for} for 循环内:绘制置乱 i i i 次后的图像。
2.3 还原操作
同样地,我在核心代码的基础上加入了一个数组和画图的代码。
img = imagesArray(:, :, :, n);
imagesNewArray = zeros(h, w, 3, n);
imagesNewArray(:, :, :, 1) = imagesArray(:, :, :, n);
- i m g \mathsf{img} img 变量用于存放置乱 n n n 次后的结果;
- i m a g e s N e w A r r a y \mathsf{imagesNewArray} imagesNewArray 数组用于存放还原 i i i 次后的结果;
i m a g e s N e w A r r a y \mathsf{imagesNewArray} imagesNewArray 数组中的元素与 i m a g e s A r r a y \mathsf{imagesArray} imagesArray 数组中的元素前后对应。后续代码逻辑与置乱操作同理,不再赘述。