He estado investigando respecto a lo que me comentasteis de IplImage y CvMat deprecados en OpenCV 2.3.1 y he encontrado un artículo muy interesante que voy a traduciros en parte. Como yo programaba en C con OpenCV desconocía esta información que espero resulte útil a los usuarios de jderobot.<br>

<br>===============================================================================================<br><br><b><u>DE C A C++</u></b><br>Desde la versión 2.0 de OpenCV, en la nueva API de C++, se introdujo el tipo cv::Mat o simplemente Mat para sustituir los tipos en C IplImage y CvMat. Aunque ambas estructuras siguen siendo soportadas, se recomienda cambiar a C++. ¿Por qué?<br>

<br>Mat engloba el concepto de matrix e imagen. De hecho, son la misma cosa al final. Mat, además incluye varias características interesantes tales como un &quot;contador de referencia&quot; (reference counter) que puede ser de gran ayuda. Te libera de la gestión de la memoria.<br>

<br>Además te permite generar un código limpio.<br><br><b><u>INTRODUCIENDO MAT</u></b><br>Antes de poder emplear la interfaz de C++, debes &quot;incluir&quot; el namespace de OpenCV. Esto se realiza añadiendo la siguiente línea después de los #include<br>

<br><div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace"><span style="color:rgb(0,0,255)">using</span> <span style="color:rgb(0,0,255)">namespace</span> cv<span style="color:rgb(0,128,128)">;</span></pre>

</div></div><br>Si no incluyeras esta línea, tendrás que emplear cv:: para tener acceso a las cosas en namespace, como cv::Mat.<br><br>El nuevo tipo Mat soporta álgebra matricial de manera parecida a la empleada en Matlab:<br>

<br><pre class="cpp" style="font-family:monospace">Mat A<span style="color:rgb(0,0,128)">=</span>Mat<span style="color:rgb(0,128,0)">(</span><span style="color:rgb(0,0,221)">3</span>,<span style="color:rgb(0,0,221)">4</span>,CV_32FC1<span style="color:rgb(0,128,0)">)</span><span style="color:rgb(0,128,128)">;</span><br>

Mat B<span style="color:rgb(0,0,128)">=</span>Mat<span style="color:rgb(0,128,0)">(</span><span style="color:rgb(0,0,221)">4</span>,<span style="color:rgb(0,0,221)">3</span>,CV_32FC1<span style="color:rgb(0,128,0)">)</span><span style="color:rgb(0,128,128)">;</span><br>

...<br><span style="color:rgb(102,102,102)">//code for initialization of A and B</span><br>...<br><span style="color:rgb(0,119,136)">Mat</span> C <span style="color:rgb(0,0,128)">=</span> <span style="color:rgb(0,0,221)">2</span><span style="color:rgb(0,0,64)">*</span>A<span style="color:rgb(0,0,64)">*</span>B<span style="color:rgb(0,128,128)">;</span></pre>

<br>En este ejemplo C es una matriz de 3x3 cuyos elementos se multiplican por el escalar 2. Esta forma de escribir operaciones matriciales algebraicas es mucho más simple e intutitiva que empleando funciones tales como cvGEMM(...). Igualmente, resulta trivial calcular la inversa o traspuesta de una matriz:<br>

<br><pre class="cpp" style="font-family:monospace">Mat C <span style="color:rgb(0,0,128)">=</span> C.<span style="color:rgb(0,119,136)">inv</span><span style="color:rgb(0,128,0)">(</span><span style="color:rgb(0,128,0)">)</span><span style="color:rgb(0,128,128)">;</span> <span style="color:rgb(102,102,102)">//Now C is its own inverse matrix</span><br>

Mat D <span style="color:rgb(0,0,128)">=</span> A.<span style="color:rgb(0,119,136)">t</span><span style="color:rgb(0,128,0)">(</span><span style="color:rgb(0,128,0)">)</span><span style="color:rgb(0,128,128)">;</span> <span style="color:rgb(102,102,102)">//D is the transposed matrix of A</span></pre>

<br>Con esta pequeña introducción, quedan claros los beneficios de emplear la nueva interfaz C++.<br><br><b><u>ESTRUCTURA INTERNA</u></b><br>Mat es similar a las viejas estructuras CvMat e IplImage. El origen se encuentra arriba a la izquierda, y filas y columnas comienzan en 0.<br>

<br><u><b>DECLARACION DE LA MATRIZ</b></u><br>Una matriz puede construirse de varias formas. Es necesario definir el formato (no como en Matlab o Python). La matriz puede tener uno, dos, tres o cuatro canales.<br><br>La manera más sencilla de declarar una matriz es la siguiente:<br>

