#画像変換の目的
ここで行う画像変換の目的は、投稿された写真の内容が「なんとなく」伝わる程度に情報を削ぎ落とし、どんな投稿があったとしても「羨ましい」と思わないようなあえて下手な絵での表現に変換することです。
#実現方法
Facebookは投稿された写真に写り込んでいる要素を識別し、タグとして情報を付加しています。このタグの情報を、背景(景色)、背景(建物)、人物、ペットといった層に分類し、それぞれの層で予め用意してある要素にマッチした絵を重ね合わせて一つの絵を合成しています。
#具体例
## 例1)背景(景色)+人物
"3人、クローズアップ、山、スマイル"がaltに指定された場合
## 例2)背景(景色)+背景(建物)+人物
"2人、海、家、座ってる"がaltに指定された場合
#実装の説明
ここで必要な処理は、タグとして抽出された絵の選択と、背景(景色)以外の絵について絵の要素以外を透過させる処理、それぞれの絵を重ね合わせて1つの絵にする処理です。
##抽出された絵の選択
facebookの投稿でよく検出される要素を、背景の景色、背景の建物、人物、ペット、食べ物の層に分けて単語と単純化された絵の組み合わせとして持っておき、単語のマッチングにより、予め作成しておいた単純化した絵を取得します。
##絵の要素以外の透過と、背景画像への重ね合わせ
各層で抽出された絵の要素は背景となる層に対して重ねて描画していきますが、
これに該当する処理はget_maskedという関数で行なっています。
def get_masked(self,foreground, background):
# グレースケールに変換する。
gray = cv2.cvtColor(foreground, cv2.COLOR_BGR2GRAY)
# 2値化する。
_, binary = cv2.threshold(gray, 250, 255, cv2.THRESH_BINARY_INV)
# 輪郭抽出する。
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 検出された輪郭内部を255で塗りつぶす。
mask = np.zeros_like(binary)
cv2.drawContours(mask, contours, -1, color=255, thickness=-1)
h, w = foreground.shape[:2] # 前景画像の大きさ
x, y = 0, 0 # 背景画像の座標上で前景画像を貼り付ける位置
roi = background[y : y + h, x : x + w, :]
masked_img = np.where(np.expand_dims(mask == 255, -1), foreground, roi)
return masked_img