# 将二进制字符串每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)];
disp('待嵌入的字符串二进制形式为');
disp(str_bin);
% 检测是否能够完全嵌入
[l,w,h]=size(data);
if length(str_bin)>=l*w*h
    error('字符长度超出!!!');
%嵌入程序
data1=data;
disp('开始嵌入');
flag1=1; %输入字符二进制长度,判断嵌入是否结束
flag2=1;
flag3=1;
for i=1:l
    if flag3==0
        break
    for j=1:w
        if flag2==0
            flag3=0;
            break
        for k=1:h
            if flag1>length(str_bin)
                disp('over');
                flag2=0;
                break
            a=dec2bin(data1(i,j,k),8);%数字取二进制
            data1(i,j,k)=bin2dec([a(1:7),str_bin(flag1)]);%二进制相加,再取十进制  
            flag1=flag1+1;
%保存图片
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
    for j=1:w
        if flag2==0
            flag3=0;
            break
        for k=1:h
            if flag1>length(str_bin)
                flag2=0;
                break
            a=dec2bin(data2(i,j,k),8);%十进制转二进制
            str_bin1=[str_bin1,a(8)];% 取最后一个数
            flag1=flag1+1;
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)];
    if a<9
        str2=[str2,a];
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) ;%去重处理

然后看主要代码:

% 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)];
disp('待嵌入的字符串二进制形式为');
disp(str_bin);
% 检测是否能够完全嵌入
[l,w,h]=size(data);
if length(str_bin)>=l*w*h
    error('字符长度超出!!!');
%嵌入程序
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
    for j=1:w
        if flag2==0
            flag3=0;
            break
        for k=1:h
            if flag1>length(str_bin)
                disp('over');
                flag2=0;
                break
            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;
%保存图片
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
    for j=1:w
        if flag2==0
            flag3=0;
            break
        for k=1:h
            if flag1>length(str_bin)
                flag2=0;
                break
            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;
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)];
    if a<9
        str2=[str2,a];
disp('转换完成');
disp('最终结果为:');
disp(str2);
disp('随机位置分别为');
disp(locationxy);
plot(locationx,locationy);

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

分类:
人工智能
标签: