Opencv基础学习笔记

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:第一次用目录,貌似有的风格显示不了目录

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值