Loren谈MATLAB的艺术

将想法转化为MATLAB

分解嵌入图像

今天我要介绍一位客座博主,汪东城他是The MathWorks的一名应用工程师。你们有些人可能知道他是本周文件交换精选

内容

我最近给弗吉尼亚联邦大学的一群工程系新生做了演讲。我想展示一些有趣的、引人注目的、相对容易解释的东西。所以我创建了这个图像相关的演示。我不是图像处理方面的专家,但在处理这个示例时,我肯定获得了很多乐趣。对于任何对硬核图像处理感兴趣的人,我建议也看一看史蒂夫的图像处理博客

这个例子演示了如何将一个图像嵌入到另一个图像中,以及如何分解这些图像。通过将两个8位RGB图像存储为16位RGB图像来创建嵌入式图像。主图像存储在最高位字节中,而次图像存储在最低位字节中。(参见标题部分“嵌入函数和解码函数”本帖的代码)。用这种方法,辅助图像可以隐藏在主图像中,而不丢失任何信息。

这篇文章主要关注演示的分解部分。

的函数图像处理工具箱

设置

curImshowBorder = iptgetpref(“ImshowBorder”);iptsetpref (“ImshowBorder”“紧”);

显示图片

这里有两张看起来一样的图片。但他们真的吗?

  • peppers_BlueHills.png

  • peppers_trees.png

如果我说这是完全不同的图像,你会相信我吗?也许你会相信MATLAB:

isequal (imread (“peppers_BlueHills.png”), imread (“peppers_trees.png”))
Ans = 0

事实上,它们嵌入了完全不同的图像。肉眼是看不出来的。

图像分解

让我们试着分解图像,看看里面隐藏了什么。

这些是16位RGB图像。看到“嵌入函数和解码函数”部分,看看我用来创建这些图像的函数。

imData = imread(“peppers_BlueHills.png”);谁imData
名称大小字节类属性imData 384x512x3 1179648 uint16

该图像包含两个8位图像。主图像存储在最高位字节中,副图像存储在最低位字节中。

将RGB 3-D阵列转换为矢量

我们会用到定型要转换数据类型,函数需要一个向量。

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

将UINT16转换为UINT8

接下来,将数据类型从UINT16UINT8.在此过程中,我们将使用定型(而不是)以保存资料。

pixelValsConv = typecast(pixelVals,“uint8”);谁pixelVals *
名称大小字节类属性pixelVals 589824x1 1179648 uint16 pixelValsConv 1179648x1 1179648 uint8

请注意,pixelValsConv有两倍的元素。这是因为有两个8位值对应一个16位值。

分开两张图片

我们将重新定义它们,以分离出最低和最高的字节。

pixelValsConv =重塑(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

在具有“little-endian”体系结构的系统上,第一列是最低有效字节,第二列是最高有效列。

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

在“大端”体系结构系统中,顺序是切换的。

[cmp,maxsize,endian] =计算机如果比较字符串(尾数法),“L”) imOrder = [2 1];其他的imOrder = [1 2];结束
cmp = PCWIN maxsize = 2.1475e+009 endian = L

我们将取每一列并将其重塑为主图像和副图像。

imdatprimary =重塑(pixelValsConv(:, imOrder(1)), size(imData));imDataSecondary =重塑(pixelValsConv(:, imOrder(2)), size(imData));

我们可以看到我们最终得到了两张图片,这两张图片都是UINT8图像。

imData *
名称大小字节类属性imData 384x512x3 1179648 uint16 imData2Primary 384x512x3 589824 uint8 imData2Secondary 384x512x3 589824 uint8 imDataPrimary 384x512x3 589824 uint8 imDataSecondary 384x512x3 589824 uint8

显示主要和次要图像

图;imshow (imDataPrimary);图;imshow (imDataSecondary);

第二图像的分解

我们将对读入的第二张图像做同样的事情。让我们看看这里面包含了什么。我们将使用decodeImage.m它是上面算法的一个函数。

[imData2Primary, imData2Secondary] = decodeImage(“peppers_trees.png”);图;imshow (imData2Primary);图;imshow (imData2Secondary);

它是如何工作的

那么,这是如何工作的呢?为什么次级图像不能被肉眼识别?这是因为副图像存储在最低有效字节中。

