GTSportのデカール画像で類似画像検索やってみた

デカール画像の類似画像検索やりたいなーと思って、ここ数日、色々弄っておりました。結論としては、Webのサービスとしてやることは諦めたものの、成果というか、こんなことは出来た、という記録は残しておこうかと。

やったこと(読み飛ばしてOK)

1月25日12:00くらい時点での全デカール画像(約72万画像)から特徴量を取得。モデルはVGG16で、重みはImageNetのものをそのまま使用。検索したい画像の特徴量を算出し、デカール画像の特徴量との距離を1個1個計算していって、近いものが類似画像だ!とする超絶力業。距離の計算は、とりあえずコサイン類似度を使用した。

デカールの画像は480×360で、それを224×224に変えて特徴量を取っているので、検索する画像もそれに倣う必要がある。やる前は、縦横比が違っても何とかならないかなーと期待していたんだが、そこまで甘くなかった模様。ある程度で構わないので、縦横比は合わせる必要がある。合わせないと全然類似度が上がらない。。。

ともかく、こんな力業で、かつ実行環境は手元の貧弱なGPU環境(GeForce GTX1650)のため、1回の検索で1時間半くらいかかる(もう少し最適化は出来そうだけど)。また、各デカール画像の特徴量をnpy形式で保存しているため、保管にも70GBくらいかかる。もしかするとAWSの超凄い環境借りることが出来れば実用に乗せることも出来るのかもしれんが、流石に、月何万何十万も出す気にはならんわ……そういうのは潤沢にお金のある公式にお任せしよう。

ということで類似画像検索してみる

①マツダの100周年ロゴ(?)

デカール検索で、少なくともGTSport上に1つあるのは分かっている。
https://www.gran-turismo.com/jp/gtsport/user/discover/search/decal/decal/1470613/7422020157576315400

色味も異なり、いきなり不得意なものをチョイスしたかも……

結果がこちら
http://gtswiki.gt-beginners.net/decal/similar/20200126225050_CsCEb.htm

素晴らしい!最上位に、欲しい画像が来た。類似度は約0.68。
全体的に、円を描いて中心に文字を書くようなロゴが、類似度の高い画像として上がってきている。ケロリンとか笑える。

②血小板ちゃん

類似画像検索をやり始める前に、画像の分類を試していたときに見つけた画像をチョイス。ネットで検索してみたところ、このデカール画像がネットに転がっている画像をベースにして作られていることが一目で分かったので、元画像を検索にかければ引っかかるだろうと踏んだ。

結果がこちら。

http://gtswiki.gt-beginners.net/decal/similar/20200126225050_7Aiuw.htm

まぁ、そりゃ引っかかるよね。類似度は0.66と0.63
アニメキャラの全身が見える立ち絵が、類似の画像として上がってきている模様。最近のアニメキャラよりも、ネロのほうが類似度が高いとかどうなってるんだろう。

③Shellのロゴ

次はShellのロゴ。黄色背景とか、デカールにはないだろうが、どうか。

結果がこちら。

http://gtswiki.gt-beginners.net/decal/similar/20200126225050_VOOQE.htm

Hellが最上位に来ちゃったよw
しかも類似度が0.688と高い。ただまぁ正しいShellの画像も類似度0.677と上位に来ているので、まぁ良しとしよう。

にしてもShellのロゴ多すぎない? Hellも多いけどw

④イカ娘

次は、目に付いた「イカ娘」。デカール画像を検索に使っても仕方ないので、ネットから拾ってきた画像を使う。全く同じものは無さそうだが、どこまで引っ掛けられるか。

http://gtswiki.gt-beginners.net/decal/similar/20200126225050_dJrJW.htm

うーん、類似度トップにイカ娘がきたが、それ以外は全く関係無いな……
類似度は0.34。なんとなくこう、斜めに構えている感じの画像が上がってきている模様。多分似た構図で、更に色味が似ているから偶然上位に来たんじゃないかと思う。

⑤DAINICHIロゴ

最後はダメ元。あの車に付いているデカールが知りたい!だけどなんの情報もねぇ!というときに使えるかどうか。そもそもそういうケースって、元々の画像もそんなに画質が良くないので、十中八九無理だろうなぁとは思うんだけど。今回検索に使った画像も、ネットに落ちてた画像から、このロゴの部分だけをくりぬいたもの。

結果がこちら。

