Opencv(3):基本数据类型
1.比较简单的原子类型
结构 | 成员 | 意义 |
CvPoint | int x,y | 图像中的点 |
CvPoint2D32f | float x,y | 二维空间中的点 |
CvPoint3D32f | float x,y,z | 三维空间中的点 |
CvSize | int width,height | 图像的尺寸 |
CvRect | intx,y,width,height | 图像的部分区域 |
CvScalar | double val[4] | GBA值 |
其中cvScalar是一个特殊例子,它有3个构造函数。第一个是cvScalar(),它需要一个,两个,三个或四个参数并将这些参数传递给数组val[]中的相应元素。
第二个函数是cvRealScalar(),它需要一个参数,它被传递给val[0],其他值被赋为0,第三个是cvScalarAll(),它需要一个参数并且val[ ]中的4个元素都会设置为这个参数。
2.矩阵和图像类型
CvArr->CvMat->IplImage
CvMat矩阵结构
在OpenCV中没有向量结构,任何时候需要向量,都只需要一个列矩阵。
CvMat结构:矩阵头
typedef struct CvMat {
int type;
int step;
int* fefount;
union {
uchar* ptr;
short* s;
int* i;
float* fl;
double* db;
}data;
union {
int rows;
int height;
};
union {
int cols;
int width;
};
}CvMat;
矩阵创建方法:
1).cvCreateMat(),它由多个原数组组成,如cvCreateMatHeader()何cvCreateData()。cvCreateMatHeader()函数常见CvMat结构,不为数据分配内存,
而cvCreateData()函数只负责分配数据的内存分配。
2).只需函数cvCreateMatHeader(),因为已因其他理由分配了内存空间,或因为还不准备分配存储空间。
3).使用函数cvCloneMat(CvMat*),它依据一个现有矩阵创建一个新的矩阵。当这个矩阵不再需要时,可以调用函数cvReleaseMat(CvMat*)释放它。
矩阵的创建和释放
//Create a new rows by cols matrix of type 'type'
CvMat* cvCreateMat(int rows, int cols, int type);
//Create only matirx header without allocating data
CvMat* cvCreateMatHeader(int rows, int cols, int type);
//Initialize header on existing CvMat structure
CvMat* cvInitMatHeader(
CvMat* mat,
int rows,
int cols,
int type,
void *data = NULL,
int step = CV_AUTOSTEP
) //Like cvInitMatHeader() but allocates CvMat as well
CvMat cvMat(
int rows,
int cole,
int type,
void *data = NULL
); //Allocate a new matrix just like the matrix 'mat' CvMat* cvCloneMat(const cvMat* mat);
void cvReleaseMat(CvMat** mat);
用固定数据创建一个OpenCV矩阵
float vals[] = { 0.8,0,5,0.4,0,3 };
CvMat rotmat;
cvInitMatHeader(
&rotmat,
2,
2,
CV_32FC1,
vals
);
一旦创建一个矩阵,便可用它来完成很多事情。最简单的操作就睡查询数组定义和数据访问等。
查询:
cvGetElemType(const CvArr* arr) :返回一个整型常数,表示存储在数组里的元素类型
cvGetDims(const CvArr* arr,int* size=NULL):取出数组以及一个可选择的整型指针,返回维数
cvGetDimSize(const CvArr* arr,int index):通过一个指示维数的整型简单地返回矩阵在那个维数上矩阵的大小。
3.矩阵数据的存取
1)简单的方法
从矩阵中得到一个元素的最简单的方法是利用宏CV_MAT_ELEM()。这个宏传入矩阵,待提取的元素的类型,行和列数这四个参数,
返回提取出的元素的值。
#include<iostream>
#include<opencv2/core/core.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<windows.h>
using namespace cv;
using namespace std;
int main() {
CvMat* cmat = cvCreateMat(, , CV_32FC1);
for (int i = ; i < ; i++) {
for (int j = ; j < ; j++) {
float element = CV_MAT_ELEM(*cmat, float, i, j);
cout << element << " ";
}
cout << endl;
}
system("pause");
return ;
}
还有一个于此类似的宏CV_MAT_ELEM_PTR(),传入矩阵,待返回元素的行和列号这3个参数,返回指向这个元素的指针。
该宏和CV_MAT_ELEM()宏的最重要的区别是后者在指针解引用之前将其转化成指定的类型。如果需要同时读取数据和设置数据
可以直接调用CV_MAT_ELEM_PTR()。但在这种情况先,必须自己将指针转化为恰当的类型。
利用CV_MAT_ELEM_PTR()为矩阵设置一个数值
CvMat* mat = cvCreateMat(5, 5, CV_32FC1);
float element_3_2 = 7.7;
*((float*)CV_MAT_ELEM_PTR(*mat, 3, 2)) = element_3_2;
但是,这些宏在每次调用的时候都重新计算指针。这意味着要查找指向矩阵基本元素数据区的指针,计算目标数据在矩阵中的相对地址,
然后将相对位置与基本位置相加。
2)麻烦的方法
为了访问普通矩阵中的数据,可以利用cvPtr*D和cvGet*D等函数族,cvPtr*D家族cvPtr1D(),cvPtr2D(),cvPtr3D()...cvPtrND()。前三个函数
都可接收CvArr*类型的矩阵指针参数,紧随其后的参数是表示索引的整数值,最后一个是可选参数,表示输出值的类型。函数返回一个指
向所需元素的指针。对于cvPtrND()来说,第二个参数是一个指向一个整数数组的指针,这个数组中包含索引的合适数字。
cvGet*D
double cvGEtReal1D(const CvArr* arr,int idx0); |
double cvGetReal2D(const CvArr* arr,int idx0,int idx1); |
double cvGetReal3D(const CvArr* arr,int idx0,int idx1,int idx2); |
double cvGetRealND(const CvArr* arr,int* idx); |
CvScalar cvGet1D(const CvArr* arr,int idx0); |
CvScalar cvGet2D(const CvArr* arr,int idx0,int idx1) |
CvScalar cvGet3D(const CvArr* arr,int idx0,int idx1,int idx2) |
CvScalar cvGetND(const CvArr* arr,int *idx); |
cvGet*D中有四个函数返回的是整数的,另外四个的返回值是CvScalar类型的。这意味着在使用这些函数的时候,会有很大的空间浪费。
所以,在使用这些函数的时候,会有很大的空间浪费。所以,只是在你认为用这些函数比较方便和高效率的时候才用它们,否则,最好
用cvPtr*D。
用cvPtr*D()函数族还有另外一个原因,即可以用这些指针函数访问矩阵中的特定的点,然后由这个点触发,用指针的算术运算得到指向
矩阵中其他数据的指针。
4.ImlIage数据结构
从本质上讲,它是一个CvMat对象,但它还有一些成员变量将矩阵解释为图像。
typedef struct _IplImage {
int nSize;
int ID;
int nChannels;
int alphaChannel;
int depth;
char colorModel[4];
char channelSeq[4];
int dataOrder;
int origin;
int align;
int width;
int height;
struct _IplROI* roi;
struct _IplImage* maskROI;
void* imageId;
struct _IplTileInfo* titleInfo;
int imageSize;
char* imageData;
int widthStep;
int BorderMode[4];
char* imageDataOrigin;
}IplImage;
width和height这两个变量很重要,其次是depth和nchannals。depth变量的值取自ipl.h中定义的一组数据,但与在矩阵中看到的对应变量不同。
因为在图像中,我们往往将深度和通道数分开处理,而在矩阵中,我们往往同时表示它们。可用的深度值如下表所示
宏 | t图像像素类型 |
IPL_DEPTH_8U | w无符号8位整数(8s) |
IPL_DEPTH_8S | y有符号8位整数(8s) |
IPL_DEPTH_16S | y有符号16位整数(16s) |
IPL_DEPTH_32s | y有符号32位整数(32s) |
IPL_DEPTH_32f | 32位浮点数单精度(32f) |
IPL_DEPTH_64f | 64位浮点数双精度(64f) |
通道数nChannels可取得值是1,2,3,4
随后两个重要成员是origin和dataOrder。origin变量可以有两种取值:IPL_ORIGIN_TL或者IPL_ORIGIN_BL,分别设置坐标原点的位置于图像的右上角
或者左下角。在计算机视觉领域,一个重要的错误来源就是原点位置的定义不同意。具体而言,图像的来源,操作系统,编解码器和存储格式等因素
都可以影响图像坐标原点的选取。举例来说,你或许认为自己正在从图像上面的脸部附近取样,但实际上却在图像下方的裙子附近取样。避免此类现象
反正的最好办法是在最开始的时候检查一下系统,在所操作的图像块的地方画点东西试试。
dataOrder的取值可以是IPL_DATA_ORDER_PIXEL或IPL_DATA_ORDER_PLANE,前者指明数据是将像素点不同通道的值交错排在一起,后者是把所有
像素通道值排在一起,形成通道平面,再把平面排列起来。
Opencv(3):基本数据类型的更多相关文章
- opencv的基本数据类型CvPoint,CvSize,CvRect,CvScalar
转自http://blog.csdn.net/gdut2015go/article/details/46301821 opencv的基本数据类型CvPoint,CvSize,CvRect,CvScal ...
- opencv之Mat数据类型
data:Mat对象中的一个指针,指向内存中存放矩阵数据的一块内存 (uchar* data) dims:Mat所代表的矩阵的维度,如 3 * 4 的矩阵为 2 维, 3 * 4 * 5 的为3维 c ...
- OpenCv中基本数据类型--Point,Size,Rect,Scalar,Vec3b类类型的详细解释
头文件路径:opencv-2.4.9/modules/core/include/opencv2/core/core.hpp 一.Point类 在这些数据类型中,最简单的就是Point点类,Point类 ...
- opencv学习笔记(三)基本数据类型
opencv学习笔记(三)基本数据类型 类:DataType 将C++数据类型转换为对应的opencv数据类型 OpenCV原始数据类型的特征模版.OpenCV的原始数据类型包括unsigned ch ...
- 深度图从ros数据类型转换成opencv数据类型
摘要:ros下,利用realsense D435采集深度图,并将其转换成opencv的数据类型. 一. RGBD图像采集 通过image_transport包,根据给定的采集速度从realsense ...
- opencv单目摄像机标定(一)
#include <string> #include <iostream> #include <cv.h> #include <highgui.h> u ...
- C++ Opencv Mat类型使用的几个注意事项及自写函数实现Laplace图像锐化
为了提升自己对Opencv中Mat数据类型的熟悉和掌握程度,自己尝试着写了一下Laplace图像锐化函数,一路坎坷,踩坑不断.现将代码分享如下: #include <opencv2/opencv ...
- OpenCV.概念(读书笔记)
ZC:学习OpenCV.pdf 1.多通道矩阵(学习OpenCV.pdf) 1.1.在学习opencv的时候看到多通道矩阵这一概率,恳求大神告诉我一下什么意思_百度知道.html(https://zh ...
- OpenCV和Qt的图像格式互转
做图像处理的时候经常使需要用到opencv的,这应该是免费的图像处理库中用得最广泛而且最好用的库了吧.然后有时候想用界面来展示点东西的时候,我们就需要编写个界面,编写界面的方法千千万,弱水三千我只取一 ...
随机推荐
- PTA 7-8 哈利·波特的考试(floyd)
哈利·波特要考试了,他需要你的帮助.这门课学的是用魔咒将一种动物变成另一种动物的本事.例如将猫变成老鼠的魔咒是haha,将老鼠变成鱼的魔咒是hehe等等.反方向变化的魔咒就是简单地将原来的魔咒倒过来念 ...
- 高盛oa
一道题根本不会,抄答案过了.一道自己写,莫名其妙出现了不会的bug.最后交了暴力解,过了5/7.估计要跪. 总结: 缺点:做过的不熟练.没做过的题不会.一个陌生的小bug也de不出来. 措施:多总结还 ...
- python中类变量和成员变量、局部变量总结
class Member(): num= #类变量,可以直接用类调用,或用实例对象调用 def __init__(self,x,y): self.x=x #实例变量(成员变量),需要它是在类的构造函数 ...
- jsplumb踩坑
一,,关于连线器label 我们全局设置中可以用 getInstance 实例化新对象 也可以通过 importDefaults 实例化新对象 当我想要给连线器上添加标签 每个连线器上的标签都不一样 ...
- 移动端 input 输入框实现自带键盘“搜索“功能并修改X
主要利用html5的,input[type=search]属性来实现,此时input和type=text外观和功能没啥区别: html代码入下: <form action="" ...
- socket 进阶
1.验证客户端链接的合法性 如果你想在分布式系统中实现一个简单的客户端链接认证功能,又不像SSL那么复杂,那么利用hmac+加盐的方式来实现 import socket import os impor ...
- python添加fluent日志记录
istio默认会进行日志的记录,但是仅仅记录到服务.以及服务之间调用的信息,不记录业务日志. 如: 所以需要添加业务日志记录. 1.python引入package fluentmsgpack 2.代码 ...
- linux强制拷贝避免输入yes方法
Linux下默认cp命令是有别名(alias cp='cp -i')的,无法强制覆盖,即使你用 -f 参数也无法强制覆盖文件,下面提供两种Linux下cp 覆盖方法. 1) 取消cp的alias,这不 ...
- 在iOS 8及以后使用UIAlertController 等各种弹出警告通知
原文转自:在iOS 8中使用UIAlertController 感谢作者分享,自我学习之用 iOS 8的新特性之一就是让接口更有适应性.更灵活,因此许多视图控制器的实现方式发生了巨大的变化.全新的UI ...
- H5C3动画
1 渐变 /* 渐变:不同颜色之间的柔和过渡 线性渐变:沿着某条直线发生渐变效果 注意:渐变准备来说是一张背景图 语法:linear-gradient */ background-image: lin ...