今回は、OpenCVの顔検出データセットで、画像から顔を検出して、顔のみをInDesignに配置する記事です。
実用性:Zero
言いたいこと:コードを簡潔(=今後のメンテナンス)にするため:
・組版のjavascript(今回はappscriptで)に、組版部分のみ書く
・組版以外のデータ処理、Pythonのような言語に任せる(今回の例だと、顔の矩形座標検出処理は、10行程度しかない)
OpenCVのインストール:pip install opencv-python
使い方:
- InDesign(例はCC2019)に画像を配置、選択
- プログラム実行
- 新規documentが作成され、その中に顔のみが表示
import os
import cv2 # pip install opencv-python
from appscript import *
# 顔検出haarcascade
frontalface = os.path.join(cv2.data.haarcascades,
"haarcascade_frontalface_default.xml")
cascade = cv2.CascadeClassifier(frontalface)
def get_face_rects(input_img, scaleFactor):
image = cv2.imread(input_img)
height, width = image.shape[:2]
faces = cascade.detectMultiScale(cv2.cvtColor(image, cv2.COLOR_BGR2GRAY),
scaleFactor=scaleFactor, # 顔検出精度
minNeighbors=2,
minSize=(30, 30))
if len(faces) == 0:
print("No faces detected.")
return [], 0, 0
"""
# draw red rectangles and save image
color = (0, 0, 255) # B,G,R !!
for (x, y, w, h) in faces:
cv2.rectangle(image, (x, y), (x + w, y + h), color, thickness=2)
cv2.putText(image, text=f"scaleFactor={scaleFactor}", org=(100, 50),
fontFace=cv2.FONT_HERSHEY_SIMPLEX,
fontScale=1, color=(255, 0, 0))
cv2.imwrite(f"__{scaleFactor}_rectangles_".join(
os.path.splitext(input_img)), image)
"""
return faces, width, height
def get_img_path_from_indesign():
# get currently selected obj in InDesign
sel = indd.selection()[0] # javascript: app.selection[0]
if sel.class_() == k.image: # convert "Direct Selection" to "selection"
sel.parent.select()
sel = indd.selection()[0]
graphic = sel.graphics[1]
img_path = graphic.item_link.file_path() # colon delimited(on the Mac OS)
return img_path.replace("Macintosh HD", "").replace(":", "/")
indd = app("Adobe InDesign CC 2019")
img_path = get_img_path_from_indesign()
rects, width, height = get_face_rects(img_path, scaleFactor=1.1)
if len(rects) != 0:
indd.copy() # copy currently selected obj
doc = indd.make(new=k.document)
for rect in rects:
indd.paste() # paste copied obj
new_img = doc.selection()[0]
new_img.fit(given=k.frame_to_content) # show whole image
new_img.move(to=[0, 0])
# height/width (any indesign unit)
indd_height, indd_width = new_img.geometric_bounds()[2:]
# convert pixel unit to percentage
x1, x2 = rect[0] / width, (rect[0] + rect[2]) / width
y1, y2 = rect[1] / height, (rect[1] + rect[3]) / height
# convert percentage to indesign unit
new_img.geometric_bounds.set([y1 * indd_height, x1 * indd_width,
y2 * indd_height, x2 * indd_width])
因みに、顔検出の精度引数scaleFactorを1.09/1.3にしたら、大分違ってくる:
get_face_rects(img_path, scaleFactor=1.09) get_face_rects(img_path, scaleFactor=1.3)


