OpenCV 编程简介(矩阵/图像/视频的基本读写操作)

PS. 由于csdn博客文章长度有限制,本文有部分内容被截掉了。
在OpenCV中文网站的wiki上有可读性更好、并且是完整的版本,欢迎浏览。

OpenCV Wiki :《OpenCV 编程简介(矩阵/图像/视频的基本读写操作)》

Introduction to programming with OpenCV
OpenCV编程简介

Gady Agam
Department of Computer Science
January 27, 2006
Illinois Institute of Technology

-- URL: http://www.cs.iit.edu/~agam/cs512/lect-notes/opencv-intro/opencv-intro.html#SECTION00040000000000000000

译: chenyusiyuan
-- January 26, 2010
-- http://blog.csdn.net/chenyusiyuan

摘要:
本文旨在帮助读者快速入门OpenCV,而无需阅读冗长的参考手册。掌握了OpenCV的以下基础知识后,有需要的话再查阅相关的参考手册。

目录
一 简介
o OpenCV的特点
o 有用的学习资源
o 命名规则
o 编译建议
o 一个例程

二 GUI命令
o 窗口管理
o 输入处理

三 OpenCV基本的数据结构
o 图像数据结构
o 矩阵与向量
o 其它数据结构

四 图像处理
o 内存分配与释放
o 读取和写入图像
o 访问图像像素
o 图像转换
o 绘图指令

五 矩阵处理
o 内存分配与释放
o 访问矩阵元素
o 矩阵/向量运算

六 视频处理
o 视频的帧捕捉
o 帧信息的读取与设置
o 保存视频文件

=================================================
一、简介
1、OpenCV的特点
(1) 总体描述
o OpenCV是一个基于C/C++语言的开源图像处理函数库
o 其代码都经过优化,可用于实时处理图像
o 具有良好的可移植性
o 可以进行图像/视频载入、保存和采集的常规操作
o 具有低级和高级的应用程序接口(API)
o 提供了面向Intel IPP高效多媒体函数库的接口,可针对你使用的Intel CPU优化代码,提高程序性能(译注:OpenCV 2.0版的代码已显著优化,无需IPP来提升性能,故2.0版不再提供IPP接口)

(2) 功能
o 图像数据操作(内存分配与释放,图像复制、设定和转换)
Image data manipulation (allocation, release, copying, setting, conversion).
o 图像/视频的输入输出(支持文件或摄像头的输入,图像/视频文件的输出)
Image and video I/O (file and camera based input, image/video file output).
o 矩阵/向量数据操作及线性代数运算(矩阵乘积、矩阵方程求解、特征值、奇异值分解)
Matrix and vector manipulation and linear algebra routines (products, solvers, eigenvalues, SVD).
o 支持多种动态数据结构(链表、队列、数据集、树、图)
Various dynamic data structures (lists, queues, sets, trees, graphs).
o 基本图像处理(去噪、边缘检测、角点检测、采样与插值、色彩变换、形态学处理、直方图、图像金字塔结构)
Basic image processing (filtering, edge detection, corner detection, sampling and interpolation, color conversion, morphological operations, histograms, image pyramids).
o 结构分析(连通域/分支、轮廓处理、距离转换、图像矩、模板匹配、霍夫变换、多项式逼近、曲线拟合、椭圆拟合、狄劳尼三角化)
Structural analysis (connected components, contour processing, distance transform, various moments, template matching, Hough transform, polygonal approximation, line fitting, ellipse fitting, Delaunay triangulation).
o 摄像头定标(寻找和跟踪定标模式、参数定标、基本矩阵估计、单应矩阵估计、立体视觉匹配)
Camera calibration (finding and tracking calibration patterns, calibration, fundamental matrix estimation, homography estimation, stereo correspondence).
o 运动分析(光流、动作分割、目标跟踪)
Motion analysis (optical flow, motion segmentation, tracking).
o 目标识别(特征方法、HMM模型)Object recognition (eigen-methods, HMM).
o 基本的GUI(显示图像/视频、键盘/鼠标操作、滑动条)
Basic GUI (display image/video, keyboard and mouse handling, scroll-bars).
o 图像标注(直线、曲线、多边形、文本标注)
Image labeling (line, conic, polygon, text drawing)

