概要
指定ディレクトリ内の画像ファイルに対して、画像の中心点を起点に放射状の直線(4, 8, 16方位)を描画するPythonツール。
- OpenCVで線を描画
- サブディレクトリも再帰的に処理可能
- 出力先は元の構造を保ったまま別フォルダに保存
- ラベル(N, NE, …)の表示もオプションで可能
- ファイル名には
_drawn{方向数}
のサフィックスを付加
フォルダ構成例
input_images/
├── a.jpg
└── sub/
└── b.png
→ 実行後:
output_images/
├── a_drawn8.jpg
└── sub/
└── b_drawn8.png
Pythonスクリプト:draw_dirs.py
import cv2
import numpy as np
import math
import argparse
from pathlib import Path
DIRECTION_LABELS = {
4: ['E', 'N', 'W', 'S'],
8: ['E', 'NE', 'N', 'NW', 'W', 'SW', 'S', 'SE'],
16: ['E', 'ENE', 'NE', 'NNE', 'N', 'NNW', 'NW', 'WNW',
'W', 'WSW', 'SW', 'SSW', 'S', 'SSE', 'SE', 'ESE']
}
def draw_directions(img, n_directions=16, thickness=2, with_label=False):
height, width = img.shape[:2]
center_x, center_y = width // 2, height // 2
length = int(np.hypot(width, height))
color = (0, 0, 255)
angle_step = 360 / n_directions
font = cv2.FONT_HERSHEY_SIMPLEX
font_scale = 0.6
font_thickness = 1
for i in range(n_directions):
theta_deg = i * angle_step
theta_rad = math.radians(theta_deg)
dx = int(length * math.cos(theta_rad))
dy = int(length * math.sin(theta_rad))
x1, y1 = center_x - dx, center_y - dy
x2, y2 = center_x + dx, center_y + dy
cv2.line(img, (x1, y1), (x2, y2), color, thickness)
if with_label:
label = DIRECTION_LABELS[n_directions][i]
label_offset = 30
lx = int(center_x + (length + label_offset) * math.cos(theta_rad))
ly = int(center_y + (length + label_offset) * math.sin(theta_rad))
cv2.putText(img, label, (lx, ly), font, font_scale, color, font_thickness, cv2.LINE_AA)
return img
def is_image_file(filename):
return filename.lower().endswith(('.jpg', '.jpeg', '.png', '.bmp', '.tif', '.tiff'))
def process_directory(input_dir, output_dir, n_directions=16, thickness=2, with_label=False):
input_dir = Path(input_dir)
output_dir = Path(output_dir)
for img_path in input_dir.rglob("*"):
if img_path.is_file() and is_image_file(img_path.name):
img = cv2.imread(str(img_path))
if img is None:
print(f"読み込み失敗: {img_path}")
continue
processed = draw_directions(img, n_directions, thickness, with_label)
rel_path = img_path.relative_to(input_dir)
stem = rel_path.stem
suffix = rel_path.suffix
parent = rel_path.parent
new_name = f"{stem}_drawn{n_directions}{suffix}"
out_path = output_dir / parent / new_name
out_path.parent.mkdir(parents=True, exist_ok=True)
cv2.imwrite(str(out_path), processed)
print(f"保存: {out_path}")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="画像中心から放射状に線を描画します(再帰対応)")
parser.add_argument("input_dir", help="入力ディレクトリ")
parser.add_argument("output_dir", help="出力ディレクトリ")
parser.add_argument("-d", "--directions", type=int, choices=[4, 8, 16], default=16,
help="線の本数(4, 8, 16 のいずれか)")
parser.add_argument("-t", "--thickness", type=int, default=2,
help="線の太さ(ピクセル)")
parser.add_argument("-l", "--label", action="store_true",
help="各方位にラベルを表示する(例:N, NEなど)")
args = parser.parse_args()
process_directory(args.input_dir, args.output_dir, args.directions, args.thickness, args.label)
実行方法
python3 draw_dirs.py ./input_images ./output_images -d 8 -t 2 -l
オプション | 意味 |
---|---|
-d または --directions
|
描画する線の本数(4, 8, 16) |
-t または --thickness
|
線の太さ(ピクセル) |
-l または --label
|
方位ラベル(N, NE, など)を表示する |
必要なライブラリ
pip install opencv-python numpy
補足
- ファイル名には自動的に
_drawn{方位数}
が追加される(例:sample.jpg
→sample_drawn16.jpg
) - 出力フォルダには、入力と同じディレクトリ構造が再現される
メモ
画像中心から放射状に線を描く処理を簡単に済ませたくて書いたスクリプト。
サブフォルダ対応、ファイル名自動命名、ラベル表示も一応入れた。
備忘録です。