"SystemError: tile cannot extend outside image" in PIL during save image

"SystemError: tile cannot extend outside image" in PIL during save image

我有这张图片 =>

这里是3.txt文件中写的上面黄色框的所有坐标。

#Y   X Height     Width 

46 135 158 118 
46 281 163 104 
67 494 188 83 
70 372 194 101 
94 591 207 98 
252 132 238 123 
267 278 189 105 
320 741 69 141 
322 494 300 135 
323 389 390 124 
380 726 299 157 
392 621 299 108 
449 312 227 93 
481 161 425 150 
678 627 285 91 
884 13 650 437 
978 731 567 158 
983 692 60 43 
1402 13 157 114 

我的意图是裁剪这些框并将所有框保存为图像。我已经为此编写了代码但出现错误。

这是我的代码=>

from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
from os import listdir
#from scipy.misc import imsave

ARR = np.empty([1,4])
# print(ARR)

i = 0
k = 0
img = Image.open('3.png')

fo = open("3.txt", "r")
for line in fo:
    if not line.startswith('#'):
        for word in line.split():

            ARR[0][i] = int(word)
            print(int(word))
            # ARR[0][i] = int(word)
            i = i +1

    img2 = img.crop((int(ARR[0][1]), int(ARR[0][0]), int(ARR[0][0] + ARR[0][2]), int(ARR[0][1] + ARR[0][3])))
    name = "new-img" + str(k) + ".png"
    img2.save(name)
    k = k + 1
    i = 0

我收到这些错误 =>

Traceback (most recent call last): File "reshape.py", line 26, in img2.save(name) File "/usr/lib/python2.7/dist-packages/PIL/Image.py", line 1468, in save save_handler(self, fp, filename) File "/usr/lib/python2.7/dist-packages/PIL/PngImagePlugin.py", line 624, in _save ImageFile._save(im, _idat(fp, chunk), [("zip", (0,0)+im.size, 0, rawmode)]) File "/usr/lib/python2.7/dist-packages/PIL/ImageFile.py", line 462, in _save e.setimage(im.im, b) SystemError: tile cannot extend outside image

我该如何解决这些问题?

参考评论,错误是由于不正确地将坐标传递给 PIL 的 crop() 函数。

the documentation 中所述,函数 returns 一个包含四个元组的图像(xywidthheight).

在给定的文本文件中,第一列中提到了 y 坐标,第二列中提到了 x 坐标。然而,crop() 函数接受 x 坐标的值作为第一个参数,y 坐标作为第二个参数。

同样适用于 OpenCV

这是ANOTHER POST关于相同的。

在我的例子中,问题是我指定了开始和结束坐标,其中开始 X 和开始 Y 并不总是小于结束 X 和 Y。你不能这样做。

例如,

开始:(0, 50) 结束:(50, 0)

这些坐标对我来说很有意义,但实际上应该指定为:

开始:(0, 0) 结束:(50, 50)

视觉上是相同的矩形,但 Pillow 需要后者才能裁剪。

网上说的方法是这样的:

imageScreenshot.crop((x, y, width, height))

但正确的做法是这样的:

imageScreenshot.crop((x, y, x + width, y + height))

意味着您应该将 x 添加到 width 并将 y 添加到 height
这是一个简单的例子(driver 用于 python selenium):

def screenShotPart(x, y, width, height) -> str:
    screenshotBytes = driver.get_screenshot_as_png()
    imageScreenshot = Image.open(BytesIO(screenshotBytes))
    imageScreenshot = imageScreenshot.crop((x, y, x + width, y + height))
    imagePath = pathPrefix + "_____temp_" + str(time.time()).replace(".", "") + ".png"
    imageScreenshot.save(imagePath)

希望对您有所帮助。

如果您正在使用深度学习软件来检测图像中的对象并且您正在尝试删除检测 - 您很可能会看到这个

我在使用 ImageAI 检测图像中的对象时遇到了同样的错误。 我已经设法通过在我的虚拟环境中从 PIL 包编辑 ImageFile.py 来解决它。

ImageFile 位于

\home\myuser\anaconda3\envs\envsName\lib\python3.7\site-packages\PIL\ImageFile.py

查找以以下内容开头的 _save 函数行:

def _save(im, fp, tile, bufsize=0):

之后:

 tile.sort(key=_tilesort)
    # FIXME: make MAXBLOCK a configuration parameter
    # It would be great if we could have the encoder specify what it needs
    # But, it would need at least the image size in most cases. RawEncode is
    # a tricky case.

插入:

tile = [e for e in tile if e[1][2] > 0 and e[1][3]>0]

这将跳过保存图像(平铺)宽度和高度大小不正确的所有检测,有时报告为 0,可能是因为检测到的对象仅部分显示在图像边缘。

------------

但是,例如,如果您知道所有图像都是 1920x1080,并且您想要丢弃所有未报告的大小大致相同的图像,您可以执行类似的操作。

tile = [e for e in tile if e[1][2] > 1720 and e[1][3]>880]

宽度和高度减少了 200 像素,以允许保存更小但可能仍然正确的图像(图块),这将丢弃所有其他图像。

Source.