8

我有一个脚本,它使用Google Maps API下载等大小的方形卫星图像序列并生成PDF。图像需要事先旋转,我已经使用PIL来完成。使用Python图像库(PIL)规范化一组图像的直方图(亮度和对比度)

我注意到,由于不同的光照和地形条件,一些图像太亮,另一些太暗,并且由此产生的pdf变得有点丑陋,“在现场”的读数条件不甚理想(这是穷乡僻壤的山地自行车,我想在这里打印特定十字路口的缩略图)。

(编辑)接下来的目标是让所有图像都具有相似的亮度和对比度。所以,太亮的图像必须变暗,黑暗的图像必须变亮。 (顺便说一句,我曾经使用imagemagick autocontrastauto-gammaequalizeautolevel或类似的东西,在医学图像中有趣的结果,但不知道如何在PIL中做任何这些)。

我已经在转换为灰度(之前有一台灰度打印机)后使用了一些图像校正功能,但结果也不好。这里是我的灰度代码:

#!/usr/bin/python 

def myEqualize(im) 
    im=im.convert('L') 
    contr = ImageEnhance.Contrast(im) 
    im = contr.enhance(0.3) 
    bright = ImageEnhance.Brightness(im) 
    im = bright.enhance(2) 
    #im.show() 
    return im 

此代码独立运行,为每个图像。我想知道是不是先分析所有图像然后“归一化”它们的视觉特性(对比度,亮度,伽玛等)会更好。

此外,我认为有必要对图像进行一些分析(直方图?),以便根据每幅图像应用自定义校正,而不是对所有图像进行相同校正(尽管任何“增强“功能隐含地考虑初始接头)。

有没有人有这样的问题和/或知道一个很好的替代方案与彩色图像(无灰度)做到这一点?

任何帮助将不胜感激,谢谢阅读!

+0

好问题!但是需要澄清一些情况。另外,张贴示例图像对于人们用作测试用例会非常有帮助。首先,下载它们时,瓷砖边缘不匹配的问题是什么?或者你正在寻找一种方法来使黑暗的瓷砖变亮,并让明亮的瓷砖变暗?或者你需要做后者,同时保持边缘的连续性? – Paul

+0

边缘不是问题,因为图像集不是连续的。正如你所说,目标是使最亮的部分变暗并使黑暗的部分变亮。 – heltonbiker

回答

4

您可能正在寻找的是执行“直方图拉伸”的实用程序。 Here is one implementation。我相信还有其他人。我认为你想保留原来的色调,并将这个功能统一应用于所有色带。

当然,很有可能一些瓷砖在它们加入的层次上会有显着的不连续性。但是,避免这种情况将涉及“拉伸”参数的空间插值,并且是一个更为复杂的解决方案。 (......但会是一个很好的锻炼,如果有这种需求。)

编辑:

这里是保存图像色调的调整:

import operator 

def equalize(im): 
    h = im.convert("L").histogram() 
    lut = [] 
    for b in range(0, len(h), 256): 
     # step size 
     step = reduce(operator.add, h[b:b+256])/255 
     # create equalization lookup table 
     n = 0 
     for i in range(256): 
      lut.append(n/step) 
      n = n + h[i+b] 
    # map image through lookup table 
    return im.point(lut*im.layers) 
+0

哇,它似乎exactely我想要的。我会很快给它一个快速的尝试和posto一些反馈! – heltonbiker

+0

实际上,这个实现似乎一次只能处理一个图像,而我正在考虑首先分析所有图像,然后应用均衡。此外,图像不会平铺,它们来自不同的位置,通常不会重叠。我会测试你的建议,看看我得到了什么。谢谢! – heltonbiker

+0

我在我的相机的普通数字图像上试过,效果很好。然而,当我在Google卫星图像的screencap上尝试它时,它非常糟糕。我认为那些坐着的图像是高度张贴的或什么的。 – Paul

1

下面的代码工作的来自显微镜的图像(它们是相似的),以在拼接前准备它们。我使用了20张图像的测试集合,结果合理。

亮度平均函数来自另一个Stackoverflow question

from PIL import Image 
from PIL import ImageStat 
import math 

# function to return average brightness of an image 
# Source: https://stackoverflow.com/questions/3490727/what-are-some-methods-to-analyze-image-brightness-using-python 

def brightness(im_file): 
    im = Image.open(im_file) 
    stat = ImageStat.Stat(im) 
    r,g,b = stat.mean 
    return math.sqrt(0.241*(r**2) + 0.691*(g**2) + 0.068*(b**2)) #this is a way of averaging the r g b values to derive "human-visible" brightness 

myList = [0.0] 
deltaList = [0.0] 
b = 0.0 
num_images = 20       # number of images 

# loop to auto-generate image names and run prior function 
for i in range(1, num_images + 1):  # for loop runs from image number 1 thru 20 
    a = str(i) 
    if len(a) == 1: a = '0' + str(i) # to follow the naming convention of files - 01.jpg, 02.jpg... 11.jpg etc. 
    image_name = 'twenty/' + a + '.jpg' 
    myList.append(brightness(image_name)) 

avg_brightness = sum(myList[1:])/num_images 
print myList 
print avg_brightness 

for i in range(1, num_images + 1): 
    deltaList.append(i) 
    deltaList[i] = avg_brightness - myList[i] 

print deltaList 

在这一点上,“修正”的值(即值之间和平均差)存储在deltaList。以下部分逐一对所有图像应用此更正。

for k in range(1, num_images + 1):  # for loop runs from image number 1 thru 20 
    a = str(k) 
    if len(a) == 1: a = '0' + str(k)  # to follow the naming convention of files - 01.jpg, 02.jpg... 11.jpg etc. 
    image_name = 'twenty/' + a + '.jpg' 
    img_file = Image.open(image_name) 
    img_file = img_file.convert('RGB')  # converts image to RGB format 
    pixels = img_file.load()    # creates the pixel map 
    for i in range (img_file.size[0]): 
     for j in range (img_file.size[1]): 
     r, g, b = img_file.getpixel((i,j)) # extracts r g b values for the i x j th pixel 
     pixels[i,j] = (r+int(deltaList[k]), g+int(deltaList[k]), b+int(deltaList[k])) # re-creates the image 
    j = str(k) 
    new_image_name = 'twenty/' +'image' + j + '.jpg'  # creates a new filename 
    img_file.save(new_image_name)       # saves output to new file name 
相关问题