基于C++的opencv(五)OpenCV基础使用

一、图像的载入、显示和输出到文件

1.1.OpenCV的命名空间

OpenCV中的C++类和函数都是定义在命名空间cv之内的,有两种方法可以访问:
**1)**是在代码开头的适当位置加上using namespace cv;这句代码,规定程序位于此命名空间之内;
**2)**是在使用OpenCV的每一个类和函数时,都加入cv::命名空间。

简单的OpenCV程序的标配:

#include
#include

using namespace cv;

1.2.Mat类简析

Mat类是用于保存图像以及其他矩阵数据的数据结构,默认情况下其尺寸为0。我们也可以指定其初始尺寸,比如定义一个Mat类对象,要写

cv::Mat pic(320,640,cv::Scalar(100))

1.3.图像的载入与显示概述

分别对应imread()以及imshow()两个函数

1.4.图像的载入

Mat imread(const string &filename,intflags=1);

**1)**第一个参数,const string&类型的filename,填我们需要载入的图片路径名。在windows操作系统下,OpenCV的imread函数支持如下类型的图像载入。
Windows位图:.bmp、.dib
JPEG文件:.jpeg、.jpg、.jpe
JPEG2000文件:
.jp2
PNG图片:.png
便携文件格式:
.pbm、.pgm、.ppm
Sum rasters光栅文件:.sr、.ras
TIFF文件:.tiff、.tif

**2)**第二个参数,int类型的flags,为载入标识,它指定一个加载图像的颜色类型。可以看到它自带默认值1,所以有时候这个参数在调用时可以忽略。
flags是int型的变量:
flags>0返回一个3通道的彩色图像;
flags=0返回灰度图像;
flags<0返回包含Alpha通道的加载图像。

1.5.图像的显示

void imshow(const string& winname,InputArray mat);

第一个参数:const string&类型的winname,填需要显示的窗口标识名称。
第二个参数:InputArray类型的mat,填需要显示的图像。

imshow函数用于在指定的窗口中显示图像。如果窗口是用CV_WINDOW_AUTOSIZE(默认值)标志创建的,那么显示图像原始大小。

1.6.关于InputArray类型

typedef const _InputArray& InputArray;

_InputArray和InputArray是一个意思

1.7.创建窗口

namedWindow函数用于创建一个窗口。

void namedWindow(const string & winname,int flags=WINDON_AUTOSIZE);

**1)**第一个参数,const string&型的name,填写被用作窗口的标识符的窗口名称。
**2)**第二个参数,int类型的flags,窗口的标识,可以填如下几种值。
WINDOW_NORMAL,设置这个值,用户可以改变窗口的大小(没有限制)。
WINDOW_AUTOSIZE,设置这个值,窗口大小会自动调整以适应所显示的图像,并且用户不能手动改变窗口大小。
WINDOW_OPENGL,设置这个值,窗口创建的时候会支持OpenGL。

1.8.输出图像到文件

bool imwrite(const string& filename,InputArray img,const vector<int>& params=vector<int>());

1)第一个参数,const string&类型的filename,填需要写入的文件名。注意要带上后缀,如“123.jpg”。
2)第二个参数,InputArray类型的img,一般填一个Mat类型的图像数据。
3)第三个参数,const vector&类型的params,表示为特定格式保存的参数编码。它有默认值vector(),所以一般情况下不需要填写。

#include
#include

using namespace cv;
using namespace std;

void createAlphaMat(Mat &mat)
{
	for(int i=0;i<mat.rows;++i)
	{
		for(int j=0;j<mat.cols;++j)
		{
			Vec4b&rgba=mat.at<Vec4b>(i,j);
			rgba[0]=UCHAR_HAX;
			rgba[1]=saturate_cast<uchar>((float(mat.cols-j))/((float)mat.cols)*UCHAR_MAX);
			rgba[2]=saturate_cast<uchar>((float<mat.rows-i))/((float)mat.rows)*UCHAR_MAX);
			rgba[3]=saturate_cast<uchar>(0.5*(rgba[1]+rgba[2]));
			}
			}
}

