主人公レンズとは

@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

ソースコード

参考

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.