ハーフトーンを削除する方法を考える

コンピュータ

スキャンした書籍の画像を、大き目のPCモニターに合わせてWaifu2xで拡大処理をしています。
印刷物などで点描で濃淡を表現する方法があり、ハーフトーンというらしいのですが、そのままWaifu2xで拡大すると、点が格子状の模様となって現れます。モノクロ画像の点を除去しベタ塗(グレースケール)状態にすることが出来ないか考えてみます。(カラーはさらにハードルが高そうなので…)

おおまかな方法としては、ぼかし処理をすることで独立した点同志を結合します。次にぼかし処理でボケてしまった輪郭などの境界部を、なんらかな方法でメリハリをつけてあげます。

1.縮小、拡大処理をする。
点同志を結合させる方法として縮小処理の補完機能を使います。その後縮小された画像を拡大することで元の大きさに戻します。
補完方法によって結果が異なります。
デメリットとして縮小することで画像の情報量が大幅に減少するため、ディティールが損失の大きい点です。
また、拡大率で調整するため、細かな調整は不向きです。

2.ガウシアンフィルタとアンシャープマスキングフィルタ
ぼかし処理にガウシアンフィルタを使い、シャープ処理にアンシャープマスキングフィルタを使います。
効果的ですが、ガウシアンフィルタを強くかけると、境界部が失われます。また、アンシャープマスキングフィルタで境界が不自然に補強される場合があります。
ガウシアンフィルタの強弱とアンシャープマスキングフィルタの強弱で調整。1.の拡大縮小よりは細かな調整が利きます。

3.バイラテラルフィルタとラプラシアンフィルタ
ぼかし処理にバイラテラルフィルタを使います。バイラテラルフィルタは境界部を残しそれ以外をぼかす処理をしてくれます。
理想的なフィルタですが、強くフィルタをかけすぎると境界部もボケてきます。また、境界部の検出するため事前にぼかし処理をする必要があるのでトーン除去に使うには向かないかもしれません。(使い方が間違ってるだけかもしれませんが…)

あと、パラメータを強めで1回で処理する場合と、パラメータを弱めで複数実行する場合で結果が異なります。

また、OpenCVにはfastNlMeansDenoisingという強力なノイズ除去フィルタがあります。強力過ぎてディテールをつぶしてしまう場合があるので、フィルターの最終段階で仕上げに使うと良さそうです。

次にラプラシアンフィルタで輪郭を抽出し、その輪郭部分を補強してあげることで境界部にメリハリをつけます。
ラプラシアンフィルタをかけた画像は、境界部が明るい白に近づき、それ以外が暗い黒になります。
PythonとNumpyの話になりますが、ぼかし処理を行った画像からラプラシアンフィルタで抽出した輪郭画像を減算すると、境界部が補強されます。文字通り数値を引き算するような書式で表現できる点はNumpyは良くできているなと感じました。
アンシャープフィルタマスクほど強力では無いですが、かなり自然な仕上がりになります。
(追記、調べてみるとこの手順は平滑化(バイラテラルフィルタ)した画像にラプラシアンフィルタを演算しているあたり、はからずもアンシャープマスキングを手動でやっているような代物になっています。また、自然な仕上がりだと変化が少なく物足りない感じですし、変化が大きいと絵の雰囲気が壊れる感じで中々調整が難しい感じです。)

この補強で満足できない場合はさらにアンシャープフィルタマスクを施します。その場合アンシャープフィルタマスクでノイズも補強されて画像が荒れるようであれば、さらにfastNlMeansDenoisingでノイズを消してあげます。

輪郭抽出のフィルタはラプラシアンフィルタ以外にも複数存在しますので、試しても見るのも良いと思います。

フィルターを多数かけることで理想の画像に近づけることは出来ますが、代わりに元画像の情報は失われます。何を残し何を消すか、何をぼかし何を強調するか、この調整が楽しいと感じるか、終わりの無い作業と感じるかは人それぞれです。

実装はPython+Numpy+OpenCVの組み合わせで試行錯誤していますが、フィルタの組み合わせを調整することで点が消え、ベタ塗に変換される結果を見ると不思議な感じがします。不可逆な処理だと思いますので、完璧に理想通りにはならないとは思いますが、うまく調整できた場合は、苦労にみあった達成感を感じることが出来ると思います。

