洛伦(Matlab)的艺术

Turn ideas into MATLAB

笔记

洛伦(Matlab)的艺术has been retired and will not be updated.

Decomposing Embedded Images

Today I’d like to introduce a guest blogger,Jiro,,,,who is an application engineer here at The MathWorks. Some of you may know him as one of the bloggers for the文件交换Pick of the Week

Contents

我最近向弗吉尼亚联邦大学的一群新生工程专业的学生介绍。我想展示一些有趣,引人注目且相对容易解释的东西。因此,我创建了与图像相关的演示。我不是图像处理方面的专家,但是在此示例上工作肯定很有趣。对于对铁杆图像处理感兴趣的任何人,我建议还要看看Steve's Image Processing blog

This example demonstrates how to embed an image into another image and how to decompose the images. The embedded image is created by storing two 8-bit RGB image as 16-bit RGB image. The primary image is stored in the most significant byte, while the secondary image is stored in the least significant byte. (See the section titled"Embed Function & Decode Function"of this post for the code). With this method, the secondary image can be concealed inside the primary image, without any loss of information.

This post focuses on the decomposition part of the demo.

This demo uses functions from theImage Processing Toolbox

Setup

curImshowBorder = iptgetpref('ImshowBorder');iptsetpref('ImshowBorder',,,,'tight');

Show Images

这是两个看起来相同的图像。但是他们是吗?

  • peppers_BlueHills.png

  • peppers_trees.png

Would you believe me if I say these were very different images? Perhaps you'll believe MATLAB:

isequal(imread('peppers_BlueHills.png'), imread('peppers_trees.png'))
ans = 0

In fact, they have completely different images embedded in them. You just can't tell with the naked eye.

Image Decomposition

Let's try to decompose the image and see what's hidden inside.

These are 16-bit RGB images. See the"Embed Function & Decode Function"本报告的一节查看我用于创建这些图像的功能。

imData = imread('peppers_BlueHills.png');谁是imData
名称大小字节类属性IMDATA 384x512x3 1179648 UINT16

The image contains two 8-bit images. The primary image is stored in the most significant byte and the secondary image is stored in the least significant byte.

Convert RGB 3-D Array to a Vector

我们将使用TYPECAST转换数据类型和功能要求s a vector.

pixelVals = imData(:); pixelVals(1:10)
ans = 16097 16352 16862 16348 16346 16344 16087 16854 16082 15822

Convert UINT16 to UINT8

Next, convert the data type fromUINT16toUINT8。这样,我们将使用TYPECAST(instead ofCAST) to preserve the data.

pixelvalsConv = typecast(pixelvals,'uint8');谁是pixelVals*
Name Size Bytes Class Attributes pixelVals 589824x1 1179648 uint16 pixelValsConv 1179648x1 1179648 uint8

Notice thatpixelValsConvhas twice as many elements. This is because there are two 8-bit values to a 16-bit value.

Separate Two Images

我们将重塑它们以分离最少和最重要的字节。

pixelvalsConv = reshape(pixelvalsConv,2,[])';PixelvalsConv(1:10,:)
ans = 225 62 224 63 222 65 220 63 218 63 216 63 215 62 214 65 210 62 206 61

On a system with "little-endian" architecture, the first column is the least significant byte and the second column is the most significant column.

(第一个像素)62*256 + 225 = 16097

On a "big-endian" architecture system, the order is switched.

[cmp,maxsize,endian] = computer如果strcmp(endian,'L')imorder = [2 1];别的imOrder = [1 2];结尾
cmp = pcwin maxsize = 2.1475e+009 endian = l

我们将每列并将它们重塑为主要和次要图像。

imDataPrimary = reshape(pixelValsConv(:, imOrder(1)), size(imData)); imDataSecondary = reshape(pixelValsConv(:, imOrder(2)), size(imData));

We can see that we end up with two images, both of which are nowUINT8images.

谁是imData*
名称大小字节类属性IMDATA 384x512x3 1179648 UINT16imData2Primary 384x512x3 589824 uint8 imData2Secondary 384x512x3 589824 uint8 imDataPrimary 384x512x3 589824 uint8 imDataSecondary 384x512x3 589824 uint8

Show Primary and Secondary Images

图; imshow(imdataprimary);图; imshow(imdataSecondary);

Decomposing the Second Image

We'll do the same thing for the second image we read in. Let's see what's embedded in that one. We'll usedecodeImage.mwhich is a function with the above algorithm.

