分配图像空间:

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: 1, 2, 3 or 4.

注意数据为交叉存取.彩色图像的数据编排为b0 g0 r0 b1 g1 r1 ...

举例:

// 分配一个单通道字节图像
IplImage* img1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
// 分配一个三通道浮点图像
IplImage* img2=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);

释放图像空间:

IplImage*
img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
cvReleaseImage(&img);

复制图像:

IplImage*
img1=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
IplImage* img2;
img2=cvCloneImage(img1);

设定/获取兴趣区域:

void  cvSetImageROI(IplImage*
image, CvRect rect);
void  cvResetImageROI(IplImage*
image);
vRect cvGetImageROI(const IplImage* image);
大部分OpenCV函数都支持ROI.

设定/获取兴趣通道:

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

读取存储图像

从文件中载入图像:

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

Supported image formats: BMP, DIB, JPEG, JPG, JPE,
PNG, PBM, PGM, PPM,SR, RAS, TIFF, TIF

载入图像默认转为3通道彩色图像. 如果不是,则需加flag:

img=cvLoadImage(fileName,flag);

flag: >0 载入图像转为三通道彩色图像
      =0
载入图像转为单通道灰度图像
      <0
不转换载入图像(通道数与图像文件相同).

图像存储为图像文件:

if(!cvSaveImage(outFileName,img)) printf("Could not
save: %s\n",outFileName);

输入文件格式由文件扩展名决定.

存取图像元素

假设需要读取在i行j列像点的第k通道. 其中, 行数i的范围为[0, height-1],
列数j的范围为[0, width-1], 通道k的范围为[0, nchannels-1].

间接存取: (比较通用, 但效率低, 可读取任一类型图像数据)

对单通道字节图像:

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

对多通道浮点或字节图像:

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

直接存取: (效率高, 但容易出错)

对单通道字节图像:

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

对多通道字节图像:

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

对多通道浮点图像:

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

用指针直接存取 : (在某些情况下简单高效)

对单通道字节图像:

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;

对多通道字节图像:

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;

对单通道浮点图像(假设用4字节调整):

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;

使用 c++ wrapper 进行直接存取: (简单高效)

对单/多通道字节图像,多通道浮点图像定义一个 c++ wrapper:

template<class T>
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<RgbPixel>          
RgbImage;
typedef
Image<RgbPixelFloat>     
RgbImageFloat;
typedef Image<unsigned
char>   
  BwImage;
typedef
Image<float>             
BwImageFloat;

单通道字节图像:

IplImage*
img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);
BwImage imgA(img);
imgA[i][j] = 111;

多通道字节图像:

IplImage*
img=cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);
RgbImage     
imgA(img);
imgA[i][j].b = 111;
imgA[i][j].g = 111;
imgA[i][j].r = 111;

多通道浮点图像:

IplImage*
img=cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);
RgbImageFloat imgA(img);
imgA[i][j].b = 111;
imgA[i][j].g = 111;
imgA[i][j].r = 111;

图像转换

转为灰度或彩色字节图像:

cvConvertImage(src, dst, flags=0);
     
src = float/byte grayscale/color image
     
dst = byte grayscale/color image
     
flags =
CV_CVTIMG_FLIP        
(flip vertically)
             
CV_CVTIMG_SWAP_RB     
(swap the R and B channels)

转换彩色图像为灰度图像:

使用OpenCV转换函数:

cvCvtColor(cimg,gimg,CV_BGR2GRAY); // cimg
-> gimg

直接转换:

for(i=0;i<cimg->height;i++)
for(j=0;j<cimg->width;j++)
     
gimgA[i][j]= (uchar)(cimgA[i][j].b*0.114 +
                          
cimgA[i][j].g*0.587 +
                          
cimgA[i][j].r*0.299);

颜色空间转换:

cvCvtColor(src,dst,code); // src ->
dst
     
code       
=
CV_<X>2<Y>

<X>/<Y>
= RGB, BGR, GRAY, HSV, YCrCb, XYZ, Lab, Luv, HLS
e.g.: CV_BGR2GRAY, CV_BGR2HSV, CV_BGR2Lab

