2022年6月25日土曜日

PowerShellによるD&Dしたファイル名などの取り出し方

PowerShellによるD&Dしたファイル名などの取り出し方

 先の投稿ではPowershellのスクリプトをD&Dで動かす方法を説明しました。
 今回は、D&Dしたファイルの名前、ファイルパス、拡張子などの取り出し方を説明していきます。

 バッチファイルではご存知のように、%~n1 でファイル名、%~dp1でファイル名を除いたパス、%~x1 で D&Dしたファイルの拡張子を取り出し、バッチファイルのスクリプト上に変数として使用できます。
 しかし Powershell においては、このように簡単に取り出すことはできません。

 そこで今回は、Get-ItemProperty と Select-Object を使って得られるプロパティ情報と、実際にプロパティの呼び出す方法を説明します。

ファイルから得られるプロパティ情報

下記のサンプルプログラムをそのままコピペし、D&Dで動かしてみてください。

#サンプル1
Get-ItemProperty  -LiteralPath $args |  Select-Object  *
 
pause
exit

 スクリプトの内容としては、 Get-ItemProperty を使って $args (D&Dした物を絶対パスとして引数にしている) のプロパティを Select-Object にパイプラインですべて流して表示しているだけに過ぎません。

 例として、 “D:\sample-pic.jpg” を上記のサンプルプログラムにD&Dすると次のような結果になると思います。
サンプル1の実行例

 左に緑でハイライトされている文字列がプロパティ名、右の白字がそのプロパティで得られる内容です。
 
 つまり、バッチファイルでいう %~n1 のように BaseName プロパティを選択したらファイル名が得られますし、%~x1 のように Extension プロパティを選択したら拡張子が得られることがわかりました。
 それでは、実際に得る方法を説明します。

プロパティの内容を取得

 また下記のサンプルプログラムをそのままコピペし、D&Dで動かしてみてください。
 スクリプトの内容としては、 Get-ItemProperty を使って $args のプロパティを、プロパティ名を使って呼び出しているだけです。

#サンプル2
Write-Host  "Name is " (Get-ItemProperty  -LiteralPath $args).BaseName
Write-Host  "Extension is " (Get-ItemProperty  -LiteralPath $args).Extension
Write-Host  "FullName(Fullpath) is " (Get-ItemProperty  -LiteralPath $args).FullName
Write-Host  "Last Access Time is " (Get-ItemProperty  -LiteralPath $args).LastAccessTime

pause
exit

 再度 “D:\sample-pic.jpg” を上記のサンプル2にD&Dすると次のような結果になると思います。
サンプル2の実行例

 このように、プロパティ名からメンバーアクセス演算子 ( . (ドット))を用いて必要な情報を取り出すことに成功しました。
 単に " . " で繋いで、 .BaseName や .Extension などと書くだけですね。

 これで、今までバッチファイルで使っていた %~n1 や %~x1 などの各種プロパティ変数を Powershell スクリプト上で実現することが出来ました。

参考資料
Microsoft プロパティについて - Powershell
Microsoft オブジェクトの一部を選択する (Select-Object)
PowerShellを使ってサイズや更新日時、バージョンなど、ファイルのプロパティ情報を取得する方法

Powershell 7 スクリプト を D&Dで実行する

Powershell 7 の ドラッグアンドドロップでの実行方法

実行環境:Windows10 x64、Powershell 7.2.4

 最近、従来のバッチファイルからPower shell 7 に頑張って乗り換えようとしています。
 そこで、自分が躓いた事を後学の人の参考になればと思い、備忘録も兼ねて書きました。
 参考になったら幸いです。 
 
 Powershell と Powershell 7 はバージョンが違うため、異なるところが多々あります!
 必ずPowershell 7 の最新バージョンをインストールした上でこの記事をお読みください!