[imData2Primary, imData2Secondary] = decodeImage('peppers_trees.png');数字;imshow(imData2Primary); figure; imshow(imData2Secondary);

这个怎么运作

So, how does this work? Why is the secondary image unrecognizable by the naked eye? That's because the secondary image is stored in the least significant byte.

要理解这一点,让我们看一下RGB飞机之一中的一排像素。我们将查看红色飞机的第150行。

pixelRow16 = imData(150, :, 1);% row 150, red plane

我们掩盖了这个向量UINT8usingTYPECAST

pixelrow8 = typecast(pixelrow16,'uint8');pixelRow8 = reshape(pixelRow8, 2, []); pixelRow8(:, 1:10)
Ans = 64 60 61 61 57 60 61 61 61 61 61 67 70 71 70 70 70 72 74 69 69 63 63 63

在小型架构系统上,第一行是辅助图像,第二行是主要图像。接下来,我们将创建一个UINT16vector with only the primary image.

%将辅助图像向量设置为零pixelRow8Main = [zeros(1, size(pixelRow8, 2),'uint8');pixelRow8(2, :)]; pixelRow16Main = typecast(pixelRow8Main(:)','uint16');

现在,让我们将总图像向量的值与主图像向量的值进行比较。

数字;ax1 =轴;保持on; plot(pixelRow16); plot(pixelRow16Main,'r');Xlabel(“像素计数”);ylabel('Pixel Value (UINT16)');传奇('Total Image',,,,'Primary Image',,,,'Location',,,,'NorthWest');rectX = 160; rectY = 15000; rectW = 30; rectH = 3500; rectangle('Position',,,,[rectX, rectY, rectW, rectH]); dar = get(ax1,'DataAspectRatio');dar = dar(2)/dar(1);w = .3;h = w*(recth/rectw)/dar;ax2 =轴(。。。'Units',,,,“归一化”,,,,。。。'Position',[.6 .2 w h],。。。'Box',,,,'上',,,,。。。'LineWidth',,,,2,,,,。。。'XTick',,,,[],。。。'Ytick',,,,[],。。。'Color',,,,[.95 .95 .95]);holdon; xlabel('Magnified Region');plot(pixelRow16); plot(pixelRow16Main,'r');xlim([rectX, rectX+rectW]); ylim([rectY, rectY+rectH]);

如该图所示,主要图像代表大多数信息。相对于主图像,辅助图像的信息要小得多。但是,如果我们本身查看次要图像的数据,您会发现我们拥有完整的8位信息。

数字;plot(pixelRow8(1, :),'g');Ylim([0 300]);传奇('Secondary Image',,,,'Location',,,,'NorthWest');title('Secondary Image');Xlabel(“像素计数”);ylabel(“像素值(UINT8)”);

The following animations show how the secondary image data becomes more apparent as we subtract out the primary image data.Animations created usingANYMATE

  • 2-D Animation

  • 3-D Animation

嵌入功能和解码功能

These are the actual functions for creating and decoding embedded images.

helpembedImage
嵌入图像将图像嵌入另一个图像嵌入图像(主图像,成像仪)将图像文件嵌入图像文件中的图像文件中。主图像和图像仪都必须是有效的文件名。图像文件必须是8位图像。输出图像文件将是16位PNG图像,名为primenatimage_imagetobed.png。主要图像数据将存储在最显着的字节中,并且嵌入式图像数据将存储在最不重要的字节中。示例:嵌入('trees.tif','football.jpg');另请参见DecoDimimage。Jiro Doke 2009年1月24日。
helpdecodeImage
DecoDimage解码嵌入式图像。decodimage(imageFile)解码嵌入图像文件图像文件。ImageFile必须是有效的文件名。它将显示一个带有3个轴的图。顶轴是原始图像。左下是主要图像,右下是嵌入式隐藏图像。[primary,hidden] = decodimage(imageFile)将主图像和隐藏的图像数据返回为RGB数据。此函数仅适用于embedimage.m创建的图像。示例:%创建嵌入式图像嵌入图像('trees.tif','football.jpg');decoDimage('tree_football.png'); See also EMBEDIMAGE. Jiro Doke Jan 24, 2009.

清理

iptsetpref('ImshowBorder',,,,curImshowBorder);

Comments?

I hope you liked this example. Images make nice examples because they are visual. Let me know if you have other fun, pedagogical examples that involve graphics. Put them on the文件交换,,,,and I'll be sure to take a look at it as a potential Pick of the Week!




以MATLAB®7.7出版

|
  • 打印
  • 发送电子邮件