详见《OpenCV3编程入门(毛星云、冷雪飞)》

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

OpenCV的命名空间

在使用OpenCV每一类的函数,都要加入cv::命名空间,推荐在代码开头加上

using namespace cv;

写简单程序时

# include <opencv2/core/core.hpp>
# include <opencv2/highgui/highgui.hpp>
using namespace cv;

Mat类图像操作

默认情况下尺寸为0,也可以指定初始尺寸,比如定义一个Mat类对象cv::Mat pic(320, 640, cv::Scalar(100));图像的载入:imread()函数

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

intflags为载入标识,flags>0 返回一个3通道的彩色图像,flags=0返回灰度图像,flags<0返回包含Alpha通道的加载图像。若以彩色模式载入图像,解码后的图像会以BGR通道顺序存储。

Mat image0=imread("1.jpg",2|4); //载入无损的源图像
Mat image1=imread("1.jpg",0); //载入灰度图
Mat image2=imread("1.jpg",199); //载入3通道彩色图像

图像显示:imshow()函数

void imshow(const string& winname, InputArray mat);
  1. const string&类型的winname:填需要显示的窗口标识名称
  2. InputArray类型mat:填需要显示的图像
    如果载入的图像是8bit unsigned,显示图像本来的样子;如果是16bit unsigned或32bit integer,像素值除以256,将值的范围[0, 255×256]映射到[0.255]。如果图像是32bit floating-point,像素值要乘以255,将值的范围是[0,1]映射到[0.255]。
    在窗口创建的时候,如果设定了支持OpenGL(WINDOW_OPENGL),那么imshow还支持ogl::Buffer, ogl::Texture2D以及gpu::GpuMat作为输入。
    IntputArray/OutputArray类型:简单当成Mat类即可。

创建窗口:namedWindow()

void nameWindow(const string& winname, int flags=WINDOW_AUTOSIZE);
  1. const string&类型的winname:填写被用作窗口的标识符的窗口名称
  2. int类型的flags:窗口的标识,WINDOW_NORMAL-用户可以改变窗口大小;WINDOW_AUTOSIZE-窗口大小会自动调整来适应所显示的图像;WINDOW_OPENGL,设置这个值,窗口创建时会支持OpenGL。
    调用destroyWindow()destroyAllWindows()函数来关闭窗口。

输出图像到文件:imwrite()函数

bool imwrite(const string& filename, InputArray img, const vector<int>& params=vector<int>());
  1. const string& 类型的filename:填需要写入的文件名
  2. InputArray类型的img:填一个Mat类型的图像数据
  3. const vector()&类型的params:表示特定格式保存的参数编码。对于JPEG格式图片,这个参数表示0-100的图像质量(CV_IMWRITE_JPEG_QUALITY),默认值是95;
    PNG格式的图片,这个参数表示压缩级别从0-9(CV_IMWRITE_PNG_COMPRESSION),较高的值意味着更小的尺寸和更长的压缩时间;
    PPM, PGM, PBM格式图片,这个参数表示一个二进制格式标志(CV_IMWRITE_PXM_BINARY),取值为0或1,默认是1。

2.2 滑动条的创建和使用

创建一个滑动条:creatTrackbar
滑动条需要一个回调函数配合起来使用

int creatTrackbar(conststring& trackbarname, conststring& winname, int* value, int count, TrackbarCallback onChange=0, void* userdata=0);
  1. const string&类型的trackbarname:轨迹条的名字
  2. const string&类型的winname:窗口的名字
  3. int*类型的value:指向整型的指针,表示滑块的位置。创建时,滑块的初始位置就是该变量当前的值
  4. int类型的count:滑块可以达到的最大位置的值。最小位置的值始终为0
  5. TrackbarCallback类型的onChange,回调函数的函数名,有默认值0。指向回调函数的指针,每次滑块位置改变时该函数都会进行回调,并且这个函数的原型必须是void XXX(int, void*),第一个参数是轨迹条的位置,第二个位置是用户数据。如果回调是NULL指针,则表示没有回调函数的调用,仅第三个参数value有变化
  6. void*类型的userdata,有默认值0。是用户传给回调函数的数据,用来处理轨迹条事件。如果使用的第三个参数value实参是全局变量,可以不管userdata参数。
    获取当前轨迹条的位置:getTrackbarPos()函数
int getTrackbarPos(conststring& trackbarname, conststring& winname);
  1. const string&类型的trackbarname,表示轨迹条的名字
  2. const string&类型的winname,表示轨迹条的父窗口的名称

例:两幅图像指定透明的混合

#include <opencv2/opencv.hpp>
#include "opencv2/highgui/highgui.hpp"
using namespace cv;

#define WINDOR_NAME "[线性混合示例]"
Mat g_srcImage1;
Mat g_srcImage2;
Mat g_dstImage;

//on_Trackerbar()滑动条回调函数
void on_Trackbar(int, void*)
{
	g_dAlphaValue = (double)g_nAlphaValueSlider/g_nMaxAlphaValue;
	g_dBetaValue = (1.0 - g_dAlphaValue);

	//根据alpha和beta进行线性混合
	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_srgImage2.data){printf("读取第二幅图片错误,请确认目录下是否有imread函数指定图片存在~!\n");return -1;}

	//设置滑动条初值为70
	g_nAlphaValueSlider = 70;
	//创建窗体
	nameWindow(WINDOW_NAME,1);
	//在窗体中创建一个滑动条 控件
	char TrackbarNme[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.3 鼠标操作

与滑动条的消息映射方向类似,都是通过一个中介函数配合一个回调函数实现的。
指定鼠标操作消息回调函数SetMouseCallbck

void setMouseCallback(const string& winname, MouseCallback onMouse, void* userdata=0)
  1. const string&类型的winname:窗口的名字
  2. 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为鼠标左键按下消息。
  3. void*类型的userdata,用户定义的传递到回调函数的参数,有默认值0。

例:使用鼠标左键按下和松开在黑色窗口中绘制出一个一个彩色的矩形

# include <opencv2/opencv.hpp>
using namespace cv;

#define WINDOR_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_bDrawimgBox=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);
	srcImage = Scalar::all(0);
	//设置鼠标操作回调函数
	nameWindow(WINDOR_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; 
			DrawRectangle(image, g_rectangle);
		}
		break;
	}
}
void DrawRectangle(cv::Mat& img, cv::Rect box){
		rectangle(img, box.t1(), box.br(), Scalar(g_rng.uniform(0,255), g_rng.uniform(0,255),g_rng.uniform(0,255)));//随机颜色
}