Visual StudioでC ++コヌドをデバッグしながらOpenCVむメヌゞを衚瀺する





C ++で画像凊理甚のコヌドを蚘述する堎合、おそらく玠晎らしいOpenCVラむブラリを䜿甚しおいるでしょう。 コヌドをデバッグする過皋で、画像を頻繁に芋たいず思っおいるこずでしょう。 このために、 imshowやimwriteなどの䟿利な機胜を䜿甚できたす。 ただし、これには゜ヌスコヌドの倉曎が必芁であり、デバッグ䞭の最新のIDEでは、倉数の倀をその堎で監芖できたす。 同じ画像を芋るのは玠晎らしいでしょうか



Visual StudioをIDEずしお䜿甚する堎合、 .NETを䜿甚 するず 、この点ですべおが 簡単になるこずが わかり たす 。 ただし、OpenCVに぀いお話しおいるのは、ネむティブC ++のみであり、ハヌドコアのみです。 この蚘事では、デバッグの過皋でVisual Studioに画像を衚瀺させ、既補の゜リュヌションぞのリンクを提䟛する方法を説明したす。 たた、Visual Studioをカスタマむズする方法に぀いおも簡単に説明したす。



はじめに



既補の゜リュヌションを䜿甚したい堎合は、すぐにリンクを提䟛したす





原則ずしおVisual Studioをカスタマむズできるツヌルに぀いお簡単に説明し、そのうちの1぀による゜リュヌションの実装に぀いお詳しく説明したす。 すべおの実隓はVisual Studio 2010で実行され、完成した゜リュヌションはVisual Studio 2005、2008、2010、2012でテストされたした理論的には2003幎に動䜜するはずです。



解決策を芋぀ける



OpenCVを䜿甚しおむメヌゞを操䜜するためにC ++コヌドをデバッグする必芁があるずき、すぐにデバッグ䞭にそれらを盎接監芖できるようにしたいず考えたした。 私は喜んでGoogleに乗り蟌み、既補の゜リュヌションを探し始めたした。 そしお...私は䜕も芋぀かりたせんでした。 OpenCVむメヌゞの堎合も、䞀般的なネむティブC ++コヌドからのレンダリングの堎合もありたせん。 原則ずしお、ネむティブコヌドデバッガヌをこのように拡匵するこずはできないず、 信頌できる居䜏者が私に蚀ったこずを 䞀般に尋ねたした 。 その瞬間、私は自転車がただ発明されおいないず確信しおいたした。



Visual Studioカスタマむズ機胜



ビゞュアラむザヌに適したツヌルを遞択するには、Visual Studioを拡匵できる䞀般的な偎面を少なくずもおおよそ想像する必芁がありたす。 たず、2぀の抂念を知る必芁がありたす。





以䞋は、Visual Studioのカスタマむズに䜿甚される゚ンティティのリストです。 リストは特定のタスクを考慮しおコンパむルされおいるため、完党であるずは䞻匵しおいたせん。





ビゞュアラむザヌはたさにあなたが必芁ずするもののようです。 しかし、ここに問題がありたす-それらはマネヌゞC ++でのみ動䜜したす。 最初の3぀のオプションマクロ、远加、および拡匵は、 Debuggerオブゞェクトの助けを借りおのみ、デバッグされたプロセスのメモリにアクセスできたす。 ただし、䞡方ずも䜕らかの圢で結果を制限されたサむズの行の圢匏で返したす。 もちろん、画像の内容をバラバラにしおバむナリ圢匏に戻すこずもできたすが、どういうわけか非垞に曲がっおいたす。



autoexp.datずいう魔法のファむルもありたす。 Visual Studioず共にむンストヌルされ、通垞は



:\Program Files (x86)\Microsoft Visual Studio <vs_version>\Common7\Packages\Debugger\autoexp.dat
      
      





ネむティブC ++コヌドのデバッグ時に倉数の内容が衚瀺されるルヌルを説明しおいたす。 たずえば、std :: vectorコンテナの内容を右偎ではなく巊偎に芋せるようにするのは、圌です。







そしお、ここに圌のやり方がありたす



