Split and Join images in Python

夙愿已清 提交于 2019-12-18 07:24:34

问题


I am trying to split an image using image slicer in python and then apply histogram equalization on each of them and combine them back. I am able to split the images into smaller blocks and I can see them being updated but after stitching them together I end up with the same image as the original one. Can someone point out what I am doing wrong. The file name is watch.png

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')

回答1:


After looking into the image_slicer code, I can see the confusion. The main problem is that each Tile object, contains both the image data and metadata, such as filename and position in final image. However, the image data is not updated when the files pointed to are updated.

Thus, when updating the files pointed to by the metadata also the image object of the tile needs to be updated. I imagine the simplest way to do this, is to reopen the image in the tile whenever the file on disk is changed. This is likely to do the trick:

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')

Thus, the main change is to add tile.image = Image.open(tile.filename) at the end of the loop. Note also that I have updated your code slightly, by removing the first loop that generates the filenames, and instead the second loop is over the tiles directly, as they contain the needed information all ready.




回答2:


This is the source code for 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

As you can see, it uses the Tile objects stored in the program (in your case, inside the list tiles), which haven't changed. You need to either change the objects in memory instead of loading from the file and rewriting, or load the files into tiles as well.

The easy way in my opinion is to modify your for loop (I hope I got the syntax right):

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


来源:https://stackoverflow.com/questions/43565275/split-and-join-images-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!