http://gtswiki.gt-beginners.net/decal/similar/20200126225050_pv2i8.htm

いや、結果見たときにちょっと興奮した。マジで。凄くない?
正直言って引っかかるとは思わなかったよ……

感想

機械学習というのもおこがましく、単純にVGG16の重みを使って類似画像検索に転用できるか試してみただけだが、なかなか面白かった。

今回は使った画像がたまたま良かっただけかも知れないが、使えないことも無さそう。専門家がもっとマシなモデルと実装をしてくれれば、実用に乗るんじゃないかなぁ?

GTSportにおけるデカールグラデーション(後半)

※前半の記事はこちら

前半は、偉大なる先達の五番煎じくらい(しかも劣化版)みたいな記事になってしまって悔しいので、突っ込んで何かしてみよう。

修正方法・対策について

取り急ぎの対策としては、先達の記事やtwitterにある通り、同一色のグラデーションを避ければ、xlink:hrefでグラデの設定を共通化されることがなくなるので、GTSport内でも正しく表示可能なSVGが出来上がる。

たださぁ……なんでそんな訳分からん制約に制作側が引っ張られなきゃいかんの?……そうだ、xlink:hrefを使わない形に書き換えてしまえば良いんじゃね?

ということでSVG修正プログラムを作ってみた。

https://gtswiki.gt-beginners.net/decal/fix-gradation.php

手抜きも手抜き。ベータ版どころかアルファ版くらい。すみません、複雑なデカールの場合、正しく動くかわからんので、上書き保存せずに別名保存してください。変な動きをしたときに動作報告してくれると助かります。

とりあえずやったこと。SVGファイルを開くと「defs」要素があって、ここにグラデーションの設定とかが記載されている。ここでxlink:hrefを使うとグラデーションに反映されなくなる。なので、xlink:href属性が使われている要素をみつけ、hrefで指定されている要素の子要素をコピーしてきてからxlink:href属性を削除してやれば良いはず。

xlink修正前後

円形グラデーション

xlink:hrefだけだと面白くないなぁということで、円形グラデーションの補正にも挑戦。

色々見てみると、GTSportではgradientTransformが使えない模様。だから楕円形のグラデーションは使えないし、回転も出来ない。真円のグラデーションの場合はgradientTransformを使わずに表現できるために、GTSportでも使用できる。真円のグラデはこんな感じで記述される。

<radialGradient id="radialGradient1499" cx="105.08" cy="126.24" r="55.185" gradientUnits="userSpaceOnUse">

gradientTransformが使われていないことが分かる。

ただ、一度作成した真円のグラデーションの位置を変えただけでも使えなくなる。これはInkscapeの仕様なのかも知れないが、位置を変えると、

<radialGradient id="radialGradient1499" cx="105.08" cy="126.24" r="55.185" gradientTransform="translate(-27.214 -27.97)" gradientUnits="userSpaceOnUse">

みたいな感じで、gradientTransformのtranslateを使って補正しようとするので、GTSportでは使用できなくなってしまう。いやいや、cx/cyの値を補正して欲しいんですが……

ということで、gradientTransform内でtranslateを使っている要素を見つけ、cx/cyへ適用する機能を付けました。

なお、拡大縮小をすると、matrixで調整し出すので修正できなくなります。Inkscape、matrix好きすぎじゃない?

translate修正前後

やる気のある方へ

今回はお手軽に構築しましたけど、多分望ましいのは、SVGOMGの1機能としてくっつけてしまうか、InkscapeのExtensionとして実装することが最善なような気がします。自分はExtensionなんて書けんので見送りましたけど、なんでもPythonにも対応しているらしいので、やる気と技術のある方がやってください(乞食)

補足

修正するプログラム作っている途中に気付いたんだけど、GTSportのSVGレンダリングエンジンは、xlink:hrefを処理できないというか、正しくはxlink:hrefがそもそも読めていないっぽい。名前空間違うと読めないのかな?
まぁ細かい話ですけど。

補足2

線形グラデーションにしても円形グラデーションにしても、このプログラムが有効となるケースなんてほとんどない気がします。グラデが真っ黒になった!円形グラデずらしちゃった!みたいなレアケースにぶち当たったときに、ダメ元で使うくらいかなぁ。

愚痴

今回初めてSimpleXML使ったけど、使いにくくない?

GTSportにおけるデカールグラデーション(前半)

