目次
概要
OpenCV で複数の画像を横方向、または縦方向に結合する方法について解説します。
横方向に結合する
横方向に結合する場合、結合するすべての画像が収まる大きさの画像を作成し、そこに各画像を貼り付ける形で作成します。 その際、結合後の画像の大きさは以下のようになります。
- 結合後の幅: 結合する画像の幅の合計値
- 結合後の幅: 結合する画像の高さの最大値
In [1]:
import cv2
import numpy as np
from IPython.display import Image, display
def imshow(img):
"""ndarray 配列をインラインで Notebook 上に表示する。"""
ret, encoded = cv2.imencode(".jpg", img)
display(Image(encoded))
In [2]:
img1 = cv2.imread("samples/sample01.jpg", cv2.IMREAD_COLOR)
img2 = cv2.imread("samples/sample02.jpg", cv2.IMREAD_COLOR)
img3 = cv2.imread("samples/sample03.jpg", cv2.IMREAD_COLOR)
def concat_w(*imgs, background=(255, 255, 255)):
"""画像を横方向に結合する。
Args:
background: 背景色
Returns:
結合した画像
"""
img_h = max(x.shape[0] for x in imgs)
img_w = sum(x.shape[1] for x in imgs)
dst = np.full((img_h, img_w, 3), background, dtype=np.uint8)
x = 0
for img in imgs:
dst[: img.shape[0], x : x + img.shape[1]] = img
x += img.shape[1]
return dst
dst = concat_w(img1, img2, img3)
imshow(dst)
縦方向に結合する
縦方向に結合する場合、結合するすべての画像が収まる大きさの画像を作成し、そこに各画像を貼り付ける形で作成します。 その際、結合後の画像の大きさは以下のようになります。
- 結合後の幅: 結合する画像の幅の最大値
- 結合後の幅: 結合する画像の高さの合計値
In [3]:
img1 = cv2.imread("samples/sample01.jpg", cv2.IMREAD_COLOR)
img2 = cv2.imread("samples/sample02.jpg", cv2.IMREAD_COLOR)
img3 = cv2.imread("samples/sample03.jpg", cv2.IMREAD_COLOR)
def concat_h(*imgs, background=(255, 255, 255)):
"""画像を縦に結合する。
Args:
background: 背景色
Returns:
結合した画像
"""
img_w = max(x.shape[1] for x in imgs)
img_h = sum(x.shape[0] for x in imgs)
dst = np.full((img_h, img_w, 3), background, dtype=np.uint8)
y = 0
for img in imgs:
dst[y : y + img.shape[0], : img.shape[1]] = img
y += img.shape[0]
return dst
dst = concat_h(img1, img2, img3)
imshow(dst)
画像を格子状に並べる
画像を格子状に並べるコードを紹介します。
In [4]:
import math
from pathlib import Path
# 画像を読み込む。
imgs = []
for img_path in Path("samples").glob("*.jpg"):
img = cv2.imread(str(img_path), cv2.IMREAD_COLOR)
imgs.append(img)
def concat_grid(imgs, cols, background=(255, 255, 255), gap=5):
"""画像を格子状に配置する。
Args:
imgs: 画像一覧
cols: 1行あたりの画像枚数
background: 背景色
gap: 画像間の隙間の大きさ
Returns:
結合した画像
"""
rows = math.ceil(len(imgs) / cols)
# 各行、各列の幅及び高さを計算する。
row_hs, col_ws = [], []
for i in range(rows):
row_h = max(x.shape[0] for x in imgs[i * cols : (i + 1) * cols])
row_hs.append(row_h)
for i in range(cols):
col_w = max(x.shape[1] for x in imgs[i::cols])
col_ws.append(col_w)
# 出力画像の大きさを計算する。
img_w = sum(col_ws) + gap * (cols - 1)
img_h = sum(row_hs) + gap * (rows - 1)
dst = np.full((img_h, img_w, 3), background, dtype=np.uint8)
# 画像を配置する。
for i, img in enumerate(imgs):
row = i // cols
col = i % cols
x = sum(col_ws[:col]) + col * gap
y = sum(row_hs[:row]) + row * gap
dst[y : y + img.shape[0], x : x + img.shape[1]] = img
return dst
dst = concat_grid(imgs, cols=3)
imshow(dst)
コメント