Edited at
OpenCVDay 18

OpenCVで主人公レンズ

More than 1 year has passed since last update.


主人公レンズとは

@itopoid さんが作ったノベルゲーム風フレームのグッズ。透明なプラスチック製?でゲームのセリフ画面をリアルに持ってこれる。

DPOdG2KUEAAiCCO.jpg

https://twitter.com/itopoid/status/933262577651433478

Web版を作ろうと思ったらもうあった。でもめげずにOpenCVで実装してみる。


素材集め

フリー素材サイトから集める。

枠は空想曲線より、サンプル背景はfreephotos.ccより取得。

枠:

message_box.png

背景:

hallway.jpg


テキストから画像を生成

OpenCVでやろうと思ったが日本語テキストは単体だと無理っぽい。しかたがないのでPillowを使う。


main.py

from PIL import Image

from PIL import ImageDraw
from PIL import ImageFont

def draw_text(img, text, color):
draw = ImageDraw.Draw(img)
draw.font = ImageFont.truetype("/Library/Fonts/ヒラギノ丸ゴ ProN W4.ttc", 20)

position = np.array([0, 0])
draw.text(position, text, color)

img = Image.new("RGBA", (750, 80))
text = "いったいアイツはどこにいったんだ。まだOpenCVのビルドの途中だってのに、、、"
draw_text(img, text, (38, 57, 54))
img.save('output/text.png')

img = Image.new("RGBA", (250, 30))
text = "CTO"
draw_text(img, text, (255, 255, 255))
img.save('output/speaker.png')



OpenCVで画像合成

alphaチャンネル付きで読み込んで合成する。imreadに-1のオプションをつけると計4チャンネルで読み込まれる


main.py

def merge_images(background, foreground_with_alpha, o_h, o_w):

alpha = foreground_with_alpha[:,:,3]
alpha = cv2.cvtColor(alpha, cv2.COLOR_GRAY2BGR) # 1 -> 3
alpha = alpha / 255.0

foreground = foreground_with_alpha[:,:,:3]

f_h, f_w, _ = foreground.shape
b_h, _, _ = background.shape
background[b_h-f_h-o_h:b_h-o_h, o_w:f_w+o_w] = (background[b_h-f_h-o_h:b_h-o_h, o_w:f_w+o_w] * (1.0 - alpha)).astype('uint8')
background[b_h-f_h-o_h:b_h-o_h, o_w:f_w+o_w] = (background[b_h-f_h-o_h:b_h-o_h, o_w:f_w+o_w] + (foreground * alpha)).astype('uint8')

return background

# -1 to read alpha channel
# foreground: (210, 960, 4)
message_box_with_alpha =cv2.imread('samples/message_box.png', -1)
# background: (640, 960, 3)
hallway = cv2.imread('samples/hallway.jpg')
result = merge_images(hallway, message_box_with_alpha, 0, 0)

# text (80, 750, 3)
text_with_alpha = cv2.imread('output/text.png', -1)
result = merge_images(result, text_with_alpha, 40, 105)

# speaker (30, 250, 3)
speaker_with_alpha = cv2.imread('output/speaker.png', -1)
result = merge_images(result, speaker_with_alpha, 145, 50)

cv2.imwrite("output/result.png", result)



結果

result.png

ソースコード


参考