2021年10月31日

FBCNNのテスト

月一更新を心掛けているつもりですが、気を抜くと忘れていますね。今回も特にないので気になったネットワークのテストです。FBCNN[1]で、考え方は以前試したJPEGの圧縮率を推定して利用する手法に似ています。GANベースではないので顔が変わったりぼかしが復元されたりはしないですが、JPEGノイズはきれいに取れますね。

実行結果

JPEG品質10まで劣化画像・復元画像・原画像

FBCNN_Lenna_blur.png

FBCNN_lenna_256.png

[1] https://github.com/jiaxi-jiang/FBCNN
posted by シンドラー at 21:36| Comment(0) | Machine Learning | 更新情報をチェックする

2021年08月31日

GFPGANのテスト

いつの間にか8月も終わりですね。今月も更新することがないので、GFPGAN[1]を試してみました。Google ColabのDemoもあって簡単に動かせてありがたいですね。AI-SCHOLARのサイトで解説を見たような気がしたのですが、勘違いだったみたいです。CVPR2021のGPENの解説[2]がありましたので、これと勘違いしたのだと思います。

facexlibを使って顔検出してその部分を復元しますが、顔以外の領域もReal-ESRGANを使って超解像処理をしてもらえるようです。

実行結果

GIMP2で顔周りをぼかして、GFPGANで復元してみました。ちょっとぼかしすぎたのか別人になっていますが、復元としてはかなりできていますね。

入力ー出力ー教師(ぼかしなし)

Lenna_blur.bmp  Lenna_blur_restore.bmp  Lenna.bmp

[1] https://github.com/TencentARC/GFPGAN
[2] https://ai-scholar.tech/articles/gan/face_restoration
posted by シンドラー at 21:47| Comment(0) | Machine Learning | 更新情報をチェックする

2021年07月20日

DLSSサンプルプログラムの確認

Twitterを見ていたらNVIDIAのDLSSがLinuxに対応したという情報を見たので、試してみました[1]。

手順
1. DeveloperサイトからSDKのダウンロード[2]
2. Ubuntu上で解凍
3. dlss-2.2.1/nvngx_dlss_sdkにngx_dlss_demo_linux.zipがあるのでunzipで解凍
4. ngx_dlss_demo_linux/DLSS_Sample_Appに移動
5. CMakeLists.txtがここにあるので、mkdir build && cd buildでbuildディレクトリに移動
6. cmake ..
7. NGX_SDK_ROOTが指定されていないというエラーが出るので、dlss-2.2.1/nvngx_dlss_sdkのパスを設定
8. cmake ..
9. includeディレクトリが見つからないというエラーが出るので、dlss-2.2.1/nvngx_dlss_sdkのIncludeとLibをincludeとlibにリネーム
10. cmake ..
11. make
12. fatal error X11/extensions/XInput2.h no such file or directoryというエラーが出たので、sudo apt install libxi-devをインストール
13. dxcがpermission deniedなエラーが出るので、確認するとdxcのシンボリックリンクが実ファイルになっていたのでシンボリックリンクに置き換える
14. 置き換えてもエラーが出たので、[3]からUbuntu用のバイナリをダウンロードして置き換える
15. 何かが足りない(メモし忘れ)というエラーが出たので、sudo apt install libncurses5をインストール
16. libvulkan.soがリンクできないというエラーが出たので確認すると、これもシンボリックリンクが実ファイルになっていたので下記をシンボリックリンクに置き換える
libshaderc_shared.so
libvulkan.so
libvulkan.so.1
17. make成功
18. make installするとMediaディレクトリがないというエラーが出るので、mediaをMediaにリネーム
19. make install成功
20. build/ngx_dlss_demoに移動
21. ./ngx_dlss_demoで実行

実行結果

dlss_sample.png

このSDKを使えば自前のVulkanプログラムでDLSSが使えるということでいいのだと思いますが、使い方を調べるのも大変ですね。素直にUnreal EngineやUnityのプラグインを使った方が良い気もします。

[1] NVIDIA DLSS SDK Now Available for All Developers with Linux Support, Unreal Engine 5 Plugin and New Customizable Options
[2] https://developer.nvidia.com/dlss-getting-started#
[3] https://github.com/microsoft/DirectXShaderCompiler
posted by シンドラー at 21:44| Comment(0) | OpenGL & Metasequoia | 更新情報をチェックする

2021年06月15日

OpenGL ES 2.0 + EGL のテスト