<br><pre class="cpp" style="font-family:monospace">Mat m <span style="color:rgb(0,0,128)">=</span> Mat<span style="color:rgb(0,128,0)">(</span>rows, cols, type<span style="color:rgb(0,128,0)">)</span><span style="color:rgb(0,128,128)">;</span></pre>

<br>donde rows y cols son el número de filas y columnas y type es el formato de la matriz.<br><br>Si lo que quieres crear es una imagen, existe un método más intuitivo:<br><br><pre class="cpp" style="font-family:monospace">

Mat m <span style="color:rgb(0,0,128)">=</span> Mat<span style="color:rgb(0,128,0)">(</span>Size<span style="color:rgb(0,128,0)">(</span>width,height<span style="color:rgb(0,128,0)">)</span>, type<span style="color:rgb(0,128,0)">)</span><span style="color:rgb(0,128,128)">;</span></pre>

<br>Y si lo que deseas es duplicar el tamaño de otra imagen, puedes emplear<br><br><pre class="cpp" style="font-family:monospace">Mat n <span style="color:rgb(0,0,128)">=</span> Mat<span style="color:rgb(0,128,0)">(</span>m.<span style="color:rgb(0,119,136)">size</span><span style="color:rgb(0,128,0)">(</span><span style="color:rgb(0,128,0)">)</span>, type<span style="color:rgb(0,128,0)">)</span><span style="color:rgb(0,128,128)">;</span></pre>

<br>donde type define el número de bytes asignados para cada elemento en la matriz. Las constantes que puedes emplear son idénticas para C y C++.<br><br><u><b>ACCEDIENDO A LOS ELEMENTOS</b></u><br>Acceder a cada pixel o elemento en una Matriz de un canal es trivial. Empleas el método at para acceder al valor en una posición particular (i,j)<br>

<br><pre class="cpp" style="font-family:monospace">Mat a<span style="color:rgb(0,0,128)">=</span> Mat<span style="color:rgb(0,128,0)">(</span><span style="color:rgb(0,0,221)">4</span>,<span style="color:rgb(0,0,221)">3</span>, CV_32FC1<span style="color:rgb(0,128,0)">)</span><span style="color:rgb(0,128,128)">;</span><br>

<span style="color:rgb(0,0,255)">float</span> elem_a<span style="color:rgb(0,0,128)">=</span> a.<span style="color:rgb(0,119,136)">at</span><span style="color:rgb(0,0,128)">&lt;</span><span style="color:rgb(0,0,255)">float</span><span style="color:rgb(0,0,128)">&gt;</span><span style="color:rgb(0,128,0)">(</span>i,j<span style="color:rgb(0,128,0)">)</span><span style="color:rgb(0,128,128)">;</span> <span style="color:rgb(102,102,102)">//access element aij, with i from 0 to rows-1 and j from 0 to cols-1</span></pre>

<br>En vez de utilizar la posición (i,j) puedes emplear un puntero:<br><br><pre class="cpp" style="font-family:monospace">Point p<span style="color:rgb(0,0,128)">=</span>Point<span style="color:rgb(0,128,0)">(</span>x,y<span style="color:rgb(0,128,0)">)</span><span style="color:rgb(0,128,128)">;</span><br>

<span style="color:rgb(0,0,255)">float</span> elem_a<span style="color:rgb(0,0,128)">=</span> a.<span style="color:rgb(0,119,136)">at</span><span style="color:rgb(0,0,128)">&lt;</span><span style="color:rgb(0,0,255)">float</span><span style="color:rgb(0,0,128)">&gt;</span><span style="color:rgb(0,128,0)">(</span>p<span style="color:rgb(0,128,0)">)</span><span style="color:rgb(0,128,128)">;</span> <span style="color:rgb(102,102,102)">//Warning: y ranges from 0 to rows-1 and x from 0 to cols-1</span></pre>

<br>Para acceder a los pixeles en una Matriz multidimensional las cosas se vuelven un poco más complicadas. Pero aún así resultan más sencillas que emplear los macros CV_MAT_ELEM o CV_IMAGE_ELEM. Debes utilizar el método ptr para obtener un puntero a una fila particular. Posteriormente debes emplear [] para acceder a un pixel en un determinado canal:<br>

