基于matlab和python的LSB隐写实现

将字符串嵌入图片可以顺序选取像素点,也可以随机选取像素点。下面我们依次来实现每种算法。

1. 顺序嵌入

顺序嵌入很简单,遍历每个像素点,然后将二进制嵌入最后一位即第八位即可。

为了写报告,我还画了一个流程图,这里贴上来方便理解:

1.1 python版本

首先我用python实现了一个,主要是对matlab不熟悉,利用python3的PIL库写起来还是很简单的。直接看代码吧

# coding:utf-8
# python 3.6.6

from PIL import Image
import time

# 将字符串转为二进制
def str_convert_bin(s):
    result = ''
    for c in s:
        b = bin(ord(c)).replace('0b', '')
        b = '0'*(7-len(b))+b
        result = result+b
    return result

# 将二进制转化为字符串
def bin_convert_str(b):
    str=''
    # 将二进制字符串每7位分割,成列表
    b1 = [b[i:i+7] for i in range(0, len(b), 7)]
    for i in range(len(b1)):
        b2 = chr(int(b1[i],2))
        str = str+b2
    return str

# 将二进制字符串嵌入图片像素B通道 im:Image()、bin1:要嵌入的二进制串
def insert(im,bin1):
    size = im.size
    length = len(bin1)
    k=0
    flag=0
    for i in range(size[0]):
        for j in range(size[1]):
            # im.getpixel((i,j))读取像素点(i,j)的像素值
            pixel_b=bin(im.getpixel((i,j))[2]).replace('0b', '')
            if pixel_b[-1:]<bin1[k]:
                # im.putpixel((i,j),(x,y,z))设置像素点(i,j)的RGB值为(x,y,z)
                im.putpixel((i,j),(im.getpixel((i,j))[0],im.getpixel((i,j))[1],im.getpixel((i,j))[2]+1))
            if pixel_b[-1:]>bin1[k]:
                im.putpixel((i,j),(im.getpixel((i,j))[0],im.getpixel((i,j))[1],im.getpixel((i,j))[2]-1))    
            k=k+1 
            if k==length:
                flag=1
                break
        if flag==1:
            break
    print("字符串嵌入完成\n\n")

# 提取字符串 im:Image()、length:二进制字符串长度
def extract(im,length):
    size = im.size
    k=0
    result=''
    flag=0
    for i in range(size[0]):
        for j in range(size[1]):
            pixel_b=bin(im.getpixel((i,j))[2]).replace('0b', '')
            result=result+pixel_b[-1:]
            k=k+1 
            if k==length:
                flag=1
                break
        if flag==1:
            break
    print("提取完成,二进制字符串为:\n%s"%result)
    str = bin_convert_str(result)
    print("转换完成,结果为:\n%s"%str)

def main():
    test_str=input("请输入字符串:\n")
    result = str_convert_bin(test_str)
    print("待嵌入字符串转化为二进制为:\n%s"%result)
    print("开始嵌入....")
    im = Image.open("2.bmp")
    insert(im, result)

    time.sleep(5)
    print("开始提取字符串:")
    extract(im, len(result))

if __name__=='__main__':
    main()

结果:

1.2 matlab 版本

后续更复杂的隐写还是需要用到matlab,于是乎还是转matlab吧。

matlab就不介绍了,我也是先学先用,代码写得粗糙,勉强贴上代码:

% By gengyanqing
% LSB隐藏(顺序隐藏)
% 可以隐藏数字、字母、英文字符 ex: hello,world.111
% jpg失真!用png/bmp

clear all;clc;
data=imread('1.png');  % 读入图片
str=input('请输入要潜入的字符串:','s'); % 接收字符串
str_bin_mat=dec2bin(str); % 字符串转二进制矩阵

% 二进制矩阵转字符串
l_str_bin_mat=size(str_bin_mat); %二进制矩阵
str_bin='';
for i=1:l_str_bin_mat(1)
    for j=1:l_str_bin_mat(2)
        str_bin=[str_bin,str_bin_mat(i,j)];
    end
end
disp('待嵌入的字符串二进制形式为');
disp(str_bin);

% 检测是否能够完全嵌入
[l,w,h]=size(data);
if length(str_bin)>=l*w*h
    error('字符长度超出!!!');
end

%嵌入程序
data1=data;
disp('开始嵌入');
flag1=1; %输入字符二进制长度,判断嵌入是否结束
flag2=1;
flag3=1;
for i=1:l
    if flag3==0
        break
    end
    for j=1:w
        if flag2==0
            flag3=0;
            break
        end
        for k=1:h
            if flag1>length(str_bin)
                disp('over');
                flag2=0;
                break
            end
            a=dec2bin(data1(i,j,k),8);%数字取二进制
            data1(i,j,k)=bin2dec([a(1:7),str_bin(flag1)]);%二进制相加,再取十进制  
            flag1=flag1+1;
        end
    end
end
%保存图片
imwrite(data1,'1-2.png')
disp('嵌入完成,保存为1-2.png');

%以下为提取程序
disp('开始提取...')
data2 = imread('1-2.png');
[l,w,h]=size(data2);
str_bin1='';%提取到的二进制字符串
locationx=[];
locationy=[];
locationxy=[];
m=length(str_bin);
flag1=1;
flag2=1;
flag3=1;
for i=1:l
    if flag3==0
        break
    end
    for j=1:w
        if flag2==0
            flag3=0;
            break
        end
        for k=1:h
            if flag1>length(str_bin)
                flag2=0;
                break
            end
            a=dec2bin(data2(i,j,k),8);%十进制转二进制
            str_bin1=[str_bin1,a(8)];% 取最后一个数
            flag1=flag1+1;
        end
    end
