使用 Python PIL 对图像进行强度归一化 - 速度问题

新手上路,请多包涵

我在业余时间处理一个小问题,涉及分析通过显微镜获得的一些图像。它是一块晶圆,到处都是一些东西,最终我想制作一个程序来检测某些材料何时出现。

无论如何,第一步是标准化整个图像的强度,因为镜头不会发出均匀的闪电。目前我使用的图像,没有任何东西,只有基材,作为背景或参考图像。我找到了 RGB 的三个(强度)值中的最大值。

 from PIL import Image
from PIL import ImageDraw

rmax = 0;gmax = 0;bmax = 0;rmin = 300;gmin = 300;bmin = 300

im_old = Image.open("test_image.png")
im_back = Image.open("background.png")

maxx = im_old.size[0] #Import the size of the image
maxy = im_old.size[1]
im_new = Image.new("RGB", (maxx,maxy))

pixback = im_back.load()
for x in range(maxx):
    for y in range(maxy):
        if pixback[x,y][0] > rmax:
            rmax = pixback[x,y][0]
        if pixback[x,y][1] > gmax:
            gmax = pixback[x,y][1]
        if pixback[x,y][2] > bmax:
            bmax = pixback[x,y][2]

pixnew = im_new.load()
pixold = im_old.load()
for x in range(maxx):
    for y in range(maxy):
        r = float(pixold[x,y][0]) / ( float(pixback[x,y][0])*rmax )
        g = float(pixold[x,y][1]) / ( float(pixback[x,y][1])*gmax )
        b = float(pixold[x,y][2]) / ( float(pixback[x,y][2])*bmax )
        pixnew[x,y] = (r,g,b)

代码的第一部分逐个像素地确定背景图像的红色、绿色和蓝色通道的最大强度,但只需执行一次。

第二部分采用“真实”图像(上面有东西),并根据背景逐个像素地标准化红色、绿色和蓝色通道。这需要一些时间,对于 1280x960 的图像需要 5-10 秒,如果我需要对多张图像执行此操作,这就太慢了。

我可以做些什么来提高速度? 我想将所有图像移动到 numpy 数组,但我似乎无法找到一种快速方法来为 RGB 图像执行此操作。我宁愿不离开 python,因为我的 C++ 是相当低级的,并且获得一个可用的 FORTRAN 代码可能需要比我在速度方面所能节省的时间更长的时间:P

原文由 Happy 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 795
2 个回答
import numpy as np
from PIL import Image

def normalize(arr):
    """
    Linear normalization
    http://en.wikipedia.org/wiki/Normalization_%28image_processing%29
    """
    arr = arr.astype('float')
    # Do not touch the alpha channel
    for i in range(3):
        minval = arr[...,i].min()
        maxval = arr[...,i].max()
        if minval != maxval:
            arr[...,i] -= minval
            arr[...,i] *= (255.0/(maxval-minval))
    return arr

def demo_normalize():
    img = Image.open(FILENAME).convert('RGBA')
    arr = np.array(img)
    new_img = Image.fromarray(normalize(arr).astype('uint8'),'RGBA')
    new_img.save('/tmp/normalized.png')

原文由 unutbu 发布,翻译遵循 CC BY-SA 3.0 许可协议

请参阅 http://docs.scipy.org/doc/scipy/reference/generated/scipy.misc.fromimage.html#scipy.misc.fromimage

你可以说

databack = scipy.misc.fromimage(pixback)
rmax = numpy.max(databack[:,:,0])
gmax = numpy.max(databack[:,:,1])
bmax = numpy.max(databack[:,:,2])

这应该比循环遍历图像的所有 (r,g,b) 三元组快得多。然后你可以做

dataold = scip.misc.fromimage(pixold)
r = dataold[:,:,0] / (pixback[:,:,0] * rmax )
g = dataold[:,:,1] / (pixback[:,:,1] * gmax )
b = dataold[:,:,2] / (pixback[:,:,2] * bmax )

datanew = numpy.array((r,g,b))
imnew = scipy.misc.toimage(datanew)

该代码未经测试,但应该以某种方式进行较小的修改。

原文由 rocksportrocker 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题