(3) OpenCV模块
o cv – 核心函数库
o cvaux – 辅助函数库
o cxcore – 数据结构与线性代数库
o highgui – GUI函数库
o ml – 机器学习函数库

2、有用的学习资源
(1) 参考手册:
o /docs/index.htm (译注:在你的OpenCV安装目录内)
? 网络资源:
o 官方网站: http://www.intel.com/technology/computing/opencv/

o 软件下载: http://sourceforge.net/projects/opencvlibrary/

(2) 书籍:
o Open Source Computer Vision Library
by Gary R. Bradski, Vadim Pisarevsky, and Jean-Yves Bouguet, Springer, 1st ed. (June, 2006).
chenyusiyuan: 补充以下书籍
o Learning OpenCV - Computer Vision with the OpenCV Library
by Gary Bradski & Adrian Kaehler, O'Reilly Media, 1 st ed. (September, 2008).
o OpenCV教程——基础篇
作者:刘瑞祯 于仕琪,北京航空航天大学出版社,出版日期:200706
(3) 视频处理例程(在 /samples/c/):
o 颜色跟踪: camshiftdemo
o 点跟踪: lkdemo
o 动作分割: motempl
o 边缘检测: laplace
(4) 图像处理例程 (在 /samples/c/):
o 边缘检测: edge
o 图像分割: pyramid_segmentation
o 形态学: morphology
o 直方图: demhist
o 距离变换: distrans
o 椭圆拟合: fitellipse

3、OpenCV 命名规则
(1) 函数名:

cvActionTargetMod(...)

Action = 核心功能(core functionality) (e.g. set, create)
Target = 目标图像区域(target image area) (e.g. contour, polygon)
Mod = (可选的)调整语(optional modifiers) (e.g. argument type)


(2) 矩阵数据类型:

CV_(S|U|F)C

S = 符号整型
U = 无符号整型
F = 浮点型

E.g.: CV_8UC1 是指一个8位无符号整型单通道矩阵,
CV_32FC2是指一个32位浮点型双通道矩阵.

(3) 图像数据类型:

IPL_DEPTH_(S|U|F)

E.g.: IPL_DEPTH_8U 图像像素数据是8位无符号整型.
IPL_DEPTH_32F图像像素数据是32位浮点型.

(4) 头文件:

#include
#include
#include
#include
#include // 一般不需要,cv.h 内已包含该头文件 4、编译建议
(1) Linux:

g++ hello-world.cpp -o hello-world /
-I /usr/local/include/opencv -L /usr/local/lib /
-lm -lcv -lhighgui -lcvaux
(2) Windows:
在Visual Studio的‘选项’和‘项目’中设置好OpenCV相关文件的路径。

5、C例程

////////////////////////////////////////////////////////////////////////
//
// hello-world.cpp
//
// 该程序从文件中读入一幅图像,将之反色,然后显示出来.
//
////////////////////////////////////////////////////////////////////////
#include
#include
#include
#include
#include

