如何在Python中将图像分割成多个片段

Elt*_*ooo 17 python split image crop python-imaging-library

我正在尝试使用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
Run Code Online (Sandbox Code Playgroud)

但它似乎没有起作用.它会分割照片但不是精确的方式(你可以尝试).

Elt*_*ooo 28

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
Run Code Online (Sandbox Code Playgroud)

  • 为什么`k`是这个函数的参数?调用函数时它不应该总是为"0"吗?什么是`area`?你为什么两次"裁剪"图像? (4认同)
  • 你所有的论点是什么意思? (2认同)

Ale*_*all 27

编辑:我相信这个答案错过了将图像切割成列和行的矩形的意图.这个答案只能分成几行.它看起来像列和行中的其他答案.

比所有这些更简单的是使用其他人发明的轮子:)它可能更复杂地设置,但是它很容易使用.

这些说明适用于Windows 7; 它们可能需要适应其他操作系统.

这里获取并安装pip .

下载安装存档,并将其解压缩到根Python安装目录.打开控制台并键入(如果我没记错的话):

python get-pip.py install
Run Code Online (Sandbox Code Playgroud)

然后通过在控制台输入以下命令,通过pip获取并安装image_slicer模块:

python -m pip install image_slicer
Run Code Online (Sandbox Code Playgroud)

将要切片的图像复制到Python根目录中,打开python shell(不是"命令行"),然后输入以下命令:

import image_slicer
image_slicer.slice('huge_test_image.png', 14)
Run Code Online (Sandbox Code Playgroud)

这个模块的美妙之处在于它

  1. 安装在python中
  2. 可以使用两行代码调用图像分割
  3. 接受任何偶数作为图像切片参数(例如,在此示例中为14)
  4. 获取该参数并自动将给定图像拆分为如此多的切片,并将结果编号的切片自动保存在同一目录中,最后
  5. 具有将图像拼接在一起的功能(我还没有测试过); 文件显然必须按照您在测试image_slicer.slice函数后在拆分文件中看到的约定命名.

  • 它看起来不错,但它的文档很差.一旦创建了瓷砖,它也可以很好地控制瓷砖,但不容易看到图像是如何切片的.我期待一种元组来设置行数和列数 (4认同)

Nir*_*Nir 14

将图像分割为MxN像素的图块(假设im为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)]
Run Code Online (Sandbox Code Playgroud)

如果您想将图像拆分为四个部分:

M = im.shape[0]//2
N = im.shape[1]//2
Run Code Online (Sandbox Code Playgroud)

tiles [0]保持左上方的tile


Iva*_*van 13

作为替代解决方案,我们将通过使用 生成坐标网格来构建图块itertools.product。我们将忽略边缘上的部分瓦片,只迭代两个区间之间的笛卡尔积, range(0, h-h%d, d) X range(0, w-w%d, d)

给定filename:图像文件名,d:图块大小,dir_in:包含图像的目录的路径,以及dir_out:将输出图块的目录:

from PIL import Image
from itertools import product
Run Code Online (Sandbox Code Playgroud)
def tile(filename, dir_in, dir_out, d):
    name, ext = os.path.splitext(filename)
    img = Image.open(os.path.join(dir_in, filename))
    w, h = img.size
    
    grid = product(range(0, h-h%d, d), range(0, w-w%d, d))
    for i, j in grid:
        box = (j, i, j+d, i+d)
        out = os.path.join(dir_out, f'{name}_{i}_{j}{ext}')
        img.crop(box).save(out)
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

  • 非常实用的解决方案,谢谢。将“fp”作为参数发送给函数可能很有用,因为“文件名”和“fp”变量可能会造成混淆。 (2认同)

unu*_*tbu 12

  1. crop如果您将裁剪代码与图像保存代码分开,那将是一个更可重用的功能.它还可以使呼叫签名更简单.
  2. im.crop返回一个 Image._ImageCrop实例.此类实例没有保存方法.相反,您必须将Image._ImageCrop实例粘贴 到新实例上Image.Image
  3. 您的范围没有正确的步长.(为什么height-2而不是 height?例如.为什么要停下来 imgheight-(height/2)?).

所以,你可能会尝试这样的事情:

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)
Run Code Online (Sandbox Code Playgroud)