引用块内容http://lib.csdn.net/article/opencv/42000
http://lib.csdn.net/article/opencv/61257
最近看完了浅墨的opencv入门,感觉有些地方理解的不是很深,尤其是对形态学的操作。
在一次实验组会议报告上,导师建议我先去了解一下二值细化骨架提取方法,在查阅了很多资料后,完全不知道怎么弄。毕竟编程能力差的孩子。然后就看了一些代码,也是似懂非懂,运行起来也是各种问题。解决不了,就看了细化原理,原来也是对像素的操作。只不过是一种迭代形式的,毕竟计算机最擅长的就是迭代嘛!
二值细化也就是用模板对图像进行卷积操作(大概是这个意思吧,姑且这么理解),然后我就想到了腐蚀操作,了解了腐蚀操作原理,应该也就能理解二值细化骨架提取操作了吧。没想到,平常用的腐蚀内核三种形式,Rect,Cross,Ellipse,其实可以自己设计内核的。而且不同的内核去形式去卷积图像,得到的效果图也不一样。
对像素的两种操作方式:at的操作很容易定位,就跟操作一个普通的二维数组一样,如img.at(i, j)[0] = 255;//对于蓝色通道进行操作;
另一种:通过指针,uchar *pointer = img.ptr(i)
for(int j = 0;j< cols;j++)
{
//pointer[j] = 255;//对蓝色通道进行操作
//pointer[j+1] = 255;//对绿色通道进行操作
pointer[j+2] = 255;//对红色通道进行操作
}
图像的数据以及图像在Mat中的存放格式的,就是我们上面那个彩色图像的存放示意图中的格式,这里把彩色图像中的一个像素点分成三份,每一份都是uchar类型,因此我们这里不需要使用Vec3b数据类型。把彩色图像看成一个rows * (cols * channels)的二维数组进行操作,其中的每个元素的类型都是uchar类型。这里需要注意的是j += 3是因为我们按照一个像素点进行操作,而一个像素点在这里面又被分成三份,因此需要j += 3,如果是灰度图像则直接j++即可
熟悉了几个变量,Mat类中用的比较少的几个变量和函数,step1(),step[],size,elemSize和elemSize1。
step1(i)表示的是Mat中的每一维的通道数;
step[i]表示的是Mat中的每一维的大小,以字节为单位;
size[i]表示的是Mat中元素的个数;
elemSize()表示的是每个元素的大小 ,以字节为单位;
elemSize1()表示的一个元素中每个通道的大小,以字节为单位。
而step[i]表示的是每一维中的大小,以字节计数,在彩色图像中一个像素分为三块,每一块为一个字节,因此step[0] = 2250 ,step[1] = 3
size表示的是每一维元素的大小,注意这里是元素,即像素,size[0]表示rows,size[1]表示cols
elemSize表示的是每个元素的大小,以字节计,一个元素分为三块,一块是1字节,因此为3(彩色图像)
elemSize1表示的是一个元素的每个通道的大小,因此为1
http://lib.csdn.net/article/opencv/33141
看完这篇文章,终于解决了我很多困惑,加强对Mat的结构的理解。同是有巩固了类的概念。
Mat是一个类,它由两个数据部分组成:矩阵头和一个指向存储所有像素值的矩阵的指针。其中矩阵头包含了矩阵的尺寸、存储方法、储存地址等信息,由此可以看出矩阵头所占的内存很小,而具体储存所有像素值的矩阵则非常大。举个例子,比如一个班级,矩阵头就相当于储存了班级里有多少人、男女比多少、平均身高、平均体重等信息,而矩阵就储存了班级中所有同学的所有基本信息,每一个同学就相当于是一个像素点,而每个像素点的颜色信息、深度信息等一串数据就相当于是每个同学的身高、体重、性别等一系列信息组成的一串数据