int main(int argc, char *argv[])
{
IplImage* img = 0;
int height,width,step,channels;
uchar *data;
int i,j,k;

if(argc<2){
printf("Usage: main /n/7");
exit(0);
}

// load an image
img=cvLoadImage(argv[1]);
if(!img){
printf("Could not load image file: %s/n",argv[1]);
exit(0);
}

// get the image data
height = img->height;
width = img->width;
step = img->widthStep;
channels = img->nChannels;
data = (uchar *)img->imageData;
printf("Processing a %dx%d image with %d channels/n",height,width,channels);

// create a window
cvNamedWindow("mainWin", CV_WINDOW_AUTOSIZE);
cvMoveWindow("mainWin", 100, 100);

// invert the image
// 相当于 cvNot(img);
for(i=0;i data[i*step+j*channels+k]=255-data[i*step+j*channels+k];

// show the image
cvShowImage("mainWin", img );

// wait for a key
cvWaitKey(0);

// release the image
cvReleaseImage(&img );
return 0;
}


=================================================
二、GUI 指令
1、窗口管理
(1) 创建和定位一个新窗口:

cvNamedWindow("win1", CV_WINDOW_AUTOSIZE);
cvMoveWindow("win1", 100, 100); // offset from the UL corner of the screen
(2) 载入图像:

IplImage* img=0;
img=cvLoadImage(fileName);
if(!img) printf("Could not load image file: %s/n",fileName);

(3) 显示图像:

cvShowImage("win1",img);
该函数可以显示彩色或灰度的字节型/浮点型图像。字节型图像像素值范围为[0-255];浮点型图像像素值范围为[0-1]。彩色图像的三色元素按BGR(蓝-红-绿)顺序存储。
(4) 关闭窗口:

cvDestroyWindow("win1");
(5) 改变窗口大小:

cvResizeWindow("win1",100,100); // new width/heigh in pixels2、输入处理
(1) 处理鼠标事件:
o 定义一个鼠标处理程序:

void mouseHandler(int event, int x, int y, int flags, void* param)
{
switch(event){
case CV_EVENT_LBUTTONDOWN:
if(flags & CV_EVENT_FLAG_CTRLKEY)
printf("Left button down with CTRL pressed/n");
break;

case CV_EVENT_LBUTTONUP:
printf("Left button up/n");
break;
}
}
x,y: 相对于左上角的像素坐标

event: CV_EVENT_LBUTTONDOWN, CV_EVENT_RBUTTONDOWN, CV_EVENT_MBUTTONDOWN,
CV_EVENT_LBUTTONUP, CV_EVENT_RBUTTONUP, CV_EVENT_MBUTTONUP,
CV_EVENT_LBUTTONDBLCLK, CV_EVENT_RBUTTONDBLCLK, CV_EVENT_MBUTTONDBLCLK,
CV_EVENT_MOUSEMOVE:

flags: CV_EVENT_FLAG_CTRLKEY, CV_EVENT_FLAG_SHIFTKEY, CV_EVENT_FLAG_ALTKEY,
CV_EVENT_FLAG_LBUTTON, CV_EVENT_FLAG_RBUTTON, CV_EVENT_FLAG_MBUTTON
o 注册该事件处理程序:

mouseParam=5;
cvSetMouseCallback("win1",mouseHandler,&mouseParam);
(2) 处理键盘事件:
o 实际上对于键盘输入并没有专门的事件处理程序.
o 按一定间隔检测键盘输入(适用于循环体中):

int key;
key=cvWaitKey(10); // wait 10ms for input
o 中止程序等待键盘输入:

int key;
key=cvWaitKey(0); // wait indefinitely for input
o 键盘输入的循环处理程序:

while(1){
key=cvWaitKey(10);
if(key==27) break;

switch(key){
case 'h':
...
break;
case 'i':
...
break;
}
}
(3) 处理滑动条事件:
o 定义一个滑动条处理程序:

void trackbarHandler(int pos)
{
printf("Trackbar position: %d/n",pos);
}
o 注册该事件处理程序:

int trackbarVal=25;
int maxVal=100;
cvCreateTrackbar("bar1", "win1", &trackbarVal ,maxVal , trackbarHandler);
o 获取当前的滑动条位置:

int pos = cvGetTrackbarPos("bar1","win1");
o 设置滑动条位置:

cvSetTrackbarPos("bar1", "win1", 25);=================================================
三、OpenCV的基本数据结构
(译注:OpenCV 1.1、1.2或2.0版本中各数据结构的结构体元素有所调整,以下仅作参考)
1、图像数据结构
(1) IPL 图像:

IplImage
|-- int nChannels; // 颜色通道数目 (1,2,3,4)
|-- int depth; // 像素的位深:
| // IPL_DEPTH_8U, IPL_DEPTH_8S,
| // IPL_DEPTH_16U,IPL_DEPTH_16S,
| // IPL_DEPTH_32S,IPL_DEPTH_32F,
| // IPL_DEPTH_64F
|-- int width; // 图像宽度(像素为单位)
|-- int height; // 图像高度
|-- char* imageData; // 图像数据指针
| // 注意彩色图像按BGR顺序存储数据
|-- int dataOrder; // 0 - 将像素点不同通道的值交错排在一起,形成单一像素平面
| // 1 - 把所有像素同通道值排在一起,形成若干个通道平面,再把平面排列起来
| // cvCreateImage 只能创建像素交错排列式的图像
|-- int origin; // 0 – 像素原点为左上角,
| // 1 – 像素原点为左下角 (Windows bitmaps style)
|-- int widthStep; // 相邻行的同列点之间的字节数
|-- int imageSize; // 图像的大小(字节为单位) = height*widthStep
|-- struct _IplROI *roi;// 图像的感兴趣区域(ROI). ROI非空时对图像的
| // 处理仅限于ROI区域.
|-- char *imageDataOrigin; // 图像数据未对齐时的数据原点指针
| // (需要正确地重新分配图像内存 )
| // (needed for correct image deallocation)
|-- int align; // 图像数据的行对齐: 4 or 8 byte alignment
| // OpenCV 中无此项,采用widthStep代替
|-- char colorModel[4]; // 颜色模型 – OpenCV中忽略此项
2、矩阵与向量
(1) 矩阵:

CvMat // 2D 矩阵
|-- int type; // 元素类型 (uchar,short,int,float,double) 与标志
|-- int step; // 整行长度字节数
|-- int rows, cols; // 行、列数
|-- int height, width; // 矩阵高度、宽度,与rows、cols对应
|-- union data;
|-- uchar* ptr; // data pointer for an unsigned char matrix
|-- short* s; // data pointer for a short matrix
|-- int* i; // data pointer for an integer matrix
|-- float* fl; // data pointer for a float matrix
|-- double* db; // data pointer for a double matrixCvMatND // N-维矩阵
|-- int type; // 元素类型 (uchar,short,int,float,double) 与标志
|-- int dims; // 矩阵维数
|-- union data;
| |-- uchar* ptr; // data pointer for an unsigned char matrix
| |-- short* s; // data pointer for a short matrix
| |-- int* i; // data pointer for an integer matrix
| |-- float* fl; // data pointer for a float matrix
| |-- double* db; // data pointer for a double matrix
|
|-- struct dim[]; // 各维信息
|-- size; // 元素数目
|-- step; // 元素间距(字节为单位)CvSparseMat // N-维稀疏矩阵
(2) 一般矩阵:

CvArr* // 仅作为函数定义的参数使用,
// 表明函数可以接受不同类型的矩阵作为参数,
// 例如:IplImage*, CvMat* 甚至是 CvSeq*.
// 矩阵的类型通过矩阵头的前4个字节信息来确定
(3) 标量:

CvScalar
|-- double val[4]; //4D 向量
初始化函数:

CvScalar s = cvScalar(double val0, double val1=0, double val2=0, double val3=0);
// Example:
CvScalar s = cvScalar(20.0);
s.val[0]=10.0;
注意该初始化函数的函数名与对应的结构体名称几乎同名,差别仅在于函数名第一个字母是小写的,而结构体名第一个字母是大写的。它并不是一个 C++ 构造函数。(译注:类似的还有 cvMat 与 CvMat、cvPoint 与 CvPoint 等等)

3、其它结构类型
(1) 点:

CvPoint p = cvPoint(int x, int y);
CvPoint2D32f p = cvPoint2D32f(float x, float y);
CvPoint3D32f p = cvPoint3D32f(float x, float y, float z);E.g.:
p.x=5.0;
p.y=5.0;
(2) 矩形框大小(以像素为精度):

CvSize r = cvSize(int width, int height);
CvSize2D32f r = cvSize2D32f(float width, float height);
(3) 矩形框的偏置和大小:

CvRect r = cvRect(int x, int y, int width, int height);=================================================
四、图像处理
1、图像的内存分配与释放
(1) 分配内存给一幅新图像:

IplImage* cvCreateImage(CvSize size, int depth, int channels); size: cvSize(width,height);

depth: 像素深度: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U,
IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F, IPL_DEPTH_64F

channels: 像素通道数. Can be 1, 2, 3 or 4.
各通道是交错排列的. 一幅彩色图像的数据排列格式如下:
b0 g0 r0 b1 g1 r1 ...
示例:

// Allocate a 1-channel byte image
IplImage* img1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);

