zoukankan      html  css  js  c++  java
  • 二值信息隐藏(分块和游程编码实现)

    使用分块进行信息隐藏,因为在对角线上的分块上进行的隐藏,所以

    可以明显看到在对角线上有一条线,

    200*200的二值图像

     

    512*512的二值图像

     

    (二)使用游程编码,书上的代码逻辑上有错误,还有一些函数错误,根本不能运行出结果

    自己修改了得到以下结果

     

    200*200的隐藏160位,可以看到微小的变化

     

    512*512的隐藏160位,基本看不到变化

     

    二值对角线分块隐藏代码

    clc;
    clear;
    
    msgfid = fopen('hidden.txt','r'); % 隐藏信息
    [msg, count] = fread(msgfid);
    fclose(msgfid);
    
    msg = dec2bin(msg,8);   %将读入的每个字节转换成二进制
    msg = str2num(msg(:));
    watermarklen = count*8;    % 需要隐藏的数目
    
    [fn,pn] = uigetfile({'*.bmp','bmpfile(*.bmp)';},'chose file');  
    filename = strcat(pn,fn);
    I = imread(filename);  % 将载体分成 count*count 个小块,在对角线隐藏信息
    [row,col] =size(I);
    
    block(1) = floor(row/watermarklen);  % block的row
    block(2) = floor(col/watermarklen);  % block的col
    pixelcount = block(1)*block(2); % 一块的像素数
    
    % 阈值,1的个数必须大于等于此值才能说明隐藏的是1
    % 0 的个数必须大于等于此值才能说明隐藏的是 0
    if mod(pixelcount, 2) == 0 
        threshold = pixelcount/2 + 1;
    else
        threshold = ceil(pixelcount/2);
    end
        
    carrier = I;  % 修改的操作都在carrier上
    
    zeroCount = zeros(1,watermarklen) ;    % 用来记录每小块上0的个数
    oneCount = zeros(1,watermarklen);    % 用来记录每小块上1的个数
    
    % 统计对角线上的小块的0和1
    for n=1:watermarklen
        %使用求和来算出每个小块有多少个·1
        oneCount(1,n) = sum(sum(I(block(1)*(n-1)+1:block(1)*n, block(2)*(n-1)+1:block(2)*n)));
        zeroCount(1,n) = pixelcount - oneCount(1,n);
    end
    %隐藏信息
    for n=1:watermarklen
        
        if msg(n,1) == 1; % 嵌入1
            
            if oneCount(1,n) < threshold; % 但是1小于阈值
                modifycount = threshold - oneCount(1,n);  % 需要修改的数目
                k =1;
                for i =block(1)*(n-1)+1:block(1)*n
                    for j =block(2)*(n-1)+1:block(2)*n
                        if(carrier(i,j) == 0 && k<=modifycount)
                            carrier(i,j) = 1;
                            k = k+1;
                        end
                    end
                end
            end
        else % 嵌入0
            if zeroCount(1,n) < threshold;  % 0的个数小于阈值时需要改
                modifycount = threshold - zeroCount(1,n);
                k =1;
                for i =block(1)*(n-1)+1:block(1)*n
                    for j =block(2)*(n-1)+1:block(2)*n
                         if(carrier(i,j) ==1 && k<=modifycount)
                            carrier(i,j) = 0;
                            k = k+1;
                         end
                    end
                end
            end
        end
    end
    
    %显示结果
    imwrite(carrier,'bwmarked.bmp');  
    figure;
    imshow(filename);
    title('原图');
    figure;
    imshow('bwmarked.bmp');
    title('载体');
    View Code

    提取代码

    clc;
    clear;
    
    [fn,pn] = uigetfile({'*.bmp','bmpfile(*.bmp)';},'chose file');  
    filename = strcat(pn,fn);
    I = imread(filename);  % 将载体分成 count*count 个小块,在对角线隐藏信息
    watermarklen = 160;  % 隐藏的数目
    [row,col] =size(I);
    
    block(1) = floor(row/watermarklen);  % block的row
    block(2) = floor(col/watermarklen);  % block的col
    pixelcount = block(1)*block(2); % 一块的像素数
    
    % 阈值,1的个数必须大于等于此值才能说明隐藏的是1
    % 0 的个数必须大于等于此值才能说明隐藏的是 0
    if mod(pixelcount, 2) == 0 
        threshold = pixelcount/2 + 1;
    else
        threshold = ceil(pixelcount/2);
    end
    
    %提取出的隐藏信息
    hideInfo = zeros(1,watermarklen);
    
    for n=1:watermarklen
        
        %使用求和来算出每个小块有多少个·1
        oneCount = sum(sum(I(block(1)*(n-1)+1:block(1)*n, block(2)*(n-1)+1:block(2)*n)));
        if oneCount >= threshold % 1的数目大于阈值,则隐藏的信息为1
            hideInfo(1, n) = 1;
        else                      % 0的数目大于阈值,则隐藏的信息为0
            hideInfo(1, n) = 0;
        end
    end
    
    
    hideInfo = reshape(hideInfo,length(hideInfo)/8,8);  %将二进制字符串分成n行,8列
    bin = num2str(hideInfo); % 二进制数值转变成二进制字符串
    dec = bin2dec(bin);%二进制字符串转换成十进制数组
    recoverdata = native2unicode(dec);% 本机编码转换成unicode
    fprintf(1, '恢复出的信息: %s
    ',recoverdata);
    View Code

    游程编码隐藏代码

    clc;
    clear;
    
    threshold = 10;
    [fn,pn] = uigetfile({'*.bmp','bmpfile(*.bmp)';},'chose file');  
    filename = strcat(pn,fn);
    oi = imread(filename);
    si = size(oi); % 保存读入图像的行列,以便恢复图像
    oi = oi(:);  % 变成一列, 按列变
    [len, col] = size(oi); %len= row,1
    carrier = oi;   % 以后数据的修改都在carrier上
    
    j=1;
    i=1;
    %统计游程长度
    while(i <= len)
        last = oi(i); % 依次取出每个数
        count = 1;
        while( i+1 <= len && oi(i+1)== last) % 下一个与上一个相同
            i = i + 1;
            count = count + 1;
        end
        RLE(j) = count;
        j = j + 1;
        i = i + 1;
    end
    
    msgfid = fopen('hidden.txt', 'r');
    [msg, msgcount] = fread(msgfid);
    fclose(msgfid);
    
    msg = dec2bin(msg,8);   %将读入的每个字节转换成二进制
    msg = str2num(msg(:));  % 
    msgcount = msgcount*8;    % 需要隐藏的数目
    
    i = 1; % msg 的索引
    count = 1; % RLE的索引,只为奇数 1 3 5...
    sum = 0;
    while count < length(RLE)-1
        addSum = RLE(count) + RLE(count+1);   %相邻两个数相加的和,从1开始
        
        if count >= 3  
            sum = sum + RLE(count - 1) + RLE(count - 2); % 当前count的在数组中的下标-1
        end
        
        if(addSum >= threshold)  % 只有当相邻游程和大于给定数的时候,才隐藏信息
            
            if RLE(count) >= RLE(count+1)
                modifyPoint = sum + RLE(count); % 修改两个游程的临界值,长的那边的
            else
                modifyPoint = sum + RLE(count) + 1;
            end
            
            if(msg(i) == 0)  % 嵌入的信息为0,但是游程为奇数,需要修改
                if(mod(RLE(count), 2) == 1) %RLE(count) == '奇数'   
                    carrier(modifyPoint) = mod(carrier(modifyPoint)+1 ,2); % 修改点的值取反 mod(carrier(modifyPoint)+1 ,2)
                end
            else  % 嵌入的信息为1,但是游程为偶数,需要修改
                if mod(RLE(count), 2) == 0 %RLE(count) == '偶数' 
                    carrier(modifyPoint) = mod(carrier(modifyPoint) + 1 ,2); % 修改点的值取反 mod(carrier(modifyPoint)+1 ,2)
                end
            end
            
            i = i + 1; % 隐藏一个位后, msg索引加1
        end
        
        count = count + 2; %不管有没有隐藏信息,count都要增加
        
        if i == msgcount  % 所有的信息都已隐藏就退出循环
            break;
        end
    end
    
    if i < msgcount
        error('不能隐藏全部信息!');
    end
    
    imwrite(reshape(carrier, si(1),si(2)), 'hide.bmp');
    figure;
    subplot(121);
    imshow(reshape(oi, si(1),si(2)));
    title('原图');
    subplot(122);
    imshow('hide.bmp');
    title('载体');
        
    View Code

    提取代码

    clc;
    clear;
    
    
    %也可以增大隐藏信息的间隔 count 1 5 9 13 以后实现
    threshold = 3;
    [fn,pn] = uigetfile({'*.bmp','bmpfile(*.bmp)';},'chose file');  
    filename = strcat(pn,fn);
    oi = imread(filename);
    oi = oi(:);  % 变成一列, 按列变
    [len, col] = size(oi); %len= row,1
    
    j=1;
    i=1;
    %统计游程长度
    while(i <= len)
        last = oi(i); % 依次取出每个数
        count = 1;
        while( i+1 <= len && oi(i+1)== last) % 下一个与上一个相同
            i = i + 1;
            count = count + 1;
        end
        RLE(j) = count;
        j = j + 1;
        i = i + 1;
    end
    
    i = 1; 
    msgcount = 160;
    msg = zeros(msgcount,1);
    count = 1; % RLE的索引,只为奇数 1 3 5...
    while i <= msgcount
       
        addSum = RLE(count) + RLE(count+1);   %相邻两个数相加的和,从1开始   
        if(addSum >= threshold)  % 只有当相邻游程和大于给定数的时候,才隐藏信息
            if mod(RLE(count),2) == 0
                msg(i) = 0;
            else
                msg(i) = 1;
            end
            i = i + 1;
        end
        count = count + 2;     
    end
    
    hideInfo = reshape(msg,length(msg)/8,8);  %将二进制字符串分成n行,8列
    bin = num2str(hideInfo); % 二进制数值转变成二进制字符串
    dec = bin2dec(bin);%二进制字符串转换成十进制数组
    recoverdata = native2unicode(dec);% 本机编码转换成unicode
    fprintf(1, '恢复出的信息: %s
    ',recoverdata);
    View Code
  • 相关阅读:
    requests库之处理响应
    requests库之自定义request
    requests库之请求异常处理
    requests库之带参请求
    BFS广度优先
    分治模板
    递归模板
    数据机构与算法学习(三)- 数组
    消息队列学习笔记
    数据结构与算法学习(二)
  • 原文地址:https://www.cnblogs.com/YKang/p/9250960.html
Copyright © 2011-2022 走看看