将RGB图像读入二进制并在Matlab中显示为RGB
Read RGB image into binary and display it as RGB in Matlab
此问题是基于之前提出的问题
为了提高代码效率并减少均方误差 (MSE),建议是:"read the file as is with and convert it to bits with de2bi(fread(fopen(filename)), 8)
. Embed these bits to your cover image with the minimum k factor required, probably 1 or 2. When you extract your secret, you'll be able to reconstruct the original file." 这是我一直在尝试的方法,但在某处我做错了,因为我没有得到任何显示.但是,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,一次一个像素,直到你 运行 out of bits.
如果嵌入 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 位,我怎么强调都不为过,您必须非常仔细地考虑如何实现所有这些内容。你不能只是拼接不同代码片段的部分,然后期望一切都按照你的意愿去做。
此问题是基于之前提出的问题
为了提高代码效率并减少均方误差 (MSE),建议是:"read the file as is with and convert it to bits with de2bi(fread(fopen(filename)), 8)
. Embed these bits to your cover image with the minimum k factor required, probably 1 or 2. When you extract your secret, you'll be able to reconstruct the original file." 这是我一直在尝试的方法,但在某处我做错了,因为我没有得到任何显示.但是,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,一次一个像素,直到你 运行 out of bits.
如果嵌入 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 位,我怎么强调都不为过,您必须非常仔细地考虑如何实现所有这些内容。你不能只是拼接不同代码片段的部分,然后期望一切都按照你的意愿去做。