二值信息隐藏(分块和游程编码实现)

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

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

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(‘载体‘);

提取代码

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\n‘,recoverdata);

游程编码隐藏代码

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(‘载体‘);
    

提取代码

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\n‘,recoverdata);

原文地址:https://www.cnblogs.com/YKang/p/9250960.html

时间: 2024-10-04 08:11:07

二值信息隐藏(分块和游程编码实现)的相关文章

Kinect 2.0 + OpenCV 显示深度数据、骨架信息、手势状态和人物二值图

1.前言 Kinect 2.0实测比第一代性能提升非常多! 本来想简单地找个教程复制黏贴一下,居然还没有人写过C++版的Kinect 2.0教程,自己摸索了一下,现在把结果拿出来和大家分享. 实现的功能是:深度数据(Depth Data),骨架信息(Body Data),手势状态(Hand State)和人物二值图(就是图1的那个东西,微软官方称法是Body Index Data)的提取和显示. 效果如下: 图1 骨架信息,人物二值图和手势状态 图2 深度信息 2.安装 Kinect 2.0的安

二值法方法综述及matlab程序

在某些图像处理当中一个关键步是二值法,二值化一方面能够去除冗余信息,另一方面也会使有效信息丢失.所以有效的二值化算法是后续的处理的基础.比如对于想要最大限度的保留下面图的中文字,以便后续的定位处理. 二值化算法包括全局二值化和局部二值化, 全局二值化具有速度快但效果相对差的特点, 局部二值化算法具有速度慢效果好的特点. 原图 全局阈值              方法一:直接采用im2bw ;手动阈值 方法二:迭代法求阈值 迭代式阈值选取的基本思路是:首先根据图像中物体的灰度分布情况,选取一个近似

(转)从信息隐藏的一个需求看C++接口与实现的分离

原文地址https://blog.csdn.net/tonywearme/article/details/6926649 让我们从stackoverflow上一个同学的问题来开始.问题的原型是这样的(原问题见:class member privacy and headers in C++):Portaljacker:"有一个类A, 有一些共有成员函数和私有数据,如下所示." class A{public: X getX(); Y getY(); Z getZ(); .. private

[转载+原创]Emgu CV on C# (四) —— Emgu CV on 二值化

重点介绍了二值化原理及数学实现,并利用emgucv方法编程实现. 一.理论概述(转载,如果懂图像处理,可以略过,仅用作科普,或者写文章凑字数)  1.概述 图像二值化是图像处理中的一项基本技术,也是很多图像处理技术的预处理过程. 图像的预处理在进行图像二值化操作前要对图像进行预处理,包括彩色图像灰化和增强.由于选取阈值需要参照直方图,因此在图像进行处理后,我们再获取图像的直方图以帮助选取阈值.整个流程如下所示: 读取图像→灰度图像→图像增强→图像直方图→二值化处理 2.数学原理(转载,基本可以不

十三种基于直方图的图像全局二值化算法原理、实现、代码及效果(转)

十三种基于直方图的图像全局二值化算法原理.实现.代码及效果(转) http://www.cnblogs.com/carekee/articles/3643394.html 图像二值化的目的是最大限度的将图象中感兴趣的部分保留下来,在很多情况下,也是进行图像分析.特征提取与模式识别之前的必要的图像预处理过程.这个看似简单的问题,在过去的四十年里受到国内外学者的广泛关注,产生了数以百计的阈值选取方法,但如同其他图像分割算法一样,没有一个现有方法对各种各样的图像都能得到令人满意的结果. 在这些庞大的分

NOIP2009pj道路游戏[环形DP 转移优化 二维信息]

题目描述 小新正在玩一个简单的电脑游戏. 游戏中有一条环形马路,马路上有 n 个机器人工厂,两个相邻机器人工厂之间由一小段马路连接.小新以某个机器人工厂为起点,按顺时针顺序依次将这 n 个机器人工厂编号为1~n,因为马路是环形的,所以第 n 个机器人工厂和第 1 个机器人工厂是由一段马路连接在一起的.小新将连接机器人工厂的这 n 段马路也编号为 1~n,并规定第 i 段马路连接第 i 个机器人工厂和第 i+1 个机器人工厂(1≤i≤n-1),第 n 段马路连接第 n 个机器人工厂和第 1个机器人

基于局部二值相似性模式(LBSP)的运动目标检测算法

基于局部二值相似性模式(LBSP)的运动目标检测算法 [email protected] http://blog.csdn.net/kezunhai 本文根据论文:Improving background subtraction using local binary similarity patternsWACV2014的内容及自己的理解而成,如果想了解更多细节,请参考原文.该文章思想借鉴了VIBE,其实可以理解成是VIBE+LBP算子变种(LBSP)运动目标检测算法的组合.在VIBE中,算法主

深入理解计算机系统(第二版)----之二:信息的表示和处理

二值信号容易被表示.存储和传输,比如穿孔卡上的有洞无洞,导线上的高低电压,对二值信号进行存储和执行的计算机的电子电路非常简单和可靠.制造商能够在一个单独的硅片上集成数百万甚至数十亿个这样的电路.单独的位没有意义,用一个二进制数字系统,能够用位组来编码负数,通过使用标准的字符码,能够对文档中的字母和符号进行编码. 2.1 信息存储 8位的块,即字节,是最小的可寻址的存储器单位,机器级程序把存储器视为一个非常大的字节数组,称为虚拟存储器,存储器的每个字节都由唯一的数字来标识,称为它的地址,所有可能地

【数字图像】C++8位和24位BMP位图的平滑、锐化、二值化处理,以及24位真彩图的灰度化

头文件: typedef unsigned char BYTE; typedef unsigned short WORD; typedef unsigned int DWORD; typedef long LONG; //BMP文件头(14字节) typedef struct tagBITMAPFILEHEADER { //WORD bfType;//位图文件的类型,必须为BM(在结构体中读取会发生错误,所以在函数中读取) DWORD bfSize;//位图文件的大小,以字节为单位 WORD b