追記

最近はバイラテラルフィルタの代わりに以下のカーネルを引数にfilter2Dを数回実行します。

kernel = np.array([[0,2/16,0],[2/16,8/16,2/16],[0,2/16,0]])

バイラテラルフィルタと比べて輪郭はボケますが、格子状のパターンをいい感じに壊してくれます。

バイラテラルフィルタはパラメータを調整すると輪郭を残したまま、ぼかし処理をすることが出来ますが、輪郭を意識しすぎるとぼかしが甘く、輪郭と同色の点が残ったり、濃淡の全くないベタ塗状態になったりします。ぼかす範囲を大きくとるか、処理を数回重ねることで対処できますが、今度は輪郭がボケてきます。理想的なフィルタだと思うのですが、自分には扱いきれない感じです。

上記フィルタで、荒れた感じになるので、次にfastNlMeansDenoisingフィルタを適度に施すことでベタ塗りになります。

この段階で輪郭がボケてくるのでアンシャープマスキングフィルタで輪郭を強調してあげます。

k = 2.0
kernel = np.array([[-k/9,-k/9,-k/9],[-k/9,1+8*k/9,-k/9],[-k/9,-k/9,-k/9]])

これまでは、ラプラシアンフィルタで輪郭を抽出して強調していたのですが、綺麗に輪郭を抽出できる画像であれば、いい感じに効果を発揮してくれますが、輪郭以外が残ってしまうと、それがノイズとして強調されしまうため、扱いが難しいので止めました。
その点アンシャープマスキングフィルタは、kの値を調整することで強調度合いを調整出来ますので、対象画像ごとに設定をつめることで理想の画像に近づけることが出来ます。

追記20211227

セルシス「CLIP STUDIO PAINT EX」の「トーンを消去」機能を使うと、トーンを消去して線画に変換したり、トーン部分をグレースケールに変換することが出来ます。

このソフトはイラストを描く人向けの定番ソフトらしく、私がそういった人種ではない為、まったくチェックしていませんでした。値段は3万円前後と結構いい価格でイラストを描かない人間には厳しいですが、この機能のために購入してしまいました。

仕上がりとして、線同士が込み合った部分など若干トーンが残る場合がありますが、線のディテールをしっかり残した状態でトーン部分のみを処理してくれます。自分が欲していた機能がそのものが入手することが出来ました。ただ、残念な点としてグレースケール化した仕上がりが灰色単色でベタ塗された感じが好みなのですが、こちらのソフトでの処理は薄墨で濃淡を表現する水墨画のような感じになってしまいます。スキャンする画像の精度や、事前処理などをして仕上がりを

使った感じクラウド上のサービスを利用しているので、時間帯によって処理時間が異なります。多量の画像を一括処理する方法があるとよいのですが無いようなので、とりあえず「オートアクション」機能でトーン消去→上書き保存→画像を閉じるマクロ手順を組んで、複数の画像をドラックアンドドロップでまとめて開いてた状態で1枚1枚オートアクションの再生ボタンをポチポチしています。

まだ先行プレビューですので、トーンが残る部分もありますが、OpenCVのフィルターを駆使して消すことが出来ないか挑戦しています。

追記20220322
「CLIP STUDIO PAIN EX」トーン消去機能は、かなり目的に近い動作をしてくれるようになりました。
なるべくトーンを綺麗に消去してくれるようにスキャン画像の前処理を行います。
モノクロの書類をカラースキャン
GIMPで脱色(またはグレースケール)
GIMPで色→レベル補正→自動入力レベルボタン。雑誌など紙の色が白色でない場合は、レベルの補正で入力レベルのグラフで白色が一番盛り上がる場所まで、手動でつまみを調整する。
GIMPでPNG形式でエクスポート
「CLIP STUDIO PAIN EX」トーン消去
複数の画像を処理する場合は、「CLIP STUDIO PAIN EX」のオートアクションでトーン消去→PNG形式で保存→閉じるを手順化しておくと便利。
さらに「おーとくりっか~」などのクリックを自動化してくれるソフトを使い「オートアクション」のボタンを押すようにするとさらに便利。
複数画像をD&Dで開き→「おーとくりっか~」→オートアクションの流れで自動化すると疑似的な一括処理をしてくれます。
窓の杜
「おーとくりっか~」あらかじめ指定した座標でマウスを自動クリックさせるソフト