// Allocate a 3-channel float image
IplImage* img2=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);


(2) 释放图像:

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
cvReleaseImage(&img);
(3) 复制图像:

IplImage* img1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
IplImage* img2;
img2=cvCloneImage(img1); // 注意通过cvCloneImage得到的图像
// 也要用 cvReleaseImage 释放,否则容易产生内存泄漏
(4) 设置/获取感兴趣区域ROI:

void cvSetImageROI(IplImage* image, CvRect rect);
void cvResetImageROI(IplImage* image);
vRect cvGetImageROI(const IplImage* image);大多数OpenCV函数都支持 ROI.
(5) 设置/获取感兴趣通道COI:

void cvSetImageCOI(IplImage* image, int coi); // 0=all
int cvGetImageCOI(const IplImage* image);大多数OpenCV函数不支持 COI.

2、图像读写
(1) 从文件中读入图像:

IplImage* img=0;
img=cvLoadImage(fileName);
if(!img) printf("Could not load image file: %s/n",fileName); 支持的图像格式: BMP, DIB, JPEG, JPG, JPE, PNG, PBM, PGM, PPM,
SR, RAS, TIFF, TIF
OpenCV默认将读入的图像强制转换为一幅三通道彩色图像. 不过可以按以下方法修改读入方式:

img=cvLoadImage(fileName,flag); flag: >0 将读入的图像强制转换为一幅三通道彩色图像
=0 将读入的图像强制转换为一幅单通道灰度图像
<0 读入的图像通道数与所读入的文件相同.
(2) 保存图像:

