Opencv step by step - 基本数据类型
CvArr,CvMat,IplImage这三者是继承的关系。
打开opencv 3.0的源码:
cvArr
/* CvArr* is used to pass arbitrary
* array-like data structures
* into functions where the particular
* array type is recognized at runtime:
*/
typedef void CvArr;
oh god,它是可变类型的数据
cvMat
再看一下cvMat。
typedef struct CvMat
{
int type;
int step; /* for internal use only */
int* refcount;
int hdr_refcount; union
{
uchar* ptr;
short* s;
int* i;
float* fl;
double* db;
} data; #ifdef __cplusplus
union
{
int rows;
int height;
}; union
{
int cols;
int width;
};
#else
int rows;
int cols;
#endif #ifdef __cplusplus
CvMat() {}
CvMat(const CvMat& m) { memcpy(this, &m, sizeof(CvMat));}
CvMat(const cv::Mat& m);
#endif }
CvMat;
这里先不管C++了,纯c的做法是:
typedef struct CvMat
{
int type;
int step; /* for internal use only */
int* refcount;
int hdr_refcount; union
{
uchar* ptr;
short* s;
int* i;
float* fl;
double* db;
} data; int rows;
int cols; }
CvMat;
这里,cvMat有几个属性,到底是干什么的呢?
可以看看它的初始化函数:
CV_INLINE CvMat cvMat( int rows, int cols, int type, void* data CV_DEFAULT(NULL))
{
CvMat m; assert( (unsigned)CV_MAT_DEPTH(type) <= CV_64F );
type = CV_MAT_TYPE(type);
m.type = CV_MAT_MAGIC_VAL | CV_MAT_CONT_FLAG | type;
m.cols = cols;
m.rows = rows;
m.step = m.cols*CV_ELEM_SIZE(type);
m.data.ptr = (uchar*)data;
m.refcount = NULL;
m.hdr_refcount = 0; return m;
}
看了之后恍然大悟:
type是矩阵中每一个数据点的类型。
cols是矩阵的列数。
rows当然是行数。
step是每一行的数据大小(应该是byte数吧)。
data是一个union的类型,里面是不同类型的指针,这样做的目的应该是可以接收 不同的数据类型吧。
比如你传了一个float*的指针进去,他就是float*了,反正这个联合体的大小就是sizeof(pointer) = 4了
internal use的先不管了。
在其他版本中把rows和height写在union里面的做法应该是做变量的兼容性吧。
IplImage
下面来重点看一下这个结构体:
typedef struct
#ifdef __cplusplus
CV_EXPORTS
#endif
_IplImage
{
int nSize; /* sizeof(IplImage) */
int ID; /* version (=0)*/
int nChannels; /* Most of OpenCV functions support 1,2,3 or 4 channels */
int alphaChannel; /* Ignored by OpenCV */
int depth; /* Pixel depth in bits: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16S,
IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F are supported. */
char colorModel[4]; /* Ignored by OpenCV */
char channelSeq[4]; /* ditto */
int dataOrder; /* 0 - interleaved color channels, 1 - separate color channels.
cvCreateImage can only create interleaved images */
int origin; /* 0 - top-left origin,
1 - bottom-left origin (Windows bitmaps style). */
int align; /* Alignment of image rows (4 or 8).
OpenCV ignores it and uses widthStep instead. */
int width; /* Image width in pixels. */
int height; /* Image height in pixels. */
struct _IplROI *roi; /* Image ROI. If NULL, the whole image is selected. */
struct _IplImage *maskROI; /* Must be NULL. */
void *imageId; /* " " */
struct _IplTileInfo *tileInfo; /* " " */
int imageSize; /* Image data size in bytes
(==image->height*image->widthStep
in case of interleaved data)*/
char *imageData; /* Pointer to aligned image data. */
int widthStep; /* Size of aligned image row in bytes. */
int BorderMode[4]; /* Ignored by OpenCV. */
int BorderConst[4]; /* Ditto. */
char *imageDataOrigin; /* Pointer to very origin of image data
(not necessarily aligned) -
needed for correct deallocation */ #ifdef __cplusplus
_IplImage() {}
_IplImage(const cv::Mat& m);
#endif
}
IplImage;
可以看出来,这个结构体和cvMat很像。
下面通过实际操作来understand一下这个结构体:
#include <cv.h>
#include <highgui.h> #define u8 unsigned char void image_operation(IplImage *image)
{
printf("nchannels:%d\n",image->nChannels);
printf("depth:%d\n",image->depth);
/* ./modules/core/include/opencv2/core/types_c.h:
* #define IPL_DATA_ORDER_PIXEL 0
*/
printf("dataOrder:%d\n",image->dataOrder);
printf("width:%d\n",image->width);
printf("height:%d\n",image->height);
printf("origin:%d\n",image->origin);
printf("widthStep:%d\n",image->widthStep); for (int y = 0; y<image->height ; y++) {
u8* row = (u8*)(image->imageData + y*image->widthStep);
for(int x = 0; x<image->width; x++) {
row[3*x + 1] = 0;
row[3*x + 2] = 0;
}
}
} int main(int argc,char **argv)
{ printf("this is image transforming plus\n");
IplImage *image;
image = cvLoadImage(argv[1]);
if(argc != 2)
{
std::cout << "No image data\n";
return -1;
} cvNamedWindow("image input");
cvNamedWindow("image output");
cvShowImage("image input", image);
image_operation(image);
cvShowImage("image output", image);
cvReleaseImage(&image);
cvWaitKey(0);
cvDestroyWindow("image input");
cvDestroyWindow("image output"); return 0;
}
这里读取一个图像,并且将两个通道变成0,结果如下:
tan@ubuntu:~/cv$ ./TransformImage image/1.jpg
this is image transforming plus
nchannels:3
depth:8
dataOrder:0
width:400
height:300
origin:0
widthStep:1200
从结果来看,这里把蓝色通道提取了,再次验证一下就可以发现opencv的存储是 BGR 顺序存储的。
重要的一个变量是image->widthStep,因为opencv会把图像数据4字节对齐,每过一行需要加上这个值而不是自己进行处理。
Opencv step by step - 基本数据类型的更多相关文章
- EF框架step by step(7)—Code First DataAnnotations(1)
Data annotation特性是在.NET 3.5中引进的,给ASP.NET web应用中的类提供了一种添加验证的方式.Code First允许你使用代码来建立实体框架模型,同时允许用Data a ...
- WPF Step By Step 自定义模板
WPF Step By Step 自定义模板 回顾 上一篇,我们简单介绍了几个基本的控件,本节我们将讲解每个控件的样式的自定义和数据模板的自定义,我们会结合项目中的具体的要求和场景来分析,给出我们实现 ...
- WPF Step By Step 控件介绍
WPF Step By Step 控件介绍 回顾 上一篇,我们主要讨论了WPF的几个重点的基本知识的介绍,本篇,我们将会简单的介绍几个基本控件的简单用法,本文会举几个项目中的具体的例子,结合这些 例子 ...
- 数据库设计 Step by Step (2)——数据库生命周期
引言:数据库设计 Step by Step (1)得到这么多朋友的关注着实出乎了我的意外.这也坚定了我把这一系列的博文写好的决心.近来工作上的事务比较繁重,加之我期望这个系列的文章能尽可能的系统.完整 ...
- Step By Step(Lua元表与元方法)
Step By Step(Lua元表与元方法) Lua中提供的元表是用于帮助Lua数据变量完成某些非预定义功能的个性化行为,如两个table的相加.假设a和b都是table,通过元表可以定义如何计算表 ...
- Step by step Dynamics CRM 2011升级到Dynamics CRM 2013
原创地址:http://www.cnblogs.com/jfzhu/p/4018153.html 转载请注明出处 (一)检查Customizations 从2011升级到2013有一些legacy f ...
- Step by Step 创建一个新的Dynamics CRM Organization
原创地址:http://www.cnblogs.com/jfzhu/p/4012833.html 转载请注明出处 前面演示过如何安装Dynamics CRM 2013,参见<Step by st ...
- Step by step Install a Local Report Server and Remote Report Server Database
原创地址:http://www.cnblogs.com/jfzhu/p/4012097.html 转载请注明出处 前面的文章<Step by step SQL Server 2012的安装 &g ...
- Step by step Dynamics CRM 2013安装
原创地址:http://www.cnblogs.com/jfzhu/p/4008391.html 转载请注明出处 SQL Server可以与CRM装在同一台计算机上,也可安装在不同的计算机上.演示 ...
- Step by step 活动目录中添加一个子域
原创地址:http://www.cnblogs.com/jfzhu/p/4006545.html 转载请注明出处 前面介绍过如何创建一个域,下面再介绍一下如何在该父域中添加一个子域. 活动目录中的森林 ...
随机推荐
- 设计模式 --- 模型-视图-控制器(Model View Controller)
模型-视图-控制器(Model-View-Controller,MVC)是Xerox PARC在20世纪80年代为编程语言Smalltalk-80发明的一种软件设计模式,至今已广泛应用于用户交互应用程 ...
- MySQL数据库初识(二)
8. 向数据表中插入数据记录(INSERT): 向数据表中插入数据记录有两种方法: 基本语法1:INSERT INTO 数据表 (字段名1,字段名2,字段名3……字段名n) VALUES (数据值1, ...
- for循环练习题
■■■■■■■■■■■■■■■■■■■■■■■■■ 代码: <script> for(i=0;i<5;i++) { for(j=0;j<5;j++) { document.wr ...
- javascript简介和基本语法
javascript简介 1.javascript是个脚本语言,需要有宿主文件,他的宿主文件是html文件. 用法:为了保险起见一般写在</html>之后<javascript ...
- 关于Solr搜索标点与符号的中文分词你必须知道的(mmseg源码改造)
关于Solr搜索标点与符号的中文分词你必须知道的(mmseg源码改造) 摘要:在中文搜索中的标点.符号往往也是有语义的,比如我们要搜索“C++”或是“C#”,我们不希望搜索出来的全是“C”吧?那样对程 ...
- jQuery Form 表单提交插件-----ajaxSubmit() 的应用
Form Plugin API 里提供了很多有用的方法可以让你轻松的处理表单里的数据和表单的提交过程. 测试环境:部署到Tomcat中的web项目. 一.ajaxSubmit() 介绍 立即通过AJ ...
- 启动rabbitmq web管理后台插件
安装完rabbitmq server之后,访问http://server_ip:15672/ 无法打开网页, 通过netstat -ano |grep 15672 查看此端口号并没有开启 需要启用 ...
- Lua面向对象编程
Lua中的table就是一种对象,看以下一段简单的代码: , b = } , b = } local tb3 = tb1 if tb1 == tb2 then print("tb1 == t ...
- SQL 分页查询的四种方法
方法一 假设现在有这样的一张表: CREATE TABLE test ( id int primary key not null identity, names ) ) 然后向里面插入大约100条数据 ...
- runc create container 流程分析
1.// runc/create.go Action: func(context *cli.Context) error 首先调用spec, err := setupSpec(context)加载配置 ...