トーン消去後若干残るトーンの点と色合いの補正はPython-OpenCVでスクリプトで補正します。
実行するフィルタとして、ガンマ補正→バイラテラルフィルタ→ローカルミーンフィルタ→アンシャープマスキングフィルタ→ローカルミーンフィルタを実行します。
フィルタの効果が強いとトーンの点も消えますが、画像自体がボケたり荒れたりしますので、処理をするかは画像によって判断します。

20220606追記

「Topaz Labs Gigapixel AI」はAIで画像を拡大するアプリケーションなのすが、AIモードを「Very Compressed」にしてSettingを調整したところ、拡大後ハーフトーンが除去されていました。クリップスタジオのトーン消去はある程度解像度が高くないとハーフトーンを構成するドットがつぶれてしまいハーフトーンとして認識できない場合があります。

Waifu2xの拡大でつぶれたドットが復活する場合もありますが、基本的に600DPIぐらいでスキャンした画像が必要になります。その点「Topaz Labs Gigapixel AI」は比較的低解像度の画像でもハーフトーンを除去していました。

多分つぶれたドットをノイズとして認識しノイズ除去処理をしていると思われ結果としてトーンの除去となっているのだと推察します。境界部分は線として認識し拡大して引き直しており、縮小画像なので詳細部分は曖昧ですが、全体的には結構くっきりとした画像になります。

元画像はグレイスケールですが、拡大処理をした画像の線はインクで描画したような感じで若干青く滲んだ感じのカラー画像になります。処理後の画像をGIMPで脱色してグレースケールに変換してあげると変換後の着色部を見ると鉛筆で濃淡を表現したような感じになりました。かなり希望に近い形の処理をしてくれるソフトが見つかりました。

 

20230107追記

今のところ「Topaz Labs Gigapixel AI」を超えるツールは発見していないので「Topaz Labs Gigapixel AI」を愛用しています。「Topaz Labs Gigapixel AI」任せは楽で良いのですが、もう少し精度を上げたいので拡大処理を行う前に以下の処理を施しています。
OpenCV-Pythonで
kernel = np.array([[0,1/8,0],[1/8,4/8,1/8],[0,1/8,0]])
dst = cv2.fliter2D(src, -1, kernel)
で格子状になったトーンを壊してあげます。このフィルタを画像によって1~3回実行します。
このkernelは斜め方向を0にしたガウシアンフィルタのようなもので、ぼかし機能が弱目です。
次にローカルミーンフィルタをh=12ぐらいで実行します。
この段階で格子状のトーンがベタ塗状態または模様のような感じになります。
ただし、ぼかし処理を施したため境界線がボケてしまいますので、その後アンシャープマスキングフィルターで境界部分を引き締めてあげます。
この下準備で取り切れないトーンは「Topaz Labs Gigapixel AI」の拡大処理に任せることが出来ますので、余り完璧を求めないほうが良さそうです。下準備段階で加工をかけすぎると、仕上がりがのっぺりした感じになります。
ここまでして、無加工の画像「Topaz Labs Gigapixel AI」を拡大処理したものと比べて、良い方を採用する感じになります。

20230215

前回と同様に「Topaz Labs Gigapixel AI」を軸に処理を行っています。

前処理でトーンを荒すためフィルタを施しますが、なるべく回数を少な目にしています。

OpenCV-Pythonで
kernel = np.array([[0,1/8,0],[1/8,4/8,1/8],[0,1/8,0]])
dst = cv2.fliter2D(src, -1, kernel)

後処理である「Topaz Labs Gigapixel AI」の仕上がりを見て回数を調整するようにしています。

「Topaz Labs Gigapixel AI」の拡大のモデルは「Very Compress」でオプションは上のつまみ(Blur)が100%下のつまみは0%にセットしています。結果がカラーになりますので、グレースケールに変換します。