5月更新してないからしないといけないなと思っていたらもう6月も半分過ぎてしまいました…。最近は機械学習なども流行っているので、Windows PCではなくLinux PCに買った中で一番性能の高いグラボを付けていたりします。そういうわけでせっかくのグラボなのでAIだけでなくCGにも使おうと思ったのですが、完全にサーバ用にしてデスクトップ環境すら入れていないので、どうせならオフスクリーンレンダリングできた方が良いかなと思って調べると、OpenGL ES 2.0 + EGL という環境でできるようでした。組み込み用なので最新機能をバリバリ使うことはできないと思いますが、ちょっとしたレンダリングであれば十分かなと思います。

[1]はGoogle Cloud Platform(GPC)のGoogle Compute Engine(GCE)上で動かされているようですが、ここにある手順でUbuntu等に導入できると思います。デスクトップ環境などがあってウィンドウ表示ができる場合は[2]などが参考になると思います。

実行結果

egl_result.png

立方体+テクスチャ[3]を描画してみました。GLSLの使い方を結構忘れていて、glBindAttribLocationとかglVertexAttribPointerとかの指定方法などでちょっと詰まりましたが、何とか解決しました。[1]でやっているようにPHPを介したサーバサイドレンダリングというのも面白そうですね。

[1] GCPでOpenGLを使用しサーバ3Dレンダリング
[2] 組み込み向けグラフィックスを試してみた(OpenGL ES 2.0 + EGL)
[3] http://geminoidi.com/downloads.htm
posted by シンドラー at 23:51| Comment(0) | OpenGL & Metasequoia | 更新情報をチェックする

2021年04月29日

PyTorchでWavelet変換のテスト

先月は初めの頃に更新できて安心していたらあっという間に4月が終わりそうです。今回は特に内容はないですが[1]の記事を見てPyTorchでWavelet変換を試してみることにしました。

詳しく論文読んでないのですが、ただ単にWavelet変換しているだけのような気がするので、同じ枚数のフィルタを用意すれば同じ結果が得られそうな気もするんですが、性能が上がったということは何か工夫があるんでしょうね。

PyTorchでWavelet変換についてですが、一つはPythonのWavelet変換ということで、PyWavelets[2]というものがあるようです。もう一つはPyTorch用ということで、PyTorch_Wavelets[3]というものがありました。

で、サンプルコードを見ると、1枚の画像を普通のDWTではLL、LH、HL、HHの4枚に分割すると思うのですが、LL以外に6枚出力されていました。よく見るとDWTではなくDTCWT(Dual-Tree Complex Wavelet Transform)という6方向に分割するような手法でした。

調べてみると下記のような並べ方で可視化されている方がいましたので真似してみました。高周波成分も見やすいように0~1に正規化しています。

dtcwt.png

この辺を使ってLiftPoolもどきを試してみましたが、あまりいい結果にならなかったので、何かを間違ってしまっている気がします。

[1] 双方向畳み込みプーリング「LiftPool」登場!
[2] PyWavelets - Wavelet Transforms in Python
[3] Pytorch Wavelets
posted by シンドラー at 18:07| Comment(0) | Machine Learning | 更新情報をチェックする

2021年03月07日

JPEG画像のノイズ除去と超解像処理

以前から構造だけは考えていたので、重い腰を上げて実装してみました。まぁ基本は既存モデルの流用なので実装というほどでもないのですが、最新技術を簡単に利用できるのは素晴らしいですね。

JPEGの圧縮ノイズ除去を行う手法も色々ありますが、JPEGのQualityをラベルとして与えてあげれば少し改善されるのではないかというのがアイデアです。未知の画像はQualityが分かりませんので、それを推定する必要があります。全体構造としては下記の図のようになります。

jpeg_sr_001.png

1. JPEG画像をEfficientNet-b7[1]に入力してJPEGのQualityを推定(10クラス分類)
2. JPEG画像をパッチサイズ(128x128x3)に分割
3. JPEGのQualityをnn.Embeddingを使ってベクトル化→128x128x1にreshape
4. 画像とラベルをtorch.catで結合して128x128x4の入力テンソルに変形
5. 4ch入力に変更したS-Net[2]に入力してJPEGノイズを除去
6. SPSR[3]に入力して画像を4倍に拡大
7. 拡大したパッチを結合して画像として保存

といった流れになります。

ポイント1
EfficientNet-b7への入力は600x600でしたので、入力画像から切り出す必要がありますが、torchivisionにtransforms.FiveCropという4隅+中央を指定したサイズで切り出すという処理がありましたので、画像から5か所切り出しでEfficientNet-b7に入力し、結果として得られた5個の結果の中央値を出力クラスとしました。かなり精度が高い印象でした。

ポイント2
nn.Embeddingはラベルをベクトルに変換してくれますが、毎回同じベクトルにするために乱数シードの固定が必要です。また、ベクトルの次元が変わると生成される値も当然変わってきますので、推論時は画像を丸々S-Netに入力するのではなく、パッチサイズに分割してサイズを固定してあげる必要があります。