正月休みの帰省先で暇にかまけて普段やらんことをやる。ということで、今回のネタはコレ。

GTSportではSVGファイルをデカールとして取り扱える機能があるものの、コイツがなかなかに曲者で、SVG仕様に完全に準拠しているわけではない。公式サイト(オンラインマニュアル)には「SVGのバージョンが1.0、ないしは1.1であること」とあるが、あれは嘘……というか、正しくない。

こんな感じで、特にグラデーション周りで問題が起こることが多く、デカール制作者の頭を悩ます種になっているらしい。何故こんなことが起こるのか不思議で、ちょっと自分でもやってみた。

再現したのがこんな感じのSVG。

なんの変哲も無い、同一のグラデーションのかかった2つの長方形があるだけであるが、これをGTSport側で表示すると……

このように、グラデーションが死んで、真っ黒になる。何故???

実は当初、上記のような状況が全く再現せず。頭を悩ませていた。その時のものがこちら。

さっきのと全く変わらない。(よく見るとフィルの設定が先ほどとは違うのだが、これが再現しなかった理由だった)

ただこれをGTSportで表示すると正しく表示される。これの違いは何だろうか?ということで中身を比較してみる。

見づらいが……言葉にすると、問題の無いSVGファイルは、長方形とグラデーションの設定が1対1であるのに対して、問題のある方は2対2対1になっている。

と、ここでお詫びです。この事象を調べていたら、偉大なる先達が既に、しかも詳しく分析・解析されていることが分かりました。

GTSportのユーザーデカール機能でグラデーションが表示されない問題と対処法(追記あり)

なるほど、分かりやすーい! 睨んでいたとおり、「xlink:href」が問題だったんだね!

と、これで終わりだと何なので、後半に続く。正月休み明ける前に何とか公開したい……

【ManufacturerSeries】2019/20 Exhibition Series – Season 2 Rd.10 メモ

12月28日に行われた最終ラウンドはGr.4のラグナセカ

フェラーリのs-shohei_選手は最終戦を欠場。ポルシェのArrow71sr選手も、ネイションズに専念するためか欠場し、ランキング1位とランキング3位が不在となった。

1位から4位までが31pt差という大混戦の中での、注目の第一部屋。スターティンググリッドはこちら。

最終戦スターティング・グリッド

シリーズチャンピョンの可能性を残しているのはジャガーのgilles_honda_v12選手と、トヨタのDual_Wield-2選手。

gilles_honda_v12選手がシリーズチャンピョンとなるには2番手以上かつ、Dual_Wield-2選手より上位で終える必要がある。

Dual_Wield-2選手は、シリーズチャンピョンとなるには優勝するしかないという状況で、なんとポールポジションを獲得。

レース序盤はDual_Wield-2選手が先行し、Restoration1660s選手がついていく展開。gilles_honda_v12選手はAkagi_1942mi選手にぴったりとつかれ、バトルの影響かRestoration1660s選手から僅かに離されてしまう。

Dual_Wield-2選手は8周目終わりでピットイン。gilles_honda_v12選手にぴったりくっついていたAkagi_1942mi選手、V1PER-ZER0-選手、S2iRcoeN選手もそれに続いたが、Restoration1660s選手、gilles_honda_v12選手はステイアウトし、9周目終わりでピットイン。

全車ピットインを済ませた10周目では、上位勢の順位変動こそ無かったものの、gilles_honda_v12選手がAkagi_1942mi選手をやや離した状態でコース復帰を果たした。

Dual_Wield-2選手とRestoration1660s選手のにらみ合いが続くかと思われた12周目で、Restoration1660s選手がグリーンベルトに乗ってスピン。gilles_honda_v12選手がRestoration1660s選手に追いつく。gilles_honda_v12選手としてはDual_Wield-2選手に勝たないとシリーズチャンピョンになれないだけに、早めにRestoration1660s選手を抜いてDual_Wield-2選手を追いかけたいところ。

14周目。Restoration1660s選手が12周目にスピンしたところと同じ所で僅かにコースアウト。コークスクリューの手前でスピードが落ちたところをgilles_honda_v12選手が追い抜いて2番手に浮上した。

gilles_honda_v12選手がペースを上げるも、Dual_Wield-2選手は更に速いペースで逃げ続け、最終的には約6秒差を付けて優勝。4位からのシリーズチャンピョン獲得となった。

