OpenCV 矩阵操作 CvMat(二)

限时加码!20+主流AI编程工具免费用 购周边加赠Coding Plan Lite,Claude Code、Cursor等即刻畅享,学习进阶更高效! 阅读详情

http://blog.csdn.net/schoolers/archive/2009/11/16/4816721.aspx

 

1.初始化矩阵:

// 方式一、逐点赋值式:

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定义的数组进行的。

 

 

2. IplImage cvMat的转换

// 方式一、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)

 

3.cvArr(IplImage或者cvMat)转化为cvMat

// 方式一、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__;

}

 

4.图像直接操作

// 方式一:直接数组操作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 )

 

5.cvMat的直接操作

 

 

 

 

// 数组的直接操作比较郁闷,这是由于其决定于数组的数据类型。

 

// 对于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);

 

6.间接访问cvMat

// 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");

     }

}

 

 

7.修改矩阵的形状——cvReshape的操作

经实验表明矩阵操作的进行的顺序是:首先满足通道,然后满足列,最后是满足行。

注意:这和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 );

 

 

 

8.计算色彩距离

 

 

// 我们要计算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;

}

 

opencvcv::Mat常用属性和函数 这篇文章包括: 1. opencv常用头文件及作用 2. cv::Mat常见初始化 3. cv::Mat常见属性 4. cv::Mat常见函数   clone()和copyTo()的区别 5.cv::Mat的RGB赋值(改颜色) 6.待续   1. opencv常用头文件: 1.1 最常用头文件: #include <opencv2/core/core.hpp> #incl... 阅读详情

相关推荐

OpenCV常用的图像IplImage矩阵CvMat操作总结

OpenCv中图像的结构体为IplImageCvMat的结构体,以及元素操作

never give up的博客 3572

OpenCvMat的一些简单使用技巧

机器学习的相关算法的实现需要大量使用到矩阵运算。用C++实现的话,OpenCv里面的Mat数据结构是一个很好的选择。 初始化 创建cv::Mat,并且初始化cv::Scalar::all(0) cv::Mat 可以直接使用cout进行输出 cv::Mat a(3, 3, CV_32FC1, cv::Scalar::all(0)); cout << a << endl;...

cxq_baby的博客 1029

