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_LBUTTONDOWN
CV_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:
CvPoint p = cvPoint(int x,int y); CvPoint2D32f p = cvPoint(float x,float y); p.x = 5.0; p.y = 5.0;
//矩形框大小:
CvSize r = cvSize(int width,int height); CvSize2D32f r = cvSize2D32f(float width,float height);
//矩形框的偏置和大小:
CvRect r = 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 imag
data = 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,HLS
e.g.
CV_BGR2GRAY,CV_BGR2HSV,CV_BGR2Lab
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,HLS
e.g.
CV_BGR2GRAY,CV_BGR2HSV,CV_BGR2Lab
绘图指令:
//1 绘制矩形
//在坐标为(100,100)和(200,200)的点之间画一个矩形,边线为红色,宽度为1
cvRectangle(img,cvPoint(100,100),cvPoint(200,200),cvScalar(255,0,0),1);
//2 绘制原形
//圆心坐标(100,100),半径20,圆周为绿色,宽度为1
cvCircle(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结构体
else
caputre = cvCreateFileCapture(argv[1]); //从指定视频文件中获取视频初始化caputre结构体
assert(caputre != NULL);
IplImage* frame;
while (1)
{
frame = cvQueryFrame(caputre); //从摄像头或者文件中抓取并返回一帧
if (!frame)
break;
cvShowImage("video",frame); //将一帧画面显示在窗口
char c = cvWaitKey(33); //每帧显示33ms
if (c == 27) //ESC退出
break;
}
cvReleaseCapture(&caputre); //停止读取文件并释放内存
cvDestroyWindow("video");
return 0;
}
效果:
参考:《学习OpenCv》
ps:第一次用目录,貌似有的风格显示不了目录