绘图命令

画长方体:

// 用宽度为1的红线在(100,100)与(200,200)之间画一长方体
cvRectangle(img, cvPoint(100,100), cvPoint(200,200),
cvScalar(255,0,0), 1);

画圆:

// 在(100,100)处画一半径为20的圆,使用宽度为1的绿线
cvCircle(img, cvPoint(100,100), 20, cvScalar(0,255,0), 1);

画线段:

// 在(100,100)与(200,200)之间画绿色线段,宽度为1
cvLine(img, cvPoint(100,100), cvPoint(200,200), cvScalar(0,255,0),
1);

画一组线段:

CvPoint     
curve1[]={10,10,     
10,100,     
100,100,     
100,10};
CvPoint     
curve2[]={30,30,     
30,130,     
130,130,     
130,30,     
150,10};
CvPoint* curveArr[2]={curve1, curve2};
int         
nCurvePts[2]={4,5};
int         
nCurves=2;
int         
isCurveClosed=1;
int         
lineWidth=1;
cvPolyLine(img,curveArr,nCurvePts,nCurves,isCurveClosed,cvScalar(0,255,255),lineWidth);

画内填充色的多边形:

cvFillPoly(img,curveArr,nCurvePts,nCurves,cvScalar(0,255,255));

添加文本:

CvFont font;
double hScale=1.0;
double vScale=1.0;
int       
lineWidth=1;
cvInitFont(&font,CV_FONT_HERSHEY_SIMPLEX|CV_FONT_ITALIC,
hScale,vScale,0,lineWidth);
cvPutText (img,"My comment",cvPoint(200,400),
&font, cvScalar(255,255,0));

Other possible fonts:

CV_FONT_HERSHEY_SIMPLEX,
CV_FONT_HERSHEY_PLAIN,
CV_FONT_HERSHEY_DUPLEX, CV_FONT_HERSHEY_COMPLEX,
CV_FONT_HERSHEY_TRIPLEX, CV_FONT_HERSHEY_COMPLEX_SMALL,
CV_FONT_HERSHEY_SCRIPT_SIMPLEX, CV_FONT_HERSHEY_SCRIPT_COMPLEX,

综述:
OpenCV有针对矩阵操作的C语言函数. 许多其他方法提供了更加方便的C++接口,其效率与OpenCV一样.

OpenCV将向量作为1维矩阵处理.

矩阵按行存储,每行有4字节的校整.

分配矩阵空间:

CvMat* cvCreateMat(int rows, int cols, int
type);
    
type: 矩阵元素类型.
格式为CV_<bit_depth>(S|U|F)C<number_of_channels>.

例如: CV_8UC1 表示8位无符号单通道矩阵, CV_32SC2表示32位有符号双通道矩阵.

例程:
    
CvMat* M = cvCreateMat(4,4,CV_32FC1);

释放矩阵空间:

CvMat* M = cvCreateMat(4,4,CV_32FC1);
cvReleaseMat(&M);

复制矩阵:

CvMat* M1 = cvCreateMat(4,4,CV_32FC1);
CvMat* M2;
M2=cvCloneMat(M1);

初始化矩阵:

double a[] = {
1,    
2,    
3,   
 4,
                 
5,    
6,    
7,    
8,
                 
9, 10, 11, 12 };
CvMat Ma=cvMat(3, 4, CV_64FC1, a);

另一种方法:

CvMat Ma;
cvInitMatHeader(&Ma, 3, 4, CV_64FC1, a);

初始化矩阵为单位阵:

CvMat* M = cvCreateMat(4,4,CV_32FC1);
cvSetIdentity(M); // 这里似乎有问题,不成功

存取矩阵元素

假设需要存取一个2维浮点矩阵的第(i,j)个元素.

间接存取矩阵元素:

cvmSet(M,i,j,2.0); // Set M(i,j)
t = cvmGet(M,i,j); // Get M(i,j)

直接存取,假设使用4-字节校正:

CvMat*
M      
= cvCreateMat(4,4,CV_32FC1);
int
n         
= M->cols;
float *data = M->data.fl;
data[i*n+j] = 3.0;

