OpenCV3 HighGUI 图形用户界面初步

该博文同步发布在我的个人主页https://lemonaaaaa.com/

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

OpenCV 的命名空间

using namespace cv;

Mat 类

Mat 类是用于保存图像以及其他矩阵数据的数据结构,默认情况下尺寸为0。我们也可以指定其初始尺寸。
cv::Mat pic(320,640,cv""Scalar(100);

读取图片文件:Mat scrImage = imread("src.jpg");

图像载入(imread()函数)

函数原型:Mat imread( const String& filename, int flags = IMREAD_COLOR );

  • 第一个参数,对应所需要载入的图片路径名
    在Windows操作系统下,支持的文件格式如下:
    1. Windows位图:bmp, dib ;
    2. JPEG 文件: jpeg, jpg, jpe ;
    3. JPEG 2000 文件:jp2 ;
    4. PNG文件:png ;
    5. 便携文件格式: pbm, pgm, ppm ;
    6. Sun rasters 光栅文件: sr, ras ;
    7. TIFF 文件: tiff, tif 。
  • 第二个参数,为载入标识,它指定一个加载图像的颜色类型,由函数原型可以看到它自带默认值为 IMREAD_COLOR (值为1),所以在调用时可以忽略这个参数。这个参数在OpenCV中标识图像格式的枚举体中取值。
    枚举的定义如下:
enum ImreadModes {
       IMREAD_UNCHANGED            = -1, //!< If set, return the loaded image as is (with alpha channel, otherwise it gets cropped). Ignore EXIF orientation.
       IMREAD_GRAYSCALE            = 0,  //!< If set, always convert image to the single channel grayscale image (codec internal conversion).
       IMREAD_COLOR                = 1,  //!< If set, always convert image to the 3 channel BGR color image.
       IMREAD_ANYDEPTH             = 2,  //!< If set, return 16-bit/32-bit image when the input has the corresponding depth, otherwise convert it to 8-bit.
       IMREAD_ANYCOLOR             = 4,  //!< If set, the image is read in any possible color format.
       IMREAD_LOAD_GDAL            = 8,  //!< If set, use the gdal driver for loading the image.
       IMREAD_REDUCED_GRAYSCALE_2  = 16, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/2.
       IMREAD_REDUCED_COLOR_2      = 17, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/2.
       IMREAD_REDUCED_GRAYSCALE_4  = 32, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/4.
       IMREAD_REDUCED_COLOR_4      = 33, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/4.
       IMREAD_REDUCED_GRAYSCALE_8  = 64, //!< If set, always convert image to the single channel grayscale image and the image size reduced 1/8.
       IMREAD_REDUCED_COLOR_8      = 65, //!< If set, always convert image to the 3 channel BGR color image and the image size reduced 1/8.
       IMREAD_IGNORE_ORIENTATION   = 128 //!< If set, do not rotate the image according to EXIF's orientation flag.
     };

所以默认载入三通道的彩色图像,其他参数用途在注释中也已明确。

  • flags > 0 : 返回一个3通道的彩色图像
  • flags = 0 : 返回灰度图像
  • flags < 0 : 返回包含Alpha通道的加载图像

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

图像显示(imshow()函数)

imshow()函数用于在指定的窗口中显示一幅图像。
原型:void imshow(const string& winname, InputArray mat)

  • 第一个参数:填需要显示的窗口标识名称。
  • 第二个参数:填需要显示的图像。

如果窗口是用 CV_WINDOW_AUTOSIZE (默认值)标志创建的,那么显示图像原始大小。否则,将根据图像的深度进行缩放以适合窗口。

创建窗口(namedWindow()函数)

namedWindow用于创建一个窗口。如果是简单地进行图片显示,则不用这个函数创建窗口。但如果需要在显示窗口之前就用到窗口名时,就需要这个函数先创建出窗口,显式地规定窗口名称,比如指定滑动条依附在某个窗口上。

函数原型:void namedWindow(const String& winname, int flags = WINDOW_AUTOSIZE);

  • 第一个参数,填写被用作窗口的标识符的窗口名称
  • 第二个参数,窗口的标识,其enum定义如下:
enum WindowFlags {
       WINDOW_NORMAL     = 0x00000000, //!< the user can resize the window (no constraint) / also use to switch a fullscreen window to a normal size.
       WINDOW_AUTOSIZE   = 0x00000001, //!< the user cannot resize the window, the size is constrainted by the image displayed.
       WINDOW_OPENGL     = 0x00001000, //!< window with opengl support.

       WINDOW_FULLSCREEN = 1,          //!< change the window to fullscreen.
       WINDOW_FREERATIO  = 0x00000100, //!< the image expends as much as it can (no ratio constraint).
       WINDOW_KEEPRATIO  = 0x00000000, //!< the ratio of the image is respected.
       WINDOW_GUI_EXPANDED=0x00000000, //!< status bar and tool bar
       WINDOW_GUI_NORMAL = 0x00000010, //!< old fashious way
    };

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

imwrite()函数用于输出图像到文件。

函数原型:bool imwrite( const String& filename, InputArray img, const std::vector& params = std::vector());

  • 第一个参数,填需要写入的文件名,注意要带上后缀。
  • 第二个参数,一般填一个Mat类型的图像数据。
  • 第三个参数,标识为特定格式保存的参数编码,有默认值vector,一般不用填写。如果要填写,需要了解以下内容:
    1. 对于 JPEG 格式的图片,这个参数表示从0到100的图片质量,默认为95;
    2. 对于 PNG 格式的图片,这个参数表示压缩级别,从0到9.较高的值意味着更小的尺寸和更长的压缩时间,默认值为3;
    3. 对于 PPM, PGM 或 PBM 格式的图片,这个参数表示一个二进制格式标志,取值为0或1,默认值为1。

imwrite函数可保存的文件格式 和imread函数可读取格式相同。

创建和使用滑动条

滑动条可以动态调节参数,它依附于窗口而存在。

此外,OpenCV没有实现按钮的功能,所以很多时候,可以用仅含0和1的滑动条来实现按钮的按下和弹起效果。

创建滑动条(createTrackbar()函数)

此函数往往会和一个回调函数配合起来使用。

函数原型:int createTrackbar(const String& trackbarname, const String& winname,int* value, int count, TrackbarCallback onChange = 0, void* userdata = 0);

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

createTrackbar函数要指定回调函数onChange,在轨迹条位置改变的时候来调用这个回调函数,并且创建的轨迹条显示在指定的winname所代表的窗口上。

示例代码:(Code by 毛星云)

//--------------------------------------【程序说明】-------------------------------------------
//		程序说明:《OpenCV3编程入门》OpenCV2版书本配套示例程序17
//		程序描述:为程序界面添加滑动条
//		开发测试所用IDE版本:Visual Studio 2010
//		开发测试所用OpenCV版本:	3.0 beta
//		2014年11月 Created by @浅墨_毛星云
//		2014年12月 Revised by @浅墨_毛星云
//------------------------------------------------------------------------------------------------


//---------------------------------【头文件、命名空间包含部分】-------------------------------
//		描述:包含程序所使用的头文件和命名空间
//-------------------------------------------------------------------------------------------------
#include 
#include 
using namespace cv;
#pragma warning(disable:4996)
//-----------------------------------【宏定义部分】-------------------------------------------- 
//  描述:定义一些辅助宏 
//------------------------------------------------------------------------------------------------ 
#define WINDOW_NAME "【滑动条的创建&线性混合示例】"        //为窗口标题定义的宏 


//-----------------------------------【全局变量声明部分】--------------------------------------
//		描述:全局变量声明
//-----------------------------------------------------------------------------------------------
const int g_nMaxAlphaValue = 100;//Alpha值的最大值
int g_nAlphaValueSlider;//滑动条对应的变量
double g_dAlphaValue;
double g_dBetaValue;

//声明存储图像的变量
Mat g_srcImage1;
Mat g_srcImage2;
Mat g_dstImage;


//-----------------------------------【on_Trackbar( )函数】--------------------------------
//		描述:响应滑动条的回调函数
//------------------------------------------------------------------------------------------
void on_Trackbar(int, void*)
{
	//求出当前alpha值相对于最大值的比例
	g_dAlphaValue = (double)g_nAlphaValueSlider / g_nMaxAlphaValue;
	//则beta值为1减去alpha值
	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);
}


