如何 trim 将对象居中放置在 canvas 上保持背景?
How to trim and center an object on the canvas keeping the background?
有这样的输入图像
我需要
- trim 比 3:4,
- 将此人放在 3:4 canvas 的中心,然后
- 保留背景。
这就是我需要的期望输出:
这是我目前的代码。它裁剪模型的边缘,但我需要它把它放在 3:4 的 canvas 上,保持背景颜色。
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()
对于以下解决方案,我假设
- 输入图像为白色背景,
- 使用图像的整个高度进行剪切,并且
- 此人周围有足够的空间 space 以获得适当的 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
----------------------------------------
有这样的输入图像
我需要
- trim 比 3:4,
- 将此人放在 3:4 canvas 的中心,然后
- 保留背景。
这就是我需要的期望输出:
这是我目前的代码。它裁剪模型的边缘,但我需要它把它放在 3:4 的 canvas 上,保持背景颜色。
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()
对于以下解决方案,我假设
- 输入图像为白色背景,
- 使用图像的整个高度进行剪切,并且
- 此人周围有足够的空间 space 以获得适当的 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
----------------------------------------