概ねベタ塗状態になるのですが、若干黒っぽい筋のようなノイズが乗ります。その後仕上げとして、fastNLMeanフィルタを施していましたが、ノイズも消えますがディテールも消える問題があるので、バイラテラルフィルタにしてみました。

dst = cv2.bilateralFilter(img, 7, sigmaColor=150, sigmaSpace=150)

画像に合わせたとパラメータの調整が必要ですが、fastNLMeanと比べて境界部分が気持ちくっきりしているように見受けられます。

新しい方法を見つけるたび、数百枚からの画像を処理しなおすのですが、出来れば1枚1枚満足いくまで調整したいところですが、なかなか時間的に厳しいものがあります。パフォーマンスの高いPCが欲しくなってきます。

20230307
「Topaz Labs Gigapixel AI」で拡大処理を行いopencvでノイズ除去した画像を、オリジナルサイズに縮小し、Real-CUGANでまた拡大する。
すこし寝ぼけた輪郭線がくっきりする。

20230317
現在の手順
「Topaz Labs Gigapixel AI」の処理は等倍(拡大しない)でノイズ除去だけを行います。その際モデルは「Very Compress」でBlurは100%にしています。その後「Real-CUGAN」で4倍に拡大します。

Real-CUGANは拡大処理というよりAI絵を描き直している感じなので、オリジナルと比べて若干やりすぎな感じもしますが、境界部分はかなりくっきりはっきりとした絵になります。

さらに、Anime2Sketchを使うと輪郭部分を抽出することが出来ます。その際パラメタのload_sizeは2048ぐらいにすると、結構良い制度の線画が出来上がります。

画像系AIのソフトはローカル実行の環境構築のハードルが高いのですが、なかなか興味深いソフトが多く試すのが楽しい分野だと思います。

20230525
現在の手順
fiter2Dでカーネルを以下のものを使用

kernel = np.array([[0,1/8,0],[1/8,4/8,1/8],[0,1/8,0]])

こちらのフィルターを1~3回施す
次にfastNlMeansDenoising(mat, h=12)フィルターを施す
この段階で画像がぼけますがトーン部分はほぼべた塗になります。

次にReal-CUGANで4倍に拡大します。
Real-CUGANのおかげでぼけた境界部がくっきりします。

ハーフトーンをベタ加工するために結構出費をしていますが、気が付いたら無料ソフトの組み合わせが好みに合った感じです。
ただ、かなりパキッとした絵になりますが、少しやりすぎ感が否めないので今後はそのあたりを何とかしたいです。
アイディアとしてはReal-CUGANで生成した画像を縮小し「Topaz Labs Gigapixel AI」で拡大してみたいと思います。
「Topaz Labs Gigapixel AI」はmodeなどのパラメータをいじることが出来ますのでなるべく自然な仕上がりになることを期待しています。

20230721
20230215の処理手順
1/4に縮小(AREA)
REAL-CUGANで4倍に拡大

20230727
・「python-OpenCV」fiter2D

kernel = np.array([[0,1/8,0],[1/8,4/8,1/8],[0,1/8,0]])

・「Topaz Labs Gigapixel AI」2倍に拡大、Very Compressed Suppress Noise:100 Remove Blur: 0
・「python-OpenCV」cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY)→1/2に縮小 cv2.INTER_AREA
・「Real-CUGAN」4倍に拡大

pythonのfilter2Dを使ってトーンを荒らすフィルタを便宜上十字フィルタとします。このフィルタの効果は平滑フィルタ(ぼかし)やガウシアンフィルタなどと比べて極めて弱く、逆に考えてるとディテールを壊さない点がメリットになります。
ただし、素材によっては十字フィルタでは弱すぎてガウシアンフィルタでは強すぎる場合もあり得ます。
中間になるようなフィルターとして拡大→縮小をする方法を見つけました。縮小⇒拡大では効果は高いのですが明らかに画質が悪化してしまいます。その点拡大→縮小ではいい感じにトーンを壊してくれます。拡大率やフィルターの回数によって効果の強弱の調整が出来ます。
拡大縮小の補管方法は拡大がLANCZOS4で縮小がAREAを使っています。倍率は大きい方が効果が高いのですがLANCZOS4は重いので小さめの1.5倍ぐらいで、フィルタの回数で効果を高めるようにしています。また、倍率はキリが良い2の倍数ではなく中途半端な数値を選ぶ方が効果が高い感じがします。