直接存取,校正字节任意:

CvMat*
M      
= cvCreateMat(4,4,CV_32FC1);
int     
step    
= M->step/sizeof(float);
float *data = M->data.fl;
(data+i*step)[j] = 3.0;

直接存取一个初始化的矩阵元素:

double a[16];
CvMat Ma = cvMat(3, 4, CV_64FC1, a);
a[i*4+j] = 2.0; // Ma(i,j)=2.0;

矩阵/向量操作

矩阵-矩阵操作:

CvMat *Ma, *Mb, *Mc;
cvAdd(Ma, Mb,
Mc);        
//
Ma+Mb     
-> Mc
cvSub(Ma, Mb,
Mc);        
//
Ma-Mb     
-> Mc
cvMatMul(Ma, Mb,
Mc);     
//
Ma*Mb     
-> Mc

按元素的矩阵操作:

CvMat *Ma, *Mb, *Mc;
cvMul(Ma, Mb,
Mc);        
//
Ma.*Mb    
-> Mc
cvDiv(Ma, Mb,
Mc);        
//
Ma./Mb    
-> Mc
cvAddS(Ma, cvScalar(-10.0), Mc); // Ma.-10 -> Mc

向量乘积:

double va[] = {1, 2, 3};
double vb[] = {0, 0, 1};
double vc[3];
CvMat Va=cvMat(3, 1, CV_64FC1, va);
CvMat Vb=cvMat(3, 1, CV_64FC1, vb);
CvMat Vc=cvMat(3, 1, CV_64FC1, vc);
double res=cvDotProduct(&Va,&Vb);
//
点乘:     
Va . Vb -> res
cvCrossProduct(&Va, &Vb,
&Vc);      
// 向量积: Va x Vb -> Vc
end{verbatim}

注意 Va, Vb, Vc 在向量积中向量元素个数须相同.

单矩阵操作:

CvMat *Ma, *Mb;
cvTranspose(Ma,
Mb);        
// transpose(Ma) -> Mb (不能对自身进行转置)
CvScalar t = cvTrace(Ma); // trace(Ma) ->
t.val[0]
double d =
cvDet(Ma);       
// det(Ma) -> d
cvInvert(Ma,
Mb);           
// inv(Ma) -> Mb

非齐次线性系统求解:

CvMat*
A    
= cvCreateMat(3,3,CV_32FC1);
CvMat*
x    
= cvCreateMat(3,1,CV_32FC1);
CvMat*
b    
= cvCreateMat(3,1,CV_32FC1);
cvSolve(&A, &b,
&x);      
// solve (Ax=b) for x

特征值分析(针对对称矩阵):

CvMat*
A    
= cvCreateMat(3,3,CV_32FC1);
CvMat*
E    
= cvCreateMat(3,3,CV_32FC1);
CvMat*
l    
= cvCreateMat(3,1,CV_32FC1);
cvEigenVV(&A, &E,
&l);    
// l = A的特征值 (降序排列)
                          
// E = 对应的特征向量 (每行)

奇异值分解SVD:

CvMat*
A    
= cvCreateMat(3,3,CV_32FC1);
CvMat*
U    
= cvCreateMat(3,3,CV_32FC1);
CvMat*
D    
= cvCreateMat(3,3,CV_32FC1);
CvMat*
V    
= cvCreateMat(3,3,CV_32FC1);
cvSVD(A, D, U, V, CV_SVD_U_T|CV_SVD_V_T); // A = U D V^T

标号使得 U 和 V 返回时被转置(若没有转置标号,则有问题不成功!!!).

视频序列操作

从视频序列中抓取一帧

OpenCV支持从摄像头或视频文件(AVI)中抓取图像.

从摄像头获取初始化:

CvCapture* capture = cvCaptureFromCAM(0); //
capture from video device #0

从视频文件获取初始化:

CvCapture* capture =
cvCaptureFromAVI("infile.avi");

抓取帧:

IplImage* img = 0;
if(!cvGrabFrame(capture)){                
// 抓取一帧
    
printf("Could not grab a frame\n\7");
    
exit(0);
}
img=cvRetrieveFrame(capture);             
// 恢复获取的帧图像

