J'essaie de diviser une photo en plusieurs morceaux en utilisant PIL.
def crop(Path,input,height,width,i,k,x,y,page):
im = Image.open(input)
imgwidth = im.size[0]
imgheight = im.size[1]
for i in range(0,imgheight-height/2,height-2):
print i
for j in range(0,imgwidth-width/2,width-2):
print j
box = (j, i, j+width, i+height)
a = im.crop(box)
a.save(os.path.join(Path,"PNG","%s" % page,"IMG-%s.png" % k))
k +=1
mais cela ne semble pas fonctionner. Il divise la photo mais pas de manière exacte (vous pouvez l'essayer).
from PIL import Image
def crop(path, input, height, width, k, page, area):
im = Image.open(input)
imgwidth, imgheight = im.size
for i in range(0,imgheight,height):
for j in range(0,imgwidth,width):
box = (j, i, j+width, i+height)
a = im.crop(box)
try:
o = a.crop(area)
o.save(os.path.join(path,"PNG","%s" % page,"IMG-%s.png" % k))
except:
pass
k +=1
Edit: Je crois que cette réponse a manqué l'intention de couper une image en rectangles dans des colonnes et des lignes. Cette réponse ne coupe qu'en lignes. Il ressemble à d'autres réponses découpées en colonnes et en lignes.
Plus simple que tout cela, c'est d'utiliser une roue inventée par quelqu'un d'autre :) Il peut être plus compliqué à configurer, mais c'est un jeu d'enfant à utiliser.
Ces instructions concernent Windows 7; ils devront peut-être être adaptés à d'autres systèmes d'exploitation.
Obtenez et installez pip depuis ici .
Téléchargez l'archive d'installation et extrayez-la dans votre répertoire racine Python. Ouvrez une console et tapez (si je me souviens bien):
python get-pip.py install
Ensuite, récupérez et installez le module image_slicer via pip, en entrant la commande suivante sur la console:
python -m pip install image_slicer
Copiez l'image que vous souhaitez découper dans le répertoire racine Python, ouvrez un shell python (pas la "ligne de commande")) et entrez ces commandes:
import image_slicer
image_slicer.slice('huge_test_image.png', 14)
La beauté de ce module est qu'il
Division de l'image en mosaïques de pixels MxN (en supposant que im est numpy.ndarray):
tiles = [im[x:x+M,y:y+N] for x in range(0,im.shape[0],M) for y in range(0,im.shape[1],N)]
Dans le cas où vous souhaitez diviser l'image en quatre parties:
M = im.shape[0]//2
N = im.shape[1]//2
tuiles [0] contient la tuile supérieure gauche
crop
serait une fonction plus réutilisable si vous séparez le code de recadrage du code d'enregistrement d'image. Cela rendrait également la signature d'appel plus simple.im.crop
Renvoie une instance de Image._ImageCrop
. De telles instances n'ont pas de méthode de sauvegarde. Au lieu de cela, vous devez coller l'instance Image._ImageCrop
Sur un nouveau Image.Image
height-2
Et non height
? Par exemple. Pourquoi s'arrêter à imgheight-(height/2)
?).Donc, vous pouvez essayer quelque chose comme ceci:
import Image
import os
def crop(infile,height,width):
im = Image.open(infile)
imgwidth, imgheight = im.size
for i in range(imgheight//height):
for j in range(imgwidth//width):
box = (j*width, i*height, (j+1)*width, (i+1)*height)
yield im.crop(box)
if __name__=='__main__':
infile=...
height=...
width=...
start_num=...
for k,piece in enumerate(crop(infile,height,width),start_num):
img=Image.new('RGB', (height,width), 255)
img.paste(piece)
path=os.path.join('/tmp',"IMG-%s.png" % k)
img.save(path)
Voici une solution concise en python pur qui fonctionne dans les deux python 3 et 2:
from PIL import Image
infile = '20190206-135938.1273.Easy8thRunnersHopefully.jpg'
chopsize = 300
img = Image.open(infile)
width, height = img.size
# Save Chops of original image
for x0 in range(0, width, chopsize):
for y0 in range(0, height, chopsize):
box = (x0, y0,
x0+chopsize if x0+chopsize < width else width - 1,
y0+chopsize if y0+chopsize < height else height - 1)
print('%s %s' % (infile, box))
img.crop(box).save('zchop.%s.x%03d.y%03d.jpg' % (infile.replace('.jpg',''), x0, y0))
Remarques:
Je ne sais pas si c'est la réponse la plus efficace, mais cela fonctionne pour moi:
import os
import glob
from PIL import Image
Image.MAX_IMAGE_PIXELS = None # to avoid image size warning
imgdir = "/path/to/image/folder"
# if you want file of a specific extension (.png):
filelist = [f for f in glob.glob(imgdir + "**/*.png", recursive=True)]
savedir = "/path/to/image/folder/output"
start_pos = start_x, start_y = (0, 0)
cropped_image_size = w, h = (500, 500)
for file in filelist:
img = Image.open(file)
width, height = img.size
frame_num = 1
for col_i in range(0, width, w):
for row_i in range(0, height, h):
crop = img.crop((col_i, row_i, col_i + w, row_i + h))
name = os.path.basename(file)
name = os.path.splitext(name)[0]
save_to= os.path.join(savedir, name+"_{:03}.png")
crop.save(save_to.format(frame_num))
frame_num += 1
Ceci est principalement basé sur la réponse DataScienceGuy ici
import cv2
def crop_image(image_path, output_path):
im = cv2.imread(os.listdir()[2])
imgheight=im.shape[0]
imgwidth=im.shape[1]
y1 = 0
M = 2000
N = 2000
for y in range(0,imgheight,M):
for x in range(0, imgwidth, N):
y1 = y + M
x1 = x + N
tiles = im[y:y+M,x:x+N]
if tiles.shape[0] < 100 or tiles.shape[1]<100:
continue
cv2.rectangle(im, (x, y), (x1, y1), (0, 255, 0))
cv2.imwrite(output_path + str(x) + '_' + str(y)+"{}.png".format(image_path),tiles)
crop_image(os.listdir()[2], './cutted/')
Ceci est mes outils de script, il est très simple de diviser l'image divisée en CSS en icônes:
Usage: split_icons.py img dst_path width height
Example: python split_icons.py icon-48.png gtliu 48 48
Enregistrez le code dans split_icons.py:
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import os
import sys
import glob
from PIL import Image
def Usage():
print '%s img dst_path width height' % (sys.argv[0])
sys.exit(1)
if len(sys.argv) != 5:
Usage()
src_img = sys.argv[1]
dst_path = sys.argv[2]
if not os.path.exists(sys.argv[2]) or not os.path.isfile(sys.argv[1]):
print 'Not exists', sys.argv[2], sys.argv[1]
sys.exit(1)
w, h = int(sys.argv[3]), int(sys.argv[4])
im = Image.open(src_img)
im_w, im_h = im.size
print 'Image width:%d height:%d will split into (%d %d) ' % (im_w, im_h, w, h)
w_num, h_num = int(im_w/w), int(im_h/h)
for wi in range(0, w_num):
for hi in range(0, h_num):
box = (wi*w, hi*h, (wi+1)*w, (hi+1)*h)
piece = im.crop(box)
tmp_img = Image.new('L', (w, h), 255)
tmp_img.paste(piece)
img_path = os.path.join(dst_path, "%d_%d.png" % (wi, hi))
tmp_img.save(img_path)
J'ai essayé les solutions ci-dessus, mais parfois tu dois le faire toi-même. Peut être décalé d'un pixel dans certains cas, mais fonctionne très bien en général.
import matplotlib.pyplot as plt
import numpy as np
def image_to_tiles(im, number_of_tiles = 4, plot=False):
"""
Function that splits SINGLE channel images into tiles
:param im: image: single channel image (NxN matrix)
:param number_of_tiles: squared number
:param plot:
:return tiles:
"""
n_slices = np.sqrt(number_of_tiles)
assert int(n_slices + 0.5) ** 2 == number_of_tiles, "Number of tiles is not a perfect square"
n_slices = n_slices.astype(np.int)
[w, h] = cropped_npy.shape
r = np.linspace(0, w, n_slices+1)
r_tuples = [(np.int(r[i]), np.int(r[i+1])) for i in range(0, len(r)-1)]
q = np.linspace(0, h, n_slices+1)
q_tuples = [(np.int(q[i]), np.int(q[i+1])) for i in range(0, len(q)-1)]
tiles = []
for row in range(n_slices):
for column in range(n_slices):
[x1, y1, x2, y2] = *r_tuples[row], *q_tuples[column]
tiles.append(im[x1:y1, x2:y2])
if plot:
fig, axes = plt.subplots(n_slices, n_slices, figsize=(10,10))
c = 0
for row in range(n_slices):
for column in range(n_slices):
axes[row,column].imshow(tiles[c])
axes[row,column].axis('off')
c+=1
return tiles
J'espère que ça aide.
Je trouve plus facile de skimage.util.view_as_windows
ou `skimage.util.view_as_blocks qui vous permet également de configurer l'étape