http://blog.csdn.net/schoolers/archive/2009/11/16/4816721.aspx
// 方式一、逐点赋值式:
CvMat* mat = cvCreateMat(2, 2, CV_64FC1);
cvZero(mat);
cvmSet(mat, 0, 0, 1);
cvmSet(mat, 0, 1, 2);
cvmSet(mat, 1, 0, 3);
cvmSet(mat, 2, 2, 4);
cvReleaseMat(&mat);
// 方式二、连接现有数组式:
double a[] = { 1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12
};
CvMat mat = cvMat(3, 4, CV_64FC1, a); // 64FC1 for double
// 不需要cvReleaseMat,因为数据内存分配是由double定义的数组进行的。
// 方式一、cvGetMat方式:
CvMat mathdr, *mat = cvGetMat(img, &mathdr);
// 方式二、cvConvert方式:
CvMat *mat = cvCreateMat(img->height, img->width, CV_64FC3);
cvConvert(img, mat);
// #define cvConvert(src, dst) cvConvertScale( (src), (dst), 1, 0)
// 方式一、cvGetMat方式:
int coi = 0;
cvMat *mat = (CvMat*)arr;
if(!CV_IS_MAT(mat))
{
mat = cvGetMat(mat, &matstub, &coi);
if(coi != 0)
reutn; // CV_ERROR_FROM_CODE(CV_BadCOI);
}
// 写成函数为:
// This is just an example of function
// to support both IplImage and cvMat as an input
CVAPI(void) cvIamArr( const CvArr* arr )
{
CV_FUNCNAME( "cvIamArr" );
__BEGIN__;
CV_ASSERT( mat == NULL );
CvMat matstub, *mat = (CvMat*)arr;
int coi = 0;
if( !CV_IS_MAT(mat) )
{
CV_CALL( mat = cvGetMat( mat, &matstub, &coi ) );
if (coi != 0) CV_ERROR_FROM_CODE(CV_BadCOI);
}
// Process as cvMat
__END__;
}
// 方式一:直接数组操作int col, row, z;
uchar b, g, r;
for(y = 0; row < img->height; y++)
{
for(col = 0; col < img->width; col++)
{
b = img->imageData[img->widthStep * row + col * 3]
g = img->imageData[img->widthStep * row + col * 3 + 1];
r = img->imageData[img->widthStep * row + col * 3 + 2];
}
}
// 方式二:宏操作:
int row, col;
uchar b, g, r;
for(row = 0; row < img->height; row++)
{
for(col = 0; col < img->width; col++)
{
b = CV_IMAGE_ELEM(img, uchar, row, col * 3);
g = CV_IMAGE_ELEM(img, uchar, row, col * 3 + 1);
r = CV_IMAGE_ELEM(img, uchar, row, col * 3 + 2);
}
}
// 注:CV_IMAGE_ELEM( img, uchar, row, col * img->nChannels + ch )
// 数组的直接操作比较郁闷,这是由于其决定于数组的数据类型。
// 对于CV_32FC1 (1 channel float):
CvMat* M = cvCreateMat(4, 4, CV_32FC1);
M->data.fl[row * M->cols + col] = (float)3.0;
// 对于CV_64FC1 (1 channel double):
CvMat* M = cvCreateMat(4, 4, CV_64FC1);
M->data.db[row * M->cols + col] = 3.0;
// 一般的,对于通道的数组:
CvMat* M = cvCreateMat(4, 4, CV_64FC1);
CV_MAT_ELEM(*M, double, row, col) = 3.0;
// 注意double要根据数组的数据类型来传入,这个宏对多通道无能为力。
// 对于多通道:
// 看看这个宏的定义:
#define CV_MAT_ELEM_CN(mat, elemtype, row, col) /
(*(elemtype*)((mat).data.ptr + (size_t)(mat).step*(row) + sizeof(elemtype)*(col)))
if(CV_MAT_DEPTH(M->type) == CV_32F)
CV_MAT_ELEM_CN(*M, float, row, col * CV_MAT_CN(M->type) + ch) = 3.0;
if(CV_MAT_DEPTH(M->type) == CV_64F)
CV_MAT_ELEM_CN( *M, double, row, col * CV_MAT_CN(M->type) + ch ) = 3.0;
// 更优化的方法是:
#define CV_8U 0
#define CV_8S 1
#define CV_16U 2
#define CV_16S 3
#define CV_32S 4
#define CV_32F 5
#define CV_64F 6
#define CV_USRTYPE1 7
int elem_size = CV_ELEM_SIZE(mat->type);
for(col = start_col; col < end_col; col++)
{
for(row = 0; row < mat->rows; row++)
{
for(elem = 0; elem < elem_size; elem++)
{
(mat->data.ptr + ((size_t)mat->step * row) + (elem_size * col))[elem] =
(submat->data.ptr + ((size_t)submat->step * row) + (elem_size * (col - start_col)))[elem];
}
}
}
// 对于多通道的数组,以下操作是推荐的:
for(row=0; row< mat->rows; row++)
{
p = mat->data.fl + row * (mat->step / 4);
for(col = 0; col < mat->cols; col++)
{
*p = (float) row+col;
*(p + 1) = (float) row + col + 1;
*(p + 2) = (float) row + col + 2;
p+=3;
}
}
// 对于两通道和四通道而言:
CvMat* vector = cvCreateMat(1, 3, CV_32SC2);
CV_MAT_ELEM(*vector, CvPoint, 0, 0) = cvPoint(100,100);
CvMat* vector = cvCreateMat(1, 3, CV_64FC4);
CV_MAT_ELEM(*vector, CvScalar, 0, 0) = cvScalar(0, 0, 0, 0);
// cvmGet/Set是访问CV_32FC1 和CV_64FC1型数组的最简便的方式,其访问速度和直接访问几乎相同
cvmSet(mat, row, col, value);
cvmGet(mat, row, col);
// 举例:打印一个数组
inline void cvDoubleMatPrint(const CvMat* mat)
{
int i, j;
for(i = 0; i < mat->rows; i++)
{
for(j = 0; j < mat->cols; j++)
{
printf("%f ",cvmGet(mat, i, j));
}
printf("/n");
}
}
// 而对于其他的,比如是多通道的后者是其他数据类型的,cvGet/Set2D是个不错的选择
CvScalar scalar = cvGet2D( mat, row, col );
cvSet2D( mat, row, col, cvScalar( r, g, b ) );
// 注意:数据不能为int,因为cvGet2D得到的实质是double类型。
// 举例:打印一个多通道矩阵:
inline void cv3DoubleMatPrint(const CvMat* mat)
{
int i, j;
for(i = 0; i < mat->rows; i++)
{
for(j = 0; j < mat->cols; j++)
{
CvScalar scal = cvGet2D(mat, i, j);
printf("(%f,%f,%f) ", scal.val[0], scal.val[1], scal.val[2]);
}
printf("/n");
}
}
经实验表明矩阵操作的进行的顺序是:首先满足通道,然后满足列,最后是满足行。
注意:这和Matlab是不同的,Matlab是行、列、通道的顺序。
我们在此举例如下:
对于一通道:
// 1 channel
CvMat *mat, mathdr;
double data[] = {
11, 12, 13, 14,
21, 22, 23, 24,
31, 32, 33, 34
};
CvMat* orig = &cvMat( 3, 4, CV_64FC1, data );
// 11 12 13 14
// 21 22 23 24
// 31 32 33 34
mat = cvReshape(orig, &mathdr, 1, 1); // new_ch, new_rows
cvDoubleMatPrint(mat); // above
// 11 12 13 14 21 22 23 24 31 32 33 34
mat = cvReshape(mat, &mathdr, 1, 3); // new_ch, new_rows
cvDoubleMatPrint( mat ); // above
//11 12 13 14
//21 22 23 24
//31 32 33 34
mat = cvReshape(orig, &mathdr, 1, 12 ); // new_ch, new_rows
cvDoubleMatPrint(mat ); // above
// 11
// 12
// 13
// 14
// 21
// 22
// 23
// 24
// 31
// 32
// 33
// 34
mat = cvReshape( mat, &mathdr, 1, 3); // new_ch, new_rows
cvDoubleMatPrint(mat); // above
// 11 12 13 14
// 21 22 23 24
// 31 32 33 34
mat = cvReshape(orig, &mathdr, 1, 2); // new_ch, new_rows
cvDoubleMatPrint(mat); // above
// 11 12 13 14 21 22
// 23 24 31 32 33 34
mat = cvReshape(mat, &mathdr, 1, 3); // new_ch, new_rows
cvDoubleMatPrint(mat); // above
// 11 12 13 14
// 21 22 23 24
// 31 32 33 34
mat = cvReshape(orig, &mathdr, 1, 6); // new_ch, new_rows
cvDoubleMatPrint( mat ); // above
// 11 12
// 13 14
// 21 22
// 23 24
// 31 32
// 33 34
mat = cvReshape(mat, &mathdr, 1, 3); // new_ch, new_rows
cvDoubleMatPrint(mat); // above
// 11 12 13 14
// 21 22 23 24
// 31 32 33 34
// Use cvTranspose and cvReshape( mat, &mathdr, 1, 2 ) to get
// 11 23
// 12 24
// 13 31
// 14 32
// 21 33
// 22 34
// Use cvTranspose again when to recover
对于三通道
// 3 channels
CvMat mathdr, *mat;
double data[] = {
111, 112, 113, 121, 122, 123,
211, 212, 213, 221, 222, 223
};
CvMat* orig = &cvMat(2, 2, CV_64FC3, data);
// (111,112,113) (121,122,123)
// (211,212,213) (221,222,223)
mat = cvReshape(orig, &mathdr, 3, 1); // new_ch, new_rows
cv3DoubleMatPrint(mat); // above
// (111,112,113) (121,122,123) (211,212,213) (221,222,223)
// concatinate in column first order
mat = cvReshape(orig, &mathdr, 1, 1); // new_ch, new_rows
cvDoubleMatPrint(mat); // above
// 111 112 113 121 122 123 211 212 213 221 222 223
// concatinate in channel first, column second, row third
mat = cvReshape(orig, &mathdr, 1, 3); // new_ch, new_rows
cvDoubleMatPrint(mat); // above
// 111 112 113 121
// 122 123 211 212
// 213 221 222 223
// channel first, column second, row third
mat = cvReshape(orig, &mathdr, 1, 4); // new_ch, new_rows
cvDoubleMatPrint(mat); // above
// 111 112 113
// 121 122 123
// 211 212 213
// 221 222 223
// channel first, column second, row third
// memorize this transform because this is useful to
// add (or do something) color channels
CvMat* mat2 = cvCreateMat(mat->cols, mat->rows, mat->type);
cvTranspose(mat, mat2);
cvDoubleMatPrint(mat2); // above
//111 121 211 221
//112 122 212 222
//113 123 213 223
cvReleaseMat( &mat2 );
// 我们要计算img1,img2的每个像素的距离,用dist表示,定义如下
IplImage *img1 = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 3);
IplImage *img2 = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 3);
CvMat *dist = cvCreateMat(h, w, CV_64FC1);
// 比较笨的思路是:cvSplit->cvSub->cvMul->cvAdd
// 代码如下:
IplImage *img1B = cvCreateImage(cvGetSize(img1), img1->depth, 1);
IplImage *img1G = cvCreateImage(cvGetSize(img1), img1->depth, 1);
IplImage *img1R = cvCreateImage(cvGetSize(img1), img1->depth, 1);
IplImage *img2B = cvCreateImage(cvGetSize(img1), img1->depth, 1);
IplImage *img2G = cvCreateImage(cvGetSize(img1), img1->depth, 1);
IplImage *img2R = cvCreateImage(cvGetSize(img1), img1->depth, 1);
IplImage *diff = cvCreateImage(cvGetSize(img1), IPL_DEPTH_64F, 1);
cvSplit(img1, img1B, img1G, img1R);
cvSplit(img2, img2B, img2G, img2R);
cvSub(img1B, img2B, diff);
cvMul(diff, diff, dist);
cvSub(img1G, img2G, diff);
cvMul(diff, diff, diff);
cvAdd(diff, dist, dist);
cvSub(img1R, img2R, diff);
cvMul(diff, diff, diff);
cvAdd(diff, dist, dist);
cvReleaseImage(&img1B);
cvReleaseImage(&img1G);
cvReleaseImage(&img1R);
cvReleaseImage(&img2B);
cvReleaseImage(&img2G);
cvReleaseImage(&img2R);
cvReleaseImage(&diff);
// 比较聪明的思路是
int D = img1->nChannels; // D: Number of colors (dimension)
int N = img1->width * img1->height; // N: number of pixels
CvMat mat1hdr, *mat1 = cvReshape(img1, &mat1hdr, 1, N); // N x D(colors)
CvMat mat2hdr, *mat2 = cvReshape(img2, &mat2hdr, 1, N); // N x D(colors)
CvMat diffhdr, *diff = cvCreateMat(N, D, CV_64FC1); // N x D, temporal buff
cvSub(mat1, mat2, diff);
cvMul(diff, diff, diff);
dist = cvReshape(dist, &disthdr, 1, N); // nRow x nCol to N x 1
cvReduce(diff, dist, 1, CV_REDUCE_SUM); // N x D to N x 1
dist = cvReshape(dist, &disthdr, 1, img1->height); // Restore N x 1 to nRow x nCol
cvReleaseMat(&diff);
#pragma comment( lib, "cxcore.lib" )
#include "cv.h"
#include <stdio.h>
int main()
{
CvMat* mat = cvCreateMat(3, 3, CV_32FC1);
cvZero(mat); // 将矩阵置
// 为矩阵元素赋值
CV_MAT_ELEM(*mat, float, 0, 0) = 1.f;
CV_MAT_ELEM(*mat, float, 0, 1) = 2.f;
CV_MAT_ELEM(*mat, float, 0, 2) = 3.f;
CV_MAT_ELEM(*mat, float, 1, 0) = 4.f;
CV_MAT_ELEM(*mat, float, 1, 1) = 5.f;
CV_MAT_ELEM(*mat, float, 1, 2) = 6.f;
CV_MAT_ELEM(*mat, float, 2, 0) = 7.f;
CV_MAT_ELEM(*mat, float, 2, 1) = 8.f;
CV_MAT_ELEM(*mat, float, 2, 2) = 9.f;
// 获得矩阵元素(0,2)的值
float *p = (float*)cvPtr2D(mat, 0, 2);
printf("%f/n",*p);
return 0;
}