【问题标题】:Efficient way to find median value of a number of RGB images找到多个 RGB 图像中值的有效方法
【发布时间】:2013-04-21 20:09:33
【问题描述】:

我正在使用 Python 中的一个脚本,我想在其中找到许多相同尺寸图像的中位数。也就是说,我不想取位置 [x,y] 中的所有(红色、绿色和蓝色)像素,并用它们的中值构造一个新图像。

我当前的方法使用 Python PIL(成像库),但速度很慢!我非常想使用 OpenCV (cv2) 接口,因为它将每个图像直接加载为 numpy 数组。但是,在堆叠尺寸为 (2560,1920,3) 的 x 图像时,我不断收到错误的索引。有什么帮助吗?

我目前使用 PIL 的低效代码如下:

from PIL import Image, ImageChops,ImageDraw,ImageFilter,cv
import sys,glob,sys,math,shutil,time,os, errno,numpy,string
from os import *

inputs = ()
path = str(os.getcwd())
BGdummyy=0
os.chdir(path)
for files in glob.glob("*.png"):
    inputs = inputs + (str(str(files)),)
BGdummy=0
for file in inputs:
    BGdummy=BGdummy+1
    im = cv.LoadImage(file)
    cv.CvtColor( im, im, cv.CV_BGR2RGB )
    img = Image.fromstring("RGB", cv.GetSize(im), im.tostring())
    vars()["file"+str(BGdummy)] = img.load()
imgnew = Image.new("RGB", (2560,1920))
pixnew = imgnew.load()
for x in range(2560):
    for y in range(1920):
        R=[];G=[];B=[];
        for z in range(len(inputs)):
            R.append(vars()["file"+str(z+1)][x,y][0])
            G.append(vars()["file"+str(z+1)][x,y][1])
            B.append(vars()["file"+str(z+1)][x,y][2])
        R = sorted(R)
        G = sorted(G)
        B = sorted(B)
        mid = int(len(inputs)/2.)
        Rnew = R[mid]
        Gnew = G[mid]
        Bnew = B[mid]
        pixnew[x,y] = (Rnew,Gnew,Bnew)
    BGdummyy = BGdummyy+1
imgnew.save("NewBG.png")

【问题讨论】:

标签: python opencv python-imaging-library median


【解决方案1】:

我将演示如何使用 5 个大小为 (3,3,3) 的小数组来做到这一点。

首先我将创建 5 个数组,然后将它们保存在列表 X 中。在您的情况下,您将在此列表中保存 30 张图像。 (我在一行中做)

X = [a,b,c,d,e] = [np.random.randint(0,255,(3,3,3)) for i in xrange(5)]

接下来,您将每个图像展平为一长行。所以早些时候你的形象会像

[R1G1B1 R2G2B2 R3G3B3,
 R4G4B4 R5G5B5 R6G6B6,
 R7G7B7 R8G8B8 R9G9B9]

这将变为 [R1 G1 B1 R2 G2 B2 R3 G3 B3......... R9 G9 B9] 。然后你将所有这些扁平化的图像堆叠起来形成一个大的二维数组。你看,在那个数组中,所有第一个红色像素都在第一列,依此类推。然后你可以简单地应用 np.median 。

Y = np.vstack((x.ravel() for x in X))

我将每张图片拉长并堆叠。在我的例子中,Y 是一个大小为 5x27 的数组(行 - 图像数,列 - 图像中的像素数)

现在我找到这个 Y 的中值并将其重塑为我们的原始图像形状:

Z = np.median(Y,axis = 0)
Z = np.uint8(Z.reshape(a.shape))

完成。

为了确保它工作正常,让我们检查任意像素的值,比如Z[0,1,2]

In [50]: G1 = [x[0,1,2] for x in X]

In [51]: G1
Out[51]: [225, 65, 26, 182, 51]

In [52]: Z[0,1,2]
Out[52]: 65.0

是的,数据是正确的。

【讨论】:

  • 我的问题是我有 30 张图像,我想将它们的中值转换为新图像。所以我需要的是:3 个带有红色、绿色和蓝色像素的堆栈。 x 和 y 方向是像素的方向,而 z 方向是单个图像。在每个像素 (x,y) 处,我想要 z 方向的中值。所以我现在最大的问题是找到一种以合理的 3D 方式堆叠图像的方法,然后我可以利用您建议的“np.median”命令。如果没有意义,请告诉我,然后我会尝试详细说明=)
  • 对不起,我误解了你的问题。检查我是否正确:您有 30 张彩色图像。结果也是彩色图像。在结果图像中,第一个像素的蓝色值是第一个像素的中值->所有 30 个图像的蓝色值。红色和绿色等也是如此。这是你想要的吗?
  • 完全正确(或任意数量的图像)。我现在可以使用 PIL 库来完成它,但它相当慢,因为我需要使用“加载像素”命令。正如您已经建议的那样,我想将所有内容保留在 Numpy 和 OpenCV (2) 中。但基本上我一直在摸索以一种很好的方式添加 numpy 数组以获得中值。提前致谢!
  • 但是内存不是很贵吗?您需要将 30 张图片加载到内存中。
  • 在这种情况下内存并不昂贵。即使是 30 张 tiff 格式和 2560x1920 的图像也不成问题,只有 ~420 mb。
猜你喜欢
  • 1970-01-01
  • 2014-12-18
  • 2017-09-13
  • 1970-01-01
  • 2014-04-24
  • 1970-01-01
  • 2021-02-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多