Dual_Wield-2選手のシリーズチャンピョンは約半年ぶり2回目。おめでとうございます!

最終リザルト(公式)
第一部屋
第二部屋

【NationsCup】2019/20 Exhibition Series – Season 2 Rd.10 メモ

12月28日に行われた最終ラウンドはGr.1のサルディーニャ

ランキング1位のSG_Kawakana選手は最終戦も欠場。ランキング2位のArrow71sr選手は332pt以上獲らないと1位になれないという状況はいかんともしがたく、SG_Kawakana選手が逃げ切ってシーズンチャンピョンを獲得した。

第一部屋は、kazunokota選手(3位)との接戦を制したkuro96GT選手(8位)が優勝し、297ptを獲得(97ptアップ)。前回3位から4位に順位を落としたkazunokota選手は284ptを獲得(16ptアップ)し、今回欠場したhide250sp選手を抜いて3位を奪還した。

第二部屋を制したのはRestoration1660s選手(5位)で、286pt獲得(61ptアップ)。前回7位から2つ上げて5位でシーズンを終えた。

今シーズンはSG_Kawakana選手が序盤で高ポイントをとり続け、終わってみれば前半5戦で早々にシリーズチャンピョンを決めてしまった。出場6戦全戦で300pt以上という驚異的な結果となった。
シリーズチャンピョンになったのは約1年半ぶり、4回目。PSNIDを現在の「SG_Kawakana」に変えて(今年2月に「Sengoku Gaming」に加入)からは初のシリーズチャンピョン。おめでとうございます!

最終リザルトはこちら

【ManufacturerSeries】2019/20 Exhibition Series – Season 2 Rd.9 メモ

12月25日に行われた第9戦はGr.3のスパ。ネイションズは明らかに参加者不足という感じだったが、マニュファクは活況。

第一部屋を制したのはフェラーリのs-shohei_選手(1位)。330ptを獲得して30ptアップ。前回2位だったが1位を奪取した。

第二部屋を制したのはフォードのLetoile-P908選手(93位)。今シーズン5戦目で一気に順位を上げた。最低有効ポイントが67ptであるため最終戦でも一気に順位を上げることが出来そうだ。

前回3位だったジャガーのgilles_honda_v12選手は第二部屋2番手。それでも302pt獲得で45ptアップ。トップのs-shohei_選手とは僅か1pt差の2位となった。

前回1位だったポルシェのArrow71sr選手(3位)は第一部屋4番手だったが、最低有効ポイントを上回れず、残念ながら3位に順位を落とした。

トヨタのDual_Wield-2選手(4位)は第一部屋2番手で、317pt獲得して82ptアップ。順位変動はなかったが、着実にポイントを積み重ねた。

残るは最終戦のみ。1位の s-shohei_選手と4位のDual_Wield-2選手までのポイント差は何と31pt。最終戦が熱い。最終戦は本日開催!

【NationsCup】2019/20 Exhibition Series – Season 2 Rd.9 メモ

12月25日に行われた第9戦はN300のレイクマジョーレ。クリスマスだなんて関係ねぇ!
……関係ねぇと言ったがそれは嘘だ。明らかに参加者が少ない。第一部屋優勝でも301ptしかない。

ということで第一部屋を制したのはArrow71sr選手(2位)で301ptを獲り、12ptアップ。今回も欠場したSG_Kawakana選手(1位)との差を30ptとした。とはいうものの最低有効ポイントが301ptであることを考えると、最終戦でSG_Kawakana選手に追いつくのはちょっと苦しいか。
第二部屋を制したのはn76w83選手(22位)で293ptを獲得(今シーズン5戦目のため293ptアップ)。最終戦でTOP10を目指して欲しい。

第一部屋2番手のhide250sp選手(3位)は288pt(10ptアップ)で、4位から3位に浮上した。一方で前回3位のkazunokota選手は第一部屋7位だったが総合ポイントを上げることが出来ず、4位に順位を落とした。hide250sp選手とkazunokota選手の差は僅か1pt。

Restoration1660s選手(7位)については今回、第一部屋6位で225pt(48ptアップ)。最終戦で1位・2位を目指すことは難しくなったが、第一部屋で優勝できれば3位を目指すことは可能だ。

残すはあと1戦! 12月28日(本日)開催!

【ManufacturerSeries】2019/20 Exhibition Series – Season 2 Rd.8 メモ