<br><pre class="cpp" style="font-family:monospace">type elem <span style="color:rgb(0,0,128)">=</span> matrix.<span style="color:rgb(0,119,136)">ptr</span><span style="color:rgb(0,0,128)">&lt;</span>type<span style="color:rgb(0,0,128)">&gt;</span><span style="color:rgb(0,128,0)">(</span>i<span style="color:rgb(0,128,0)">)</span><span style="color:rgb(0,128,0)">[</span>N<span style="color:rgb(0,0,128)">&lt;</span>sub<span style="color:rgb(0,0,128)">&gt;</span>c<span style="color:rgb(0,0,128)">&lt;</span><span style="color:rgb(0,0,64)">/</span>sub<span style="color:rgb(0,0,128)">&gt;</span><span style="color:rgb(0,0,64)">*</span>j<span style="color:rgb(0,0,64)">+</span>c<span style="color:rgb(0,128,0)">]</span></pre>

<br>donde type es el tipo (float, int, uchar, etc...), i es la fila que buscas, N&lt;sub&gt;c el número de canales, j la columna que buscas y c el canal en el que estás interesado (varía de 0 a 3).<br><br>Este método podría utilizarse en las matrices unidimensionales, pero N&lt;sub&gt;c sería 1 y c sería 0 siempre.<br>

<b><u><br>REORGANIZANDO</u></b><br>Aquí vamos a enseñar como jugar con el número de canales y fila de la Matriz. Imaginemos que tenemos una matriz Nx1 con Nc canales y deseamos convertirla en una matriz de un canal y NxNc. Una sencilla forma de conseguirlo sería:<br>

<br><pre class="cpp" style="font-family:monospace">Mat a<span style="color:rgb(0,0,128)">=</span> Mat<span style="color:rgb(0,128,0)">(</span><span style="color:rgb(0,0,221)">4</span>,<span style="color:rgb(0,0,221)">1</span>, CV_32FC3<span style="color:rgb(0,128,0)">)</span><span style="color:rgb(0,128,128)">;</span> <span style="color:rgb(102,102,102)">//a is 4x1, 3 channels</span><br>

Mat b<span style="color:rgb(0,0,128)">=</span>a.<span style="color:rgb(0,119,136)">reshape</span><span style="color:rgb(0,128,0)">(</span><span style="color:rgb(0,0,221)">1</span><span style="color:rgb(0,128,0)">)</span><span style="color:rgb(0,128,128)">;</span> <span style="color:rgb(102,102,102)">//b is 4x3, 1 channel</span></pre>

<br>¿Dónde sería útil esto? Imaginemos que tenemos una lista de punteros:<br><br><pre class="cpp" style="font-family:monospace">vector<span style="color:rgb(0,0,128)">&lt;</span>Point3f<span style="color:rgb(0,0,128)">&gt;</span> v<span style="color:rgb(0,128,128)">;</span> <span style="color:rgb(102,102,102)">//suppose it is already full</span></pre>

<br>Supongamos que ya se encuentra llena, con los puntos:<br><br><pre>[(x0, y0, z0)]<br>[(x1, y1, z1)]<br>[(x2, y2, z2)]<br>[(x3, y3, z3)]<br>[(..., ..., ...)]</pre><br>Podemos &quot;importar&quot; esta lista a una matriz de la siguiente manera:<br>

<br><pre class="cpp" style="font-family:monospace">Mat m1<span style="color:rgb(0,0,128)">=</span>Mat<span style="color:rgb(0,128,0)">(</span>v, <span style="color:rgb(0,0,255)">true</span><span style="color:rgb(0,128,0)">)</span><span style="color:rgb(0,128,128)">;</span> <span style="color:rgb(102,102,102)">//boolean value true is necessary in order to copy data from v to m1</span></pre>

<br>Si el booleano no los especificamos a true, la matriz solamente apuntará a la lista y no sería una auténtica copia (duplicación de data en memoria).<br><br>De esta forma, m1 tiene varias filas (las mismas que v.size() ), exactamente 1 columna y 3 filas. Puedes reorganizar esta matriz a una matriz con v.size() filas, 3 columnas y un canal.<br>

<br><b><u>ALGUNAS EQUIVALENCIAS</u></b><br>Aquí teneis una equivalencia entre código en C y C++ que será útil para portar código:<br><ul><li><em>CvSize</em> -&gt; <em>Size</em></li><li><em>CvVideoCapture</em> -&gt; <em>VideoCapture</em></li>

<li><em>IplImage, CvMat</em> -&gt; <em>Mat</em></li><li><em>cvQueryFrame </em>-&gt;<em> &gt;&gt; </em>(operator)</li><li><em>cvShowImage -&gt; imshow</em></li><li><em>cvLoadImage -&gt; imread</em></li></ul><br><br><br><br>

<br><br><br><br><br><br>