如何在保持背景的画布上修剪对象并将其居中?

Posted

技术标签:

【中文标题】如何在保持背景的画布上修剪对象并将其居中?【英文标题】:How to trim and center an object on the canvas keeping the background? 【发布时间】:2021-09-13 06:52:26 【问题描述】:

有这样的输入图像

我需要

修剪到 3:4 的比例, 将人放在 3:4 画布的中心,然后 保留背景。

这是我需要的输出:

这是我到目前为止的代码。它会裁剪模型的边缘,但我需要将其放置在 3:4 的画布上,以保持背景颜色。

import cv2
import numpy as np
#img = cv2.imread("test.png")
img = cv2.imread("1.jpg")
blurred = cv2.blur(img, (3,3))
canny = cv2.Canny(blurred, 50, 200)

## find the non-zero min-max coords of canny
pts = np.argwhere(canny>0)
y1,x1 = pts.min(axis=0)
y2,x2 = pts.max(axis=0)

## crop the region
cropped = img[y1:y2, x1:x2]
cv2.imwrite("cropped.png", cropped)

tagged = cv2.rectangle(img.copy(), (x1,y1), (x2,y2), (0,255,0), 3, cv2.LINE_AA)
cv2.imshow("tagged", tagged)
cv2.waitKey()

【问题讨论】:

【参考方案1】:

对于以下解决方案,我假设

    输入图像具有白色背景, 使用图像的整个高度制作切口,并且 人物周围有足够的空间来获得适当的 3:4 切口。

过程很简单:

    调整图像大小,使高度为 4 的倍数,以获得精确的 3:4 切口。 对灰度图像进行反向二值化以掩盖人物。 获取人物的边界矩形。 计算边界矩形的水平中心,并从高度计算所需的宽度。 将图像从“中心 - 0.5 * 宽度”切片到“中心 + 0.5 * 宽度”。

这就是完整的代码:

import cv2

# Read image
img = cv2.imread('qUgOO.jpg')
h, w = img.shape[:2]

# Resize such that height is a multiple of 4
th = h & (-4)
tw = int((th / h) * w)
img = cv2.resize(img, (tw, th))

# Get bounding rectangle of person (assuming white-ish background)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
thr = cv2.threshold(gray, 192, 255, cv2.THRESH_BINARY_INV)[1]
bx, by, bw, bh = cv2.boundingRect(thr)

# Create 3:4 cutout around center of bounding rectangle of person
cx = bx + bw // 2
tw = int(th * (3 / 4))
l = int(cx - (1 / 2) * tw)
out = img[:, l:l+tw]
print(out.shape[1] / out.shape[0])
# 0.75

生成的图像看起来与您想要的输出几乎相同。

关于所做的假设:

    如果您有不同的背景,尤其是深色背景,则需要调整人物边界矩形的发现。 如果剪裁也应考虑高度(即人的头部低于图像上边框),您还需要计算边界矩形的垂直中心。 如果人可以在图像的最左侧或最右侧,您需要检查最终的切片是否会违反图像尺寸,并进行相应的修正。
----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.19041-SP0
Python:        3.9.1
PyCharm:       2021.1.2
OpenCV:        4.5.2
----------------------------------------

【讨论】:

几行代码中的大量逻辑!非常感谢!

以上是关于如何在保持背景的画布上修剪对象并将其居中?的主要内容,如果未能解决你的问题,请参考以下文章

FabricJS:始终在画布上居中对象

如何清除画布属性和事件并将其添加回fabricjs?

如何使用 CreateJS 在画布上居中图像

在 FabricJS 中调整窗口大小时如何始终将剪切区域居中?

如何在 python 中创建路径并将其显示在 qml 画布上

如何在 AngularJS 中使用图像作为背景?