Pythonで画像分割や画像結合を実行する方法

2021年6月19日

画像分割のやり方

以下のプログラムを実行してください。

なお、フォルダ名や画像ファイル名はみなさんの環境に合わせ変更してください。

# 画像分割 sepa.py
import os
import cv2
import numpy as np
# 画像読み込み
image = cv2.imread('./test_photo/001.jpg')
# 画像サイズを調べる(高さ:h 、幅:w)
h, w = image.shape[:2]
n = 3  # 画像分割数
y0 = int(h/n)
x0 = int(w/n) 
# 分割した画像を内包表記でリスト化
c = [image[x0*x:x0*(x+1), y0*y:y0*(y+1)] for x in range(n) for y in range(n)]
# c のリストから1つづつ取り出して
# ファイル番号(0.jpg、1.jpg、・・)を付けて、sepaフォルダに保存
for i, img in enumerate(c):
    cv2.imwrite(os.path.join('./test_photo/sepa', '{}.jpg'.format(i)), img)

cv2を使うので、OpenCVをインストールしていない場合は以下の方法でインストールしてください。

OpenCVのインストール方法

AnacondaがインストールしてあればAnaconda Prompt から以下を実行。

> pip install opencv-python

ソースコードのポイント

1.内包表記で分割画像をリスト化

画像サイズが大きい場合や分割数が多くなると for 文では実行速度が遅くなります。

このため、リスト内包表記を使うのがおすすめです。

2enumerate関数を使ってインデックスと要素を同時取得

あとあと結合させることを考えファイル番号を数字にしておきます。

これにより一連番号でフォルダにストックされます。

メリットは画像に順番を付けやすいことです。

自然順(ファイル番号の小さい順)に読み込んで結合させれば元通りの画像ができます。

分割結果(例)

画像結合のやり方

以下のプログラムを実行してください。

# 画像結合  comb.py
import cv2
import glob
import numpy as np
from PIL import Image
from natsort import natsorted
# 所定のフォルダ内にある jpg ファイルを連続で読み込んでリスト化する
files = glob.glob("./test_photo/sepa" + "/*.jpg")
# 空のリストを準備
d = []
# natsortedで自然順(ファイル番号の小さい順)に1個づつ読み込む
for i in natsorted(files):
    img = Image.open(i)    # img は'JpegImageFile' object
    img = np.asarray(img)  # np.asarrayで img を ndarray に変換
    d.append(img)          # d にappend で img を追加
# 画像の高さ方向と幅方向を結合
img_x = np.vstack((np.hstack(d[0:3]),
                   np.hstack(d[3:6]),
                   np.hstack(d[6:9])
                  ))
# 色をBGR から RGB に変更
img_x = cv2.cvtColor(img_x, cv2.COLOR_BGR2RGB)
cv.imshow('img_after', img_x)
cv.imwrite('./test_photo/result.jpg', img_x)
cv.waitKey(0)
cv.destroyAllWindows()

ソースコードのポイント

1natsorted を使う

これにより自然順(ファイル番号の小さい順)にファイルを読み込むことができます。

d のリスト内ではファイル番号順に画像が並んでいるとは限りません。

もし画像の順番がバラバラだと、np.vstack(高さ方向の結合) や np.hstack(幅方向の結合) で画像を結合した際、分割画像がバラバラに組み合わさったものになります。

2.cv2.COLOR_BGR2RGBで色をRGBにする

これをしないと青ざめた写真になります。RとBが逆になるので。

結合結果(例)

まとめ

画像分割するとき

  • OpenCVを使うことで静止画の取り込みができる。
  • 実行速度を考慮し分割画像を内包表記でリスト化するのがおすすめ。
  • enumerate関数でインデックスを取得しファイル番号に利用するのがおすすめ。

画像結合するとき

  • natsorted を使って自然順(ファイル番号の小さい順)にファイルを読み込む。
  • Numpynp.vstack(高さ方向の結合)、np.hstack(幅方向の結合)で画像を結合できる。

参考にした書籍

Pythonで大量のデータを高速に処理をしたい方はNumPyが必須です。

NumPyは奥が深く便利な関数がいろいろと用意されており、本書に分かり易くまとめられています。

辞書として使えば、開発効率が非常に上がります。

ちなみに、私も何度も読み返しています。

ちょっと高いですが、それだけの価値はあります。

「NumPyデータ処理入門」の方が初心者向けです。

NumPyの基礎から便利関数まで幅広く掲載されており、大変分かり易いです。

中級者~上級者は「NumPy & SciPy数値計算 実装ハンドブック」がおすすめです。

numpy.vstack や numpy.hstack の使い方はこちらの本を参考にしています。