用R重新组织从PNG图像获得的矩阵

时间:2015-09-19 01:47:25

标签: r mapply

问题与Matrix reorganization

中的问题相似但不一样

我有一些PNG文件,想要做一些像素分析。使用png库我可以轻松读取图像:

myImage <- readPNG("4colorpattern_15.png",native=FALSE)
str(myImage)

输出

##  num [1:483, 1:483, 1:3] 0 0 0 0 0 0 0 0 0 0 ...

我希望将其重组为类似

的内容
X Y R G B A
0 0 0 0 0 0 
1 0 0 0 0 0
...

X,Y是坐标,RGB是该像素的红色,绿色和蓝色的值,A是alpha(如果图像有)。

我一直在阅读关于重塑和融化的内容,似乎这不是一个例子。我没有R技能来设计一个mapply函数来做到这一点。我想避免创建可以工作但效率低下的嵌套fors。

修改 数组似乎可以解决问题:

nrow  <- dim(myImage)[1]
ncol  <- dim(myImage)[2]
nbands <- dim(myImage)[3]
array(myImage,dim=c(nrow*ncol,nbands))

我仍然需要检查订单是否正确,但我仍然认为其中一个应用功能可以做到。此外,这个解决方案没有给我X和Y坐标。

修改2

我添加了一个非常小的PNG Itsy bitsy non-polka-dotted PNG - 抱歉很难点击它!它是一个9x4 PNG,具有3x2像素的3x2图案。在顶行的颜色是黑色,红色,绿色,底行颜色是蓝色,黄色,洋红色。

从那张图片中,我希望得到一个类似于

的数据框
X Y R G B (no A in this case)
0 0 0 0 0
1 0 0 0 0
2 0 0 0 0
3 0 1 0 0
4 0 1 0 0
5 0 1 0 0
6 0 0 1 0
7 0 0 1 0
8 0 0 1 0
...
0 2 0 0 1
1 2 0 0 1
2 2 0 0 1
3 2 1 1 0
4 2 1 1 0
5 2 1 1 0
6 2 1 0 1
7 2 1 0 1
8 2 1 0 1

(许多省略)

以下是图片的较大版本供参考,但结果基于9x4图片。

Larger one

2 个答案:

答案 0 :(得分:1)

这似乎可以解决问题:

matrix(c(unlist(expand.grid(seq_len(dim(myImage)[1]), seq_len(dim(myImage)[2]))),
         as.vector(myImage)),
       ncol=dim(myImage)[3]+2)

这里的关键概念是在R中,所有多维结构都是糖涂层矢量。

可能更容易理解另一种方法 - 创建矩阵,R将采用第一个rows项并将它们放在第一列;然后下一个rows项将成为第二列。重复此过程,直到填满所有列或向量耗尽。对阵列中的剩余维度重复进行。

您可以运行array(1:108, c(4,9,3))来帮助想象这个想法。

现在让我们分解我提出的解决方案。

as.vector(myImage)

这将以下划线矢量形式呈现数组。如果您只关心R,G和B的数据框,那么您可以使用matrix(as.vector(myImage), ncol=3)

seq_len(dim(myImage)[1])
seq_len(dim(myImage)[2])

这些将创建n个连续数字的向量,其中n是数组第一维和第二维中的项数。它们并不那么有趣,仅作为输入数据:

expand.grid(...)

这个很有意思。它创建了数据框架,其中包含作为参数给出的所有级别因子的所有可能组合。第一个因素变化最快。它将给第一个参数的每个值赋予第二个参数的第一个值;然后第一个参数的每个值与第二个参数的第二个值;等等。而这并非巧合,它与构成PNG阵列第一维和第二维的值相对应!

由于expand.grid提供了数据框,我们需要向量,因此我将其传递给unlist

然后我将X和Y坐标的矢量与实际值的矢量连接起来。

最后,我将一个单个向量作为参数传递给matrix并强制R“包裹”它,这样我得到5列(R,G和B三个,X和Y加两个)。我假设带有alpha通道的PNG在第三维中有4个值,所以我指的是dim(myImage)[3]而不是硬编码值。

唯一剩下的就是更改列的名称(Y,X,R,G,B和可能的A),以及可选的重新排序行。我把它们作为读者练习。

答案 1 :(得分:0)

使用Miroslav的提示,这有效:

myImage <- readPNG("origs/small.png",native=FALSE)
arr  <- matrix(c(unlist(expand.grid(seq_len(dim(myImage)[1]), seq_len(dim(myImage)[2]))),
    as.vector(myImage)),
    ncol=dim(myImage)[3]+2)
imFrame <- as.data.frame(arr)
colnames(imFrame) <- c('X','Y','R','G','B')
str(imFrame)
imFrame