HighGUI 图形用户界面初识(二)

 

 

参考学习书籍:《OpenCV3 编程入门》

环境:OpenCV4.1.1+VS2019

上一篇博客梳理了OpenCV的一些常用函数,imread(),imshow(),waitKey(),namedWindow(),inwrite(),addWeighted(),但都是静态函数。

这一篇博客学习一些常用的动态函数,包括滑动条和鼠标操作。

一.滑动条的创建和使用

createTrackbar函数用于创建滑动条,并将这一滑动条依附在一个窗口中。常常需要与一个回调函数搭配使用。

int createTrackbar(conststring& trackbarname, conststring& winname, int* value, int count, TrackbarCallback onChange = 0, void* userdata = 0);

/* 第一个参数 conststring& 类型的 trackbarname 创建的轨迹条名称
   第二个参数 conststring& 类型的 winname  轨迹条所依附的窗口的名字
   第三个参数 int* 类型的 value 表示滑块的位置 在创建时,value的值就是滑块的初始位置
   第四个参数 int 类型的 count  表示滑块可以达到的最大位置的值(最小位置的值始终为0)
   第五个参数 TrackbarCallback 类型的 onChange 默认值为0 这是一个指向回调函数的指针
   第六个参数 void* 类型的 userdata 默认值为0 是用户传给回调函数的数据用来处理轨迹条事件 */

例如:

createTrackbar("透明度:", "【效果图】", &g_nAlphaValueSlider, 300, on_Change);

例程:

#include <opencv2/opencv.hpp>
#include <stdio.h> 
#include <iostream>

#define 	WINDOW_NAME   "线性混合示例"       //为窗口标题定义的宏

using namespace cv;

const int g_nMaxAlphaValue = 100;                   //Alpha的最大值
int g_nAlphaValueSlider;                                    //滑动条对应变量
double g_dAlphaValue;
double g_dBetaValue;
char* TrackbarName;

//声明存储图像的变量
Mat dst;
Mat src1;
Mat src2;

//响应滑动条的回调函数
void on_Trackbar(int ,void*)
{
	g_dAlphaValue = (double) (g_nAlphaValueSlider/g_nMaxAlphaValue);
	g_dBetaValue = (1.0 - g_dAlphaValue);
	addWeighted(src1, g_dAlphaValue, src2, g_dBetaValue, 0.0, dst);
	imshow(WINDOW_NAME,dst);           //显示效果图
}

int main()
{
	//加载图像(两幅图尺寸需相同)
    src1 = imread("1.jpg");
	src2 = imread("2.jpg");
	if ( !src1.data)
	{
		printf("读取第一幅图片错误,请确定目录是否有imread函数指定图片存在\n");
		return -1;
	}
	if ( !src2.data)
	{
		printf("读取第二幅图片错误,请确定目录是否有imread函数指定图片存在\n");
		return -1;
	}
	//设置滑动条初值为70
	g_nAlphaValueSlider = 70;
	//创建窗体
	namedWindow(WINDOW_NAME);
	//在创建的窗体中创建一个滑动条控件
	//char TrackbarName[50];
	TrackbarName = new char[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;
}

在项目生成时,可能会遇到一个问题:

这是因为VS中,sprintf的安全性较低,所以微软提供了sprintf_s来代替,我们可以进行下面几步操作,规避这一错误。

在属性管理器中,选择Debud|x64(∵我们的调试环境是这一个),右击Microsoft.Cpp.x64.use,选择属性,在C/C++中的预处理器中的预处理器定义添加_CRT_SECURE_NO_DEPRECATE,点击确认。

再次生成项目就不会有这一错误了。

二.鼠标操作

与滑动条类似,鼠标操作也有一个创建函数setMouseCallback

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

/* 第一个参数 conststring& 类型的 winname 窗口名
   第二个参数 MouseCallback 类型的 onMouse 窗口里每次鼠标事件发生时被调用的函数指针
   第三个参数 void* 类型的 userdata 默认值为0   */

例程:

#include <opencv2/opencv.hpp>

using namespace cv;

#define WINDOW_NAME "【鼠标操作】"

void on_MouseHandle(int event, int x, int y, int flags, void* param);
void DrawRactangle(Mat& img, Rect box);

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)
		{
			DrawRactangle(tempImage, g_rectangle);   //进行绘制
		}
		imshow(WINDOW_NAME, tempImage);
		if (waitKey(10) == 27)            // 按下ESC键,程序退出
			break;
	}
	return 0;
}

//  鼠标回调函数,根据不同的鼠标事件进行不同的操作
void on_MouseHandle(int event, int x, int y, int flags, void* param)
{
	Mat& image = *(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:
	{
		// 标识符为false
		g_bDrawingBox = 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;
		}
		//调用函数进行绘制
		DrawRactangle(image, g_rectangle);
	}
	break;
	}
}

// 画矩形
void DrawRactangle(Mat& img, Rect box)
{
	rectangle(img, box.tl(), box.br(), Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255)));
}

​

效果图:

在窗口中点击鼠标左键画矩形,窗口中就会出现所画矩形。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值