はじめに・・・Powershellの実行ポリシーの変更

 Powershellで自分のスクリプトを書いても、デフォルトのセキュリティの都合により実行できないという事が多々あります。
 はじめに、ローカルファイルにあるPowershellスクリプトの実行ポリシーを変更しましょう。
 
 必ず Powershell 7 を管理者権限で起動し、下記のコマンドで実行ポリシーを変更してください。

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

 デフォルトの設定だと、Powershell の ExecutionPolicy は Undefined となっています。
 そこでローカルで作成された Powershell スクリプトを容易に動かせるように、現在のユーザー (CurrentUser) に対して RemoteSigned されたファイルの実行ポリシー (ExecutionPolicy) をこのコマンドで変更しています。
 このコマンドにより、インターネット上で取得した署名済みの Powershell スクリプトと、ローカルで作成された Powershell スクリプト(署名なし含む) が動かせるようになります。

ここまでの参考資料
Qiita : PowerShellの実行ポリシー変更
Microsoft : 実行ポリシーについて - Powershell

D&Dによる Powershell スクリプトの実行方法

 さて本題です。
 自作した Powershell スクリプトを D&D で実行させる方法です。

 最初に作ったPowershell スクリプトのショートカットを作ります。
 その後、作ったショートカットファイルの ”リンク先” に以下のように記入してください。

"C:\Program Files\PowerShell\7\pwsh.exe" -File  "C:\hoge\Powershell-Script.ps1"

 “C:\hoge\Powershell-Script” の部分は適宜変更してください。

 これで、PowershellスクリプトがD&Dで動くようになりました。バッチファイルのようにスクリプトを書けばD&Dで動かせるようになります。

 ただ、D&Dしたファイルの名前の取り出し方や、ファイルパス、拡張子の取り出し方は、バッチファイルと違って一工夫必要です。次回はその事をネタにした記事を書きます。

参考資料
Qiita : PowerShellをダブルクリックやドラッグアンドドロップで実行したい。
PowerShellスクリプトへファイルをドラッグ&ドロップする(bat不要)

2020年10月2日金曜日

ランベルトのW関数を用いたおべんきょう(その2)

2020年9月7日月曜日

ランベルトのW関数を用いたおべんきょう(その1)

2020年7月26日日曜日

個人的に新しいインターレース解除の方法(Avisynth):24pソースな60iから30pにする。



はじめに(TL;DR)

最近、GTX1660ti買いました。それまではRadeon7970を使っていましたが、技術の進歩は素晴らしいですね。GTX1660tiのグラフィック処理能力も(Radeon7970と比較して)素晴らしいものですが、GPUエンコードの能力も昔(2013~2014年頃)と比較して素晴らしいものになりました。

これを見ている皆さんはご存知かもしれませんが最近のGPU(Geforce)は、CUDAとGPUエンコード/デコードが独立しており、何かしらのゲームをしながら同時にYoutubeを見たり、ゲームをキャプチャして録画or配信も余裕で出来るようになりました。

また、昔のGPUエンコードを使ったことある方ならわかりますが、画質なんて10Mbps積んでもようやく見れるかどうかというとても酷いものでした。しかし、現在のGPUエンコードはHEVCにも対応しており、品質もCPUエンコードと比べて遜色ないものになりました。私はrigaya氏のNVEncを利用しています。

さすがに、極めて細かい点(ファイルサイズ、1フレーム単位でみた動画の画質の比較)を比較するとCPUエンコードが優りますが、文字通り極めて細かい点ですし、どうしてもCPUではないとイヤだ!という場合でなければGPUエンコードでも全く問題ありません。

しかし、GPUエンコードが進化したことによって別の問題が発生するようになりました。それは、Avisynth自体のデコード速度です。

CPUエンコードで品質と処理速度を両立しようとすると、どう頑張っても最大エンコード速度が 20 frame/sec 程度となり、Avisynthのデコード速度が別にその程度でもCPUエンコードがどちらにしろボトルネックになるので、別にAvisynthのデコード速度なんてあんまり考えなくても大丈夫でした。

しかし、今では妥協しない品質の設定でGPUエンコードを行っても 200~300 frame/sec とか余裕でエンコード出来るようになり、むしろボトルネックがAvisynthのデコード速度となりました。

そこで今回は、主にアニメなど24pへのソースを想定しながら、60iから30pへの高いクオリティでのデインターレース(インターレース解除)を行いながらも、高速なデコードを速度を両立したデインターレース方法を紹介したいと思います。


