Opencv基础学习笔记

来源:互联网 发布:人工智能语言知乎 编辑:程序博客网 时间:2024/05/22 15:51

GUI指令

创建和定位一个新窗口:

cvNamedWindow("win1",CV_WINDOW_AUTOSIZE);cvMoveWindow("win1",100,100);//从屏幕的左上开始偏移

载入图像:

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

显示图像:

cvShowImage("win1,img");

关闭窗口:

cvDestroyWindow("win1");

改变窗口大小:

cvResizeWindow("win1",100,100);//新的窗口大小

输入处理

(1) 处理鼠标事件:

1 定义一个鼠标处理程序(监听):

void mouseHandler(int event,//各种鼠标事件:CV_EVENT_LBUTTONDOWNCV_EVENT_RBUTTONDOWN……int x,int y,//x,y相当于左上角的像素坐标int flags,//void* param)

例子:

e.g.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;}}}

2 注册该事件处理程序(响应):

mouseParam = 5;cvSetMouseCallback("win1",mouseHandler,&mouseParam);

 处理键盘事件

//1 按一定时间间隔检测键盘输入(适用于循环体中)int key;key = cvWaitKey(10);//2 中止程序等待键盘输入:int key;key = cvWaitKey(0);

例子

e.g.while(1){key = cvWaitKey(10);//返回值为按下的码键if(key == 27)break;switch(key){case 'h':...break;case 'i':...break;}}

处理滑动条事件

//1 定义一个滑动条处理程序:void trackbarHandler(int pos){printf("Trackbar position: %d\n",pos);}//2 注册该事件的处理程序:int trackbarVal = 25;int maxVal = 100;cvCreateTrackbar("bar1","win1",&trackbarVal,maxVal,trackbarHandler);//3 获取当前滑动条的位置:int pos = cvGetTrackbarPos("bar1","win1");//4 设置滑动条的位置:cvSetTrackbarPos("bar1","win1",25);

例子:

e.g. one//弹出一个窗口并显示图片#include<cv.h>#include<highgui.h>int main(int argc,char* argv[]){IPlImage* image;if(argc != 2)return -1;image = cvLoadImage(argv[1]);if(!image)return -1;cvNamedWindow("Sample",1);cvShowImage("Sample",image);cvWaitKey();cvDestroyWindow("sample");cvReleaseImage(&image);return 0;}//run:sample example_pic.jpg


OpenCV数据结构

//PlImage:

typedef struct _IplImage{int nSize; /*该结构体的大小*/int ID; /*图像头的版本=0*/int nChannels; /*通道数,可取1,3,4。如24位图,即RGB是3通道x8位(depth)。取值4,表示32位位图,有Alpha值,即位图透明度*/int alphaChannel; /*Alpha通道数,没有取0,有则取4(被OpenCV忽略)*/int depth; /*每个通道的位数*/char colorModel[4]; /*颜色模式,有Gray、RGB、RGBA、CMYK等(被OpenCV忽略)*/char channelSeq[4]; /*通道顺序,如“RGB”、“BGR”等*/int dataOrder; /*0 - 交叉存取颜色通道, 1 - 分开的颜色通道.数据的排列方式(使用像素格式)cvCreateImage只能创建交叉存取图像*/int origin; /*坐标原点,有左上角和左下角两种*/int align; /*图像行排列 (4 or 8). OpenCV 忽略它,使用 widthStep 代替 */int width; /*图像的宽*/int height; /*图像的高*/struct _IplROI *roi; /*图像感兴趣区域. 当该值非空只对该区域进行处理*/struct _IplImage *maskROI; /*OpenCV中必须为NULL*/void *imageId; /*同上*/struct _IplTileInfo *tileInfo; /*同上*/int imageSize; /*图像数据大小(在交叉存取格式下imageSize=image->height*image->widthStep),单位字节*/char *imageData; /*指向图像数据的指针*/int widthStep; /*排列的图像行大小,以字节为单位*/int BorderMode[4]; /*边际结束模式, 被OpenCV忽略*/int BorderConst[4]; /*同上*/char *imageDataOrigin; /*该指针指向完整的、没有校准的图像*/}IplImage;

//matrix:

typedef struct CvMat{/*一维矩阵*/int type;/*数据类型(CV_32FC1、CV_8UC3)*/int step;/*每行数据的字节数:元素个数*元素类型的字节长度*//*仅供内部使用*/int* refcount;int hdr_refcount;union{uchar* ptr;/*指向date的第一个元素*/short* s;int* i;float* fl;double* db;} data;typedef struct CvMatND/*N-维矩阵*/{int type;/*数据类型*/int dims;/*矩阵维数*/int* refcount;int hdr_refcount;union{uchar* ptr;float* fl;double* db;int* i;short* s;} data;struct/*各维信息*/{int size;/*元素数目*/int step;/*元素间距:字节*/}dim[CV_MAX_DIM];}CvMatND;

//point:

CvPointp = cvPoint(int x,int y);CvPoint2D32fp = cvPoint(float x,float y);p.x = 5.0;p.y = 5.0;

//矩形框大小:

CvSizer = cvSize(int width,int height);CvSize2D32fr = cvSize2D32f(float width,float height);

//矩形框的偏置和大小:

CvRectr = cvRect(int x,int y,int width,int height);


图像和视频处理

复制图像:

IPlImage*img1 = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);IPlImage*img2;imag2 = cvCloneImage(img1);/*通过克隆得到的图像也需要使用cvReleaseImage释放内存*/

图像的读写和保存:

Opencv默认将读入的图像转换为一副三通道彩色图像,但可以通过一下方法修改:

Opencv默认将读入的图像转换为一副三通道彩色图像,但可以通过一下方法修改:img = cvLoadImage(filename,flag);flag:>0 将读入的图像强制转换为一幅三通道彩色图像=0 将读入的图像强制转换为一个单通道灰度图像<0 读入图像保持原样

保存图像:

cvSaveImage(outfilename,img);//保存的图像格式由outfilename的后缀决定

访问图像像素

假设要访问第K通道,第i行,第j列的像素

way1:间接访问(通用,但效率低,可以访问任意格式的图像)


//a、 对于单通道字节型:IPlImage*img = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);CvScalar s;s = cvGet2D(img,i,j);//获取该图像中第i行,第j列的像素值printf("intensity = %f\n",s.val[0]);//输出原来的像素值s.val[0] = 111;//输入最新值cvSet2D(img,i,j,s);//重置像素值//b、 对于多通道字节型/浮点型:IPlImage*img = cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,3);CvScalar s;s = cvGet2D(img,i,j);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);

way2:直接访问(效率高,但容易出错)

//a、 对于单通道字节型图像:IPlImage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);((uchar*)(img->imageData + i*img->widthStep))[j] = 111;//偏移地址//b、 对于多通道字节型图像:IPlImage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);((uchar*)(img->imagData + i*img->widthStep))[j*img->nChannels + 0] = 111;//B((uchar*)(img->imagData + i*img->widthStep))[j*img->nChannels + 1] = 112;//B((uchar*)(img->imagData + i*img->widthStep))[j*img->nChannels + 2] = 113;//B//c、 对于单通道浮点型图像:IPlImage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,3);((float*)(img->imagData + i*img->widthStep))[j*img->nChannels + 0] = 111;//B((float*)(img->imagData + i*img->widthStep))[j*img->nChannels + 1] = 112;//B((float*)(img->imagData + i*img->widthStep))[j*img->nChannels + 2] = 113;//B

way3:基于指针的直接访问:(简单高效)

//a、 对于单通道字节型图像:IPlImage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);int height  = img->heigth;int width  = img->width;int step  = img->widthStep/sizeof(uchar);//每一行字节数uchar* data  = (uchar*)img->imagData;//获取原图像数据的字节型指针data[i*step +j] = 111;//b、 对于多通道字节型图像:IPlImage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_8U,1);int height  = img->heigth;int width  = img->width;int step  = img->widthStep/sizeof(uchar);//每一行字节数uchar* data  = (uchar*)img->imagData;//获取原图像数据的字节型指针data[i*step +j*channels] = 111;//c、 对于多通道浮点型图像:假设图像采用4字节行对齐方式,即每行数据的长度必须是四字节的整数倍数IPlImage* img = cvCreateImage(cvSize(640,480),IPL_DEPTH_32F,1);int height  = img->heigth;int width  = img->width;int step  = img->widthStep/sizeof(float);//每一行字节数float* float  = (float*)img->imagData;//获取原图像数据的字节型指针data[i*step +j*channels] = 111;

 图像转换:

//a、 字节型图像的灰度-彩色转换:cvConvertImage(src,dst,flags=0);//图像转换函数src = float/byte grayscale/color imagdata = byte grayscale/color imag//输入图像的通道数必须是1,3或者4//输出图像的深度必须是8位的单通道或3通道。flags:CV_CVTIMG_FLIP//(垂直翻转图像)CV_CVTIMG_SWAP_RB//(置换R-B通道)//b、 彩色图像->灰度图像://way1:使用函数cvCvtColor(cimg,gimg,CV_BGR2GRAY);//cimg->gimg//way2:直接转换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);//c、 不同彩色空间之间的转换:cvCvColor(src,dst,code)://src->dst//格式:code = CV_<X>2<Y><X>/<Y> = RGB,BGR,GRAY,HSV,YCrCb,XYZ,Lab,Luv,HLSe.g.CV_BGR2GRAY,CV_BGR2HSV,CV_BGR2Lab

绘图指令:

//1 绘制矩形//在坐标为(100,100)和(200,200)的点之间画一个矩形,边线为红色,宽度为1cvRectangle(img,cvPoint(100,100),cvPoint(200,200),cvScalar(255,0,0),1);//2 绘制原形//圆心坐标(100,100),半径20,圆周为绿色,宽度为1cvCircle(img,cvPoint(100,100),20,cvScalar(0,255,0),1);//3 绘制线段//在坐标为(100,100)和(200,200)的点之间画一条宽为1的绿色线段cvLine(img,cvPoint(100,100),cvPoint(200,200),cvScalar(0,255,0),1);

e.g.

//获取摄像头图像实例:获取摄像头视频显示在窗口里#include "stdafx.h"#include "cv.h"#include "highgui.h"int _tmain(int argc, _TCHAR* argv[])//vs2013中需改为多字节编码方式{cvNamedWindow("video", CV_WINDOW_AUTOSIZE);//创建窗口CvCapture* caputre;//该结构体存放一帧图像if (argc == 1)caputre = cvCaptureFromCAM(0);//从摄像头获取视频初始化caputre结构体elsecaputre = cvCreateFileCapture(argv[1]);//从指定视频文件中获取视频初始化caputre结构体assert(caputre != NULL);IplImage* frame;while (1){frame = cvQueryFrame(caputre);//从摄像头或者文件中抓取并返回一帧if (!frame)break;cvShowImage("video",frame);//将一帧画面显示在窗口char c = cvWaitKey(33);//每帧显示33msif (c == 27)//ESC退出break;}cvReleaseCapture(&caputre);//停止读取文件并释放内存cvDestroyWindow("video");return 0;}

效果:


参考:《学习OpenCv》


ps:第一次用目录,貌似有的风格显示不了目录

0 0