为了理解这一点,让我们看一看其中一个RGB平面上的单行像素。我们看一下红色平面的第150行。

pixelRow16 = imData(150,:, 1);第150行,红色飞机

我们将这个向量变换为UINT8使用定型

pixelRow8 = typecast(pixelRow16,“uint8”);pixelRow8 =重塑(pixelRow8, 2, []);pixelRow8 (: 1:10)
Ans = 64 60 61 61 57 60 61 61 61 61 67 70 71 70 70 72 74 69 63 63

在小端体系结构系统中,第一行是辅助图像,第二行是主图像。接下来,我们将创建一个UINT16只有主图像的向量。

%设置二级图像矢量为零pixelRow8Main = [0 (1, size(pixelRow8, 2),“uint8”);: pixelRow8 (2)];pixelRow16Main = typecast(pixelRow8Main(:)',“uint16”);

现在,让我们比较总图像向量的值和主图像向量的值。

图;Ax1 =坐标轴;保持;情节(pixelRow16);情节(pixelRow16Main“r”);包含(“像素”);ylabel (“像素值(UINT16)”);传奇(“总形象”“主要形象”“位置”“西北”);rectX = 160;rectY = 15000;rectW = 30;rectH = 3500;矩形(“位置”, [rectX, rectY, rectW, rectH]);Dar = get(ax1,“DataAspectRatio”);Dar = Dar (2)/ Dar (1);W = .3;h = w*(rectH/rectW)/dar;Ax2 =轴(...“单位”“归一化”...“位置”,(。6.2w h],...“盒子”“上”...“线宽”2,...“XTick”[],...“Ytick”[],...“颜色”,(。95.95.95]);hold;包含(“放大区域”);情节(pixelRow16);情节(pixelRow16Main“r”);xlim ([rectX, rectX + rectW]);ylim ([rectY, rectY + rectH]);

如图所示,主图像代表了大部分信息。次要图像的信息相对于主要图像要小得多。但是如果我们单独看辅助图像的数据,你会看到我们有完整的8位信息。

图;情节(pixelRow8 (1:)‘g’);ylim (300 [0]);传奇(“二次形象”“位置”“西北”);标题(“二次形象”);包含(“像素”);ylabel (“像素值(UINT8)”);

下面的动画展示了当我们减去主图像数据时,辅助图像数据如何变得更加明显。使用ANYMATE

  • 二维动画

  • 三维动画

嵌入函数和解码函数

这些是创建和解码嵌入图像的实际函数。

帮助embedImage
Embed (PRIMARYIMAGE, IMAGETOEMBED)将图像文件IMAGETOEMBED嵌入到图像文件PRIMARYIMAGE中。PRIMARYIMAGE和IMAGETOEMBED都必须是有效的文件名。映像文件必须是8位映像。输出图像文件将是一个16位PNG图像,命名为PRIMARYIMAGE_IMAGETOEMBED.png。主图像数据将存储在最高有效字节中,而嵌入的图像数据将存储在最低有效字节中。示例:embeddimage ('trees.tif', 'football.jpg');参见DECODEIMAGE。二郎道克,2009年1月24日。
帮助decodeImage
DECODEIMAGE解码嵌入图像。DECODEIMAGE(IMAGEFILE)解码嵌入的图像文件IMAGEFILE。IMAGEFILE必须是一个有效的文件名。它将显示一个有3个轴的图形。上面的轴是原始图像。左下为主图像,右下为嵌入的隐藏图像。[PRIMARY, HIDDEN] = DECODEIMAGE(IMAGEFILE)返回主图像和作为RGB数据的隐藏图像数据。这个函数只作用于由embeddimage .m创建的图像。示例:% create embedded image embeddimage ('trees.tif', 'football.jpg');decodeImage(“trees_football.png”); See also EMBEDIMAGE. Jiro Doke Jan 24, 2009.

清理

iptsetpref (“ImshowBorder”, curImshowBorder);

评论?

我希望你喜欢这个例子。图像是很好的例子,因为它们是可视化的。如果你有其他有趣的教学例子,请告诉我。把它们放在文件交换,我一定会把它作为潜在的本周最佳选择来看待!




与MATLAB®7.7发布

|
  • 打印
  • 发送电子邮件

评论

如欲留言,请点击在这里登录到您的MathWorks帐户或创建一个新帐户。