Avisynthでのデインターレースと新しい自分なりのインターレース解除の方法


まずは自分の環境

Avisynth+ 3.6.0 64bit
CPU:3930K
GPU:1660ti
MEM:32GB

TIVTC.dll の x64版 は、pinterf氏の .dllを使っています。この dll の中に TFM 、TDeint 、IsCombedTIVTC などの関数があります。

また、今のうちに書いておきますが yadifmod2.dll の x64版 は asd-g氏の .dll 、nnedi3.dll の x64版 は jpsdr氏の .dll を使っています。


主なデインターレースの方法

Avisynthのデインターレースには、主に有名な方法で、

  1. TFM
  2. TDeint
  3. nnedi3
  4. yadifmod2

などがあります。メジャーなのはこんな感じですが、他にもあるので気になる方は調べてみてください。

それぞれ一長一短があり、品質が良いけれども処理が遅いとか、その逆もあります。

新しい自分なりのインターレース解除の方法(コード)

自分なりの新しい方法はこちらです。


LoadPlugin("TIVTC.dll")
##ここに何かしらの60iビデオソース##

ConditionalFilter(DoubleWeave().SelectOdd(), last,"Crop(0,250,0,-180).IsCombedTIVTC()", "=", "true")
#ConditinalFilterの部分が新しい自分なりの方法です。

「くっさ!こんな簡単そうなコードで良いインタレ解除出来るわけ無いやろ!」とか思うのは当然だと思います。

でも自分が研究してみた限りでは、これがいい方法だったんですよね・・・

関数の内容自体は、 IsCombedTIVTC() でインターレースなフレームかプログレッシブなフレームか判定し、インターレースなフレームのみに対し DoubleWeave().SelectOdd() をかけています。

Crop(0,250,0,-180) をしているのは、右から流れるテロップとか、特にBS11に出るAnime+のロゴに誤爆対策にわざとトリミングしてインターレースかプログレッシブか判定を行っています。



技術的な詳細はこちら

こちらや、こちらがわかりやすいのですが、特に元は24pのソースを60iで放送している場合、任意の5フレームを抽出した内、3フレームはプログレッシブなフレーム、2フレームはインターレースなフレームです。

1t 2t 2t 3t 4t
1b 2b 3b 4b 4b
60iなソースから任意に抽出した5フレームをフィールド単位に分割したイメージ
tはtop、 bはbottomの略

欲しいフレームは2フレームのインターレースなフレーム(この場合は、2tと3bと、3tと4bがインターレースなフレーム)を、プログレッシブなフレームに変えて、5フレームの内5フレームともプログレッシブなフレームに変えたものです。

1t 2t 3t 4t 4t
1b 2b 3b 4b 4b
5フレームともプログレッシブなフレームに変えた場合のイメージ

ということは、インターレースなフレームと判定された場合にのみインターレース解除を行えばよいわけです。

ここで、インターレースなフレームと判定するために IsCombedTIVTC() を使っています。

もちろん全てのフレームに対しまずは IsCombedTIVTC() をかけなければ行けないため、そのために ConditinalFilter を使っています。

Cropの部分は前述の通り、誤爆対策です。

その後のインターレース解除は、Doubleweave() でフィールドを合成し、奇数フレームのみプログレッシブなフレームができるため SelectOdd() でプログレッシブなフレームのみ抽出しています。

古典的ですがシンプルで一番キレイな方法です。



デコード速度と画質の比較

初期条件

TFM、TDeint、nnedi3、yadifmod2 と 今回の ConditinalFilter関数でのデインターレースを用いて、比較を行います。

映像ソースは、とある科学の超電磁砲TのTSソース(1920x1080)のOP部分のみで、フレーム数は2696フレームです。

それぞれの関数の内容は以下のとおりです。

ConditionalFilter(DoubleWeave().SelectOdd(), last, "Crop(0,250,0,-180).IsCombedTIVTC()", "=", "true")
TFM(mode=5,pp=7,slow=2,blockx=4,blocky=4,MI=16)
nnedi3(field=-1,nsize=4,nns=4)
TDeint(mode=0,order=-1, field=-1)
yadifmod2(order=-1,field=-1, opt=3)