int main()
{
	//创建带Alpha通道的Mat
	Mat mat(480,640,CV_8UC4);
	createAlphaMat(mat);

	vector<int>compression_params;
	compression_params.push_back(IMWRITE_PNG_COMPRESSION);
	compression_params.push_back(9);

	try{
		imwrite("透明Alpha值图.png“,mat,compression_params);
		imshow("生成的PNG图",mat);
		fprintf(stdout,"PNG图片文件的alpha数据保存完毕~\n可以在工程目录下查看由imwrite函数生成的图片\n");
		waitKey(6000);
		}
		catch(runtime_error& ex)
		{
			fprintf(stderr,”图像转换成PNG格式发生错误:%s\n",ex.what());
			return 1;
			}
			return 0;
	}
#include
#include

using namespace cv;

int main()
{
	Mat girl=imread("girl.jpg");
	namedWindow("动漫画“);
	imshow("动漫画",girl);
	
	Mat image=imread("dota.jpg",199);
	Mat logo=imread("dota_logo.jpg");
	namedWindow("原画图”);
	imshow("原画图",image);

	namedWindow("logo图");
	imshow("logo图”,logo);

	Mat imageROI;
	imageROI=image(Rect(800,350,logo.cols,logo.rows));

	//imageROI=image(Range(350,350+logo.rows),Range(800,800+logo.cols));

	addWeighted(imageROI,0.5,logo,0.3,0.,imageROI);

	nameWindow("原图+logo图");
	imshow("原图+logo图",image);

	imwrite("由imwrite生成的图片.jpg",image);

	waitKey();

	return 0;
}

二、滑动条的创建和使用

滑动条(Trackbar)是OpenCV动态调节参数特别好用的一种工具,它依附于窗口而存在。

2.1.创建滑动条

createTrackbar函数用于创建一个可以调整数值的滑动条(常常也被称作轨迹条),并将滑动条附加到指定的窗口上,使用起来很方便。
int createTrackbar(const string& trackbarname,const string& winname,int *value,int count,TrackbarCallback onChange=0,void * userdata=0);

第一个参数,const string&类型的trackbarname,轨迹条的名字,用来代表我们创建的轨迹条。
第二个参数,const string&类型的winname,窗口的名字,表示这个轨迹条会依附到哪个窗口上,即对应namedWindow()创建窗口时填的某一个窗口名。
第三个参数,int类型的value,一个指向整型的指针,表示滑块的位置。在创建时,滑块的初始位置就是该变量当前的值。
第四个参数,int类型的count,表示滑块可以达到的最大位置的值。滑块最小位置的值始终为0.
第五个参数,TrackbarCallback类型的onChange,他有默认值0.这是一个指向回调函数的指针,每次滑块位置改变时,这个函数都会进行回调。并且这个函数的原型必须为void XXXX(int,void
);其中第一个参数是轨迹条的位置,第二个参数是用户数据(看下面的第六个参数)。如果回调是NULL指针,则表示没有回调函数的调用,仅第三个参数value有变化。
第六个参数,void*类型的userdata,也有默认值0.这个参数是用户传给回调函数的数据,用来处理轨迹条事件。如果使用的第三个参数value实参是全局变量的话,完全可以不去管这个userdata参数。

createTrackbar函数为我们创建了一个具有特定名称和范围的轨迹条(Trackbar,或者说是滑块范围控制工具),指定一个和轨迹条位置同步的变量,而且要指定回调函数onChange(第五个参数),在轨迹条位置改变的时候来调用这个回调函数,并且,创建的轨迹条显示在指定的winname(第二个参数)所代表的窗口上。

至于回调函数,就是一个通过函数指针调用的函数。如果我们把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,就称其为回调函数。回调函数不由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用,用于对该事件或条件进行响应。

createTrackbar("对比度:","【效果图口】",&g_nContrastValue,300,on_Change);
#include
#include

using namespace cv;

#define WINDOW_NAME "【线性混合】"


const int g_nMaxAlphaValue=100;
int g_nAlphaValueSlider;
double g_dAlphaValue;
double g_dBetaValue;

Mat g_srcImage1;
Mat g_srcImage2;
Mat g_dstImage;

void on_Trackbar(int,void*)
{
	g_dAlphaValue=(double)g_nAlphaValueSlider/g_nMaxAlphaValue;
	g_dBetaValue=(1.0-g_dAlphaValue);

	addWeighted(g_srcImage1,g_dAlphaValue,g_srcImage2,g_dBetaValue,0.0,g_dstImage);

	imshow(WINDOW_NAME,g_dstImage);
}


int main(int argc,char **argv)
{
	g_srcImage1=imread("1.jpg");
	g_srcImage2=imread("2.jpg");
	if(!g_srcImage1.data)
	{
		printf("读取第一幅图片错误,请确定目录下是否有imread函数指定图片存在~!\n");
		return -1;
	}
	if(!g_srcImage2.data)
	{
		printf("读取第二幅图片错误,请确定目录下是否有imread函数指定图片存在~!\n");
		return -1;
	}

	g_nAlphaValueSlider=70;

	namedWindow(WINDOW_NAME,1);

	char TrackbarName[50];
	sprintf(TrackbarName,"透明值  %d",g_nMaxAlphaValue);

			createTrackbar(TrackbarName,WINDOW_NAME,&g_nAlphaValueSlider,g_nMaxAlphaValue,on_Trackbar);

	on_Trackbar(g_nAlphaValueSlider,0);
	waitKey(0);

	return 0;
}

2.2.获取当前轨迹条的位置:getTrackbarPos()函数

int getTrackbarPos(const string& trackbarname,const string& winname);

第一个参数,const string&类型的trackbarname,表示轨迹条的名字。
第二个参数,const string&类型的winname,表示轨迹条的父窗口的名称

三、鼠标操作

OpenCV中的鼠标操作和滑动条的消息映射方式很类似,都是通过一个中介函数配合一个回调函数来实现。创建和指定滑动条回调函数的函数为createTrackbar,而指定鼠标操作消息回调函数的函数为SetMouseCallback。

void setMouseCallback(const string& winname,MouseCallback onMouse,void* userdata=0)

第一个参数,const string&类型的winname,窗口的名字。
第二个参数,MouseCallback类型的onMouse,指定窗口里每次鼠标事件发生的时候,被调用的函数指针。这个函数的原型的大概形式为void Foo(int event,int x,int y,int flags,void * param)。其中event是EVENT_+变量之一,x和y是鼠标指针的图像坐标系中的坐标值,flags是EVENT_FLAG的组合,param是用户定义的传递到SetMouseCallback函数调用的参数。如EVENT_MOUSEMOVE为鼠标移动消息、EVENT_LBUTTONDOWN为鼠标左键按下消息等。
第三个参数,void*类型的userdata,用户定义的传递到回调函数的参数,有默认值0。

#include

using namespace cv;

#define WINDOW_NAME "【程序窗口】"

void on_MouseHandle(int event,int x,int y,int flags,void* param);
void DrawRectangle(cv::Mat& img,cv::Rect box);
void ShowHelpText();

Rect g_rectangle;
bool g_bDrawingBox=false;
RNG g_rng(12345);

int main(int argc,char ** argv)
{
	g_rectangle=Rect(-1,-1,0,0);
	Mat srcImage(600,800,CV_8UC3),tempImage;
	srcImage.copyTo(tempImage);
	g_rectangle=Rect(-1,-1,0,0);
	srcImage=Scalar::all(0);

	namedWindow(WINDOW_NAME);
	setMouseCallback(WINDOW_NAME,on_MouseHandle,(void*)&srcImage);

	while(1)
	{
		srcImage.copyTo(tempImage);
		if(g_bDrawingBox)
		DrawRectangle(tempImage,g_rectangle);
		imshow(WINDOW_NAME,tempImage);
		if(waitKey(10)==27)
		break;
	}
	return 0;
}

void on_MouseHandle(int event,int x,int y,int flags,void* param)
{
	Mat &image=*(cv::Mat*)param;
	switch(event)
	{
		case EVENT_MOUSEMOVE:
		{
			if(g_bDrawingBox)
			{
				g_rectangle.width=x-g_rectangle.x;
				g_rectangle.height=y-g_rectangle.y;
				
				}
		}
		break;

		case EVENT_LBUTTONDOWN:
		{
			g_bDrawingBox=true;
			g_rectangle=Rect(x,y,0,0);
		}
		break;

		case EVENT_LBUTTONUP:
		{
			g_bDrawingBox=false;
			if(g_rectangle.width<0)
			{
				g_rectangle.x+=g_rectangle.width;
				g_rectangle.width*=-1;
			}

			if(g_rectangle.height<0)
			{
				g_rectangle.y+=g_rectangle.height;
				g_rectangle.height*=-1;
			}

			DrawRectangle(image,g_rectangle);

		}
		break;
		}
}

void DrawRectangle(cv::Mat& img,cv::Rect box)
{
	rectangle(img,box.tl(),box.br(),Scalar(g_rng.uniform(0,255),
	g_rng.uniform(0,255),g_rng.uniform(0,255)))
}

你可能感兴趣的:(c++,OpenCV,opencv,图像处理)