end
disp('提取完成!');
disp('提取到的二进制字符串为:');
disp(str_bin1);
disp('开始转换...')

% 二进制转字符串
str2='';
for q=1:length(str_bin1)/l_str_bin_mat(2)
    w=str_bin1((q-1)*l_str_bin_mat(2)+1:q*l_str_bin_mat(2));%w为每七位
    a=bin2dec(w); % 转换为十进制
    if a>9
        str2=[str2,char(a)];
    end
    if a<9
        str2=[str2,a];
    end
end
disp('转换完成');
disp('最终结果为:');
disp(str2);

可以嵌字符,数字,字母,结果如下:

2. 随机LSB隐写

其实这个和顺序差不多,无非就是在遍历像素点的时候,将(i,j)改为随机的点,我们可以写个随机函数随机生成列表X和Y,当要嵌入(i,j)时我们就将其变为(X(i+j), Y(i+j)),为什么不是(X(i), Y(j))读者可以想想(这样不随机)。

这个我也画了一个流程图,但是好像有问题,时间紧急就暂且这样吧。

接下来看生成随机列表的函数 randomxy.m:

% 随机生成两个列表
% l为长,w为宽,len_str_bin为嵌入二进制长度,key为随机种子
function [x,y]=randxy(l,w,len_str_bin,key)
    %设置随机种子,生成一串随机数
    rand('seed',key);
    disp('hhhhhhhhh');
    x=randperm(l,len_str_bin);
    y=randperm(w,len_str_bin);
    %x = unique(x); %去重处理
    %y = unique(y) ;%去重处理
end

然后看主要代码:

% By gengyanqing
% LSB隐藏(随机隐藏)
% 可以隐藏数字、字母、英文字符 ex: hello,world.111
% jpg失真!用png/bmp

clear all;clc;
data=imread('1.png');  % 读入图片
str=input('请输入要潜入的字符串:','s'); % 接收字符串
str_bin_mat=dec2bin(str); % 字符串转二进制矩阵

% 二进制矩阵转字符串
l_str_bin_mat=size(str_bin_mat); %二进制矩阵
str_bin='';
for i=1:l_str_bin_mat(1)
    for j=1:l_str_bin_mat(2)
        str_bin=[str_bin,str_bin_mat(i,j)];
    end
end
disp('待嵌入的字符串二进制形式为');
disp(str_bin);

% 检测是否能够完全嵌入
[l,w,h]=size(data);
if length(str_bin)>=l*w*h
    error('字符长度超出!!!');
end

%嵌入程序
data1=data;
disp('开始嵌入');
flag1=1; %输入字符二进制长度,判断嵌入是否结束
flag2=1;
flag3=1;
% 调用randxy函数
[x,y]=randxy(l,w,length(str_bin),88);
for i=1:l
    if flag3==0
        break
    end
    for j=1:w
        if flag2==0
            flag3=0;
            break
        end
        for k=1:h
            if flag1>length(str_bin)
                disp('over');
                flag2=0;
                break
            end
            a=dec2bin(data1(x(i+j),y(i+j),k),8);%数字取二进制
            data1(x(i+j),y(i+j),k)=bin2dec([a(1:7),str_bin(flag1)]);%二进制相加,再取十进制  
            flag1=flag1+1;
        end
    end
end
%保存图片
imwrite(data1,'1-2.png')
disp('嵌入完成,保存为1-2.png');

%以下为提取程序
%这里提供了x和y,提取二进制字符串位数的信息
disp('开始提取...')
data2 = imread('1-2.png');
[l,w,h]=size(data2);
str_bin1='';%提取到的二进制字符串
locationx=[];
locationy=[];
locationxy=[];
m=length(str_bin);
flag1=1;
flag2=1;
flag3=1;
for i=1:l
    if flag3==0
        break
    end
    for j=1:w
        if flag2==0
            flag3=0;
            break
        end
        for k=1:h
            if flag1>length(str_bin)
                flag2=0;
                break
            end
            a=dec2bin(data2(x(i+j),y(i+j),k),8);%十进制转二进制
            locationx=[locationx,x(i+j)];%随机点x坐标
            locationy=[locationy,y(i+j)];%随机点y坐标
            locationxy=[locationxy;x(i+j),y(i+j),k];
            str_bin1=[str_bin1,a(8)];% 取最后一个数
            flag1=flag1+1;
        end
    end
end
disp('提取完成!');
disp('提取到的二进制字符串为:');
disp(str_bin1);
disp('开始转换...')

% 二进制转字符串
str2='';
for q=1:length(str_bin1)/l_str_bin_mat(2)
    w=str_bin1((q-1)*l_str_bin_mat(2)+1:q*l_str_bin_mat(2));%w为每七位
    a=bin2dec(w); % 转换为十进制
    if a>9
        str2=[str2,char(a)];
    end
    if a<9
        str2=[str2,a];
    end
end
disp('转换完成');
disp('最终结果为:');
disp(str2);

disp('随机位置分别为');
disp(locationxy);
plot(locationx,locationy);

结果:

下图为隐藏点的图(可以看出来确实是随机的)

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容