TDeintとYadifmod2は少しいい加減な設定


デコード速度

最初にデコード速度です。

デコード速度は数値が高ければ良く、処理時間は小さければ良いです。

AVSMeterでデコード速度をそれぞれ1回のみ測りました。
以下の表に示します。

関数 デコード速度(frame/sec) 処理時間(sec)
ConditinalFilter and TIVTC (今回の関数)
interf氏の使用
411.2 6.557
Yadifmod2 asd-g氏の使用 416.4 6.457
nnedi3 jpsdr氏の使用 54.0 49.961
TFM interf氏の使用 20.2 133.572
TDeint interf氏の使用 19.8 136.383
デコード速度と処理時間の表

順位は、表の通り

① Yadifmod2
② 今回の関数
③ nnedi3
④ TFM
⑤ TDeint

流石Yadifmod2と言ったところでしょうか、0.1秒の差ながら自分の作った関数よりも速いです。

個人的には nnedi3 が一番遅いのかなと思っていましたが、 jpsdr氏の最適化が進んでいるためか NN で計算速度多そうながらも思ったより速かったです。

ここで処理速度が一番良いのは Yadifmod2 であることはわかりましたが、次は画質の面で比較しましょう。

処理速度が良くても画質が悪ければ意味ないですからね。

画質面での比較

プログレッシブなフレームでの比較

最初は、プログレッシブなフレームで比較してみましょう。
まずはその最初のオリジナルなフレームから。

Original Progressive Frame

至って普通ですね。プログレッシブなフレームです。

次に、今回の関数で見てみましょう。

Myfunc Progressive Frame

今回の関数は、プログレッシブなフレームは全く触らないようにしているので、左上の字幕以外は全くの同じです。もし違いがわかる方が居たら教えて下さい。

次に TFM で見てみましょう。

TFM Progressive Frame

TFMで見ても、気持ちプラセボレベルで変わったかな・・・?というぐらいです。99%は同じでしょう。
処理速度は遅いものの、プログレッシブなフレームでの品質は良いですね。

次に nnedi3 で見てみましょう。

nnedi3 Progressive frame

結構変わりました。御坂の脚の部分の線と、原作者の文字がオリジナルと比較して結構変わっています。
わかりやすい点は、レールガン独特の明朝フォントが潰れた形になり、NNを使ってもこのような細かい補正は難しいことが伺えます。

次に TDeint で見てみましょう。

TDeint Progressive Frame

nnedi3 ほど文字は潰れていないものの、オリジナルのフレームと比較してみると御坂の脚の部分の黒い線にノイズが少し載っているのがよく見ると分かると思います。すこしぼやけてノイズがかかっているような感じですね。
また、御坂の服の薄い線がオリジナルと比べてやや薄くなっています。

次に Yadifmod2 で見てみましょう。

Yadifmod2 Progressive Frame

はい、御坂の脚の部分にコーミングノイズが載っています。オリジナルと比較してもすぐに分かるのではないでしょうか。オリジナルと比較しても御坂の服の薄い線の書き込みがぼやかした状態になり、いくら処理速度が速いと言っても個人的に常用としては採用し難いです。

個人的な主観ではありますが、オリジナルのプログレッシブなフレームの品質を100点満点とすると、それぞれのフレームの品質は以下の表となります。

関数 点数
オリジナル 100
今回の関数 100
TFM 99
nnedi3 70
TDeint 75
yadifmod2 55
プログレッシブな場合の得点表

結構、プログレッシブなフレームでも処理によっては少し画質が下がることがわかりました。

デインターレースの処理を行う以上、どうしても画質の低下は避けられない話にはなりますが、あまり下がりすぎるというのもよくありません。
そのような意味において、今回の関数はインターレースだとは判定されない限りは全く手をつけないので、少なくともAvisynth上においてオリジナルのフレームと同等の物を維持できます。

次にインターレースの場合の画質を見てみます。

インターレースなフレームでの比較

オリジナルのインターレースなフレームを見てみます。

Original interlace  Frame

はい。わかりやすいインターレースなフレームですね。これを元にしてデインターレースを行い、画質の比較を行います。

