ただのメモ

開発で得た知識のアウトプット

MinGWでUI Automationを使う (CMake, MinGW-w64, uiautomationclient.h)

 C++のコンパイラを自由に選べる環境ならば、GNUのg++を利用したいと考えている人は少なくないかと思います。Windowsでは、MinGWやCygwinなどを利用することになると思いますが、付属されているWindows SDKが完全なモノとは限りません。今回は頻繁に利用されないWindows APIを利用し、不完全ゆえのエラーが出力された時の対策を考えます。

Microsoft UI Automation

 Microsoft UI Automation (UIA) は、プログラムからWindowsのGUIのコンポーネントを操作するためのAPIです。前身であるMicrosoft Active Accessibility (MSAA)は、身体的または認知的困難を持つ障碍者やアプリケーションの自動化のためにWindows 95から導入されています。身近なものだと、Windowsのナレーター機能などがあります。ナレーションをするには、UIを認識する必要があるわけです。UIAとMSAAはどちらもComponent Object Model(COM)に基づいています。

参考
docs.microsoft.com

問題

 Mingw-w64にて、次のように、単にインクルードしたところ、宣言・定義されていないとのエラーを大量に吐かれました。

#include <uiautomationclient.h>

 そこで、MinGWのuiautomationclient.h (MinGW/x86_64-w64-mingw32/include)を参照したところ、マクロの羅列ばかりで実装が不完全でした。

2015年にも同様の報告があります。
sourceforge.net
最新のMinGWとMinGW-w64のソースコードを確認しましたが、未だ実装されていません。

対策

 公式で提供されているWindows SDKを利用するのが手っ取り早いので、CMakeでWindows SDKを検出し、MinGWと使い分けるようにインクルードします。

Windows SDKは次のリンクからインストールできます。
developer.microsoft.com

CMakeでは、WindowsのレジストリからWindows SDKのパスを読み出して、最新のWindows SDKのパスの検出を行うようにします。

# CMake
set(WINDOWS_SDK_INCLUDE_DIR "")
if("${WINDOWS_SDK_INCLUDE_DIR}" STREQUAL "")
    get_filename_component(WINDOWS_SDK_ROOT_DIR "[HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\Windows Kits\\Installed Roots;KitsRoot10]" REALPATH)
    file(GLOB WINDOWS_SDK_INCS LIST_DIRECTORIES true "${WINDOWS_SDK_ROOT_DIR}/Include/10.0.*.*")
    list(SORT WINDOWS_SDK_INCS ORDER DESCENDING)
    list(GET WINDOWS_SDK_INCS 0 WINDOWS_SDK_INCLUDE_DIR)
endif()
if(NOT EXISTS ${WINDOWS_SDK_INCLUDE_DIR})
    message(FATAL_ERROR "Could not find the directory; ${WINDOWS_SDK_INCLUDE_DIR}. You can fix by the cmake flag; -DWINDOWS_SDK_INCLUDE_DIR=<Path>")
endif()
message(STATUS "Detected Windows SDK: ${WINDOWS_SDK_INCLUDE_DIR}")

以上で、${WINDOWS_SDK_INCLUDE_DIR}に次のような値が得られます。

C:/Program Files (x86)/Windows Kits/10/Include/10.0.19041.0

したがって、${WINDOWS_SDK_INCLUDE_DIR}include_directoriesで読み込むことで、次のようにMinGWのものと区別してuiautomationclient.hを読み込むことができます。

#include <um/uiautomationclient.h>


GitHubにも置いておきます。
github.com

 

UI AutomationのGUID

 先ほどの手順でuiautomationclient.hを読み込むことはできますが、COMオブジェクトが必要とするGUIDが定義されていないため、CLSID_CUIAutomationIID_CUIAutomationなどでリンクエラーが生じると思います。

対策1: Windows SDKのGUIDをまとめたライブラリをリンクする

 先ほどインクルードしたWindows SDKのlibディレクトリのlibuuid.libというライブラリをリンクします。ただ、プロジェクトによってはその他のライブラリと競合し、multiple definitionとしてリンクエラーを吐かれることがあります。私は、wxWidgetsと併用してuuidライブラリをリンクしたところ、定義の重複が生じました。その際、リンカに--allow-multiple-definitionオプションを渡すことでリンクすることができます。