12月21日に行われた第8戦はGr.4の筑波サーキット

ネイションズカップと同じで欠場者が多めだが、上位勢の欠場はやや少なめ?

第一部屋を制したのはジャガーのgilles_honda_v12選手(3位)で、318pt獲得。今シーズン5戦目で、9位から3位にジャンプアップ。最低有効ポイントが257ptなので、残り2戦でトップに躍り出ることも十分あり得る。最終戦が熱そう。
第二部屋を制したのはホンダのRestoration1660s選手(10位)で297ptを獲得。こちらも今シーズン5戦目。有効ポイントが下から207pt・232ptなので、残り2戦次第ではTOP5入りが狙えるか。

ポルシェのArrow71sr選手(1位)は第一部屋で4番手となり265ptだが、最低有効ポイント303ptを上回れず、ポイント変動無し。フェラーリのs-shohei_選手(2位)も第一部屋5番手で最低有効ポイント300ptを上回れず変動無しとなった。

トヨタのDual_Wield-2選手(4位)は第一部屋2番手で305ptを獲得し、72ptアップ。メルセデスのV1PER-ZER0-選手(5位)は今回残念ながら欠場。BMWのS2iRcoeN選手(6位)は今シーズン5戦目。第一部屋で3番手となり、292ptを獲得した。

本シーズンも残り2戦。3位以下は最低有効ポイントが250pt前後以下で、順位変動が激しそう。

【NationsCup】2019/20 Exhibition Series – Season 2 Rd.8 メモ

12月21日に行われた第8戦はワンメイクのドラゴントレイル・ガーデンズ

そろそろポイントが出そろってきたことによる影響か、今回は欠場の上位プレイヤーが多く、上位10名中5名欠場。全体でも参加者が752名しかいないという第8戦となった。

第一部屋はAkagi_1942mi選手(174位)がトップで304ptを獲得。Akagi_1942mi選手は10月に行われたワールドツアー ネイションズカップで世界一を獲得したトップ選手だが、今シーズンは2戦目。残り2戦全部参加しても規定ラウンド数に満たないため、スポット的に参加するのみか。
第二部屋はEDGE–RS選手(97位)が制して274pt獲得となった。EDGE–RS選手は今シーズン3戦目。あと2戦とも出れば規定ラウンド数に達する。2戦の結果次第ではTOP10に食い込めるか。

そのほか、上位勢を見ると、kazunokota選手(3位)が第一部屋で2番手を獲り291pt獲得。今シーズン5戦目ということで、一気に3位に上がってきた。hide250sp選手(4位)は第一部屋3番手となり、278ptを獲得(2ptアップ)
Restoration1660s選手(7位)も今シーズン5戦目。最低有効ポイントが今回獲得した177ptであるため、残り2戦次第でTOP3に食い込んでくることはあり得る。

2019年最後のシーズンである本シーズンも残り2戦。トップはSG_Kawakana選手が独走という感じだが、3位以下はかなり混戦模様。

【ManufacturerSeries】2019/20 Exhibition Series – Season 2 Rd.7 メモ

12月14日に行われた第7戦はGr.3のレイクマジョーレ

第一部屋はポルシェのArrow71sr選手(1位)が制し、342pt獲得(48ptアップ)。第二部屋はアウディのkazunokota選手(5位)が制し、322ptを獲得した(322ptアップ)。

フェラーリのs-shohei_選手(2位)は第一部屋で4番手。300ptを獲得し、93ptアップ。Arrow71sr選手を抜くことは出来なかったが、差はたったの17pt。最低有効ポイントもArrow71sr選手が303pt、s-shohei_選手が300ptと、かなり激しい混戦模様。残り3戦で、如何に第一部屋上位を取れるかの勝負に。

前回記事で注目としていたメルセデスのV1PER-ZER0-選手(3位)は第二部屋5番手で268ptを獲得(268ptアップ)。3位に躍り出た。トヨタのDual_Wield-2選手(4位)は第一部屋2番手で328ptを獲得し(124ptアップ)、着実にポイントを重ねている。

ジャガーのgilles_honda_v12選手(9位)だが、今回は第一部屋7番手で257ptを獲得。トップとの差は351ptだが、これでもまだ有効ラウンドが規定に1足らない状態。例えば残りの3戦で300pt以上を2回とればトップに追いつく。ラストスパートに期待したい。