2017-04-22 85 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