【问题标题】:How to convert a PNG file in to a matrix of pixels?如何将PNG文件转换为像素矩阵?
【发布时间】:2015-01-12 20:44:41
【问题描述】:

我想将 PNG 文件转换为像素矩阵。我试过了

I = imread('d:\image.png'); 

在 matlab 中,我得到 3 个单独的矩阵(R 矩阵、G 矩阵、B 矩阵)。
我想要一个表示图像像素数据的单个 RBG 矩阵。

【问题讨论】:

标签: image matlab matrix png


【解决方案1】:

有许多不同的方式来表示图像。直接去option3快速解答,不过我也会在option1和2中解释图片是如何表示的:

为了举一个非常小的样本的例子,我将使用一个非常简单的图像。蓝色-ish 要点:

实际使用的图片是上面显示的要点的缩小版本 (5x5px)。你可以在这里找到它:http://i.imgur.com/QvuBpmI.png

选项1

如果您使用命令阅读:

>> I = imread('icon-bullet_5x5.png')
I(:,:,1) =
    0    0    0    0    0
    0   15   53   26    0
    0   41   89   59    1
    0   16   36   23    1
    0    0    2    0    0
I(:,:,2) =
    0    0    0    0    0
    0   31  103   54    0
    0   96  187  130    4
    0   46  110   69    2
    0    0    4    0    0
I(:,:,3) =
    0    0    0    0    0
    0   56  163   91    0
    0  167  255  216   13
    0   91  212  133    4
    0    0   12    0    0