ポイント3
分割してからノイズ除去→拡大を実行すると、かなり切れ目が目立ちました。下記のようにオフセットとして畳み込みで影響しそうな領域を大きめに切り取ってノイズ除去→拡大したのち、余分な部分をカットしました。
jpeg_sr_002.png

ポイント4
パッチ分割する利点ですが、画像が大きすぎるとSPSRで拡大するときにメモリが足りなくなるので、その点でも有効だったと思います。

実験条件

EfficientNet-b7は出力層を10層に変更[4]して、DIV2Kを使ってファインチューニングしました。LossはCrossEntropy誤差を使用しました。
S-NetはEncoder部分の入力を4chに変更して、DIV2Kを使ってLossをSSIMLossで学習させました。元々原画像とJPEG圧縮したものをDatasetとして使うようになっていましたので、圧縮時のQuality÷10をラベル情報として追加で出力するように変更しました。
SPSRは全く変更しておらず、学習済みモデルをそのまま使用させていただきました。

実行結果

拡大しないと分かりにくいかもしれませんが結構きれいにできていると思います。

jpeg_sr_003.jpg
入力画像:Set14の画像をQuality=40で保存したJPEG画像

jpeg_sr_004.png
(左)Bicubic補間で入力画像を4倍したもの(右)1.~7.を実行したもの(一部切り出して拡大)

[1] https://github.com/lukemelas/EfficientNet-PyTorch
[2] "S-Net: A Scalable Convolutional Neural Network for JPEG Compression Artifact Reduction"
[3] Structure-Preserving Super Resolution with Gradient Guidance (CVPR 2020)
[4] EfficientNetの事前学習モデルをPytorchで使う
posted by シンドラー at 15:37| Comment(0) | Machine Learning | 更新情報をチェックする

2021年02月04日

PyTorch3Dを使ったボリュームレンダリング

もう一つのチュートリアル(Fit A Simple Neural Radiance Field)も面白そうですが、今回はとりあえずボリュームレンダリングのテストです。データは[1]のBonsai1をV^3 Library[2]のpvm2rawを使ってrawデータに変換して、それをnpzに変換したものを使用しました。この辺の話もブログに書いた気がしたんですが見当たらないので気のせいでしょうか。

ソース
volume_rendering_test.html

前回のチュートリアルの一部を残して、学習してボリュームデータを最適化する代わりにnpzファイルを読み込んでレンダリングしています。

実行結果

result.png

結局伝達関数をどうするのかがネックな気もしますが、この辺も学習で何とかなるんですかね。教師データとなる画像があるのならできそうですが…。

[1] The Volume Library
[2] VVV - Real-Time Volume Renderer
[3] https://github.com/facebookresearch/pytorch3d
posted by シンドラー at 23:14| Comment(0) | Machine Learning | 更新情報をチェックする

2021年01月31日

PyTorch3Dを使ったボリュームデータのフィッティング

PyTorch3D[1]も気が付くとバージョンアップしていたりチュートリアルが増えていたりしていいことですね。今回はボリュームデータに関するチュートリアルが増えていたので試してみることにしました。

手法としては、ポリゴンモデルを複数の視点からレンダリングして、その視点座標+レンダリング結果(カラー画像とシルエット画像)の組を教師データとして、128x128x128のボリュームデータをレンダリング→カラー画像とシルエット画像との誤差を計算→ボリュームデータの色や不透明度を修正というもののようです。

これを使えばポリゴンモデルのボリュームデータ化なんかが簡単にできそうな気がしますね。

実行結果
pytorch3d_fit_volume_result.png

左上がボクセルをレンダリングしたカラー画像、右上が教師カラー画像、左下がボクセルをレンダリングしたシルエット画像、右下が教師シルエット画像です。ボリュームデータが最適化されているのがわかるかと思います。

適当に訳したコード+npz保存
fit_textured_volume_jp.html

最適化されたデータをnpzで保存して、voxデータに変換してMagicaVoxelで表示してみました。

pytorch3d_fit_volume_result_002.png

データは[0-1]なので255倍して、densityが10未満のデータについては空域としました。ボリュームレンダリングすれば見やすいのでしょうが、無理やりボクセル化すると周辺の黒い部分が残ってしまいます。閾値を大きくすると中身も削れてしまったので、あくまでもボリュームデータ作成に使える、といった感じのようです。

手元にあまりいいボリュームレンダラがないので、次回はボリュームレンダリングにPyTorch3Dを使ってみようかなと思います。

[1] https://github.com/facebookresearch/pytorch3d
posted by シンドラー at 20:54| Comment(0) | Machine Learning | 更新情報をチェックする

