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

コンピュータ

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

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

1.縮小、拡大処理をする。
点同志を結合させる方法として縮小処理の補完機能を使います。その後縮小された画像を拡大することで元の大きさに戻します。
補完方法によって結果が異なります。
デメリットとして縮小することで画像の情報量が大幅に減少するため、ディティールが損失の大きい点です。
また、拡大率で調整するため、細かな調整は不向きです。
トーンは近づいてみると点に見えますが、離れてみると中間色に見える視覚効果だと考えると、拡大縮小するアプローチは悪くない感じがします。多分トーン以外の部分が拡大縮小によりディティールが失われることが問題なのだと思われます。

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

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

4.拡大⇒縮小処理をする。(追加)
縮小⇒拡大と比べて効果がうすく変化が無さそうですが、リサイズ処理の補間方法の違いなどで出力される画像が異なります。
原理的なことは全く理解していませんが、拡大、縮小で各々異なる補間方法及び拡縮の倍率を選ぶことで最適な画像が生成される可能性があります。

5.ガウシアンフィルターとノンローカルミーンフィルター⇒AIアップスケーラー(追加)
ガウシアンフィルターとノンローカルミーンフィルターでほぼトーンを除去することが出来ます。ただ、問題点としてディテールがつぶれることと、画像がボケた感じになります。その2点をAIアップスケーラーで解決してもらう作戦。
AIアップスケーラー次第ですが、とりあえずReal-CUGANあたりが良い感じです。

あと、パラメータを強めで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系のアップスケーラーの相性が悪いです。ということでボケた状態でアップスケール処理を行ったほうが良さそうです。アップスケーラーで先鋭化してくれますし、それで物足りない場合さらにアンシャープマスキングフィルターを掛けることも出来ます。

追記20240514
色々フィルターを重ねていましたが、AI系のアップスケーラーなどを利用する場合、なるべく加工をくわえないほうが仕上がりが良い感じがします。

現在のところ以下の組み合わせが一番良い仕上がりなります。
blur(3×3,Gaussianではない)⇒AIアップスケーラー+AI線画抽出

ただ、残念なことにGigapixel AIの「Very Compressed」の方が好ましい結果になります。

追記20240522
Real-ESRGANとReal-CUGANをGUIから実行できるアプリ。
Real-ESRGANとReal-CUGANをGUIから実行できるアプリ
画像をAIでアップスケールする方法としてReal-ESRGANとReal-CUGANがあります。 これらを使いたい場合pythonがインストールされたPCでgithubで公開されているリポジトリからローカルにクローンを作成して、依存している...

その中のReal-CUGANのモデルmodels-noseで拡大処理をするとトーンが除去されていました。
ディティールはGigapixel AIの「Very Compressed」より良い感じがします。
ただ、画像によってはトーンが残る場合もあり完全にGigapixel AIの「Very Compressed」から乗り換えるとは行かなさそうです

追記20240614
・「Topaz Labs Gigapixel AI」2倍に拡大、Very Compressed Suppress Noise:100 Remove Blur: 100
・「python-OpenCV」cv2.Resize(AREA)で1/2に縮小
この段階でオリジナル解像度でトーンが除去されています。

「Topaz Labs Gigapixel AI」の拡大率を4倍にしていましたがトーン除去目的で使う分には2倍が良さそうな感じがします。

あとはお好みのアップスケーラーで拡大するところですが、解像度が高くなると加工ソフトでマシンパワーが必要となるとなるので、オリジナルサイズである程度加工するようにしています。
IOPaint(旧Lama Cleaner)を使って不要部分を削除し、不自然な部分をGIMPなどで修正します。
修正後の画像をアップスケーラーで拡大処理をするようにしています。

手順ごとに新しいツールや手法が発見されることがあるので、中間ファイルはなるべく残すようにしています。
それに伴いストレージの使用率が高くなっており、大容量HDDの導入も検討したいところです。
また機械学習のモデルのファイルサイズが結構大きいのでシステムストレージもひっ迫しがちな感じなります。

話はかわりますが、「Topaz Labs Gigapixel AI」の最新アップデートV.7.2.0を行ったところ当方の環境では画像をドラッグアンドドロップをするとアプリケーションが強制終了されるようになりました。クリーンインストールも試しましたが症状が改善されない為、バージョンダウンすることにしました。旧バージョンのセットアップファイルが残っていて幸いでした。
旧バージョンの方は正常に動作することが確認出来て一安心です。ちなみに「Very Compressed」モデルはレガシーに分類され、将来的に廃止される可能性があるので、バージョンアップは控えようかと考えています。せっかくお金を払ってバージョンアップの権利を購入しているのにもったいない話ではありますが…

追記:20240621
「Topaz Labs Gigapixel AI」をアップデートすると画像が読み込めない現象ですが、32bitのRGBAの画像や8bitのグレースケールの画像で発生するようです。24bitのRGB画像では発生しないようなのでpython-opencvで画像を変換するスクリプトを作成して対応することにします。
ちなみに8bitグレースケールは画像を読み込めますが真っ黒になってしまいます。(沢山画像を読み込むとたまに読み込める画像もある)32bitのRGBAは画像をアプリケーションにドラッグアンドドロップした段階で「Topaz Labs Gigapixel AI」強制終了します。

