老板让让做一个东东,输入端要用到opencv顺便就来学习一下。买了本书《学习opencv》翻来一看,opencv1.0,去官网上一看,opencv2.49,瞬间有种蛋碎的赶脚。看着第二章介绍一个头文件,在opencv2.49下面招了半天都没找到。。。泪奔~~
不过看到一些论坛上说,这本书里还是讲了一些有用的算法的,所以还是决心仔细读一读,里面的测试程序基本是亲手输入运行成功的,很多例子我自也用不同的方法实现了一下,毕竟入门级新手。望各位老鸟勿喷。还请各位大手多多指点。
1.opencv基本数据结构:
结构 |
成员 |
意义 |
CvPoint |
int x,y |
图像中的点 |
CvPoint2D32f |
float x,y |
二维空间中的点 |
CvPoint3D32f |
float x,y,z |
三维空间中的点 |
CvSize |
int width,height |
图像的尺寸 |
CvRect |
int x,y,width,height |
图像的部分区域 |
CvScalar |
double val[4] |
RGBA值 |
2.CvMat矩阵结构:
(1)两点注意:
1.在Opencv中没有向量结构,任何时候需要向量,都只是一个列矩阵。
2.Opencv矩阵的概念与我们在线性代数课上学习过的概念相比,更抽象,特别是矩阵的元素。
(2)CvMat结构:
typedef struct CvMat{ int type; int step; int* refcount; union{ uchar* ptr; short* s; int* i; float *f1; double* db; } data; union{ int rows; int height; }; union{ int cols; int width; }; }CvMat;
(3)矩阵的创建与释放
CvMat* cvCreateMat( int rows, int cols, int type ); //创建一个矩阵
CvMat* cvCreateMatHeader( int rows, int cols, int type ); //创建一个矩阵结构,不分配空间
CvMat* cvInitMatHeader(CvMat* mat,int rows,int cols,int type,void* data = NULL,int step = CV_AUTOSTEP);//用一个现有矩阵初始化矩阵
CvMat cvMat(int rows,int cols,int type,void* data = NULL);//初始化矩阵结构,不分配空间
CvMat* cvCloneMat( const cvMat* mat );//复制一个mat副本
void cvReleaseMat( CvMat** mat ); //释放矩阵
(4)创建一个矩阵程序:
#include <cv.h> #include <iostream> using namespace std; int _tmain(int argc, _TCHAR* argv[]) { float vals[] = {1,2,3,4}; CvMat rotmat; cvInitMatHeader( &rotmat, 2, 2, CV_32FC1, vals ); cout << rotmat.cols <<endl; cout << rotmat.step <<endl; cout << rotmat.rows <<endl; cout << rotmat.type <<endl; getchar(); return 0; }
3.矩阵数据的存取(简单的方法,麻烦的方法,恰当的方法)
(1)简单的方法:
利用CV_MAT_ELEM()宏存取矩阵
#include "stdafx.h" #include <cv.h> #include <iostream> using namespace std; int _tmain(int argc, _TCHAR* argv[]) { float vals[] = {1,2,3,4}; CvMat* rotmat = cvCreateMat( 2, 2, CV_32FC1 ); cvInitMatHeader( rotmat, 2, 2, CV_32FC1, vals ); float ele = CV_MAT_ELEM(*rotmat,float,1,1); cout << ele << endl; getchar(); return 0; }
另外宏CV_MAT_ELEM_PTR()需要三个参数,传入矩阵,待返回元素的行和列。
它和上个宏一样,只不过返回的是指向元素的指针。需要自己固定类型。
(2)麻烦的方法
使用cvPtr*D访问矩阵,其结构为:
uchar* cvPtr1D( const CvArr* arr, //访问矩阵 int idx0, //元素索引 int* type = NULL//元素类型 ); uchar* cvPtr2D( const CvArr* arr, int idx0, int idx1, int* type = NULL ); uchar* cvPtr3D( const CvArr* arr, int idx0, int idx1, int idx2, int* type = NULL ); uchar* cvPtrND( const CvArr* arr, int* idx, int* type = NULL, int create_node = 1, unsigned* precalc_hashval = NULL );
访问实例:
#include <cv.h> #include <iostream> using namespace std; int _tmain(int argc, _TCHAR* argv[]) { float vals[] = {1,2,3,4}; CvMat* rotmat = cvCreateMat( 2, 2, CV_32FC1 ); cvInitMatHeader( rotmat, 2, 2, CV_32FC1, vals ); float *p = (float*) cvPtr2D(rotmat,1,1); cout <<*p<<endl; getchar(); return 0; }
计算机视觉是一种密集型的任务,所以应该利用最有效的方法做事。
方法:
#include <cv.h> #include <iostream> using namespace std; float sum( CvMat* mat ) { float s = 0.0f; for( int row=0; row<mat->height; row++ ) { float* ptr = mat->data.fl + row * mat->step/4; for( int col=0; col<mat->width; col++ ) { s += *ptr++; } } return( s ); }; int main(int argc, char** argv) { CvMat *mat = cvCreateMat(2,2,CV_32FC1); float elem = 2; *((float*)CV_MAT_ELEM_PTR( *mat, 0,0) ) = elem; cvmSet(mat,0,1,3); cvSetReal2D(mat,1,0,4); cvSetReal2D(mat,1,1,5); float s = sum(mat); printf("%f\n",s); getchar(); return 0; }to be continued