主人公レンズとは
@itopoid さんが作ったノベルゲーム風フレームのグッズ。透明なプラスチック製?でゲームのセリフ画面をリアルに持ってこれる。
https://twitter.com/itopoid/status/933262577651433478
Web版を作ろうと思ったらもうあった。でもめげずにOpenCVで実装してみる。
素材集め
フリー素材サイトから集める。
枠は空想曲線より、サンプル背景はfreephotos.ccより取得。
テキストから画像を生成
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)