20230906

前処理として実行していた十字フィルタや拡大→縮小フィルタをやめました。
AIによる拡大処理後にfastNlMeansDenoising()フィルタを追加してノイズ除去をしています。
・「Topaz Labs Gigapixel AI」4倍に拡大、Very Compressed Suppress Noise:100 Remove Blur: 0
・「python-OpenCV」cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)→cv2.fastNlMeansDenoising(gary, h=7)→1/4に縮小 cv2.INTER_AREA
・「Real-CUGAN」4倍に拡大
「Topaz Labs Gigapixel AI」で拡大した画像の線が画鉛筆ぽい感じで、詳細を見ると境界部分が少し曖昧だったりして加工しずらいので、「Real-CUGAN」で再描画しています。

20231218
Gigapixel AIの拡大とその後の縮小処理を2回繰り返すようにしました。
・「Topaz Labs Gigapixel AI」4倍に拡大、Very Compressed Suppress Noise:100 Remove Blur: 0
・「python-OpenCV」cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)→cv2.fastNlMeansDenoising(gary, h=15)→1/4に縮小
・「Topaz Labs Gigapixel AI」4倍に拡大、Very Compressed Suppress Noise:100 Remove Blur: 0
・「python-OpenCV」cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)→cv2.fastNlMeansDenoising(gary, h=15)→1/4に縮小
・「Real-CUGAN」4倍に拡大
2回繰り返すと、トーンの判別の難しい詳細部分がバッサリ省略された感じになります。

20240130
Gigapixel AIの拡大・縮小 x 2の後、Real-CUGANの代わりにReal-ESRGANを使用。Real-CUGANと比べて滲む感じが少なくグラデーション部分も自然な感じがします。

Real-ESRGANの追加学習でトーンを除去するモデルが作れないか試行錯誤してみましたが、そちらは失敗しました。
失敗はしましたが、拡大処理ではなく等倍でノイズ除去をするAIがあれば又チャレンジしてみたいと思います。

20240227追記
SCUNetというノイズ除去のAIでスキャンした画像を処理し「CLIP STUDIO PAIN EX」トーン消去をすると、かなりいい感じの画像になりました。
以前は大きな画像は処理できなかったトーン消去機能も処理できるようになっていたました。
近いうちにVer3.0へバージョンアップするらしいのですが、購入を検討したいと思います。

20240311追記
Real-ESRGANとReal-CUGANのGUIラッパー
GitHub - tsukumijima/Real-ESRGAN-GUI: Lovely Real-ESRGAN / Real-CUGAN GUI Wrapper
Lovely Real-ESRGAN / Real-CUGAN GUI Wrapper. Contribute to tsukumijima/Real-ESRGAN-GUI development by creating an accoun...

こちらのReal-CUGANのmodels-noseで低解像度かつスクリーントーンが使われた画像を処理したところ、スクリーントーン部分がグレーのベタ塗に変換されていました。
同様の処理がされるGigapixel AIのVery Compressedと比較予定
githubを散策していたら、Screentone-Removerなるものを発見
GitHub - natethegreate/Screentone-Remover: Script with GUI that removes screentones, using DSP
Script with GUI that removes screentones, using DSP - natethegreate/Screentone-Remover

pythonスクリプトでAIではなくopencvのフィルターでグレースケール化している模様。
コードを眺めてみると、blurでぼかして、fastNLMeanでノイズ除去、アンシャープマスキングで先鋭化する方法でした。
自分も同じ組み合わせで思考錯誤していますが、フィルターのオプションやカーネルの設定値が優秀(最適)なのか、自分が作ったもより良好な結果になります。

20240312追記
Real-CUGANのmodels-noseとGigapixel AIのVery Compressedを比較したところGigapixelの方が好みの絵を作ってくれます。

20240318追記
トーン除去とは直接関係ないのですが、Real-ESRGANの追加学習を使ってグレースケール画像に特化したモデルを作成してみました。出来る限り学習素材となる画像ファイルをかき集め、RTX3060搭載のPCで4日ほどかけて学習させたところ、曖昧だった部分がきっちりした絵を描いてくれるようになりました。労力に見合った結果かというと正直微妙な感じで、出来上がった絵の良し悪しは人それぞれだと思いますが、個人的に好みの絵には近づいています。

