繁体   English   中英

将RGB图像读取为二进制图像,并在Matlab中将其显示为RGB

[英]Read RGB image into binary and display it as RGB in Matlab

这个问题是基于先前提出的一个问题: 通过LSB替代方法了解图像隐写术

为了使代码高效并减少均方误差(MSE),建议:“按原样读取文件,并使用de2bi(fread(fopen(filename)), 8)将其转换为位。)将这些位嵌入到您的封面图片所需的最小k因子,可能是1或2。提取秘密时,您将能够重建原始文件。” 这是我一直在尝试的方法,但是在某个地方我做错了,因为没有得到任何显示。 但是,MSE确实减少了。 基本上,我对如何将图像转换为二进制,对数据执行算法并在提取后显示图像感到困惑。

有人可以帮忙吗?

我已经对您的代码进行了一些修改,以使其能够正常工作,无论实际图像是什么。 但是,它们都必须是彩色或灰度。 您的代码中还存在一些错误,这些错误使我无法在我的MATLAB版本上运行它。

首先,您没有正确读取图像。 您正在为图像打开字节流,然后在字节流上使用imread来读取图像。 错了-只需提供实际文件的路径即可。

其次,图像已经在uint8 ,因此您可以对此进行本地的位置换和移位。

除了调整图像大小外,其余代码与之前相同。 您无需指定频道数。 另外, bitcmp出现语法错误。 我使用'uint8'代替了值8因为我的MATLAB版本要求您指定期望数据类型的字符串。 这里的值8我假设您的意思是8位,因此在此处放置'uint8'是有意义的。

我还将直接从Stack Overflow中读取您的图像。 我假设恐龙图像是封面,而花是消息:

%%% Change
x = imread('https://i.stack.imgur.com/iod2d.png');         % cover message
y  = imread('https://i.stack.imgur.com/Sg5mr.png');    % message image
n = input('Enter the no of LSB bits to be subsituted- ');

                                     %%% Change
S = uint8(bitor(bitand(x,bitcmp(2^n-1,'uint8')),bitshift(y,n-8))); %Stego
E = uint8(bitand(255,bitshift(S,8-n))); %Extracted

origImg = double(y);   %message image
distImg = double(E);   %extracted image

[M N d] = size(origImg);
distImg1=imresize(distImg,[M N]); % Change

figure(1),imshow(x);title('1.Cover image')
figure(2),imshow(y);title('2.Message to be hide')
figure(3),imshow((abs(S)),[]);title('3.Stegnographic image')
figure(4),imshow(real(E),[]); title('4.Extracted image');

这为我运行,我设法重建消息图像。 选择位数大约为4,可以在封面和消息图像之间做出很好的折衷。

加载字节流而不是密钥的像素数组将导致较小的有效负载。 它的大小取决于图像格式以及颜色的重复性。

如果该文件名是有效的图像文件,则imread()需要文件名并加载像素数组。 加载文件的字节流并将其传递给imread()没有任何意义。 你想要的是这个

% read in the byte stream of a file
fileID = fopen(filename);
secretBytes = fread(fileID);
fclose(fileID);

% write it back to a file
fileID = fopen(filename);
fwrite(fileID, secretBytes);
fclose(fileID);

请注意,封面图像会以像素阵列的形式加载,因为您需要对其进行修改。

有效载荷的大小为length(secretBytes) * 8 ,这必须适合您的封面图像。 如果您决定为每个像素嵌入k位,则对于您的所有彩色平面,必须满足以下要求

secretBytes * 8 <= prod(size(coverImage)) * k

如果您只想嵌入一个颜色平面,而不论您的封面介质是RGB还是灰度,都需要对其进行修改,以

secretBytes * 8 <= size(coverImage,1) * size(coverImage,2) * k

如果不满足此要求,则可以选择

  • 停止进程
  • 要求用户嵌入一个较小的文件
  • 增加k
  • 包括更多颜色平面(如果有)

以下是仅在最低有效位(k = 1)中嵌入一个颜色平面的原型。

HEADER_LEN = 24;

coverImage = imread('lena.png');
secretBytes = uint8('Hello world'); % this could be any byte stream

%% EMBEDDING
coverPlane = coverImage(:,:,1);     % this assumes an RGB image
bits = de2bi(secretBytes,8)';
bits = [de2bi(numel(bits), HEADER_LEN) bits(:)'];
nBits = length(bits);
coverPlane(1:nBits) = bitset(coverPlane(1:nBits),1,bits);
coverImage(:,:,1) = coverPlane;

%% EXTRACTION
nBits = bi2de(bitget(coverPlane(1:HEADER_LEN),1));
extBits = bitget(coverPlane(HEADER_LEN+1:HEADER_LEN+nBits),1);
extractedBytes = bi2de(reshape(extBits',8,length(extBits)/8)')';

除了消息字节以外,还必须嵌入密钥的长度,因此提取器知道要提取多少位。

如果将k> 1嵌入或在多个颜色平面中嵌入,则逻辑会变得更加复杂,并且必须注意如何实现更改。

例如,您可以选择一次嵌入每个颜色平面,直到用完所有要隐藏的位为止,或者可以使用coverImage(:)展平整个像素阵列,该图像将嵌入每个像素的RGB中,一个像素一次直到您用完所有位。

如果嵌入k> 1,则必须用0填充bits向量,直到其长度可被k整除。 然后,您可以将k个组中的位合并为

bits = bi2de(reshape(a',k,length(bits)/k)')';

要嵌入它们,您想返回使用bitand()bitor()

coverPlane(1:nBits) = bitor(bitand(coverPlane(1:nBits), bitcmp(2^k-1,'uint8')), bits);

还有更多细节,例如准确地提取24位消息长度,我不得不强调,您必须非常仔细地考虑如何实现所有这些内容。 您不能只是缝合来自不同代码段的部件,并期望一切都能做您想要的事情。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM