python - 如何使用 Python 在网格中连接 * 最多 * 4 个图像?
问题描述
我正在学习如何使用 PIL,我想将 4 个单独的图像连接成一个网格(所有256x256
PNG)。使用 PIL(以及可选的 NumPy)。通过我发现的几个示例,当我正好有 4 张图像时,我已经能够通过将它们全部水平/垂直堆叠或作为网格堆叠来连接图像。
我现在想要做的是将最多4 个图像组合成一个网格,即将 1 到 4 个图像之间的任何地方传递到一个函数中。
用例:
我的第一个想法是将图像列表分成对,水平连接每个,然后垂直连接两个结果,但感觉效率低下。
编辑:我已经使用 OpenCV 进行了上述工作,因为它比 PIL 更容易使用。这是我的代码:
images = ["images/img1.png", "images/img2.png", "images/img3.png", "images/img4.png"]
def combine(images):
if len(images) == 1:
img1 = cv2.imread(images[0])
return cv2.imwrite("Combined.png", img1)
elif len(images) == 2:
img1 = cv2.imread(images[0])
img2 = cv2.imread(images[1])
combined_image = cv2.hconcat([img1, img2])
return cv2.imwrite("Combined.png", combined_image)
elif len(images) == 3:
img1 = cv2.imread(images[0])
img2 = cv2.imread(images[1])
img3 = cv2.imread(images[2])
img4 = cv2.imread("images/Blank.png") # Just a transparent PNG
image_row_1 = cv2.hconcat([img1, img2])
image_row_2 = cv2.hconcat([img3, img4])
combined_image = cv2.vconcat([image_row_1, image_row_2])
return cv2.imwrite("Combined.png", combined_image)
elif len(images) == 4:
img1 = cv2.imread(images[0])
img2 = cv2.imread(images[1])
img3 = cv2.imread(images[2])
img4 = cv2.imread(images[3])
image_row_1 = cv2.hconcat([img1, img2])
image_row_2 = cv2.hconcat([img3, img4])
combined_image = cv2.vconcat([image_row_1, image_row_2])
return cv2.imwrite("Combined.png", combined_image)
combine(images)
有没有更好的办法?
解决方案
如果您对 NumPy 中的替代方案感兴趣。这是将1到4 个图像平铺在2x2网格上的一种方法。
考虑x
定义为形状数组的输入,(n, c, h, w)
其中n
是图像的数量(可以是1、2、3或4)、c
通道数(此处为3)以及h, w
图像的高度和宽度(我们将坚持2x2,但它适用于任何尺寸。
出于演示目的,x
定义为:
x = np.array([
np.arange(1, 5).reshape((2,2))*1,
np.arange(1, 5).reshape((2,2))*10,
np.arange(1, 5).reshape((2,2))*100,
np.arange(1, 5).reshape((2,2))*1000,
])
x = np.stack([x]*3, axis=1) # make it 3-channel
首先用零填充输入作为丢失图像的占位符。这将确保我们有一个形状,4, c, h, w
即四个图像dim=0
:
x_fill = np.concatenate([x, np.zeros((4-n, c, h, w))])
首先广播到2x2x...形状(按列!使用order='F'
):
x_fill = x_fill.reshape((2, 2, c, h, w), order='F')
最后连接axis=3
then axis=1
:
grid = np.concatenate(np.concatenate(x_fill, axis=3), axis=1)
以下是输出(仅显示 的第一个通道grid
):
1 张图片:
array([[[ 1., 2., 0., 0.], [ 3., 4., 0., 0.], [ 0., 0., 0., 0.], [ 0., 0., 0., 0.]]])
2 张图片:
array([[[ 1., 2., 10., 20.], [ 3., 4., 30., 40.], [ 0., 0., 0., 0.], [ 0., 0., 0., 0.]]])
3 张图片:
array([[[ 1., 2., 10., 20.], [ 3., 4., 30., 40.], [100., 200., 0., 0.], [300., 400., 0., 0.]]])
4 张图片:
array([[[ 1., 2., 10., 20.], [ 3., 4., 30., 40.], [100., 200.,1000.,2000.], [300., 400.,3000.,4000.]]])
这是输入的x
样子:
array([[[[ 1, 2],
[ 3, 4]],
[[ 1, 2],
[ 3, 4]],
[[ 1, 2],
[ 3, 4]]],
[[[ 10, 20],
[ 30, 40]],
[[ 10, 20],
[ 30, 40]],
[[ 10, 20],
[ 30, 40]]],
[[[ 100, 200],
[ 300, 400]],
[[ 100, 200],
[ 300, 400]],
[[ 100, 200],
[ 300, 400]]],
[[[1000, 2000],
[3000, 4000]],
[[1000, 2000],
[3000, 4000]],
[[1000, 2000],
[3000, 4000]]]])
推荐阅读
- linux - 用 PHP 编译 C 程序返回“gcc:错误试图执行 'cc1':execvp:没有这样的文件或目录”
- arrays - excel vba索引匹配数组以分隔文件
- python - 如何在 python 中使用 hmmlearn GMMHMM 库拟合我的连续数据?
- c++ - 如何在 C++ 中正确表达两个具有相同实现的派生类函数?
- javascript - HERE 地图 API 不显示地图 - 此帖子中的照片
- php - 手动在您的网站中使用自定义帖子类型
- python - 将一个类传递给另一个类
- gitlab - How to use protected enviroment variables from gitlab CI/CD inside serverless script?
- ruby-on-rails - Get bounding box from array of points
- html - 如何优化 Chrome 浏览器中网页的背景视频?