対策2: GUIDを定義する

 GUIDは、基本的に一意な128 bitの定数なので、自前で定義することも可能です。WindowsのGUIDは以下のデータベースで検索することができます。
www.magnumdb.com

これにより、次のように定義が可能です。

#include <initguid.h>

DEFINE_GUID(IID_IUIAutomation,   0x30cbe57d, 0xd9d0, 0x452a, 0xab, 0x13, 0x7a, 0xc5, 0xac, 0x48, 0x25, 0xee) ;
DEFINE_GUID(CLSID_CUIAutomation, 0xff48dba4, 0x60ef, 0x4201, 0xaa, 0x87, 0x54, 0x10, 0x3e, 0xef, 0x59, 0x4e) ;


参考になれば幸いです。

【VALORANT】無限ローディングの対処法

突然黒い画面になり、再起動後に次のようにロビー画面でフリーズしたので、その対処法です。
f:id:pit-ray:20200602234132j:plain

VALORANTは、チート防止のために多くの認証システムを導入しています。
Demolishing Wallhacks with VALORANT's Fog of War | Riot Games Technology

そのせいか分かりませんが、プレイ中のままサーバに取り残されたような形になったのかと思います。
これは既存のバグのようで、海外のサイトに多くの報告がありました。

次の手順で回復できました。自己責任でお願いいたします。



1. タスクトレイから
Riot Vanguard>More>Uninstall Vanguard

2. VALORANTインストーラを起動し、Vanguardを再インストール

3. PCを再起動

4. LEAGUE OF LEGENDSをダウンロード
(インストール済みなら不要)

5. LOLにVALORANTと同じアカウントでログイン
Riotのサーバ上のプレイ情報をリセットするためかと思います。

6. 以下のファイル削除

C:/Riot Games/VALORANT/live/Manifest_DebugFiles_Win64.txt
C:/Riot Games/VALORANT/live/Manifest_NonUFSFiles_Win64.txt

7. VALORANTを管理者権限で起動
プロパティ>互換性>管理者としてこのプログラムを実行する
にチェック


LOLにログインすることで、
「違うゲームを始めたから、VALORANTは終了していいよ」
というメッセージをサーバに送る仕組みならば、実質4だけで解決するのかもしれません。
同じバグを再現することができないため、確証はありません。

また、極端にping値が高くなった場合には、画面が黒くなるようですが、待つと元に戻るそうです。

追記

メンテナンスが入ったようなので、修正されるかもしれません。

ラベルマップから二次元美少女イラストを生成する (SPADE pix2pix)

今回は、ピクセル上の位置情報から二次元美少女イラストを生成したのでその結果をまとめます。

ソースコードは、GitHubで参照することができます。今は亡きChainerでの実装となります。
github.com

モデルの概要

次の画像のようにSemanticなラベルと髪色の色マップを入力として与えると、ラベルに沿った構成と指定した髪色で着色されたイラストが生成されます。


今回の構成は、GauGANをベースにしています。

アーキテクチャ

  • オリジナルのSPADEでは、それぞれのSPADEが別々にラベルをエンコードする必要がありますが、StyleGANのようにマッピングネットワークで事前に計算し、そのweightをSPADEに入れ込むようにしました。ただし、FCNではダウンサンプリングにより位置情報が失われてしまうので、AtrousConvolutionで解像度を変えないConstant-FCNを実装しました。
  • 髪色を指定したかったため、マッピングネットワークを二つ用意し、一つはSemanticなラベルを入力し、もう一つには髪色とその位置情報をもつ同解像度のRGBマップを入力しました。また、StyleGANのように複数のweightは混ぜて渡すようにしました。
  • StyleGANのようにノイズを入れるレイヤを追加しました。
  • Discriminatorには、Multi-scale discriminatorの代わりにSelfAttentionを持つPatch Discriminatorとしました。
  • Discriminatorの損失には、Hinge lossとZero Centered Gradient Penaltyを用いました。
  • Generatorの損失には、Hinge lossとFeature Matching lossとPerceptual lossを用いました。

