learning OpenCV(3)

本文详细介绍了OpenCV的基本数据类型,包括CvPoint、CvSize、CvRect等,并深入解析了IplImage结构,讨论了其nChannels、depth、dataOrder等关键成员。此外,还提到了矩阵和图像操作、ROI设置以及数据存储的相关内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.OpenCV的基本数据类型

结构               成员

CvPoint            int x,int 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值

cvScalar有三个构造函数:cvScalar()有一个、两个、三个或者四个参数;

cvRealScalar()有一个参数赋给val[0],其他的赋零值

cvScalarAll()一个参数,四个元素都设置为这个参数

2.CvMat矩阵结构

派生关系:CvArr->CvMat->IplImage,出现CvArr*参数的地方,都可以吧CvMat*, IplImage传递到程序;

typedef  struct  CvMat{
//...重点是step行的长度用字节表示
}CvMat;
创建方法:
CvMat cvMat(int rows, int cols, int types, void*data = NULL);
CvMat* cvCreateMat( int rows, int cols,int type);//type CV_<bit_depth>(S|U|F)C<number_of_channels>
CvMat* cvCloneMat (CvMat*);
CvMat* cvInitMatHeader(CvMat*mat, int rows, int cols, int types, void*data = NULL, int step = CV_AUTOSTEP);
存取:
1.简单的方法,缺点:每次调用都要重新计算指针,而且只适用于一维或者二维
float element = CV_MAT_ELEM(rotmat, float, 1,0);//CV_MAT_ELEM_PTR返回指向这个元素的指针
float element = *((float*)CV_MAT_ELEM_PTR(rotmat, 1, 0));
2.麻烦的方法,扩展到了N维数组
uchar* cvPtr1D( const   CvArr*arr,  int   idx0,  int   * type = NULL);
double cvGetReal1D (const CvArr* arr, int idx0);

CvScalar cvGet1D(const CvArr* arr, int idx0);

void cvSetReal1D (CvArr* arr, int idx0, double value);
voidcvSet1D(CvArr*arr, int idx0, CvScalar value);
对于浮点型单通道:double cvmGet(const CvMat*mat, int row, int col);
void cvmSet(CvMat* mat, int row, int col, double value);
3.恰当的方法

重点:
1. 在多通道的矩阵中,通道是连续的,矩阵数据如下存储:rgbrgbrgb......指针移动到下一通道,增加1,,指针移到下一元素集,增加通道数的偏移量;
2.矩阵数组的step元素是矩阵中行的长度,仅靠cols无法在矩阵中的不同行之间移动指针,出于效率的考虑,矩阵或图像的内存分配都是4字节的整数倍。step+当前字节的指针 = 该点下一行元素,如果是整型或者浮点数,step/4 + 指针 = 下一行;如果是双精度的step/8 + 当前自己的指针 = 该点下一行元素;
累加一个三通道矩阵中的所有元素
float sum (const CvMat* mat){
float s = 0.0f;
for(int row = 0; row < mat->rows; row++){
    const float* ptr = (const float*)(mat->data.ptr + mat->step* row);
    for(int col = 0; col < mat->cols; col ++){
        s += *ptr++;
    }
}
return s;
}


3.IplImage数据结构

//Example 3-10. IplImage header structure
typedef struct _IplImage {
  int                  nChannels;//可取的值为1,2,3,4
  int                  depth;//depth变量的值取自ipl.h中定义的一组数据,IPL_DEPTH_(8|16|32|64)(U|S|F)   无符号8位整数
  int                  dataOrder;/*IPL_DATA_ORDER_PIXEL或IPL_DATA_ORDER_PLANE前者指明数据是将像素点不同通道的值交错排在一起,后者是把所有的像素通道值排在一起,形成通道平面,再把平面排列起来*/
  int                  origin;//IPL_ORIGIN_TL 或者IPL_ORIGIN_BL分别设置坐标原点的位置于图像的左上角或者左下角。
  int                  width;
  int                  height;/*如果图像中有独立的平面,把他们作为单独的图像连续摆放,总行数为height×nChannels,否则总行数为高度,每一行都有序的包含交错的通道*/
  struct _IplROI*      roi;/*包含xOffdet,yOffset,height,width,coi成员变量,coi代表channel of intrest按兴趣的通道,一旦设定ROI通常作用于整个图像的函数只对ROI子图进行操作*/
  char*                imageData;//指向第一行图像数据的指针
  int                  widthStep;//与前面讨论过的step参数相似
} IplImage;

尽量最大化HSV图像的S和V部分

void saturate_sv(IplImage* img){
    for(int y = 0; y < img->height; y++)
    {
        uchar* ptr = (uchar*)(img->imageData + img-> widthStep * y);
        for(int k = 0; k < img->width; k++){
            ptr[3*k + 1] = 255;
            ptr[3*k + 2] = 255;
        }
    }

设置和取消ROI

void cvSetImageROI(IplImage* image, CvRect rect);

void cvResetImage(IplImage* image);

用widthStep设置子图 Q:为什么y不用乘nChannels?

 sub_img->imageData = interest_img->imageData + 
          interest_rect.y * interest_img->widthStep  +
          interest_rect.x * interest_img->nChannels;

4.矩阵和图像操作

AbsDiff, Add
CalcCovarMatrix, EigenVV
Avg, AvgSdv
Copy
Merge, Repeat
Pow,Log

5.绘图


5.数据存储


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值