autoexp.datのstd :: vector出力ルヌル
 ; ------------------------------------------------- -----------------------------
 ;  std :: <vector>からのベクトル
 ; ------------------------------------------------- -----------------------------
 ; ベクトルは「[<size>]<elements>」でプレビュヌされたす。
 ;  [size]および[capacity]の子があり、その埌にその芁玠が続きたす。
 ; 他のコンテナはその䟋に埓いたす。
 std :: vector <*> {
	プレビュヌ
		 
			 「[」、
			 $ e._Mylast-$ e._Myfirst、
			 "]"、
			 #array
				 expr$ e._Myfirst [$ i]、
				サむズ$ e._Mylast-$ e._Myfirst
			 、
			 「」
		 
	 

	子
		 
			 [サむズ]$ e._Mylast-$ e._Myfirst、
			 [容量]$ e._Myend-$ e._Myfirst、
			 #array
				 expr$ e._Myfirst [$ i]、
				サむズ$ e._Mylast-$ e._Myfirst
			 
		 
	 
 }
 std :: _ Vector_iterator <*> | std :: _ Vector_const_iterator <*> {
	プレビュヌ
		 * $ e._Ptr
	 

	子
		 [ptr]$ e._Ptr
	 
 }


これは、文曞化が䞍十分な叀い技術です。 Visual C ++ 6.0以降でサポヌトされおいたす。 小さな䜿甚ガむドはこちらです。 しかし、デバッグされたプロセスのメモリぞの通垞のアクセスを可胜にするのは、ロシア民䞻䞻矩の父を救うのは圌女であるこずが刀明したした。 さらに、耇雑なマルチレベル構造を頻繁に䜿甚する堎合たずえば、 CGALを䜿甚しおゞオメトリを怜蚎する堎合、このファむルに手動で远加されたいく぀かのルヌルにより、人生が倧幅に簡玠化されたす。



autoexp.datファむルの構文を䜿甚するず、たずえばアドレス挔算などの匏を蚘述するだけでなく、䞀般にサヌドパヌティのコヌドを呌び出すこずができたす これは、特別な$ ADDINコンストラクトを䜿甚しお行われたす。 最高のものがない堎合、このツヌルをビゞュアラむザヌに䜿甚したした。



Expression Evaluatorアドむン゜リュヌション



autoexp.datファむルのラむブラリを䜜成するための小さなガむドは、MSDNで利甚できたす 。 ラむブラリ関数を呌び出すには、.dllファむルぞのパスず呌び出される関数の名前を指定するだけです。



 cv::Mat=$ADDIN(NativeViewer.dll,CvMatViewer)
      
      





dll内の関数のプロトタむプは次のずおりです。



 HRESULT WINAPI CvMatViewer(DWORD dwAddress, DEBUGHELPER* pHelper, int nBase, BOOL bUniStrings, char* pResult, size_t max, DWORD reserved)
      
      





pHelper匕数は、デバッグプロセスのメモリにアクセスする機胜を提䟛し、デバッガヌに衚瀺されるオブゞェクトのアドレスを返すDEBUGHELPER構造䜓ぞのポむンタヌを枡したす。



DEBUGHELPER構造コヌド
 typedef struct tagDEBUGHELPER { DWORD dwVersion; HRESULT (WINAPI *ReadDebuggeeMemory)( struct tagDEBUGHELPER *pThis, DWORD dwAddr, DWORD nWant, VOID* pWhere, DWORD *nGot ); // from here only when dwVersion >= 0x20000 DWORDLONG (WINAPI *GetRealAddress)( struct tagDEBUGHELPER *pThis ); HRESULT (WINAPI *ReadDebuggeeMemoryEx)( struct tagDEBUGHELPER *pThis, DWORDLONG qwAddr, DWORD nWant, VOID* pWhere, DWORD *nGot ); int (WINAPI *GetProcessorType)( struct tagDEBUGHELPER *pThis ); } DEBUGHELPER;
      
      





pResultでは、デバッガヌによっお衚瀺される行を保存する必芁がありたす。 理論的には、これがこの関数が行うべきこずのすべおです。 しかし、誰が私たちを止めるでしょうか すでにメモリにアクセスしおいたす。 そしお、圌らが蚀うように、技術の問題。



画像コンテンツを抜出する


珟圚利甚可胜なタむプ情報は、その名前cv :: Matのみです。 ぀たり、特定のバヌゞョンのOpenCVの.hファむルに基づいおフィヌルドのアドレスを蚈算する必芁がありたす。 しかし、将来、この基本的なクラスのフィヌルド構造が倉わるずは思いたせん。



メモリからオブゞェクトを読み取る方法、アドレスを知っおいる、説明付きの.hファむルを持っおいるなど、技術的な問題に぀いおは觊れたせん。゜ヌスはSourceForgeで入手できたす。 pHelper構造により、デバッグされおいるプロセスのビット数を知るこずができるこずに泚意しおください。 そしお、これは、ポむンタヌのサむズが4バむトたたは8バむトである可胜性があるこずを考慮する必芁があるこずを意味したす。 cv :: Matオブゞェクトのすべおのフィヌルドを読み取るず、同じ方法で画像のコンテンツを読み取るこずができたす。 そのアドレスはデヌタフィヌルドにありたす。



衚瀺文字列のフォヌマット


さお、ただここにいるので、デバッガヌによっお衚瀺される行を実際にフォヌマットしたしょう。 そしお、暙準的な内郚はあたりきれいに芋えたせん。 このようなこずをしたしょう







画像レンダリング


実際、私たち党員がここにいお集たったもののために。 これで画像ができたので、.NETを䜿甚しおレンダリングできたす。 叀き良きWindowsフォヌムずCを䜿甚したした。 芖芚化のためのダむアログを含むフォヌムは別のアセンブリにあり、System.Bitmapオブゞェクトがコンストラクタヌで枡されたす。 それを構築するために、元のdllは/ clrスむッチを䜿甚しお.NETサポヌトで構築されたした。 これにより、C ++ / CLIを䜿甚できたした。



ネむティブラむブラリから.NETダむアログを呌び出すのは難しく、自分でAppDomainを䜜成する必芁があるのではないかず心配したした。 ただし、スタゞオ自䜓は.NETアプリケヌションなので、䜕もする必芁はありたせんでした。 すべおがすぐに機胜したので、私は詳现に理解したせんでした。 ApartmentState :: STAパラメヌタヌを䜿甚しお別のスレッドからダむアログを衚瀺する必芁があるこずに泚意しおください。そうしないず、たずえば、むメヌゞをディスクに保存するために远加ダむアログを開くずきに問題が発生したす。



ここで、遞択したアプロヌチの䞻な欠点に盎面しおいたす-りォッチりィンドりぞの出力をフォヌマットするずきに関数が呌び出されるか、ナヌザヌが゚ディタヌで倉数の䞊にマりスを眮いたずきに関数が呌び出されるかどうかを刀断できたせん。 りィンドりに画像を衚瀺するたびに䜿甚するこずはできたせん。



私が思い付く唯䞀の適切な解決策はこれですりィンドりは特別なキヌが抌された堎合にのみ衚瀺されたす。 ぀たり、Ctrl。 それ以倖の堎合、出力文字列はフォヌマットのみです。 したがっお、デバッグ䞭に画像を衚瀺するには、Ctrlキヌを抌しながら゚ディタヌで倉数をポむントするず、りィンドりがポップアップ衚瀺されたす。 曲がった、はい、しかし実際にはそれは䜿甚するのに非垞に䟿利であるこずが刀明したした。







画像のあるりィンドりが衚瀺されるず、Visual Studioプロセスがブロックされたす。 正匏には、デバッガヌの出力をフォヌマットする機胜にありたす。 これは䞍快ですが、これには臎呜的なこずは䜕もありたせん。 同時に画像を勉匷し、スタゞオずやり取りし続ける必芁はありたせん。



Visual Studioの統合


解決策がありたすが、今はパッケヌゞ化する必芁がありたす。 これには既存の拡匵メカニズムが最適です。 最初はVisual Studio 2010に重点を眮いおいたため、より汎甚的なアドオンではなく、より新しい拡匵機胜を遞択したした。



拡匵機胜の䜜成に぀いおは十分に文曞化されおいたす 。 たず、 Visual Studio SDK 2010たたは2012甚が必芁です。 むンストヌル埌、新しいVisual Cプロゞェクト→拡匵性→Visual Studioパッケヌゞを䜜成できたす。 これにより、拡匵機胜に関する情報を芁求するりィザヌドが起動したす。







デフォルトでは、圌はメニュヌコマンドメニュヌコマンド、ツヌルバヌツヌルりィンドりの䜜成、たたぱディタヌの調敎カスタム゚ディタヌを提䟛しおいたす。 これは必芁ありたせん。 実際、拡匵子はVSIXファむルであり、これは単なるzipアヌカむブです。 Visual Studioにむンストヌルするず、ナヌザヌディレクトリの1぀に解凍されたす詳现はこちら 。 MEFず察話するラむブラリが存圚する堎合もありたすが、他のファむルが存圚する堎合もありたす。 たずえば、Expression Evaluatorアドむンを備えたラむブラリです。



芖芚化のためのフォヌムを含むアセンブリの読み蟌みには小さな問題がありたす。 Referencesに远加するず、実行可胜ファむルdevenv.exeのあるディレクトリずGACで怜玢が行われたす。 これは拡匵子を持぀ディレクトリにあるため、 Assembly :: LoadFrom関数を䜿甚しお手動で読み蟌む必芁がありたす 。 その埌、ダむアログが䜜成され、 反射法を䜿甚しお衚瀺されたす。



メニュヌの[ツヌル]→[オプション]から倉曎できる蚭定を行いたいず思いたした。 これは、MSDNのマニュアルに詳しく説明されおいたす 。 暙準のキヌ/倀グリッド、および任意の圢状を䜜成する方法に぀いお説明したす。











autoexp.datファむルに行を自動的に远加するには、最埌のフォヌムが必芁です。 残念ながら、VSIX拡匵機胜のむンストヌル時にコマンドを実行するこずはできたせんサポヌトされおいる機胜の衚を参照 。 したがっお、拡匵機胜をむンストヌルした埌、ナヌザヌはこのペヌゞに移動しお[゚ントリの远加]ボタンをクリックする必芁がありたす。



autoexp.datファむルを芋぀けるには、Visual Studioがむンストヌルされおいる堎所を知る必芁がありたす。 レゞストリで確認できたすが、DTEを䜿甚しお自分で確認するこずをお勧めしたす。 拡匵からDTEオブゞェクトを取埗する方法はここに曞かれおいたす 。 FullNameプロパティは、devenv.exeファむルぞのフルパスを返したす。



Visual Studio 2012には驚きたした。぀いに、廃止されたautoexp.datファむルの眮き換えであるNATVISテクノロゞヌが提案されたした。 ドキュメント自䜓はただありたせんが、Microsoftブログに適切な説明がありたす。 そしお、埌方互換性の栄光により、同じメカニズムを介しおサヌドパヌティのコヌドを呌び出す可胜性が残りたしたが、今ではLegacyAddin匕数で瀺されおいたす。 私が芋぀けた唯䞀の説明はこの質問ぞの答えにありたす。 この技術は最近発衚されたず思われたす。



NATIVSの倧きな利点は、芖芚化ルヌルnatvis拡匵子を持぀個別のXMLファむルずしお蚭蚈されおいるが異なるディレクトリに分散できるこずです。 カスタムを含め、拡匵機胜に含めるこずができたす。 これを行うには、拡匵機胜を構築するずきに.nativsファむルをAssetsに远加するだけです。 したがっお、Visual Studio 2012のNativeViewer拡匵機胜には統合ペヌゞがなく、そのたた䜿甚できたす。



VSIX拡匵機胜のデバッグに぀いお。 非垞に䟿利に実装されるこずがわかりたした。 VSIXプロゞェクトを実行するず、Visual Studioの実隓コピヌが開き、珟圚のバヌゞョンの拡匵機胜がむンストヌルされたす。 デバッグは正垞に機胜し、゜ヌススタゞオでdllのネむティブコヌドをデバッグするこずができたした。これは実隓コピヌによっおロヌドされたした。



拡匵機胜はVisual Studio 2010にのみ登堎したため、以前のバヌゞョンでは手動でむンストヌルする必芁がありたす。 マニュアルを曞きたしたが、良い方法で、もちろん、むンストヌラヌを䜜成する必芁がありたす。



おわりに



この蚘事では、開発プロセス䞭に遭遇した問題の解決策に぀いお説明したした。 䞀般的な開発ツヌル向けであるこずは泚目に倀したすが、奇劙なこずに、類䌌物はありたせん。 たあ、少なくずも私はそのようなものを芋぀けるこずができたせんでした。



この蚘事では、技術的な詳现にあたり泚意を向けず、豊富なリンクでこれを補おうずしたした。 興味がある人は、゜ヌスコヌドを芋お質問をするこずができたす。 ある偎面が䞀般に十分に興味深いず思われる堎合は、より詳现な蚘事を曞くこずができたす。



この拡匵機胜が倚くの人に圹立぀こずを本圓に願っおいたす。 誰かがプロゞェクトの開発に参加したい堎合は、曞いおください。



参照資料








All Articles