追記:20240718
トーン除去とは直接関係ないのですが、copainterというAIを使って下書きなどのラフ画からペン入れをしてくれるサービスを試してみました。抽出した線画の線を一本一本なめらかにしてくれることを期待したのですが、元絵とは全く異なる画風の絵が生成されていました。
つたない絵を上手に補正してくれる機能だと考えることもできますが、元絵が改変されてしまうと個人的に使い道を見つけることが出来ませんでした。

追記:20240723
 有償のAIアップスケーラーGigapixel AIのアップデートでCLIが対応とのお知らせがあり、コマンドラインから実行すると思われるgigapixel.exeがインストールされていました。これは使えると思って喜んだのですが、Pro用のライセンスが必要で価格が$499とのこと、ぬか喜びでした。一般ライセンスの$99も自分にとって結構勇気が必要な価格で、その約5倍の価格を払う勇気は今のところ無いです。同様にAPIも使えるとのことですので、Webアプリを作成し公開して収益化がOKとかなら十分安いとは思いますが、多分それはダメだと思われますので、経費で買える人(団体)向けのライセンスだと思われます。

 不要部分を消去してくれるソフトiopaintにはバッチモードがあり、消去したい部分を白抜き(黒背景)のマスク画像を用意することで複数画像を一括処理することが出来ます。
マスク用の画像を作る必要がありますが、元画像を2値化して収縮⇒膨張フィルタをかけると、面積の小さい部分が消去されます。
比較的小さいトーンの点が消されると思われます。トーン以外の小さい図形も消されると思いますが、こちらと2値画像との差分でトーン部分の白抜きマスク画像を作ることが出来ると思われます。それをiopaintのバッチモードで処理すればトーンを除去した線画が出来上がるのではというアイディアが思いつきました。

 マスク画像を作るpythonスクリプトを作り実行してみたところ、トーンの点が白抜きで浮かび上がりました。また予想通りトーン以外の小さな図形も対象にされていました。とりあえず作成したマスク画像をiopaintのバッチモードにかけてみましたが、残念ながら1枚も処理することが出来ませんでした。処理開始数時間後、強制終了されていました。要因を考えると画像サイズが大きい点と処理する部分が多い点が想定されます。

 残念ながら上手く行きませんでしたが、学習したプログラミングスキルやツールを組み合わせると、色々な可能性が生まれ、それを試すのは結構楽しいです。昔は学んだことを何かに使うことは本人のやる気だけでは中々難しい感じでしたが、無償のツールや開発環境、理解しやすいプログラミング言語などと相まって結構簡単に試すことが出来るようになっており、その点は良い時代なったなぁと感じます。

追記:20240925

元画像(グレイスケール)⇒縮小⇒拡大⇒元画像との差分⇒変化が部分をぼかしピクセルと置き換え⇒アンシャープマスキングフィルタ

どうなるか後で確認

import cv2
import numpy as np
import os

def unsharp(src, k=1.5):
    kernel = np.array( [[-k/9.0, -k/9.0, -k/9.0],
                        [-k/9.0, 1.0+(8.0*k)/9.0, -k/9.0],
                        [-k/9.0, -k/9.0, -k/9.0]])
    dst = cv2.filter2D(src, -1, kernel)
    return dst

def filter(src, n=3.3):
    h, w = src.shape[:2]
    scale = 1.0 / n
    small = cv2.resize(src, None, fx=scale, fy=scale, interpolation=cv2.INTER_NEAREST)
    big = cv2.resize(small, (w, h), interpolation=cv2.INTER_NEAREST)

    blur = cv2.blur(src, (3,3))
    dif = np.where(src == big, src, blur)
    return dif

if __name__ == '__main__':
    src = cv2.imread("F:/deinoji025/dl/168.jpg",0)

    dst = filter(src)
    dst = cv2.fastNlMeansDenoising(dst, h=15)
    dst = unsharp(dst, 1.0)

    #x2 = cv2.resize(dst, None, fx=1.0, fy=1.0, interpolation=cv2.INTER_LINEAR)

    cv2.imshow('dst', dst)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

トーン画像を縮小⇒拡大(元のサイズに戻す)して元の画像と差分を取ると、トーンの部分とそうで無い部分を抽出でし、トーン部分だけぼかし処理をかけると良いのではないかと思いました。結果として悪くはないが良くもない感じです。

追記:20240925

情報量を減らす(劣化させる)実験(トーンとは無関係)

水平方向に似たような色を同じ色に置き換えるプログラム。ランレングス圧縮をしたら圧縮率が高まりそうです。

#!/usr/bin/env python3
import cv2
import numpy as np

def myfilter02(src):
    c = np.uint8(0)
    dst = src.copy()
    (h, w) = src.shape[:2]
    for y in range(0, h):
        for x in range(0, w):
            v = src[y][x]
            if (v < (c-4) or v > (c+4)):
                c = v
            dst[y][x] = c
    return dst 
    
if __name__ == '__main__':
    src_file = "H:/py/001.png"

    src = cv2.imread(src_file, 0)

    dst = myfilter02(src)

    cv2.imshow('src', src)
    cv2.imshow('dst', dst)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

減色処理になるため、グラデーション部分でくっきり色のの違いが出るようになってしましました。

コメント