//-----------------------------【ShowHelpText( )函数】--------------------------------------
//		描述:输出帮助信息
//-------------------------------------------------------------------------------------------------
//-----------------------------------【ShowHelpText( )函数】----------------------------------
//		描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
void ShowHelpText()
{
	//输出欢迎信息和OpenCV版本
	printf("\n\n\t\t\t非常感谢购买《OpenCV3编程入门》一书!\n");
	printf("\n\n\t\t\t此为本书OpenCV3版的第17个配套示例程序\n");
	printf("\n\n\t\t\t   当前使用的OpenCV版本为:" CV_VERSION);
	printf("\n\n  ----------------------------------------------------------------------------\n");
}


//--------------------------------------【main( )函数】-----------------------------------------
//		描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main(int argc, char** argv)
{

	//显示帮助信息
	ShowHelpText();

	//加载图像 (两图像的尺寸需相同)
	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; }

	//设置滑动条初值为70
	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;
}

运行效果:(分别为透明度0%、50%、100%的情况)
OpenCV3 HighGUI 图形用户界面初步_第1张图片OpenCV3 HighGUI 图形用户界面初步_第2张图片OpenCV3 HighGUI 图形用户界面初步_第3张图片

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

函数原型:int getTrackbarPos(const String& trackbarname, const String& winname);

  • 第一个参数:表示轨迹条的名字。
  • 第二个参数:表示轨迹条的父窗口的名称。

