[英]How to crop an image given proportional coordinates with Python PIL?
我有一张尺寸为 (1920x1080) 的图像,其比例坐标提供了对检测到的人物区域的描述。 我只想使用提供的比例坐标从图像中裁剪检测到的人。 我查阅了PIL crop 文档并尝试了以下操作:
在集成文档中提供:
x0, y0 人物检测框右下角对应的x, y坐标。 它们与图像左上角的距离成比例。
x1, y1 人物检测框左上角对应的x, y坐标。 它们与图像左上角的距离成比例。
提供的示例集成说明:
def img_crop(url, box):
box = {
'x0': 0.974,
'x1': 0.922,
'y0': 0.502,
'y1': 0.315
}
img = Image.open(requests.get(url, stream=True).raw)
h, w = img.size
print(img.size)
return img.crop((box['x0']*h, box['y0']*w, box['x1']*h, box['y1']*w))
这会导致以下错误
ValueError: Coordinate 'right' is less than 'left'
但是您的绘图与您自己对 x0,y0,x1,y1 的描述相矛盾。 据说(顺便说一句, 在文字图片中;最好避免这种情况)x0,y0 是右下角,x1,y1 是左上角。
只需反转 x0、y0 和 x1、y1。
另外,请注意,PIL 中的坐标系(通常在大多数图像处理系统中都是如此。因为图像格式也是这样做的)从左上角开始。 就像英文文本一样:像素是从左到右,从上到下组织的。
编辑:(回答您的评论)
一种方法是真正地交换它们并将.crop
行替换为
return img.crop((box['x1']*h, box['y1']*w, box['x0']*h, box['y0']*w))
这将在您的代码中起作用。 尽管如此,还有一些其他更可取的更改。 首先,您将图像的宽度称为h
,将图像的高度称为w
。 当然,从 python 的角度来看这不是问题,但它无助于可读性(我猜你这样做是因为当图像是 np.array 时,例如 opencv 图像,要获得 w 和 h,你会h,w,_=img.shape
。但是 PIL .size
首先返回w
,然后返回h
。然后,你在crop
线中反转w
和h
以保持一致。
其次,靠x0和y0是box最大的x和y,x1,y1是最小的,还是比较奇怪的。 最好在调用代码中进行反转。 您没有提供它,我没有尝试显示更正的原因:必须在未提供的代码中进行更正。 (你确实提供了一个盒子,来覆盖传递的内容。所以在那个盒子里你也可以进行交换)
box = {
'x1': 0.974,
'x0': 0.922,
'y1': 0.502,
'y0': 0.315
}
但最安全的方法,特别是因为您似乎不确定所有角点在哪里,并且考虑到有时x0
可能小于x1
,而y0
大于y1
,计算哪个是最小值,哪个是最大值。
像这样:
from PIL import Image
import matplotlib.pyplot as plt
def img_crop(url, box):
box = {
'x0': 0.216,
'x1': 0.419,
'y0': 0.237,
'y1': 0.697
}
img = Image.open(requests.get(url, stream=True).raw)
w, h = img.size
print(img.size)
xmin=min(box['x0'], box['x1'])
xmax=max(box['x0'], box['x1'])
ymin=min(box['y0'], box['y1'])
ymax=max(box['y0'], box['y1'])
return img.crop((xmin*w, ymin*h, xmax*w, ymax*h))
在那里,没问题。 只需按x,y,x,y
的顺序传递两个 x 和两个 y,而不必担心先发送哪个 x 和先发送哪个 y。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.