そのほかは、GauGANとほぼ同じ構成なので、割愛します。というのも、SPADEが登場したときは、NVIDIAの新技術ということでバズり、日本語の解説記事がゴロゴロ転がっているからです。

結果

データセットには、Pixivイラスト500枚の非常に小規模なものを用いています。
また、上に示したテストデータセットは、前回実装したAnime-Semantic-Segmentation-GANを用いて生成しました。訓練データは、手作業でアノテーションしたものを用いましたが、元の画像の著作権のため公開することはできません。

 今回得られた学習済みのパラメータはGitHubのリポジトリに置いているスクリプトを実行することで、私のGoogleDriveからダウンロードできます。100 MBしかないので比較的短い時間で落とせるはずです。
https://github.com/pit-ray/SPADE-pix2pix-for-Anime#pretrained-weights


まとめ

生成された画像のクオリティはそこまで高くありませんが、粗いアノテーションと、小規模のデータセットということを考えると、十分な結果が得られたと思います。
少々手抜きすぎる記事でしたが、参考になると幸いです。

参考文献

[1] Taesung Park, Ming-Yu Liu, Ting-Chun Wang, Jun-Yan Zhu. Semantic Image Synthesis with Spatially-Adaptive Normalization. arXiv preprint arXiv:1903.07291, 2019

[2] Tero Karras, Samuli Laine, Timo Aila. A Style-Based Generator Architecture for Generative Adversarial Networks
. arXiv preprint arXiv:1812.04948, 2019

[3] Han Zhang, Ian Goodfellow, Dimitris Metaxas, Augustus Odena. Self-Attention Generative Adversarial Networks. arXiv preprint arXiv:1805.08318, 2019

[4] Ian J. Goodfellow, Jean Pouget-Abadie, Mehdi Mirza, Bing Xu, David Warde-Farley, Sherjil Ozair, Aaron Courville, Yoshua Bengio. Generative Adversarial Networks. arXiv preprint arXiv:1406.2661, 2014

[5] Jonathan Long, Evan Shelhamer, Trevor Darrell. Fully Convolutional Networks for Semantic Segmentation. arXiv preprint arXiv:1411.4038, 2015

[6] Liang-Chieh Chen, George Papandreou, Florian Schroff, Hartwig Adam. Rethinking Atrous Convolution for Semantic Image Segmentation. arXiv preprint arXiv:1706.05587, 2017 (v3)

[5] Liang-Chieh Chen, George Papandreou, Iasonas Kokkinos, Kevin Murphy, Alan L. Yuille. DeepLab: Semantic Image Segmentation with Deep Convolutional Nets, Atrous Convolution, and Fully Connected CRFs. arXiv preprint arXiv:1606.00915, 2017 (v2)

[6] Takeru Miyato, Toshiki Kataoka, Masanori Koyama, Yuichi Yoshida. Spectral Normalization for Generative Adversarial Networks. arXiv preprint arXiv:1802.05957, 2018

[7] Wenzhe Shi, Jose Caballero, Ferenc Huszár, Johannes Totz, Andrew P. Aitken, Rob Bishop, Daniel Rueckert, Zehan Wang. Real-Time Single Image and Video Super-Resolution Using an Efficient Sub-Pixel Convolutional Neural Network. arXiv preprint arXiv:1609.05158, 2016

[8] Qi Mao, Hsin-Ying Lee, Hung-Yu Tseng, Siwei Ma, Ming-Hsuan Yang. Mode Seeking Generative Adversarial Networks for Diverse Image Synthesis. arXiv preprint arXiv:1903.05628, 2019(v6)

[9] Lars Mescheder, Andreas Geiger, Sebastian Nowozin. Which Training Methods for GANs do actually Converge?. arXiv preprint arXiv:1801.04406, 2018

[10] Ting-Chun Wang, Ming-Yu Liu, Jun-Yan Zhu, Andrew Tao, Jan Kautz, Bryan Catanzaro. High-Resolution Image Synthesis and Semantic Manipulation with Conditional GANs. arXiv preprint arXiv:1711.11585, 2018

[11] Phillip Isola, Jun-Yan Zhu, Tinghui Zhou, Alexei A. Efros. Image-to-Image Translation with Conditional Adversarial Networks. arXiv preprint arXiv:1611.07004, 2018