您获得了uint8(8 位无符号整数)的 3D 矩阵。矩阵的每个“切片”都是红色、蓝色和绿色的比例(在 [0 255] 范围内)。您可以隐约认识到该值位于矩阵中,就像在图像上一样(中心有一些颜色,外围没有任何颜色。

这可以被视为您所问的“单一 RGB”矩阵(正如 Ander 在他的答案的 cmets 中讨论的那样,Matlab 处理得很好,而且非常方便)。


选项2

这里提出的另一种方法是将其转换为颜色图的索引。如果你这样做:

>> [X,map] = rgb2ind(I,8)
X =
    0    0    0    0    0
    0    2    6    7    0
    0    6    5    3    0
    0    7    4    1    0
    0    0    0    0    0
map =
                         0                         0       0.00392156862745098
        0.0901960784313725         0.270588235294118          0.52156862745098
        0.0588235294117647          0.12156862745098         0.219607843137255
         0.231372549019608         0.509803921568627         0.847058823529412
         0.141176470588235         0.431372549019608         0.831372549019608
         0.349019607843137         0.733333333333333                         1
         0.184313725490196         0.388235294117647         0.647058823529412
        0.0823529411764706         0.196078431372549         0.356862745098039

这代表相同的图像。 map 变量包含一个包含 8 个 RGB 三元组的列表,定义了 8 种不同的颜色(我只选择了 8 种颜色以免示例过载,但地图当然可以定义更多颜色)

X 中的值与图像中的位置相同,表示map 中的“行号”。在这种情况下,行号从 0 开始。 例如,X(2,2) 位置的像素(x=2,y=2 从左侧,从顶部)具有值2,因此该像素的颜色由地图中的第 3 行定义 => R/G/B = 0.0588235294117647, 0.12156862745098, 0.219607843137255 .

小心,这里每种颜色的比例从01(而不是[0 255]),但解释是一样的。


选项3

但是,对于您的应用程序,如果您必须与芯片通信,您将无法从 Matlab 矩阵处理中受益,您必须“序列化”它。在内存中,没有 2D、3D 甚至更高阶的概念。内存只有一维,一连串的地址。只是指针和处理程序的使用给了我们更多维度的印象,以便更方便地处理这些数据。

要将其发送到您的芯片,您不需要 RGB 值的“单个矩阵”,而是单个 向量(单个列或行)。一系列连续的像素信息,以及定义它们在向量中的顺序和它们在矩阵中的位置之间关系的约定(例如,Matlab 将它们排列,从上到下从左到右)

以串行方式表示像素颜色的一种常用方法(但绝对不是唯一方法)是将它们表示为一系列 24 位值。每个 24 位值实际上由 3 个连接字节(8 位无符号整数)组成,代表R / G / B。由于 24 位整数在表示颜色方面不太可读,因此通常以十六进制格式表示(当您直接处理微芯片时,这也非常方便)。

Matlab 提供工具帮助您轻松转换。

RGBhex = [ dec2hex(I(:,:,1)) dec2hex(I(:,:,2)) dec2hex(I(:,:,3)) ]  ;
>> RGBhex
RGBhex =
000000
000000
000000
000000
000000
000000
0F1F38
2960A7
102E5B
000000
000000
3567A3
... // and so on

在此表示中,值为0F1F38 的第7 个像素具有Red=0F=15Green=1F=31Blue=0F=56。 如果你从左上角开始逐列计算像素,他在图像中的位置与我们上面示例中的像素相同 x=2,y=2(从左到上)

注意:某些格式还包括Alpha channel 中每个像素的“透明度”。在这种情况下,它通常与 RGB 三元组连接,每个像素变成一个 32 位(4 字节)值Alpha / R / G / B。为了简单起见,我没有在此处包含它。


作为验证,您可以注意到该值与示例 1 中的相同(该位置的像素显示为 15/31/56)。

快速转换还表明这是与示例 2 中相同的 RGB 值:

>> uint8([[0.0588235294117647, 0.12156862745098, 0.219607843137255]]*256)
ans =
   15   31   56

如果你不想处理十六进制值而更喜欢字节数组,你也可以简单地reshape原始矩阵:

>> RGBuint = reshape( I , [] , 3 )
RGBuint =
    0    0    0
    0    0    0
    0    0    0
    0    0    0
    0    0    0
    0    0    0
   15   31   56
   41   96  167
   16   46   91
    0    0    0
    ... // and so on

这会为您提供一个整数数组 (uint8)。每个像素的位置使用与上述十六进制示例相同的规则给出。根据您的芯片是处理 8/16 位还是 32 位通信,您可以一个一个地发送字节或将它们连接起来以数据包的形式发送。

【讨论】:

  • 您的第三个选项正是我想要的。因为我认为在内存(硬件)中像素是以这种方式存储的。谢谢先生。
【解决方案2】:

由于似乎没有人能够在 Matlab 中做你想做的事,我将向你展示如何使用 ImageMagick 来做,这样你至少可以继续你正在尝试做的事情。

首先,创建一个 8x4 像素的 PNG 图像,每个像素的 RGB 分量设置为 R=00hex、G=44hex、B=55hex,这样我们就有了一些东西可以玩。

convert -size 8x4 xc:"#004455" image.png

检查它看起来是否正确,identify

identify image.png 
image.png PNG 8x4 8x4+0+0 8-bit sRGB 2c 276B 0.000u 0:00.000

现在,将图像的通道分离为 RGB,并交换通道 1 和 2,即交换绿色和蓝色通道,保持红色(通道 0)不变,然后重新组合分离的通道并写入原始二进制文件

convert image.png -separate -swap 1,2 -combine RGB:out.raw    

现在查看文件内容,xxd 分成三组:

xxd -g3 -c12 out.raw
0000000: 005544 005544 005544 005544  .UD.UD.UD.UD
000000c: 005544 005544 005544 005544  .UD.UD.UD.UD
0000018: 005544 005544 005544 005544  .UD.UD.UD.UD
0000024: 005544 005544 005544 005544  .UD.UD.UD.UD
0000030: 005544 005544 005544 005544  .UD.UD.UD.UD
000003c: 005544 005544 005544 005544  .UD.UD.UD.UD
0000048: 005544 005544 005544 005544  .UD.UD.UD.UD
0000054: 005544 005544 005544 005544  .UD.UD.UD.UD

您有望看到该文件包含 4 行 8 像素,每行带有 RBG #005544

或者,如果你喜欢它作为文本:

convert image.png -separate -swap 1,2 -combine out.txt

# ImageMagick pixel enumeration: 8,4,255,srgb
0,0: (0,85,68)  #005544  srgb(0,85,68)
1,0: (0,85,68)  #005544  srgb(0,85,68)
2,0: (0,85,68)  #005544  srgb(0,85,68)
3,0: (0,85,68)  #005544  srgb(0,85,68)
4,0: (0,85,68)  #005544  srgb(0,85,68)
5,0: (0,85,68)  #005544  srgb(0,85,68)
6,0: (0,85,68)  #005544  srgb(0,85,68)
7,0: (0,85,68)  #005544  srgb(0,85,68)
0,1: (0,85,68)  #005544  srgb(0,85,68)
1,1: (0,85,68)  #005544  srgb(0,85,68)
2,1: (0,85,68)  #005544  srgb(0,85,68)
3,1: (0,85,68)  #005544  srgb(0,85,68)
4,1: (0,85,68)  #005544  srgb(0,85,68)
5,1: (0,85,68)  #005544  srgb(0,85,68)
6,1: (0,85,68)  #005544  srgb(0,85,68)
7,1: (0,85,68)  #005544  srgb(0,85,68)
0,2: (0,85,68)  #005544  srgb(0,85,68)
1,2: (0,85,68)  #005544  srgb(0,85,68)
2,2: (0,85,68)  #005544  srgb(0,85,68)
3,2: (0,85,68)  #005544  srgb(0,85,68)
4,2: (0,85,68)  #005544  srgb(0,85,68)
5,2: (0,85,68)  #005544  srgb(0,85,68)
6,2: (0,85,68)  #005544  srgb(0,85,68)
7,2: (0,85,68)  #005544  srgb(0,85,68)
0,3: (0,85,68)  #005544  srgb(0,85,68)
1,3: (0,85,68)  #005544  srgb(0,85,68)
2,3: (0,85,68)  #005544  srgb(0,85,68)
3,3: (0,85,68)  #005544  srgb(0,85,68)
4,3: (0,85,68)  #005544  srgb(0,85,68)
5,3: (0,85,68)  #005544  srgb(0,85,68)
6,3: (0,85,68)  #005544  srgb(0,85,68)
7,3: (0,85,68)  #005544  srgb(0,85,68)

【讨论】:

  • ImageMagick 对我来说是新的。你能告诉我如何在 imagemagick 中创建一个 png 文件吗?
  • 我创建了一个作为上述答案的第一步,尺寸为 8x4。可以使用convert -size 10x10 xc:red red.png 制作 10x10 红色图像,或使用 640x480 黑色 JPEG 制作如下 convert -size 640x480 xc:"#000000" black.jpg
  • 我明白了。我的问题是..我应该把这段代码放在哪里? Imagemagick 是软件还是在线工具?
  • 我在网上试过,我从网上下载了一些软件。但在两者中,我都没有找到可以放置和编译此代码的任何编辑器。
  • 您只需在终端窗口中键入它并按Enter/Return - 没有要编译的内容。
【解决方案3】:

您如何获得 3 个单独的矩阵?

您应该有 1 个矩阵,大小为 MxNx3。如果你想让那个 3 变成 1,你很可能会丢失信息。你有几个选择,这取决于你想要什么。

其中之一是将您的 RGB 图像转换为灰度,使用 Ig=rgb2gray(I) 很容易做到。

另一个,正如@Dan 所建议的,是创建一个索引图像。索引图像具有整数而不是颜色,整数应该是存储真实颜色的字典的索引。你可以做[Iind,dict]=rgb2ind(I)。例如,索引图像允许您在更少的内存中存储具有少量颜色的大图像。

我将把它留在这里,如果这不是您想要的,请告诉我以更新答案并提供更多信息。

【讨论】:

  • 从您的回答中得到了一些想法。谢谢你。你说矩阵的大小是 MxNx3。那么如何将这个矩阵存储在内存中呢?记忆是二维的吧?
  • @tollin 不是!您可以在 Matlab 中制作任何维度矩阵!试试看!创建一个 5 维随机矩阵:A=rand(3,3,3,3,3)!试试吧。创建它并在工作区中检查它的尺寸。
  • 不在系统内存中。我问的是FPGA。所以到 RAM (2D) 我必须移植这个图像数据。
  • @tollin 抱歉,我不习惯 FPGA,但在计算机内存中并非如此。一维矩阵是指向内存位置的指针。二维数组是指向一维矩阵的指针数组。 3D 矩阵是指向 2D 矩阵的指针数组,它们本身就是指向 1D 矩阵的指针数组......但是我相信你比我更了解电子学!无论如何,在 Matlab 中,您可以创建任何维度矩阵,如果您使用的是 Matlab 的 VHDL 代码生成工具,请不要担心,Matlab 知道如何处理这些事情(我相信)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-01-05
  • 1970-01-01
  • 1970-01-01
  • 2013-03-14
  • 2019-08-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多