※ replitで「You've used up all your Development time」というメッセージが出た人は
こちらを参考にして新しくreplitのアカウントを作ってください。
※ 本題に入る前に、必ず動画の
連絡
を見てください。
- リサイズ
- 鮮鋭化
- 減色
- 太枠の作成
- トゥーン化
元画像の選定
今回の課題2ではエッジをくっきりさせる処理を行う。そのため、画像中のどこかにエリア間のエッジが必要になる (あえてボケた写真にする必要はない)。
また、課題3~5ではエッジを検出したあとでそれを太くし、元画像に重ねてトゥーン的な画像を作る。そのため、複雑な構造がない背景の中に輪郭がはっきりした被写体がある写真が望ましい。
実写のものをトゥーン的な表現に変える処理を行うので、元画像にアニメや漫画のような画像を使うのはNG。
(これは解説動画中で使っているものなので、課題には使わないこと)
鮮鋭化
第5回では平滑化処理で元画像をぼやけさせた。
これと逆の処理を行えば画像をくっきりさせられる。
元画像

ぼやけさせた画像

くっきりさせた画像

具体的には、特定のピクセルに注目して元画像での赤成分が80, ぼやけさせた画像で100だったとすると、「20増やしたらぼやけた」ということになるので、逆に20減らして60にすればよい。
元画像を image, ぼやけさせた画像を blured, くっきりさせた画像を sharpened とすると、ぼやけさせたときの赤成分の変化は
「bluredの赤成分 - imageの赤成分」
となるので、sharpened の赤成分は
「imageの赤成分」-「bluredの赤成分 - imageの赤成分」
つまり
「imageの赤成分 × 2」-「bluredの赤成分」
で求められる。これを緑、青成分についても同様のことをすべてのピクセルについて行う。OpenCVの
addWeighted文では重みをつけて2枚の画像を合成することができるので、これを使えば上記のことが1文で完了する。
sharpened = cv2.addWeighted(image, 2.0, blured, -1.0, 0)
減色
カラー画像のピクセルは赤・緑・青それぞれの成分が0~255の値をとり、それらを組み合わせることですべての色が表現される。
この色の段階をあえて減らすことで、実写の画像をアニメ的な雰囲気に変えられる。
赤・緑・青それぞれの成分が0か255の値しか取れないようにすると、以下の8色のみになる。
| 赤 |
緑 |
青 |
色 |
| 0 |
0 |
0 |
黒 |
| 255 |
0 |
0 |
赤 |
| 0 |
255 |
0 |
緑 |
| 0 |
0 |
255 |
青 |
| 255 |
255 |
0 |
黄 |
| 255 |
0 |
255 |
マゼンタ |
| 0 |
255 |
255 |
シアン |
| 255 |
255 |
255 |
白 |

画素値を128で割った値の整数部分は0か1になるので、以下のようにすればこの減色ができる (ここでは元画像が image, 8色に減色した画像が posterized)。
posterized = np.uint8(image / 128) * 255
白線の膨張
第7回の課題5ではCanny法で元画像のエリア間のエッジを検出した。
この処理で得られる画像は、どのピクセルも完全な白か黒のどちらかになる。

このような画像に対して「膨張」という処理を行うと、白い部分を一回り大きくできる。
元になった画像が今回のような細線だけの場合なら、「線を太くする」という処理になる。

細い線の画像を edges, 太くした画像を thickened とすると、OpenCVでの書式は以下の通り。
kernel = np.ones((3, 3), np.uint8)
thickened = cv2.dilate(edges, kernel, iterations=1)
トゥーン化 (参考)
減色画像に上記の太い白線の画像を合成すれば、エッジ部分が強調された画像になる。

また、白線の画像の中の白い部分を黒として減色画像に重ねれば、漫画の枠線的な表現になる。

numpyのwhere文を使えばこのような選択的な合成ができる (白枠としての合成なら上記のaddWeighted文でもできる)。
where文で「枠線画像の白い部分を減色画像に白として重ねてframed_whiteに入れる」(枠線画像がframe, 減色画像がimage) という処理は以下のようになる。
framed_white = np.where(frame == 255, 255, image)
「枠線画像の白い部分を減色画像に黒として重ねてframed_blackに入れる」という処理は以下のようになる。
framed_black = np.where(frame == 255, 0, image)
第1引数が「置き換えるかどうかの条件」、第2引数が置き換える色(ここに画像を指定することもできる)、第3引数が減色画像にあたる。