要从多个摄像头同时获取图像, 首先从每个摄像头抓取一帧.
在抓取动作都结束后再恢复帧图像.

释放抓取源:

cvReleaseCapture(&capture);

注意由设备抓取的图像是由capture函数自动分配和释放的. 不要试图自己释放它.

获取/设定帧信息

获取设备特性:

cvQueryFrame(capture); // this call is necessary to
get correct
                         
// capture properties
int
frameH      
= (int) cvGetCaptureProperty(capture,
CV_CAP_PROP_FRAME_HEIGHT);
int
frameW      
= (int) cvGetCaptureProperty(capture,
CV_CAP_PROP_FRAME_WIDTH);
int
fps         
= (int) cvGetCaptureProperty(capture, CV_CAP_PROP_FPS);
int numFrames = (int)
cvGetCaptureProperty(capture,    
CV_CAP_PROP_FRAME_COUNT);

所有帧数似乎只与视频文件有关. 用摄像头时不对,奇怪!!!.

获取帧信息:

float
posMsec     
=         
cvGetCaptureProperty(capture, CV_CAP_PROP_POS_MSEC);
int
posFrames     
= (int) cvGetCaptureProperty(capture,
CV_CAP_PROP_POS_FRAMES);
float
posRatio    
=         
cvGetCaptureProperty(capture, CV_CAP_PROP_POS_AVI_RATIO);

获取所抓取帧在视频序列中的位置, 从首帧开始按[毫秒]算. 或者从首帧开始从0标号,
获取所抓取帧的标号. 或者取相对位置,首帧为0,末帧为1, 只对视频文件有效.

设定所抓取的第一帧标号:

// 从视频文件相对位置0.9处开始抓取
cvSetCaptureProperty(capture, CV_CAP_PROP_POS_AVI_RATIO,
(double)0.9);

只对从视频文件抓取有效. 不过似乎也不成功!!!

存储视频文件

初始化视频存储器:

CvVideoWriter *writer = 0;
int isColor = 1;
int
fps       
=
25;    
// or 30
int
frameW    
= 640; // 744 for firewire cameras
int
frameH    
= 480; // 480 for firewire cameras
writer=cvCreateVideoWriter("out.avi",CV_FOURCC('P','I','M','1'),

fps,cvSize(frameW,frameH),isColor);

其他有效编码:

CV_FOURCC('P','I','M','1')      
= MPEG-1 codec
CV_FOURCC('M','J','P','G')      
= motion-jpeg codec (does not work well)
CV_FOURCC('M', 'P', '4', '2') = MPEG-4.2 codec
CV_FOURCC('D', 'I', 'V', '3') = MPEG-4.3 codec
CV_FOURCC('D', 'I', 'V', 'X') = MPEG-4 codec
CV_FOURCC('U', '2', '6', '3') = H263 codec
CV_FOURCC('I', '2', '6', '3') = H263I codec
CV_FOURCC('F', 'L', 'V', '1') = FLV1 codec

若把视频编码设为-1则将打开一个编码选择窗口(windows系统下).

存储视频文件:

IplImage* img = 0;
int nFrames = 50;
for(i=0;i<nFrames;i++){
    
cvGrabFrame(capture);            
// 抓取帧
    
img=cvRetrieveFrame(capture);    
// 恢复图像
    
cvWriteFrame(writer,img);        
// 将帧添加入视频文件
}

若想在抓取中查看抓取图像, 可在循环中加入下列代码:

cvShowImage("mainWin", img);
key=cvWaitKey(20);             
// wait 20 ms

若没有20[毫秒]延迟,将无法正确显示视频序列.

释放视频存储器:

cvReleaseVideoWriter(&writer);