if(!cvSaveImage(outFileName,img)) printf("Could not save: %s/n", outFileName);保存的图像格式由 outFileName 中的扩展名确定.

3、访问图像像素
(1) 假设你要访问第k通道、第i行、第j列的像素。
(2) 间接访问: (通用,但效率低,可访问任意格式的图像)
o 对于单通道字节型图像:

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
CvScalar s;
s=cvGet2D(img,i,j); // get the (i,j) pixel value
printf("intensity=%f/n",s.val[0]);
s.val[0]=111;
cvSet2D(img,i,j,s); // set the (i,j) pixel value
o 对于多通道字节型/浮点型图像:

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
CvScalar s;
s=cvGet2D(img,i,j); // get the (i,j) pixel value
printf("B=%f, G=%f, R=%f/n",s.val[0],s.val[1],s.val[2]);
s.val[0]=111;
s.val[1]=111;
s.val[2]=111;
cvSet2D(img,i,j,s); // set the (i,j) pixel value
(3) 直接访问: (效率高,但容易出错)
o 对于单通道字节型图像:

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
((uchar *)(img->imageData + i*img->widthStep))[j]=111;

o 对于多通道字节型图像:

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0]=111; // B
((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1]=112; // G
((uchar *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2]=113; // R
o 对于多通道浮点型图像:

IplImage* img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 0]=111; // B
((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 1]=112; // G
((float *)(img->imageData + i*img->widthStep))[j*img->nChannels + 2]=113; // R
(4) 基于指针的直接访问: (简单高效)
o 对于单通道字节型图像:

IplImage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
int height = img->height;
int width = img->width;
int step = img->widthStep/sizeof(uchar);
uchar* data = (uchar *)img->imageData;
data[i*step+j] = 111;
o 对于多通道字节型图像:

IplImage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
int height = img->height;
int width = img->width;
int step = img->widthStep/sizeof(uchar);
int channels = img->nChannels;
uchar* data = (uchar *)img->imageData;
data[i*step+j*channels+k] = 111;
o 对于多通道浮点型图像(假设图像数据采用4字节(32位)行对齐方式):

IplImage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
int height = img->height;
int width = img->width;
int step = img->widthStep/sizeof(float);
int channels = img->nChannels;
float * data = (float *)img->imageData;
data[i*step+j*channels+k] = 111;
(5) 基于 c++ wrapper 的直接访问: (更简单高效)
o 首先定义一个 c++ wrapper ‘Image’,然后基于Image定义不同类型的图像:

template class Image
{
private:
IplImage* imgp;
public:
Image(IplImage* img=0) {imgp=img;}
~Image(){imgp=0;}
void operator=(IplImage* img) {imgp=img;}
inline T* operator[](const int rowIndx) {
return ((T *)(imgp->imageData + rowIndx*imgp->widthStep));}
};

typedef struct{
unsigned char b,g,r;
} RgbPixel;

typedef struct{
float b,g,r;
} RgbPixelFloat;

typedef Image RgbImage;
typedef Image



obj格式简介

我们经常见到的*.obj文件有两种:第一种是基于COFF(Common Object File Format)格式的OBJ文件(也称目标文件),这种格式用于编译应用程序;第二种是Alias|Wavefront公司推出的OBJ模型文件。我要讲的OBJ文件格式是指第二种-OBJ模型文件。  说起3D文件格式,大家一定不会感到陌生,"*.3ds","*.max","*.lw","*.mb","*.dxf","*.obj",相信人人都能列举出几种来。但是说起OBJ文件的具体特征,却很少有人能给出较为圆满的描述。 很多人认识OBJ文件是从使用Poser开始的,Poser是一款人体建模软件,要把Poser生成的人体导出到其它3D软件中进行再加工,就用到了OBJ文件。OBJ文件是一种标准的3D模型文件格式,很适合用于3D软件模型之间的互导。比如你在3dsMax或LightWave中建了一个模型,想把它调到Maya里面渲染或动画,导出OBJ文件就是一种很好的选择。目前几乎所有知名的3D软件都支持OBJ文件的读写,不过很多软件需要通过插件才能做到这一点。

另外,作为一种优秀的文件格式,很多游戏引擎也都支持OBJ文件的读取。 了解OBJ文件格式有什么用呢?如果你不学编程的话,用处确实不大。不过,3D软件模型之间的互导是一件很常见的事情,不幸的是,目前的3D软件模型导出功能都不那么完美,经常会出现缺面少线的情况,有时还会遇到导出的模型根本打不开的情况。如果情况非常紧急的话,你一定会不惜一切代价仔细研究,期望找到原因,解决问题。在这种情况下,我的教程也许会对你有很大帮助

OBJ文件是一种文本文件格式,这就意味着你可以直接用写字板打开进行查看修改,如果你能看懂每一行的内容是什么意思,相信距离你成功的解决问题已经不远了。

OBJ文件是Wavefront公司为它的一套基于工作站的3D建模和动画软件"Advanced Visualizer"开发的一种文件格式。

  OBJ新版本是v3.0,代替以前的v2.11版本。

  OBJ3.0格式支持多边形(Polygon),直线(Lines),表面(Surfaces),和自由形态曲线(Free-form Curves)。

直线和多角形通过它们的点来描述,曲线和表面则根据于它们的控制点和依附于曲线类型的额外信息来定义。这些信息支持规则和不规则的曲线,包括那些基于贝塞尔(Bezier)曲线,B样条(B-spline),基数(Cardinal/Catmull-Rom样条),和泰勒方程(Taylor equations)的曲线。

   OBJ文件 — 特点

  (1)OBJ是一种3D模型文件,因此不包含动画、材质特性、贴图路径、动力学、粒子等信息。

  (2)OBJ文件主要支持多边形(Polygons)模型。

  (3)OBJ文件支持三个点以上的面。

(4)OBJ文件支持法线和贴图坐标。

OBJ文件不支持有孔的多边形面

OBJ文件不包含面的颜色定义信息,不过可以引用材质库,材质库信息储存在一个后缀是".mtl"的独立文件中。关键字"mtllib"即材质库的意思。材质库中包含材质的漫射(diffuse),环境(ambient),光泽(specular)的定义值,   "usemtl"指定了材质之后,以后的面都是使用这一材质,直到遇到下一个"usemtl"来指定新的材质。

OBJ文件 — 基本结构

OBJ文件由一行行文本组成,注释行以一个“井”号(#)为开头,空格和空行可以随意加到文件中以增加文件的可读性。有字的行都由一两个标记字母也就是关键字(Keyword)开头,关键字可以说明这一行是什么样的数据。多行可以逻辑地连接在一起表示一行,方法是在每一行最后添加一个连接符(/)。

注意连接符(/)后面不能出现空格或tab格,否则将导致文件出错。

  下列关键字可以在OBJ文件使用。

  在这个列表中, 关键字根据数据类型排列,每个关键字有一段简短描述。

  顶点数据(Vertex data):

   v 几何体顶点 (Geometric vertices)

  vt 贴图坐标点 (Texture vertices)

  vn 顶点法线 (Vertex normals)

  vp 参数空格顶点 (Parameter space vertices)

  自由形态曲线(Free-form curve)/表面属性(surface attributes):

  deg 度 (Degree)

  bmat 基础矩阵 (Basis matrix)

  step 步尺寸 (Step size)

  cstype 曲线或表面类型 (Curve or surface type)

  元素(Elements):

  p 点 (Point)

  l 线 (Line)

  f 面 (Face)

  curv 曲线 (Curve)

  curv2 2D曲线 (2D curve)

  surf 表面 (Surface)

  自由形态曲线(Free-form curve)/表面主体陈述(surface body statements):

  parm 参数值 (Parameter values )

  trim 外部修剪循环 (Outer trimming loop)

  hole 内部整修循环 (Inner trimming loop)

  scrv 特殊曲线 (Special curve)

  sp 特殊的点 (Special point)

  end 结束陈述 (End statement)

  自由形态表面之间的连接(Connectivity between free-form surfaces):

  con 连接 (Connect)

-  成组(Grouping):

   g 组名称 (Group name)

  s 光滑组 (Smoothing group)

  mg 合并组 (Merging group)

  o 对象名称 (Object name)

-  显示(Display)/渲染属性(render attributes):

bevel 导角插值 (Bevel interpolation)

  c_interp 颜色插值 (Color interpolation)

  d_interp 溶解插值 (Dissolve interpolation)

  lod 细节层次 (Level of detail)

  usemtl 材质名称 (Material name)

  mtllib 材质库 (Material library)

  shadow_obj 投射阴影 (Shadow casting)

  trace_obj 光线跟踪 (Ray tracing)

  ctech 曲线近似技术 (Curve approximation technique)

  stech 表面近似技术 (Surface approximation technique)


vs2008 + OpenCV-2.1.0-win32-vs2008安装

vs2008 + OpenCV-2.1.0-win32-vs2008安装


1. 安装vs2008+sp1
2. 安装opencv-2.1.0-win32-vs2008
,假设安装目录为c:/opencv2.1。安装过程中注意选择添加环境变量,把 “add it to your Current User PATH “前的复选框勾上 .
3. 为vs2008配置openvc,过程如下:
工具->选项->项目和解决方案->vc++目录,
“显示一下内容的目录”下拉列表中选择“包含文件”,添加条目“C:/OpenCV2.1/include/opencv”;
“显示一下内容的目录”下拉列表中选择“库文件” ,添加条目“C:/OpenCV2.1/lib”;
"显示一下内容的目录"下拉列表选择“源文件”,添加条目”C:/OpenCV2.1/src/cv” ,”C:/OpenCV2.1/src/cvaux” ,”C:

/OpenCV2.1/src/cxcore” ,”C:/OpenCV2.1/src/highgui”。
点击“确定”。
4. 为单个工程配置运行环境,如:
(1) 新建一个win32命令控制台项目opencvhello
(2) 在解决方案资源管理器中右键点击项目名称opencvhello,选择“属性”,
在“配置(C)”下拉列表中选择Debug, 然后“配置属性”->“链接器”->“输入”->附加依赖项,添加 cxcore210d.lib

cv210d.lib highgui210d.lib
在“配置(C)”下拉列表中选择Release, 然后“配置属性”->“链接器”->“输入”->附加依赖项,添加 cxcore210.lib

cv210.lib highgui210.lib
中间如果提示要保存的话,就保存。最后点击确定。
(3) 测试。用下列代码代替源代码,注意imagename中保存的是图片的硬盘地址,程序的运行结果是显示imagename指向的图片。

/***********************************************************************
* OpenCV 2.0 测试例程
* 于仕琪 提供
***********************************************************************/

#include "stdafx.h"
#include "highgui.h"

//所有的以新风格命名的函数都在 cv 命名空间中
//如果希望不要每次都输入 cv:: ,则可使用下面语句
//using namespace cv;

int _tmain(int argc, _TCHAR* argv[])
{

const char* imagename = "E://OpenCV2.1//samples//c//lena.jpg";

cv::Mat img = cv::imread(imagename); // Matlab风格的 cvLoadImage 函数的另一种调用
if(img.empty())
{
fprintf(stderr, "Can not load image %s/n", imagename);
return -1;
}

if( !img.data ) // 检查是否正确载入图像
return -1;

cv::namedWindow("image", CV_WINDOW_AUTOSIZE); //创建窗口
cv::imshow("image", img); //显示图像

cv::waitKey();

return 0;
}


你可能感兴趣的:(OpenCV 编程简介(矩阵/图像/视频的基本读写操作))