天天看点

对视频流进行边缘检测【OpenCV学习笔记6】

#include "stdafx.h" #include "cv.h" #include "highgui.h" #include <ctype.h> #include <stdio.h> int main( int argc, char** argv ) { IplImage* laplace = 0; IplImage* colorlaplace = 0; IplImage* planes[3] = { 0, 0, 0 }; // 多个图像面 CvCapture* capture = 0; //CvCapture // //视频获取结构 //typedef struct CvCapture CvCapture; //结构CvCapture 没有公共接口,它只能被用来作为视频获取函数的一个参数。 // 下面的语句说明在命令行执行程序时,如果指定AVI文件,那么处理从 // AVI文件读取的视频流,如果不指定输入变量,那么处理从摄像头获取 // 的视频流 //capture = cvCaptureFromAVI( "3.avi" ); if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0]))) capture = cvCaptureFromCAM( argc == 2 ? argv[1][0] - '0' : 0 ); else if( argc == 2 ) capture = cvCaptureFromAVI( argv[1] ); if( !capture ) { fprintf(stderr,"Could not initialize capturing...\n"); return -1; } cvNamedWindow( "Laplacian", 0 ); // 循环捕捉,直到用户按键跳出循环体 for(;;) { IplImage* frame = 0; int i; //cvQueryFrame // //从摄像头或者文件中抓取并返回一帧 //IplImage* cvQueryFrame( CvCapture* capture ); //capture //视频获取结构。 //函数cvQueryFrame从摄像头或者文件中抓取一帧,然后解压并返回这一帧。 //这个函数仅仅是函数cvGrabFrame和函数cvRetrieveFrame在一起调用的组合。 //返回的图像不可以被用户释放或者修改。 抓取后,capture被指向下一帧, //可用cvSetCaptureProperty调整capture到合适的帧。 // //注意: cvQueryFrame返回的指针总是指向同一块内存。建议cvQueryFrame后拷贝一份 //。而且返回的帧需要FLIP后才符合OPENCV的坐标系。 若返回值为NULL,说明到了视频的最后一帧。 frame = cvQueryFrame( capture ); if( !frame ) break; if( !laplace ) { for( i = 0; i < 3; i++ ) planes[i] = cvCreateImage( cvSize(frame->width,frame->height), 8, 1 ); //CreateImage //创建头并分配数据 //IplImage* cvCreateImage( CvSize size, int depth, int channels ); //size //图像宽、高. //depth //图像元素的位深度,可以是下面的其中之一: //IPL_DEPTH_8U - 无符号8位整型 //IPL_DEPTH_8S - 有符号8位整型 //IPL_DEPTH_16U - 无符号16位整型 //IPL_DEPTH_16S - 有符号16位整型 //IPL_DEPTH_32S - 有符号32位整型 //IPL_DEPTH_32F - 单精度浮点数 //IPL_DEPTH_64F - 双精度浮点数 //channels //每个元素(像素)的颜色通道数量.可以是 1, 2, 3 或 4.通道是交叉存取的,例如通常的彩色图像数据排列是: //b0 g0 r0 b1 g1 r1 ... //虽然通常 IPL 图象格式可以存贮非交叉存取的图像,并且一些OpenCV 也能处理他, 但是这个函数只能创建交叉存取图像. //函数 cvCreateImage 创建头并分配数据,这个函数是下列的缩写型式 //header = cvCreateImageHeader(size,depth,channels); //cvCreateData(header); //只是创建空间,并不会初始化空间内的数据 laplace = cvCreateImage( cvSize(frame->width,frame->height), IPL_DEPTH_16S, 1 ); colorlaplace = cvCreateImage( cvSize(frame->width,frame->height), 8, 3 ); } //cvCvtPixToPlane // //  openCV里面的一个函数 //  可以看作cvSplit是他的宏: //  #define cvCvtPixToPlane cvSplit //  void cvSplit( const CvArr* src, CvArr* dst0, CvArr* dst1,CvArr* dst2, CvArr* dst3 ); //  作用是:分割多通道数组成几个单通道数组或者从数组中提取一个通道 //  一般用法是cvCvtPixToPlane(IplImage * src,IplImage * dst1,IplImage *dst2,IplImage * dst3,IplImage *dst4) //  第一个参数是源图像,后面是分离出来每个通道的目标图像,如果圆筒到时3通道的,可以把最后一个参数设置为空。 // 例如cvCvtPixToPlane(IplImage * src,IplImage * dst1,IplImage *dst2,IplImage * dst3,NULL) cvCvtPixToPlane( frame, planes[0], planes[1], planes[2], 0 ); for( i = 0; i < 3; i++ ) { // Laplace //计算图像的 Laplacian 变换 //void cvLaplace( const CvArr* src, CvArr* dst, int aperture_size=3 ); //src //输入图像. //dst //输出图像. //aperture_size //核大小 (与 cvSobel 中定义一样). cvLaplace( planes[i], laplace, 3 ); // 3: aperture_size //ConvertScaleAbs //使用线性变换转换输入数组元素成8位无符号整型 //void cvConvertScaleAbs( const CvArr* src, CvArr* dst, double scale=1, double shift=0 ); //#define cvCvtScaleAbs cvConvertScaleAbs //src //原数组 //dst //输出数组 (深度为 8u). //scale //比例因子. //shift //原数组元素按比例缩放后添加的值。 //函数 cvConvertScaleAbs 与前一函数是相同的,但它是存贮变换结果的绝对值: //dst(I)=abs(src(I)*scale + (shift,shift,...)) //函数只支持目标数数组的深度为 8u (8-bit 无符号) , 对于别的类型函数仿效于cvConvertScale 和 cvAbs 函数的联合 cvConvertScaleAbs( laplace, planes[i], 1, 0 ); // planes[] = ABS(laplace) } //cvCvtPixToPlane是cvCvtPlaneToPix的逆函数 cvCvtPlaneToPix( planes[0], planes[1], planes[2], 0, colorlaplace ); //IplImage // IPL 图像头 // 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 *tileInfo; // int imageSize; // char *imageData; // int widthStep; // int BorderMode[4]; // int BorderConst[4]; // char *imageDataOrigin; //} // IplImage; //IplImage结构来自于 Intel Image Processing Library(是其本身所具有的)。OpenCV 只支持其中的一个子集: //alphaChannel 在OpenCV中被忽略。 //colorModel 和channelSeq 被OpenCV忽略。OpenCV颜色转换的唯一函数 cvCvtColor把原图像的颜色空间的目标图像的颜色空间作为一个参数。 //dataOrder 必须是IPL_DATA_ORDER_PIXEL (颜色通道是交叉存取),然而平面图像的被选择通道可以被处理,就像COI(感兴趣的通道)被设置过一样。 //align 是被OpenCV忽略的,而用 widthStep 去访问后继的图像行。 //不支持maskROI 。处理MASK的函数把他当作一个分离的参数。MASK在 OpenCV 里是 8-bit,然而在 IPL他是 1-bit。 //tileInfo 不支持。 //BorderMode和BorderConst是不支持的。每个 OpenCV 函数处理像素的邻近的像素,通常使用单一的固定代码边际模式。 //除了上述限制,OpenCV处理ROI有不同的要求。要求原图像和目标图像的尺寸或 ROI的尺寸必须(根据不同的操作, //例如cvPyrDown 目标图像的宽(高)必须等于原图像的宽(高)除以2 ±1)精确匹配,而IPL处理交叉区域,如图像的大小或ROI大小可能是完全独立的。 colorlaplace->origin = frame->origin; //让他们结构一致 cvShowImage("Laplacian", colorlaplace ); if( cvWaitKey(10) >= 0 ) break; } cvReleaseCapture( &capture ); cvDestroyWindow("Laplacian"); return 0; }

继续阅读