2017-04-22 101 views
0

我想在Python中使用圖像切片器分割圖像,然後在每個圖像上應用直方圖均衡並將它們合併回來。我能夠將圖像分成更小的塊,我可以看到它們正在更新,但是在將它們拼接在一起後,我會得到與原始圖像相同的圖像。有人能指出我做錯了什麼嗎?文件名watch.png在Python中分割並加入圖像

import cv2 
import numpy as np 
from matplotlib import pyplot as plt 
from scipy.misc import imsave 
# import scipy 
from scipy import ndimage 
from scipy import misc 
import scipy.misc 
import scipy 

import sys 
import argparse 
import image_slicer 
from image_slicer import join 


img = 'watch.png' 
num_tiles = 64 
tiles = image_slicer.slice(img, num_tiles) 



file = "watch" 
k = 0 
filelist =[] 
for i in range(1,9): 
    for j in range(1,9): 
     filelist.insert(k, file+"_"+str(i).zfill(2)+"_"+str(j).zfill(2)+".png") 
     k=k+1 

for i in range(0,num_tiles): 
    img = scipy.misc.imread(filelist[i]) 
    hist,bins = np.histogram(img.flatten(),256,[0,256]) 
    cdf = hist.cumsum() 
    cdf_normalized = cdf *hist.max()/ cdf.max() 
    plt.plot(cdf_normalized, color = 'g') 
    plt.hist(img.flatten(),256,[0,256], color = 'g') 
    plt.xlim([0,256]) 
    plt.legend(('cdf','histogram'), loc = 'upper left') 
    cdf_m = np.ma.masked_equal(cdf,0) 
    cdf_o = (cdf_m - cdf_m.min())*255/(cdf_m.max()-cdf_m.min()) 
    cdf = np.ma.filled(cdf_o,0).astype('uint8') 
    img3 = cdf[img] 
    cv2.imwrite(filelist[i],img3) 


image = join(tiles) 
image.save('watch-join.png') 
+0

你的例子似乎是不完整的,因爲你永遠不會將你的瓷磚存儲在'filelist'中插入的文件中。然而,從代碼猜測我確實認爲你這樣做,因爲你似乎能夠閱讀不同的圖像。但我的猜測是,你忘了在最後更新'tiles'so,你只是'加入'原始的,未修改的(因此未更新)瓷磚,這當然會再次給你原始圖像。 – JohanL

+0

@JohanL我正在將修改後的圖像塊寫回相同的文件名,所以我認爲它不應該有所作爲。我試過打印瓷磚,它給了我所指的文件名列表,並指向正確的文件名。有沒有其他的方法可以在我將圖像拼接之前更新瓷磚 – user2808264

回答

0

展望image_slicer代碼後,我可以看到的混亂。主要問題是每個對象都包含圖像數據和元數據,例如最終圖像中的文件名和位置。但是,當更新指向的文件時,圖像數據不會更新。

因此,當更新元數據所指向的文件時,也需要更新圖塊的圖像對象。我想象做到這一點的最簡單方法是每當磁盤上的文件發生變化時,重新打開磁貼中的圖像。這可能做的伎倆:

import cv2 
import numpy as np 
from matplotlib import pyplot as plt 
from scipy.misc import imsave 
from scipy import ndimage 
from scipy import misc 
import scipy.misc 
import scipy 
import image_slicer 
from image_slicer import join 
from PIL import Image 

img = 'watch.png' 
num_tiles = 64 
tiles = image_slicer.slice(img, num_tiles) 

for tile in tiles: 
    img = scipy.misc.imread(tile.filename) 
    hist,bins = np.histogram(img.flatten(),256,[0,256]) 
    cdf = hist.cumsum() 
    cdf_normalized = cdf *hist.max()/ cdf.max() 
    plt.plot(cdf_normalized, color = 'g') 
    plt.hist(img.flatten(),256,[0,256], color = 'g') 
    plt.xlim([0,256]) 
    plt.legend(('cdf','histogram'), loc = 'upper left') 
    cdf_m = np.ma.masked_equal(cdf,0) 
    cdf_o = (cdf_m - cdf_m.min())*255/(cdf_m.max()-cdf_m.min()) 
    cdf = np.ma.filled(cdf_o,0).astype('uint8') 
    img3 = cdf[img] 
    cv2.imwrite(tile.filename,img3) 
    tile.image = Image.open(tile.filename) 

image = join(tiles) 
image.save('watch-join.png') 

因此,主要的變化是在循環的末尾添加tile.image = Image.open(tile.filename)。還要注意,我已經稍微更新了代碼,通過刪除生成文件名的第一個循環,而第二個循環直接在tile上,因爲它們包含所有需要的信息。

+0

不幸的是,這會拋出一個錯誤,說 AttributeError:'圖像'對象沒有屬性'打開' – user2808264

+1

我的不好。 Image.open是一個類方法,而不是對象metod。因此它需要用'Image.open()'來調用。這也需要導入「Image」。我已經更新了代碼。 – JohanL

0

這是image_slicer.join()的源代碼:

def join(tiles): 
    """ 
    @param ``tiles`` - Tuple of ``Image`` instances. 
    @return ``Image`` instance. 
    """ 
    im = Image.new('RGB', get_combined_size(tiles), None) 
    columns, rows = calc_columns_rows(len(tiles)) 
    for tile in tiles: 
     im.paste(tile.image, tile.coords) 
    return im 

正如你所看到的,它使用存儲在程序的Tile對象(在你的情況,裏面的列表tiles),它們沒有改變。您需要更改內存中的對象,而不是從文件加載並重寫,也可以將文件加載到tiles

在我看來,最簡單的辦法是修改你的for循環(我希望我的語法正確):

for i in range(0, num_tiles): 
    img = tiles[i].image 
    hist, bins = np.histogram(img.flatten(), 256, [0, 256]) 
    cdf = hist.cumsum() 
    cdf_normalized = cdf * hist.max()/cdf.max() 
    plt.plot(cdf_normalized, color = 'g') 
    plt.hist(img.flatten(), 256, [0, 256], color='g') 
    plt.xlim([0, 256]) 
    plt.legend(('cdf', 'histogram'), loc='upper left') 
    cdf_m = np.ma.masked_equal(cdf, 0) 
    cdf_o = (cdf_m - cdf_m.min()) * 255/(cdf_m.max() - cdf_m.min()) 
    cdf = np.ma.filled(cdf_o, 0).astype('uint8') 
    img3 = cdf[img] 
    tiles[i].image = img3 
+0

有沒有其他方法可以做到這一點,因爲使用上述方法無法應用拼合功能 我最終出現此錯誤 AttributeError:'Image 'object has no attribute'flatten' – user2808264