前言
今天在做人脸识别时遇到个关于图像裁剪的问题,SystemError: tile cannot extend outside image(图块无法扩展到外部图像),总的来说就是图像裁剪时不能存在负值。第一次接触这个问题,我看其他博主也未提出解决方案,因此我在这简单的提下,希望能帮助到同样是第一次遇到的小白们。
错误产生原因分析
在人脸识别前需要先进行人脸检测,然后对检测到的人脸进行裁剪,而 SystemError: tile cannot extend outside image 就是出现在裁剪过程中的,正常情况下从摄像头内读取一帧若人脸全在图片内,情况如下(蓝色代表摄像头的范围即传入的原图,橙色代表人脸位置):
此时人脸的四个检测点x1,x2,y1,y2均为正值,因此此时进行裁剪不会报错(crop_img = old_image[y1:y2, x1:x2])
若当使用笔记本摄像头截图的时候,由于离镜头太近,导致边框超出摄像头截图范围,情况如下:
由上图很容易得知此时人脸的四个检测点中x1,x2,y2为正值,而y1为负值,因此此时使用若采用 crop_img = old_image[y1:y2, x1:x2] 进行图像裁剪,那么系统会因为y1为负值而报 SystemError: tile cannot extend outside image(图块无法扩展到外部图像)
同理当x1为负值时也会报同样错误,情况如下:
解决方案
在找到错误产生原因后相信各位都已经想到解决的办法了,没错就是采用 np.maximum(x,y) 和 np.minimum(x,y) 的方法,在numpy中 maximum 是选择x与y当中的较大值,而 minimum 则是选择较小值。因此我们来看看具体的解决方案吧。
会导致报错的代码如下:
for b in boxes_conf_landms:
text = "{:.4f}".format(b[4])
b = list(map(int, b))
x1 = b[0]
x2 = b[2]
y1 = b[1]
y2 = b[3]
crop_img = old_image[y1:y2, x1:x2]
scaled = np.array(Image.fromarray(crop_img).resize((160, 160)))
此时由于未对x1与y1做处理,因此x1与y1会存在负值的情况,因此会报错。
处理后的代码:
for b in boxes_conf_landms:
text = "{:.4f}".format(b[4])
b = list(map(int, b))
x1 = np.maximum(b[0],0)
x2 = np.minimum(b[2],old_image.shape[1])
y1 = np.maximum(b[1],0)
y2 = np.minimum(b[3],old_image.shape[0])
crop_img = old_image[y1:y2, x1:x2]
scaled = np.array(Image.fromarray(crop_img).resize((160, 160)))
此时当b[0]与b[1]为负值时小于0,x1与y1会取0,而不是取b[0]与b[1],因此x1与y1不会取到负值,所以无论你的人脸是否在图像内程序都不会报SystemError: tile cannot extend outside image(图块无法扩展到外部图像)。
以上就是我对SystemError: tile cannot extend outside image报错的分析与总结了,希望能帮到遇到同样错误的你。