鼠标操作

和创建滑动条的函数类似,指定鼠标操作消息回调函数的函数为setMouseCallback

函数原型:setMouseCallback(const String& winname, MouseCallback onMouse, void* userdata = 0);

  • 第一个参数:窗口的名字。
  • 第二个参数:指定窗口里每次鼠标事件发生的时候,被调用的函数指针。
    这个函数的原型大概是void Foo(int event, int x, int y, int flags, void *param);其中event变量enum值的定义见后文,x和y是鼠标指针在图像坐标系中的坐标值,flag是的enum值的定义见后文。param是用户定义的传递到setMouseCallback函数调用的参数。
  • 第三个参数:用户定义的传递到回调函数的参数,默认值为0。
//! Mouse Events see cv::MouseCallback
enum MouseEventTypes {
       EVENT_MOUSEMOVE      = 0, //!< indicates that the mouse pointer has moved over the window.
       EVENT_LBUTTONDOWN    = 1, //!< indicates that the left mouse button is pressed.
       EVENT_RBUTTONDOWN    = 2, //!< indicates that the right mouse button is pressed.
       EVENT_MBUTTONDOWN    = 3, //!< indicates that the middle mouse button is pressed.
       EVENT_LBUTTONUP      = 4, //!< indicates that left mouse button is released.
       EVENT_RBUTTONUP      = 5, //!< indicates that right mouse button is released.
       EVENT_MBUTTONUP      = 6, //!< indicates that middle mouse button is released.
       EVENT_LBUTTONDBLCLK  = 7, //!< indicates that left mouse button is double clicked.
       EVENT_RBUTTONDBLCLK  = 8, //!< indicates that right mouse button is double clicked.
       EVENT_MBUTTONDBLCLK  = 9, //!< indicates that middle mouse button is double clicked.
       EVENT_MOUSEWHEEL     = 10,//!< positive and negative values mean forward and backward scrolling, respectively.
       EVENT_MOUSEHWHEEL    = 11 //!< positive and negative values mean right and left scrolling, respectively.
     };
