# [メタ情報] # 識別子: PDFまたは画像から切り抜き画像の生成workflow_exe # システム名: 未分類 # 技術種別: Misc # 機能名: Misc # 使用言語: ShellScript # 状態: 実行用 # [/メタ情報] PDFまたは画像から切り抜き画像の生成.workflow ワークフローが受け取る現在の項目:ファイルまたはフォルダ 検索対象:Finder.app シェルスクリプトを実行 入力の引き渡し方法:引数として #!/bin/bash FILE_PATH="$1" EXTENSION="${FILE_PATH##*.}" BASENAME=$(basename "$FILE_PATH" .${EXTENSION}) DIRNAME=$(dirname "$FILE_PATH") cd "$DIRNAME" # JPEG変換(PDFのみ) if [[ "$EXTENSION" == "pdf" ]]; then /usr/local/bin/pdftoppm -jpeg -r 300 "$FILE_PATH" "${BASENAME}_page" mv "${BASENAME}_page-1.jpg" "${BASENAME}_page.jpg" IMAGE_NAME="${BASENAME}_page.jpg" elif [[ "$EXTENSION" == "gif" ]]; then # GIF → JPEG(最初のフレーム)に変換 IMAGE_NAME="${BASENAME}_frame.jpg" /usr/local/bin/convert "$FILE_PATH[0]" "$IMAGE_NAME" else # その他の画像はそのまま使う cp "$FILE_PATH" "${BASENAME}_page.jpg" IMAGE_NAME="${BASENAME}_page.jpg" fi # Bash変数を Python に渡すため export export BASENAME export DIRNAME export IMAGE_NAME /Users/xxxxxxxx/python_scripts/venv_pdfcrop/bin/python3 <<"EOF" import cv2 import numpy as np from PIL import Image import os basename = os.environ.get("BASENAME") dirpath = os.environ.get("DIRNAME") jpg_path = os.path.join(dirpath, os.environ.get("IMAGE_NAME")) img = cv2.imread(jpg_path, cv2.IMREAD_COLOR) # === PNGやJPEGからの入力の場合は人工的に解像度アップ === # PDF由来なら元から300dpiあるが、画像は低解像度の可能性があるためスケーリング img = cv2.resize(img, None, fx=2.0, fy=2.0, interpolation=cv2.INTER_LINEAR) # === 線の抽出(濃い部分全体を抽出)=== gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) _, thresh = cv2.threshold(gray, 200, 255, cv2.THRESH_BINARY_INV) # 線を適度に太らせて塗り潰す(85%程度に抑える) kernel = np.ones((3,3), np.uint8) filled = cv2.dilate(thresh, kernel, iterations=1) # RGBA画像を生成し、黒で完全に塗りつぶし、不透明に rgba = np.zeros((img.shape[0], img.shape[1], 4), dtype=np.uint8) rgba[:, :, 0:3] = 0 rgba[:, :, 3] = filled png2_path = os.path.join(dirpath, f"{basename}_lineonly.png") cv2.imwrite(png2_path, rgba) # === 外周内側白塗り(PNG画像3)=== contours, _ = cv2.findContours(filled, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) mask = np.zeros_like(gray) cv2.drawContours(mask, contours, -1, 255, -1) white_fill = np.zeros((img.shape[0], img.shape[1], 4), dtype=np.uint8) white_fill[:, :, 0:3] = 255 white_fill[:, :, 3] = mask png3_path = os.path.join(dirpath, f"{basename}_filled.png") cv2.imwrite(png3_path, white_fill) # === 合成してPNG画像4を作成 === img2 = Image.open(png2_path).convert("RGBA") img3 = Image.open(png3_path).convert("RGBA") combined = Image.alpha_composite(img3, img2) png4_path = os.path.join(dirpath, f"{basename}_cropped.png") combined.save(png4_path) # === 中間ファイル削除 === os.remove(jpg_path) os.remove(png2_path) os.remove(png3_path) EOF