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 
相關問題