今回の関数の場合を見てみましょう。

Myfunc interlace Frame

御坂が前に行っているフレームを抽出したようですね。
理論的にはこのフレームが綺麗にデインターレースできたフレーム・・・のはず・・・

TFMでデインターレースした場合を見てみましょう。

TFM interlace Frame

これ以降、基準フレーム + 1フレーム のフレームを抽出しています。例えば、これよりも上の2枚が50フレームの所を参照していたならば、この1枚の画像は51フレームの所を参照している形です。本来ならば同じフレームを以て比較すべきですが、それだとインターレースの仕様上、アニメの絵が1コマズレる形になり、画質の比較が困難な為やむを得ず1フレームだけズラしています。予めご了承ください。
画質の内容ですが、とても素晴らしく綺麗にデインターレースできていると評価しても良いでしょう。本当に処理時間がネックです。

次に nnedi3 を見てみましょう。

nnedi3 Interlace Frame

御坂の服の薄い線が少しぼやけているのと、プログレッシブな場合と同じくフォントが潰れているのが分かると思います。

次に TDeint で見てみましょう。

TDeint Interlace Frame

御坂の脚の部分が、これもプログレッシブの場合と同じくややノイズというか、ジャギっているのがわかると思います。文字は潰れていませんし、ジャギー以外は全くもって問題ありませんが、今回の関数と比較するとやや劣ると言えるでしょう。

次に、yadifmod2 を見てみましょう。

yadifmod2 interlace frame

御坂の服の部分の線が潰れているのが分かると思います。また、TDeintのインターレースなフレームと比較してみると、ジャギーもコーミングノイズも増えています。今回の関数でのデインターレースがスッキリしていると感じられるのに対し、これはノイズなどの情報量が増えていると感じられても仕方ないでしょう。

個人的な主観ではありますが、今回のデインターレースされたプログレッシブなフレームの品質を100点満点とすると、それぞれのフレームの品質は以下の表となります。

関数 点数
今回の関数 100
TFM 99
nnedi3 75
TDeint 85
yadifmod2 60
インターレースな場合の得点表

まとめ

以上の比較より、結果の表と得点付け、最終的な総合順位をまとめていきます。
今回は、処理速度と画質の両立を狙って総合順位を付けます。

見ている方によって意見は分かれると思いますが、その場合は自分で順位を付けてみてください。

関数 デコード速度(frame/sec) 処理時間(sec) プログレッシブ得点 インターレース得点 総合順位
ConditinalFilter and TIVTC (今回の関数) 411.2 6.557 100 100 ①
Yadifmod2 416.4 6.457 55 60 ④
nnedi3 54.0 49.961 75 70 ②
TFM 20.2 133.572 99 99 ③
TDeint 19.8 136.383 85 75 ⑤
結果と総合順位

今回の関数は、処理速度も速く、画質も良いので1位となりました。
Yadifmod2は、処理速度は1番速いですが、画質はいずれも悪く、4位となりました。
nnedi3は、処理速度はこの中では速い(と言っても今回の関数とyadifmod2の7~8倍かかりますが)、ですが文字が潰れる欠点があるので2位となりました。
TFMは、画質は良いものの処理速度が遅いため、3位となりました。
TDeintは、器用貧乏と評価さぜるを得ず、5位となりました。

無論この順位にはいろいろ意見があると思いますが、それでも今回の関数が良いのは揺るがないと思います。

この関数を使ってみて、良いエンコードライフを送っていただければ幸いです。

多くの方はデインターレースした後、逆テレシネの作業に入ると思いますが個人的には、NVEncの --vpp-decimate の blockx, blocky を 4 か 8 にした上で処理にかければ速く誤爆せずに逆テレシネ出来ると思います。

参考(AVS Meterの結果を貼り付けているだけ)



見たい人はどうぞ

今回の関数

今回の関数のAVS Meter Benchmark.

Yadifmod2

yadifmod2 のAVS Meter Benchmark.

nnedi3

nnedi3 のAVS Meter Benchmark.

TFM

TFM の AVS Benchmark.

TDeint

TDeint の AVS Benchmark.

Written with StackEdit.