2021年01月22日

SSIMのテスト

前回の続きです。

PyTorchでAutoencoderの[1]ですが、loss関数にRMSE(Root Mean Square Error)が使われています。

loss = torch.sqrt((y_hat - y).pow(2).mean())

これをSSIMに変更して学習させてみます。PythonでSSIMを計算する場合、piqa[2]というパッケージが簡単に使用できるようです。SSIMの他にもたくさん指標が実装されているようですので、簡単に比較なども出来そうです。

使い方は[3]にありましたのでその通りにしました。

実行結果

ae_ssim_001.png
ae_ssim_002.png
ae_ssim_003.png

どちらも120エポック学習したものです。8エポック改善されなかったら学習率を下げるようになっているのですが、結構効果があるみたいですね。過学習かもしれませんが。

最終的にはSSIMが0.971まで上がりましたので、数値的には結構近づいてきていますが、画像を見ると少し色合いが変わっている気がしますね。RMSEの最終的な値は記録するのを忘れました。基本的に機械学習もRGBでやっていますが、HSVに変換したりするとまた少しは変わるんでしょうか。

[1] https://github.com/foamliu/Autoencoder
[2] https://github.com/francois-rozet/piqa
[3] https://stackoverflow.com/questions/53956932/use-pytorch-ssim-loss-function-in-my-model
posted by シンドラー at 01:29| Comment(0) | Machine Learning | 更新情報をチェックする

2021年01月20日

画像の情報量と評価指標

年末年始に更新しようと思っていたのにいつの間にか1月も下旬ですね…。

深層学習に使うデータセットを準備しているとき、解像度の高い画像からランダムクロップでデータ数を増やしたりするんですが、たまたま真っ黒な背景の部分だけ切り取ってきたりした場合は、あまり学習データとして良くない気がします(実は必要なのかもしれませんが…)。

また、ノイズ除去とかで、劣化画像と原画像のペアを用意する場合、平坦な部分などほとんど違いが感じられない場合もあるので、2枚の画像を比べてどれくらい違っているかの指標も必要かと思います。

前者は画素値の分散を計算して閾値以下のものをはじくといったのでも良いかと思いますが、画像の複雑さとしてはエントロピーを計算するのもいいかなと思いますので、その辺を計算してみます。

後者はMAE(Mean Absolute Error)、MSE(Mean Squared Error)、PSNR(Peak Signal-to-Noise Ratio)などが有名かと思いますが、SSIM(Structural Similarity)というものが最近?はよく使われているようですので、それも試してみることにしました。

1. エントロピー[1]~[4]
画像のエントロピーというと、その画素値がどれくらいの頻度で発生しているかを確率としてみて、単色なら0、全色均等に使われている場合は最大値になるような指標です。ヒストグラムを計算して、合計1になるように正規化して後はlogとって掛け算するだけですね。RGBだけではなく、例えばグレースケール画像は除きたい場合などもあると思うので、HSVでも計算してみました。

2. SSIM[5]~[7]
ガウスでぼかして近傍との分散を計算しないといけないみたいで、計算量が多そうです。OpenCVで実装サンプル[8]がそのままありましたので、使わせていただきました。こちらもRGBとHSVで計算してみました。

実行結果

pix2pix用にDIV2K dataset[9]からランダム切り出しして原画像(左)/JPEG圧縮画像(右)のペアを作っています。JPEGで劣化させた場合はブロックノイズのせいでエントロピーは下がるかな、と思いましたが、画像によるみたいですね。

__000840.jpg
ssim_fig_1.png
論文等でよく見る蝶々の一部ですね。拡大しないとあまり違いが分かりませんが、類似度は高くないようです。

__000480.jpg
ssim_fig_2.png
空の一部?です。割と違っているように見えますが、PSNRもSSIMも高いですね。こちらはJPEG圧縮で減色状態になったのか分散はほぼ一緒ですがエントロピーが結構下がっています。類似度が高くてもエントロピーに差があるので学習に使う、というのもありかもしれません。

深層学習ではロスの計算にL1LossやMSEが良く使われていますが、SSIM使うとどうなるのか試してみようかなと思います。

[1] 平均情報量 Entropy
[2] 平均情報量の性質(3章)(pdf)
[3] 画像のエントロピーをpythonで求めてみた
[4] 医用画像工学実験 -画像の情報量 編- (pdf)
[5] SSIMとは何か?その3
[6] 画質評価アラカルト
[7] Googleが薦める「Jpegの品質は85」を検証する
[8] OpenCV Tutorial Video Input PSNR SSIM
[9] DIV2K dataset
posted by シンドラー at 02:59| Comment(0) | Image Processing | 更新情報をチェックする