//! Mouse Event Flags see cv::MouseCallback
enum MouseEventFlags {
       EVENT_FLAG_LBUTTON   = 1, //!< indicates that the left mouse button is down.
       EVENT_FLAG_RBUTTON   = 2, //!< indicates that the right mouse button is down.
       EVENT_FLAG_MBUTTON   = 4, //!< indicates that the middle mouse button is down.
       EVENT_FLAG_CTRLKEY   = 8, //!< indicates that CTRL Key is pressed.
       EVENT_FLAG_SHIFTKEY  = 16,//!< indicates that SHIFT Key is pressed.
       EVENT_FLAG_ALTKEY    = 32 //!< indicates that ALT Key is pressed.
     };

示例代码:(Code by 毛星云)

//--------------------------------------【程序说明】-------------------------------------------
//		程序说明:《OpenCV3编程入门》OpenCV2版书本配套示例程序18
//		程序描述:HelloOpenCV
//		开发测试所用IDE版本:Visual Studio 2010
//		开发测试所用OpenCV版本:	3.0 beta
//		2014年11月 Created by @浅墨_毛星云
//		2014年12月 Revised by @浅墨_毛星云
//------------------------------------------------------------------------------------------------

//---------------------------------【头文件、命名空间包含部分】-----------------------------
//		描述:包含程序所使用的头文件和命名空间
//-------------------------------------------------------------------------------------------------
#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);



//-----------------------------------【main( )函数】--------------------------------------------
//		描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-------------------------------------------------------------------------------------------------
int main(int argc, char** argv)
{
	//【0】改变console字体颜色
	system("color 9F");

	//【0】显示欢迎和帮助文字
	ShowHelpText();

	//【1】准备参数
	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);

	//【2】设置鼠标操作回调函数
	namedWindow(WINDOW_NAME);
	setMouseCallback(WINDOW_NAME, on_MouseHandle, (void*)&srcImage);

	//【3】程序主循环,当进行绘制的标识符为真时,进行绘制
	while (1)
	{
		srcImage.copyTo(tempImage);//拷贝源图到临时变量
		if (g_bDrawingBox) DrawRectangle(tempImage, g_rectangle);//当进行绘制的标识符为真,则进行绘制
		imshow(WINDOW_NAME, tempImage);
		if (waitKey(10) == 27) break;//按下ESC键,程序退出
	}
	return 0;
}



//--------------------------------【on_MouseHandle( )函数】-----------------------------
//		描述:鼠标回调函数,根据不同的鼠标事件进行不同的操作
//-----------------------------------------------------------------------------------------------
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)//如果是否进行绘制的标识符为真,则记录下长和宽到RECT型变量中
		{
			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;//置标识符为false
		//对宽和高小于0的处理
		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;

	}
}



//-----------------------------------【DrawRectangle( )函数】------------------------------
//		描述:自定义的矩形绘制函数
//-----------------------------------------------------------------------------------------------
void DrawRectangle(cv::Mat& img, cv::Rect box)
{
	cv::rectangle(img, box.tl(), box.br(), cv::Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255)));//随机颜色
}


//-----------------------------------【ShowHelpText( )函数】-----------------------------
//          描述:输出一些帮助信息
//----------------------------------------------------------------------------------------------
void ShowHelpText()
{
	//输出欢迎信息和OpenCV版本
	printf("\n\n\t\t\t非常感谢购买《OpenCV3编程入门》一书!\n");
	printf("\n\n\t\t\t此为本书OpenCV3版的第18个配套示例程序\n");
	printf("\n\n\t\t\t   当前使用的OpenCV版本为:" CV_VERSION);
	printf("\n\n  ----------------------------------------------------------------------------\n");
	//输出一些帮助信息
	printf("\n\n\n\t欢迎来到【鼠标交互演示】示例程序\n");
	printf("\n\n\t请在窗口中点击鼠标左键并拖动以绘制矩形\n");

}

运行结果:
OpenCV3 HighGUI 图形用户界面初步_第4张图片

总结

前面几张比较基础,学得比较细致。虽然现在还在入门,但是已经学到了许多其他的知识,比如C++的一些以前没有理解或者不知道的操作。学习,重在坚持,希望能够坚持下去。后面要看算法了,可能花在这上面的时间不会太多。

你可能感兴趣的:(OpenCV,c++,opencv,计算机视觉,cv,图像识别)