opencv学习笔记(七)-CvMat矩阵结构以及矩阵数据访问

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 首先说一下对矩阵维度和通道的理解: 维:体现为坐标。 通道: 对于这样一个数组矩阵float data[18] = { 30, 60, 40, 60, 50, 40,

孤旅人。。。的博客 7758

OpenCV教程】OpenCV中对矩阵的常用操作

OpenCV教程】OpenCV中对矩阵的常用操作

在这里你甚至能学算卦,快进来看看 1023

Opencv-C++笔记 (2) : opencv矩阵操作

这个混杂(“scrambled”)矩阵的特征值将和真正的协方差矩阵的特征值匹配,真正的特征向量可以很容易的从混杂 (“scrambled”)协方差矩阵的特征向量中计算出来。或者如果协方差矩阵是部分计算出来的 - 倘若这样, avg 不是输入向量的子集的平均值,而是整个集合的平均向量。目前这个函数比函数 cvSVD 要慢,精确度要低, 如果已知 A 是正定的,(例如, 它是一个协方差矩阵), 它通常被交给函数 cvSVD 来计算其特征值和特征向量,尤其是在不需要计算特征向量的情况下。

jiyanghao19的博客 4044

opencv矩阵运算

90、cvScale:是cvConvertScale的一个宏,可以用来重新调整数组的内容,并且可以将参数从一种数。150、cvCopyMakeBorder:将特定的图像轻微变大,然后以各种方式自动填充图像边界;97、cvFillPoly、cvFillConvexPoly、cvPolyLine:画多边形;86、cvConvertScaleAbs:计算可选的缩放值的绝对值之后再转换数组元素的类型;27、cvAddWeighted:两个数组的元素级的加权相加运算(alpha运算)

stationinthemind的博客 953

庞峰Opencv学习()--对矩阵结构体CvMat的基本操作

1. CvMat结构体:(注释)typedef struct CvMat { int type; //数据类型以 CV_N{U|S|F}C{1,2,3...}表示 int step; //表示一行有多少个字,在32位操作系统中,一个字为4个字节 /* for internal use only */ int* refcount; in

兔美酱 1800

OpenCv学习笔记(一)——数字图形的基础和结构

一图像基础 1 数字图像 又称数码图像或数位图像,是维图像用有限数字数值像素的表示。数字图像是由模拟图像数字化得到的、以像素为基本元素的、可以用数字计算机或数字电路存储和处理的图像。 2. 像素 像素(或像元,Pixel)是数字图像的基本元素,像素是在模拟图像数字化时对连续空间进行离散化得到的。每个像素具有整数行(高)和列(宽)位置坐标,同时每个像素都具有整数灰度值或颜色值。 通常,像素

slamer的专栏 868

OpenCV 矩阵操作 CvMat

综述: OpenCV有针对矩阵操作的C语言函数. 许多其他方法提供了更加方便的C++接口,其效率与OpenCV一样.OpenCV将向量作为1维矩阵处理.矩阵按行存储,每行有4字节的校整.分配矩阵空间:CvMat* cvCreateMat(int rows, int cols, int type); type: 矩阵元素类型. 格式为CV_(S|

schoolers的专栏 1万+

opencv 中的cvMat详解

1 cvMat简介 图像在计算机中是以数组的形式存放的,MatOpenCV中用于存放图像的数据结构。通过调用相关方法,我们能够实现对图像的输入输出以及一些操作。同时,Mat又不止可以作为图像容器,它也可以作为一种比较纯粹的描述矩阵这种数学对象的结构。它比C中的IplImage好的地方在于,由于它的“计数器”机制,我们不需要对它进行手动的内存回收,从而避免了常常困扰C/C++程序员的“内存泄

彼岸花 1万+

OpenCV 获取CvMat的数据(用double数组设置CvMat矩阵

直接上code吧,注意采用数组设置矩阵比较方便 #include #include #include #include #include #include using namespace std; #pragma comment(lib,"cv.lib"); #pragma comment(lib,"cvaux.lib"); #pragma commen

5765

Study notes for OpenCV——第八节 CvMat结构体与矩阵的创建

一、数据类型CvMat CvMat与IplImage的关系就如同C++中的继承关系,IplImage可以视为从CvMat派生的。CvArr可以视为抽象类。 CvMat矩阵结构 首先我们要知道OpenCV中没有向量结构,需要向量的时候,都用列矩阵或者行矩阵(转置)来代替。 矩阵头代码: typedef struct CvMat { int type; //类型

Voidwalkerxiaohui 1670

OpenCV矩阵CvMat

OpenCV中有一种数据类型CvMat,也就是OpenCV矩阵结构。虽然OpenCV完全由C语言实现,但是CvMat和IplImage之间的关系就像C++中的继承关系。实质上,IplImage可以被视为从CvMat中派生的,我想下图应该是很多要知道的:CvMat矩阵结构在介绍CvMat矩阵结构时,我们先来说两个两个问题:1、在OpenCV中没有向量结构。任何时候需要向量,都只需要一个列矩阵(如果

技术小白 999

用Socket保存OpenCVCvMat结构

接着上个月写的一篇发送IplImage结构的来说,因为Socket发送结构的部分上一篇写过了,所以不再多写了。 CvMat的结构如下: typedef struct CvMat { int type; int step; /* for internal use only */ int* refcount; int hdr_refcount; un

生命在于折腾 1408

opencv java 矩阵运算_opencv CvMat矩阵学习

1.初始化矩阵:方式一、逐点赋值式: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 );方式、连接现有...

weixin_36032446的博客 595

《学习opencv》笔记——基本数据结构,CvMat矩阵访问

《学习opencv》笔记——基本数据结构,CvMat矩阵访问

睿不可挡的专栏 2650

opencv中的MatCvMat以及IplImage介绍以及三者之间的转换

OpenCV中常见的与图像操作有关的数据容器有MatcvMat和IplImage。这三种类型都可以代表和显示图像,区别是:Mat类型侧重于计算,数学性较高,OpenCVMat类型的计算进行了优化;CvMat和IplImage类型更侧重于“图像”,opencv对其中的图像操作(缩放、单通道提取、图像阈值操作等)进行了优化。在opencv2.0之前,opencv是完全用C实现的,但是,IplIma...

yangdeshun888的博客 1751

opencv-矩阵操作总结

1.初始化矩阵:方式一、逐点赋值式: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 );方式、连接现有数组式:

crystal8700的专栏 2335

opencv CvMat操作总结

综述:         OpenCV有针对矩阵操作的C语言函数. 许多其他方法提供了更加方便的C++接口,其效率与OpenCV一样.         OpenCV将向量作为1维矩阵处理.         矩阵按行存储,每行有4字节的校整.           分配矩阵空间:     CvMat* cvCreateMat(int rows, int cols, int type)

todayq的专栏 1058
上一篇: OpenCV 矩阵操作 CvMat(一)
下一篇: 如何解决VS2005的MSDN无法显示网页
小大小丑
博客等级 码龄18年 483粉丝 425原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值