VisualStudio 2012のデバッグ中にOpenCVのcv::Matの中身を確認する方法
私はVisualStudioの拡張機能であるImageWatchを使っています。
ImageWatchはOpenCVで読み込んだ画像などをデバッグ中に可視化する事ができます。
ImageWatchはとても便利なのですが、大きなCV_64Fの二次元のcv::Mat型などの中身を見るのには不便です。
以下のようにコマンドウィンドウを用いる方法もありますが、
>? ((double*)mat.data)[mat.rows*4+2]
ある要素(上の場合は(4,2))を見たいだけならいいのですが、
内容をずらっと見たい時に不便ですし、何より入力するのが面倒です。
今回はImageWatchのnatvisを改造して、この問題に対処したいと思います。
natvisとは
公式ページによると、
ということみたいです。
ImageWatchを入れると、cv::Matのデバッグ表示が変わるのはこのためです。
今回はImageWatchのnatvisを改造してcv::Matの中身を一緒に表示させるようにします。
natvisの改造
ImageWatchのOpenCV関連のnatvisファイルはデフォルトで、
C:\Users\username\AppData\Local\Microsoft\VisualStudio\11.0\Extensions\謎文字列?\ImageWatchOpenCV.natvis
に保存されています。
この中の
※念のためバックアップは取ってください。
・・・ <Type Name="cv::Mat"> <AlternativeType Name="cv::Mat_<*>"/> <DisplayString Condition="(flags&7)==0">{{UINT8, {((flags&0xfff)>>3)+1} x {cols} x {rows}}}</DisplayString> <DisplayString Condition="(flags&7)==1">{{INT8, {((flags&0xfff)>>3)+1} x {cols} x {rows}}}</DisplayString> <DisplayString Condition="(flags&7)==2">{{UINT16, {((flags&0xfff)>>3)+1} x {cols} x {rows}}}</DisplayString> <DisplayString Condition="(flags&7)==3">{{INT16, {((flags&0xfff)>>3)+1} x {cols} x {rows}}}</DisplayString> <DisplayString Condition="(flags&7)==4">{{INT32, {((flags&0xfff)>>3)+1} x {cols} x {rows}}}</DisplayString> <DisplayString Condition="(flags&7)==5">{{FLOAT32, {((flags&0xfff)>>3)+1} x {cols} x {rows}}}</DisplayString> <DisplayString Condition="(flags&7)==6">{{FLOAT64, {((flags&0xfff)>>3)+1} x {cols} x {rows}}}</DisplayString> <DisplayString Condition="(flags&7)==7">{{USER, {((flags&0xfff)>>3)+1} x {cols} x {rows}}}</DisplayString> <Expand> <Synthetic Name="[type]" Condition="(flags&7)==0"> <DisplayString>UINT8</DisplayString> </Synthetic> <Synthetic Name="[type]" Condition="(flags&7)==1"> <DisplayString>INT8</DisplayString> </Synthetic> <Synthetic Name="[type]" Condition="(flags&7)==2"> <DisplayString>UINT16</DisplayString> </Synthetic> <Synthetic Name="[type]" Condition="(flags&7)==3"> <DisplayString>INT16</DisplayString> </Synthetic> <Synthetic Name="[type]" Condition="(flags&7)==4"> <DisplayString>INT32</DisplayString> </Synthetic> <Synthetic Name="[type]" Condition="(flags&7)==5"> <DisplayString>FLOAT32</DisplayString> </Synthetic> <Synthetic Name="[type]" Condition="(flags&7)==6"> <DisplayString>FLOAT64</DisplayString> </Synthetic> <Item Name="[channels]">((flags&0xfff)>>3)+1</Item> <Item Name="[width]">cols</Item> <Item Name="[height]">rows</Item> <Synthetic Name="[detail]" Condition="dims == 2 && (flags & 7) == 0 && (flags & 16384) == 16384"><!-- 8U --> <Expand> <Synthetic Name="row[0]" Condition="rows > 0"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((unsigned char*)data)[$i+0*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[1]" Condition="rows > 1"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((unsigned char*)data)[$i+1*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[2]" Condition="rows > 2"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((unsigned char*)data)[$i+2*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[3]" Condition="rows > 3 && rows < 7"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((unsigned char*)data)[$i+3*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[4]" Condition="rows > 4 && rows < 7"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((unsigned char*)data)[$i+4*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[5]" Condition="rows > 5 && rows < 7"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((unsigned char*)data)[$i+5*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="..." Condition="rows > 6"><DisplayString> </DisplayString></Synthetic> <Synthetic Name="row[-3]" Condition="rows > 6"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((unsigned char*)data)[$i+(rows-3)*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[-2]" Condition="rows > 6"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((unsigned char*)data)[$i+(rows-2)*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[-1]" Condition="rows > 6"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((unsigned char*)data)[$i+(rows-1)*cols])</ValueNode></IndexListItems></Expand></Synthetic> </Expand> </Synthetic> <Synthetic Name="[detail]" Condition="dims == 2 && (flags & 7) == 1 && (flags & 16384) == 16384"><!-- 8S --> <Expand> <Synthetic Name="row[0]" Condition="rows > 0"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((char*)data)[$i+0*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[1]" Condition="rows > 1"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((char*)data)[$i+1*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[2]" Condition="rows > 2"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((char*)data)[$i+2*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[3]" Condition="rows > 3 && rows < 7"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((char*)data)[$i+3*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[4]" Condition="rows > 4 && rows < 7"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((char*)data)[$i+4*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[5]" Condition="rows > 5 && rows < 7"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((char*)data)[$i+5*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="..." Condition="rows > 6"><DisplayString> </DisplayString></Synthetic> <Synthetic Name="row[-3]" Condition="rows > 6"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((char*)data)[$i+(rows-3)*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[-2]" Condition="rows > 6"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((char*)data)[$i+(rows-2)*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[-1]" Condition="rows > 6"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((char*)data)[$i+(rows-1)*cols])</ValueNode></IndexListItems></Expand></Synthetic> </Expand> </Synthetic> <Synthetic Name="[detail]" Condition="dims == 2 && (flags & 7) == 2 && (flags & 16384) == 16384"><!-- 16U --> <Expand> <Synthetic Name="row[0]" Condition="rows > 0"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((unsigned short*)data)[$i+0*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[1]" Condition="rows > 1"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((unsigned short*)data)[$i+1*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[2]" Condition="rows > 2"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((unsigned short*)data)[$i+2*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[3]" Condition="rows > 3 && rows < 7"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((unsigned short*)data)[$i+3*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[4]" Condition="rows > 4 && rows < 7"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((unsigned short*)data)[$i+4*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[5]" Condition="rows > 5 && rows < 7"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((unsigned short*)data)[$i+5*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="..." Condition="rows > 6"><DisplayString> </DisplayString></Synthetic> <Synthetic Name="row[-3]" Condition="rows > 6"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((unsigned short*)data)[$i+(rows-3)*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[-2]" Condition="rows > 6"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((unsigned short*)data)[$i+(rows-2)*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[-1]" Condition="rows > 6"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((unsigned short*)data)[$i+(rows-1)*cols])</ValueNode></IndexListItems></Expand></Synthetic> </Expand> </Synthetic> <Synthetic Name="[detail]" Condition="dims == 2 && (flags & 7) == 3 && (flags & 16384) == 16384"><!-- 16S --> <Expand> <Synthetic Name="row[0]" Condition="rows > 0"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((short*)data)[$i+0*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[1]" Condition="rows > 1"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((short*)data)[$i+1*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[2]" Condition="rows > 2"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((short*)data)[$i+2*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[3]" Condition="rows > 3 && rows < 7"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((short*)data)[$i+3*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[4]" Condition="rows > 4 && rows < 7"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((short*)data)[$i+4*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[5]" Condition="rows > 5 && rows < 7"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((short*)data)[$i+5*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="..." Condition="rows > 6"><DisplayString> </DisplayString></Synthetic> <Synthetic Name="row[-3]" Condition="rows > 6"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((short*)data)[$i+(rows-3)*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[-2]" Condition="rows > 6"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((short*)data)[$i+(rows-2)*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[-1]" Condition="rows > 6"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((short*)data)[$i+(rows-1)*cols])</ValueNode></IndexListItems></Expand></Synthetic> </Expand> </Synthetic> <Synthetic Name="[detail]" Condition="dims == 2 && (flags & 7) == 4 && (flags & 16384) == 16384"><!-- 32S --> <Expand> <Synthetic Name="row[0]" Condition="rows > 0"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((int*)data)[$i+0*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[1]" Condition="rows > 1"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((int*)data)[$i+1*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[2]" Condition="rows > 2"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((int*)data)[$i+2*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[3]" Condition="rows > 3 && rows < 7"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((int*)data)[$i+3*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[4]" Condition="rows > 4 && rows < 7"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((int*)data)[$i+4*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[5]" Condition="rows > 5 && rows < 7"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((int*)data)[$i+5*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="..." Condition="rows > 6"><DisplayString> </DisplayString></Synthetic> <Synthetic Name="row[-3]" Condition="rows > 6"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((int*)data)[$i+(rows-3)*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[-2]" Condition="rows > 6"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((int*)data)[$i+(rows-2)*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[-1]" Condition="rows > 6"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((int*)data)[$i+(rows-1)*cols])</ValueNode></IndexListItems></Expand></Synthetic> </Expand> </Synthetic> <Synthetic Name="[detail]" Condition="dims == 2 && (flags & 7) == 5 && (flags & 16384) == 16384"><!-- 32F --> <Expand> <Synthetic Name="row[0]" Condition="rows > 0"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((float*)data)[$i+0*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[1]" Condition="rows > 1"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((float*)data)[$i+1*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[2]" Condition="rows > 2"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((float*)data)[$i+2*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[3]" Condition="rows > 3 && rows < 7"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((float*)data)[$i+3*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[4]" Condition="rows > 4 && rows < 7"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((float*)data)[$i+4*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[5]" Condition="rows > 5 && rows < 7"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((float*)data)[$i+5*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="..." Condition="rows > 6"><DisplayString> </DisplayString></Synthetic> <Synthetic Name="row[-3]" Condition="rows > 6"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((float*)data)[$i+(rows-3)*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[-2]" Condition="rows > 6"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((float*)data)[$i+(rows-2)*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[-1]" Condition="rows > 6"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((float*)data)[$i+(rows-1)*cols])</ValueNode></IndexListItems></Expand></Synthetic> </Expand> </Synthetic> <Synthetic Name="[detail]" Condition="dims == 2 && (flags & 7) == 6 && (flags & 16384) == 16384"><!-- 64F --> <Expand> <Synthetic Name="row[0]" Condition="rows > 0"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((double*)data)[$i+0*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[1]" Condition="rows > 1"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((double*)data)[$i+1*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[2]" Condition="rows > 2"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((double*)data)[$i+2*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[3]" Condition="rows > 3 && rows < 7"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((double*)data)[$i+3*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[4]" Condition="rows > 4 && rows < 7"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((double*)data)[$i+4*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[5]" Condition="rows > 5 && rows < 7"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((double*)data)[$i+5*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="..." Condition="rows > 6"><DisplayString> </DisplayString></Synthetic> <Synthetic Name="row[-3]" Condition="rows > 6"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((double*)data)[$i+(rows-3)*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[-2]" Condition="rows > 6"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((double*)data)[$i+(rows-2)*cols])</ValueNode></IndexListItems></Expand></Synthetic> <Synthetic Name="row[-1]" Condition="rows > 6"> <Expand><IndexListItems><Size>cols</Size><ValueNode>(&((double*)data)[$i+(rows-1)*cols])</ValueNode></IndexListItems></Expand></Synthetic> </Expand> </Synthetic> <Item Name="[stride]">step.p[0]</Item> <Item Name="[continous]">(flags & 16384) == 16384</Item> <Item Name="[submatrix]">(flags & 32678) == 32678</Item> <Item Name="[refcount]">refcount</Item> <Item Name="[data]">data</Item> </Expand> </Type> ・・・
natvisファイルではループ等は使えないため、ゴリゴリ書いています。
今回はcv::Matの中身を6行(上3行、下3行)を見るためのnatvisを(ゴリゴリ)書きました。
他にも色々と可視化したほうがいいような気もしますが、
私個人としてはcv::Matさえ確認できればそれで良いのでこのままです。
必要なら自分で足してください。
これを適用すると、こんな感じになります。
大きな行列の中身を見るときに便利になりました!
めでたしめでたし。