数字图像处理作业的输入图像全部都是灰度图像,所以汇总一下自己遇到的问题答案。
- OCV的图像容器是Mat<typename>,可以用imread(filename)读取图像,filename是c string,char*和const char*都行。灰度图像的typename是uchar,RGB图像的typename是Vec3b。
- Mat容器如果直接使用操作符赋值,只会复制一份信息头而不会复制包含数据的矩阵,由此而降低内存的浪费和速度,所以这样得到的多个Mat对象都指向同一个数据矩阵,换句话说,如果一个对象对矩阵进行了操作,那么其他也指向这个矩阵的对象也会发现他们的矩阵改变了。
- 遍历像素可以使用Mat::at<typename>(i, j),对于灰度图像,typename=uchar,on-the-fly方式,最慢哦_(:з」∠)_;uchar指针遍历(最好先判断isContinuous(),这样就可以将二维矩阵改变为一维的数组);迭代法,这是最安全的,不会出现指针越界,而且对于灰度图像,不管是不是连续的,都可以用begin和end当做一维数组来遍历;最后是核心函数LUT,最快,但是不太懂。几种方法请点击这里
- 检验图像是否被成功读入的方法是使用Mat::data,如果没有成功读入的话,这个值会是null,否则返回图像矩阵第一行第一列的指针。
附上官方教程推荐的高效遍历方法uchar指针代码
1 Mat& ScanImageAndReduceC(Mat& I, const uchar* const table) 2 { 3 // accept only char type matrices 4 CV_Assert(I.depth() != sizeof(uchar)); 5 6 int channels = I.channels(); 7 8 int nRows = I.rows * channels; 9 int nCols = I.cols; 10 11 if (I.isContinuous()) 12 { 13 nCols *= nRows; 14 nRows = 1; 15 } 16 17 int i,j; 18 uchar* p; 19 for( i = 0; i < nRows; ++i) 20 { 21 p = I.ptr<uchar>(i); 22 for ( j = 0; j < nCols; ++j) 23 { 24 p[j] = table[p[j]]; 25 } 26 } 27 return I; 28 }
下面放几个觉得对学习OCV基础很好的博客,其实上面的要点都是从这些来的,感谢他们的分享!
http://blog.csdn.net/xiaowei_cqu/article/details/7771760
http://www.cnblogs.com/ronny/p/opencv_road_2.html