20240409
スキャンしたグレースケールのスクリーントーンは、カラー⇒グレスケール化⇒色の調整(GIMPでレベル調整)⇒縮小⇒Gigapixel AIで拡大する手順が今のところ最良。グレースケール化を2値化に変えてみたが余り良い結果にならなかった。

20240416
Gigapixel AIのアップデートが来ていたのでVersion7にアップデート。そうしたところ「Very Compressed」がなくなっていました。Legacyなモデルを有効にすると選択肢に出てくるのですが、そのうち無くなりそうな予感がします。新しいモデルもいくつかあって代替できないか試してみましたが、「Very Compressed」のかわりになりそうなモデルは皆無でした。
アップデートの権利にお金を支払っているので忸怩たる思いですが、次回以降のアップデートはスルーすることにします。
突然使えなくなる可能性もありえるので、代替手段を探したいと思います。
多少情報量は落ちますが、python+OpenCVでそれらしく加工することは出来るのですが、これをAI系のアップスケーラーにかけると境界線部分が不自然に拡大処理されてしまいます。拡大前はそれほど目ただないのですが、輪郭線とトーンを構成する●が癒着していて、それが凸凹とした不自然な線を作っている原因だと思われます。

20240419
Stable-Diffusion-WebUIで生成画像の事前加工処理用?のControl-Netというフィルターがありその中のLineart処理でmodelをlineart_anime_denoiseを行うと、スクリーントーンが施された画像から線画を抽出してくれます。モノクロ画像をカラーで彩色する前処理に使われるものみたいです。ガウシアンフィルターなどのぼかし処理をすととトーン画像をグレスケール化することは出来ますが、ぼかし処理ですので輪郭までボケてしまいまいます。それに対し線画で輪郭を補強することでくっきりした画像にすることが出来るはずです。ただこの方法だと漫画など輪郭線がしっかりした画像が対象になります。(自然画に施すと漫画的な雰囲気になるフィルターになりそうです。)また、今のところStable-Diffusionの生成出来る画像(主にGPUの処理能力やVRAMの容量的な問題)は512×512~786×786ぐらいが限界ですので余り大きな画像を扱うことが出来ません。Control-Netだけでいえばもう少し(2倍程度)大きな画像も扱えるようです。試した感じGigapixel AIの「Very Compressed」に近い画像を作ることは出来ました。ただ、グレースケール化と線画との合成部分はお手製のプログラムを組む必要があり、パラメータ的(フィルターの強度や回数)な要素を画像ごとに設定する必要がありそうなので、かなり面倒な感じがします。その面倒さも趣味の楽しみの範疇だとは思いますが、限られた時間を効率よく使いたいところです。通常トーン画像から輪郭を抽出するとトーンも抽出されてしまい、いたるところに点が現れるようになります。lineart_anime_denoiseは多分その点をノイズと見立てて消去していると思われます。
ソーベルフィルターや膨張と収縮などを使って自前でプログラミングしたことがありましたが、ここまで綺麗に線画を抽出することは出来ませんでした。

20240503
Gigapixel AIの「Very Compressed」の代替方法を検討しています。
モノクロ画像であればガウシアンフィルターとノンローカルミーンフィルターでトーンを除去することができますが、いずれもぼかし処理ですので、境界線がボケてしまいます。
C#のWPFでOpenCVSharpのフィルターを任意の順番で実行するアプリケーション
OpenCVには画像を加工してくれるフィルターが沢山あります。欲しい画像が出来上がるまでフィルターのパラメーターの調整作業をする場合GUIがあると便利です。フィルターが1つの場合やフィルターの実行手順が決まっている場合のプログラムは以前作成...

アンシャープマスキングフィルターを使って境界線をくっきりさせる方法がありますが、この処理を施した画像とAI系のアップスケーラーの相性が悪いです。ということでボケた状態でアップスケール処理を行ったほうが良さそうです。アップスケーラーで先鋭化してくれますし、それで物足りない場合さらにアンシャープマスキングフィルターを掛けることも出来ます。

コメント