今回やりたいことはなんなのか
簡単にいうと、こんな感じの漫画の強調画像を作りたい。
OpenCVのしきい値の処理と色空間の変換を使って、今回写真の画像を漫画の強調画像っぽいものを作るスクリプトを描いてみようと思います。
参考にしたサイト
https://algorithm.joho.info/programming/python/opencv-manga-filter-py/
用意するもの
こんな感じの画像
ただ画像を用意するにあたって一応条件があります。
条件
- 中心に強調したいオブジェクトが存在すること
- 背景は白い画像を使用すること。
- 周縁の部分に多少はオブジェクトがあっても問題なし
→周縁全部にオブジェクトがあると、強調のエフェクトがあまり表示されなくなりますが、上の画像のように手だけ写っているのであれば、エフェクトが効果的に映るので問題ないです。
環境構築とかはこちらをご参考に頂けると幸いです。
コード
manga_emp.ipynb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
import cv2 import numpy as np # 漫画っぽい強調フィルタ def manga_emp_filter(src, bg, th1=50, th2=125,th3 = 200, th4 = 250): # グレースケール変換 gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY) bg = cv2.cvtColor(bg, cv2.COLOR_BGR2GRAY) # 強調画像を入力画像と同じ大きさにリサイズ bg = cv2.resize(bg,(gray.shape[1],gray.shape[0])) # Cannyアルゴリズムで輪郭検出し、色反転 edge = 255 - cv2.Canny(gray, 80, 120) cv2.imwrite("edge_apple.jpg", edge) # x =色の値(黒0 -- 白255) # しきい値処理1:0<x<=50 -> 0 gray[gray <= th1] = 0 cv2.imwrite("th1_apple.jpg", gray) # しきい値処理2:50<x<=125 -> 85 gray[ np.where((gray > th1) & (gray < th2)) ] = 85 cv2.imwrite("th2_apple.jpg", gray) # しきい値処理3:125<x<=200 -> 160 gray[ np.where((gray > th2) & (gray < th3)) ] = 180 cv2.imwrite("th3_apple.jpg", gray) # しきい値処理4:200<x<=250 -> 225 gray[ np.where((gray > th3) & (gray < th4)) ] = 225 cv2.imwrite("th4_apple.jpg", gray) # しきい値処理5:250<x<=255 -> 強調画像 gray[gray >= th4] = bg[ np.where(gray >= th4) ] cv2.imwrite("th5_apple.jpg", gray) # しきい値処理した画像と輪郭画像を合成 return cv2.bitwise_and(gray, edge) def main(): # 入力画像とスクリーントーン画像を取得 img = cv2.imread("apple.jpg") bg = cv2.imread("background.jpg") # 画像の漫画っぽい強調を行う manga_emp = manga_emp_filter(img, bg, 50, 125, 200,250) # 結果を出力 cv2.imwrite("emp_apple.jpg", manga_emp) if __name__ == '__main__': main() |
BGRの色空間の画像を、グレースケール(白黒)の画像に変換し、白黒データ(黒0~白255)を5段階に分けて、一定の色を割り当てています。
注意すべきはしきい値処理5でほとんど白色の部分に強調のエフェクト画像を置き換えることで、すこしでも黒いところに強調のエフェクト画像が覆い被さらないようにしています。
https://github.com/Tonbi00080/color_edit
途中の画像
OpenCVに多少慣れている人なら、コードでなんとなく意味がわかるかと思いますが、
画像がどのように加工されていくのか変遷を追うほうが、OpenCVに慣れているかにかかわらず、わかりやすいかと思います。
cv2.imwriteという記述のところで、加工途中の画像をあえて保存しています。(本来は不要)
各画像名と上のコードを比較すると、加工処理の内容がわかりやすいかと思います。
background.jpg
edge_apple.jpg
輪郭を抽出
th1_apple.jpg
th2_apple.jpg
th3_apple.jpg
th4_apple.jpg
th5_apple.jpg
ほぼ白いところにbackground.jpgを合成する
最終的な加工画像
emp_apple.jpg
th5_apple.jpgとedge_apple.jpgを合成することで、漫画っぽい強調画像の完成です。
あとがき
今回つくったスクリプトは特定の条件で加工がうまくいくとは思うのですが、うまくいかないシチュエーションもあるかと思います。その際は、このスクリプトのしきい値の設定などをいじると良いかと思います。
当然、手元で試したい場合は画像やファイルのパスは、臨機応変に変えてください。
ここで前提としている色空間などの知識やこのスクリプトで使っているメソッドのことは下の記事で紹介しています。