一些常用的opencv函数的更多相关文章

  1. 常用的OpenCV函数速查

    常用的OpenCV函数速查 1.cvLoadImage:将图像文件加载至内存: 2.cvNamedWindow:在屏幕上创建一个窗口: 3.cvShowImage:在一个已创建好的窗口中显示图像: 4 ...

  2. OpenCV常用数据结构和函数

    点的表示:Point类 Point类数据结构表示二维坐标系下的点,即由其图像坐标x,y指定的2D点. 用法如下 Point point; point.x = 10; point.y = 8; 或者 P ...

  3. 常用的WinAPI函数整理

    常用的WinAPI函数整理 一.进程  创建进程:    CreateProcess("C:\\windows\\notepad.exe",0,0,0,0,0,0,0,&s ...

  4. 最常用的截取函数有left,right,substring

    最常用的截取函数有left,right,substring 1.LEFT ( character_expression , integer_expression ) 返回从字符串左边开始指定个数的字符 ...

  5. Appium常用的API函数

    在学习应用一个框架之前,应该了解一下这个框架的整体结构或是相应的API函数.这篇文章还不错:http://blog.sina.com.cn/s/blog_68f262210102vzf9.html,就 ...

  6. MYSQL常用内置函数详解说明

    函数中可以将字段名当作变量来用,变量的值就是该列对应的所有值:在整理98在线字典数据时(http://zidian.98zw.com/),有这要一个需求,想从多音字duoyinzi字段值提取第一个拼音 ...

  7. 常用的Sql 函数

    常用的Sql 函数 1: replace 函数,替换字符. 语法 replace (original-string, search-string, replace-string ) 第一个参数你的字符 ...

  8. 【python游戏编程之旅】第四篇---pygame中加载位图与常用的数学函数。

    本系列博客介绍以python+pygame库进行小游戏的开发.有写的不对之处还望各位海涵. 在上一篇博客中,我们学习了pygame事件与设备轮询.http://www.cnblogs.com/msxh ...

  9. 常用的sql函数

    常用的sql函数 concat('hello','world') 结果:helloworld  作用:拼接 substr('helloworld',1,5)      hello           ...

随机推荐

  1. MVC5 Entity Framework学习之实现主要的CRUD功能

    在上一篇文章中,我们使用Entity Framework 和SQL Server LocalDB创建了一个MVC应用程序,并使用它来存储和显示数据.在这篇文章中,你将对由 MVC框架自己主动创建的CR ...

  2. mongodb 初学 目录

    mongodb 初学 索引 啦啦啦 MongoDB 教程 NoSQL 简介 MongoDB 简介 Windows 平台安装 MongoDB Linux平台安装MongoDB mongodb 在 Ubu ...

  3. 8 -- 深入使用Spring -- 2...1 搜索Bean类

    8.2.1 搜索Bean类 既然不再使用Spring配置文件来配置任何Bean实例,那么只能希望Spring会自动搜索某些路径下的Java类,并将这些Java类注册成Bean实例. tips:Rail ...

  4. 有人在群里问关于SQL表组合数据问题

    他的问题如下 如此我建表如下: 如果想根据用户进行分组后 又要显示所属门店在同一个字段中的话,这里需要用group_concat来显示 同时关联的时候可用find_in_set来处理 我设计的SQL如 ...

  5. iOS开发--提交应用Your binary is not optimized for iPhone 5

    ERROR ITMS-: "Your binary is not optimized for iPhone 5 - New iPhone apps and app updates submi ...

  6. java.util.concurrent.RejectedExecutionException 线程池饱和

    java.util.concurrent.RejectedExecutionException at java.util.concurrent.ThreadPoolExecutor$AbortPoli ...

  7. 无刷新上传图片以及使用C#语言

    写这个纯属是给自己一个记忆啦 一.前台的代码以及调用的js <!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtm ...

  8. zip&unzip范例

    范例: zip命令可以用来将文件压缩成为常用的zip格式.unzip命令则用来解压缩zip文件. 1. 我想把一个文件abc.txt和一个目录dir1压缩成为yasuo.zip: # zip -r y ...

  9. .net webservices 代理类生成命令

    wsdl.exe /l:cs /out:d:/WxPayment.cs http://localhost/WxPayment.asmx

  10. Material Design系列第六篇——Defining Custom Animations

    Defining Custom Animations //自定义动画 This lesson teaches you to //本节课知识点 Customize Touch Feedback //1. ...