ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java实现特征保持的图像加密算法

2021-06-12 14:29:57  阅读:225  来源: 互联网

标签:Java int float rgb widthI 图像 x2 new 加密算法


算法说明

算法用灰度图作为输入输出。

  1. 图像加密
    (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将各块内像素进行置乱处理。
  2. 图像解密基本是加密的逆过程。
  3. 特征提取。当用户向远程服务器发出图像查询请求时,允许云服务器直接在密文图像中提取图像特征。该加密算法保证了加密前后,图像分块均值直方图保持不变。图像特征提取过程为:
    (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,int,float,rgb,widthI,图像,x2,new,加密算法
来源: https://blog.csdn.net/qq_37348364/article/details/117845784

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有