Java实现特征保持的图像加密算法
2021/6/12 14:51:09
本文主要是介绍Java实现特征保持的图像加密算法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
算法说明
算法用灰度图作为输入输出。
- 图像加密
(1)输入密钥key与原图像I
(2)利用logistic映射生成伪随机整数序列P1对图像块进行置乱,改变图像像素在每个块内的位置。
x n + 1 = λ x n ( 1 − x n ) , x n ∈ [ 0 , 1 ] x_{n+1}= \lambda x_{n}\left ( 1-x_{n} \right ),x_{n}\in [0,1] xn+1=λxn(1−xn),xn∈[0,1]
其中 3.569946 … ≤ λ ≤ 4 , 0 < x n < 1 3.569946… \leq \lambda \leq 4 , 0 < x_{n} < 1 3.569946…≤λ≤4,0<xn<1
(3)将图像I分成b*b大小的图像块,利用P1对各图像块进行位置置换。
(4)利用logistic映射生成伪随机整数序列P2,利用P2将各块内像素进行置乱处理。 - 图像解密基本是加密的逆过程。
- 特征提取。当用户向远程服务器发出图像查询请求时,允许云服务器直接在密文图像中提取图像特征。该加密算法保证了加密前后,图像分块均值直方图保持不变。图像特征提取过程为:
(1)将图像分块。
(2)计算各图像均值。
(3)计算分块均值直方图。
效果图
大概就这么个效果。就算密码错误,特征也是一致的。
代码
import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.Arrays; public class Main { public static void main(String[] args) { File I=new File("C:\\Users\\Coyamo\\Desktop\\raw.bmp"); File IW=new File("C:\\Users\\Coyamo\\Desktop\\out.bmp"); File NI=new File("C:\\Users\\Coyamo\\Desktop\\new.bmp"); int pwd=96585678; encode(pwd,I,IW); decode(96595679,IW,NI); int[] f1=getFeature(I); Arrays.sort(f1); System.out.println("I "+Arrays.toString(f1)); int[] f2=getFeature(IW); Arrays.sort(f2); System.out.println("IW "+Arrays.toString(f2)); int[] f3=getFeature(NI); Arrays.sort(f3); System.out.println("NI "+Arrays.toString(f3)); System.out.println(Arrays.equals(f1,f3)&&Arrays.equals(f2,f3));//true } public static int toGray(int color){ int r = (color >> 16) & 0xff; int g = (color >> 8) & 0xff; int b = color & 0xff; return (r*30+g*60+b*10)/100; } //获取特征 public static int[] getFeature(File I){ try { BufferedImage imageI = ImageIO.read(I); int widthI = imageI.getWidth(), heightI = imageI.getHeight(); int sizeI = widthI * heightI; //gray int[] gray =new int[sizeI]; for(int i=0;i<widthI;i++){ for(int j=0;j<heightI;j++){ int color=imageI.getRGB(i, j); gray[j*widthI+i]=toGray(color); } } int b = 20; int col,row; int blockCount=(widthI/b)*(heightI/b); int[] feature=new int[blockCount]; int perRowCount=heightI/b; int perColCount=widthI/b; int avg; //块循环 for (int i = 0; i <blockCount; i++){ col=(i%perColCount)*b; row=(i/perRowCount)*b; avg=0; //块内循环 for (int j = 0; j <b; j++){ for (int k = 0; k <b; k++){ avg+=gray[(row+j)*widthI+col+k]; } } avg/=b*b; feature[i]=avg; } //即求每个块灰度的平均值 return feature; }catch (Exception e){ e.printStackTrace(); } return null; } //加密 public static void encode(int pwd,File I,File IW){ float x0,x0_2; float u = 4f; pwd%=100000000; x0=(pwd%10000)*0.0001f;//1~4 x0_2=(pwd/10000)*0.0001f;//5~8 try { BufferedImage imageI = ImageIO.read(I); int widthI = imageI.getWidth(), heightI = imageI.getHeight(); int sizeI=widthI*heightI; int b=20; //gray int[] gray =new int[sizeI]; for(int i=0;i<widthI;i++){ for(int j=0;j<heightI;j++){ int color=imageI.getRGB(i, j); gray[j*widthI+i]= toGray(color); } } int blockCount=(widthI/b)*(heightI/b); //块置换序列 float[] x = new float[blockCount]; x[0] = x0; for (int i = 0; i < 500; i++) x[0] = u * x[0] * (1 - x[0]); for (int i = 0; i < blockCount - 1; i++) x[i + 1] = u * x[i] * (1 - x[i]); int[] index=sort(x); //块内置换序列 float[] x2 = new float[b*b]; x2[0] = x0_2; for (int i = 0; i < 500; i++) x2[0] = u * x2[0] * (1 - x2[0]); for (int i = 0; i < b*b - 1; i++) x2[i + 1] = u * x2[i] * (1 - x2[i]); int[] index2=sort(x2); int[] rgb=new int[sizeI]; int[] rgb_rep=new int[sizeI]; int col,row; int perRowCount=heightI/b; int perColCount=widthI/b; for (int i = 0; i <blockCount; i++){ col=(i%perColCount)*b; row=(i/perRowCount)*b; int repCol=(index[i]%perRowCount)*b; int repRow=(index[i]/perRowCount)*b; //块置换 for (int j = 0; j <b; j++){ for (int k = 0; k <b; k++){ //复制打乱的块 rgb[(row+j)*widthI+col+k]=gray[(repRow+j)*widthI+repCol+k]; } } //这2个循环应该可以合并。。 //懒得管了 //块内置换 for (int j = 0; j <b; j++){ for (int k = 0; k <b; k++){ //打乱块内像素 int pos=index2[j*b+k]; int nCol=(pos%b); int nRow=pos/b; rgb_rep[(row+j)*widthI+col+k]=rgb[(row+nRow)*widthI+col+nCol]; } } } //灰度值转颜色 for (int i = 0; i <sizeI; i++){ int g=rgb_rep[i]; rgb_rep[i]=g<<16|g<<8|g; } BufferedImage image = new BufferedImage(widthI, heightI, imageI.getType()); image.setRGB(0, 0, widthI, heightI, rgb_rep, 0, widthI); String suffix = I.getName().substring(I.getName().lastIndexOf('.') + 1); ImageIO.write(image, suffix, IW); image.flush(); } catch (IOException e) { e.printStackTrace(); } } //加密的逆过程 public static void decode(int pwd,File IW,File I){ float x0,x0_2; float u = 4f; pwd%=100000000; x0=(pwd%10000)*0.0001f;//1~4 x0_2=(pwd/10000)*0.0001f;//5~8 try { BufferedImage imageIW = ImageIO.read(IW); int widthIW = imageIW.getWidth(), heightIW = imageIW.getHeight(); int sizeIW=widthIW*heightIW; //gray int[] gray =new int[sizeIW]; for(int i=0;i<widthIW;i++){ for(int j=0;j<heightIW;j++){ int color=imageIW.getRGB(i, j); gray[j*widthIW+i]= toGray(color); } } int b=20; int blockCount=(widthIW/b)*(heightIW/b); int perRowCount=heightIW/b; int perColCount=widthIW/b; int col,row; //块置换序列 float[] x = new float[blockCount]; x[0] = x0; for (int i = 0; i < 500; i++) x[0] = u * x[0] * (1 - x[0]); for (int i = 0; i < blockCount - 1; i++) x[i + 1] = u * x[i] * (1 - x[i]); int[] index=sort(x); //块内置换序列 float[] x2 = new float[b*b]; x2[0] = x0_2; for (int i = 0; i < 500; i++) x2[0] = u * x2[0] * (1 - x2[0]); for (int i = 0; i < b*b - 1; i++) x2[i + 1] = u * x2[i] * (1 - x2[i]); int[] index2=sort(x2); int[] rgb=new int[sizeIW]; int[] rgb_rep=new int[sizeIW]; for (int i = 0; i <blockCount; i++){ col=(i%perRowCount)*b; row=(i/perRowCount)*b; for (int j = 0; j <b; j++){ for (int k = 0; k <b; k++){ int pos=index2[j*b+k]; int ncol=(pos%b); int nrow=pos/b; rgb_rep[(row+nrow)*widthIW+col+ncol]=gray[(row+j)*widthIW+col+k]; } } int repCol=(index[i]%perRowCount)*b; int repRow=(index[i]/perRowCount)*b; for (int j = 0; j <b; j++){ for (int k = 0; k <b; k++){ rgb[(repRow+j)*widthIW+repCol+k]=rgb_rep[(row+j)*widthIW+col+k]; } } } for (int i = 0; i <sizeIW; i++){ int g=rgb[i]; rgb[i]=g<<16|g<<8|g; } BufferedImage image = new BufferedImage(widthIW, heightIW, imageIW.getType()); image.setRGB(0, 0, widthIW, heightIW, rgb, 0, widthIW); String suffix = IW.getName().substring(IW.getName().lastIndexOf('.') + 1); ImageIO.write(image, suffix, I); image.flush(); } catch (IOException e) { e.printStackTrace(); } } //根据混沌序列生成置换顺序 private static int[] sort(float[] x){ int size=x.length; int[] index=new int[size]; for (int i = 0; i <size; i++){ index[i]=i; } for (int i = 0; i <size-1; i++) { int min = i; for (int j = i + 1; j < size; j++) { if (x[min] > x[j]) { min = j; } } float temp = x[min]; x[min] = x[i]; x[i] = temp; int temp2 = index[min]; index[min] = index[i]; index[i] = temp2; } return index; } }
总结
这个算法主要以学习为目的,限制图像大小为分块大小的整数倍,且是正方形。里面一些实现也许还可以简化…
这种实现无非是保持像素不变,打乱顺序,保持统计特征一致。关键在于打乱顺序的算法。
这篇关于Java实现特征保持的图像加密算法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-10-06小米11i印度快充版ROM合集:极致体验,超越期待
- 2024-10-06【ROM下载】小米11i 5G 印度版系统, 疾速跃迁,定义新速度
- 2024-10-06【ROM下载】小米 11 青春活力版,青春无极限,活力全开
- 2024-10-05小米13T Pro系统合集:性能与摄影的极致融合,值得你升级的系统ROM
- 2024-10-01基于Python+Vue开发的医院门诊预约挂号系统
- 2024-10-01基于Python+Vue开发的旅游景区管理系统
- 2024-10-01RestfulAPI入门指南:打造简单易懂的API接口
- 2024-10-01初学者指南:了解和使用Server Action
- 2024-10-01Server Component入门指南:搭建与配置详解
- 2024-10-01React 中使用 useRequest 实现数据请求