この記事は公開から2年以上経過しています。
Markdown Preview EnhancedでPuppeteerを使って出力したPNG画像を不規則なサイズで複数画像に分割したい事情があり、この作業を手作業で繰り返す時間が無駄になると感じたので、OpenCVの画像パターンマッチング機能を使って複数画像に分割するツールを作成してみたので紹介します。
サンプルソースコード
OpenCVのテンプレートマッチング関数matchTemplate()
で分割対象画像image.png
内の分割マーカー画像divider.png
を検索し、見つかった位置のY座標で画像を水平分割して連番付きの画像として出力します。
実行環境はMicrosoft Visual Studio 2019同梱のPython 3.9で、opencv-python
とnumpy
パッケージを利用しています。
import os
import cv2
import numpy as np
# 処理対象画像を配置するディレクトリ
base_dir = r'c:\temp'
# 分割対象画像
img = cv2.imdecode(
np.fromfile(os.path.join(
base_dir, 'image.png'), dtype=np.uint8),
cv2.IMREAD_UNCHANGED)
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 分割マーカー画像
img_divider = cv2.imdecode(
np.fromfile(os.path.join(
base_dir, 'divider.png'), dtype=np.uint8),
cv2.IMREAD_UNCHANGED)
img_divider_gray = cv2.cvtColor(img_divider, cv2.COLOR_BGR2GRAY)
# 分割マーカーの位置を検索
res = cv2.matchTemplate(img_gray, img_divider_gray, cv2.TM_CCOEFF_NORMED)
pos_y, _ = np.where(res >= 0.9)
# 分割マーカーの位置で画像を分割
dividing_pos_y = 0
image_num = 1
image_h, image_w = img_gray.shape
divider_h = img_divider_gray.shape[0]
for y in np.r_[pos_y, image_h]:
retval, buf = cv2.imencode('.png', img[dividing_pos_y:y, 0:image_w])
buf.tofile(os.path.join(
base_dir, f'image{image_num:02}.png'))
dividing_pos_y = y + divider_h
image_num += 1
動作検証データ
-
動作検証に使用する処理対象画像、分割マーカー画像は以下のとおりです。
出力後に分割を行いたい位置を示す⏎
記号を挿入しておきます。 -
sample.md(処理対象画像のMarkdown)
# Markdown Preview Enhanced<br>画像分割テスト ## ページ 1 1 2 3 4 5 ⏎ ## ページ 2 A B C D E ⏎ ## ページ 3 a b c d e
-
image.png(分割前のイメージ)
-
divider.png(この画像の位置で分割)
出力結果
出力結果は以下のとおりです。目論見通り分割マーカー位置で入力画像を3分割できていることが確認できます。
-
image01.png
-
image02.png
-
image03.png
OpenCVのテンプレートマッチングは類似画像でマッチングを行うことはできないようですが、気軽に使えるので日常業務で色々なことを自動化するのには便利そうです。
参考ウェブサイトなど
- OpenCV
OpenCV-Python Tutrial/Image Processing in OpenCV/Template Matching
以上です。