首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在Python中使用Pillow从图像中裁剪区域

在Python中使用Pillow从图像中裁剪区域
EN

Stack Overflow用户
提问于 2019-02-05 03:22:15
回答 3查看 1.3K关注 0票数 3

我想在python中使用Pillow从图像中裁剪一个矩形区域。问题是矩形不需要与图像边距平行,所以我不能使用.crop((left,top,right,bottom))函数。

有没有办法用Pillow实现这一点?(假设我们知道矩形的所有4个点的坐标)如果不知道,如何使用不同的Python库来完成?

EN

回答 3

Stack Overflow用户

发布于 2019-02-05 19:46:17

您可以在OpenCV中使用最小旋转矩形:

代码语言:javascript
运行
复制
rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)

结果是:中心坐标(x,y),宽度,高度,矩形的旋转角度。您可以旋转整个图像的角度从这个矩形。您的图像现在将被旋转:

你可以计算四个矩形顶点的新坐标(你得到了角度)。然后只计算这个点的法线矩形(法线矩形=非最小,没有任何旋转)。使用此矩形,您可以裁剪旋转后的图像。如果我没理解错的话,这张裁剪图像中的图片就是你想要的。大概是这样的:

所以你只需要Opencv。也许有一些库可以让你更容易做到这一点。

票数 2
EN

Stack Overflow用户

发布于 2019-02-05 19:55:44

这里有一个基于scikit-image (而不是Pillow)的解决方案,你可能会发现它很有用。

您可以将希望裁剪的区域的顶点传递给函数skimage.draw.polygon,然后使用检索到的像素坐标来遮罩原始图像(例如,通过alpha通道)。

代码语言:javascript
运行
复制
import numpy as np
from skimage import io, draw

img = io.imread('https://i.stack.imgur.com/x5Ym4.png')

vertices = np.asarray([[150, 140],
                       [300, 240],
                       [210, 420],
                       [90, 320],
                       [150, 150]])

rows, cols = draw.polygon(vertices[:, 0], vertices[:, 1])

crop = img.copy()
crop[:, :, -1] = 0
crop[rows, cols, -1] = 255

io.imshow(crop)

票数 2
EN

Stack Overflow用户

发布于 2020-06-28 09:25:22

为了与PIL一起使用,我对this opencv-based solution (sub_image)进行了修改。它接受我从cv2.minAreaRect得到的(center, size, theta) rect,但可以通过数学方法从点构造,等等。

我已经看到了一些其他的解决方案,但是他们留下了一些奇怪的东西。

代码语言:javascript
运行
复制
def crop_tilted_rect(image, rect):
    """ crop rect out of image, handing rotation
    
    rect in this case is a tuple of ((center_x, center_y), (width, height), theta),
    which I get from opencv's cv2.minAreaRect(contour)
    """
    # Get center, size, and angle from rect
    center, size, theta = rect
    width, height = [int(d) for d in size]

    if 45 < theta <= 90:
        theta = theta - 90
        width, height = height, width

    theta *= math.pi / 180 # convert to rad
    v_x = (math.cos(theta), math.sin(theta))
    v_y = (-math.sin(theta), math.cos(theta))
    s_x = center[0] - v_x[0] * (width / 2) - v_y[0] * (height / 2)
    s_y = center[1] - v_x[1] * (width / 2) - v_y[1] * (height / 2)
    mapping = np.array([v_x[0],v_y[0], s_x, v_x[1],v_y[1], s_y])
    return image.transform((width, height), Image.AFFINE, data=mapping, resample=0, fill=1, fillcolor=(255,255,255))
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54522956

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档