opencv3学习笔记(三)--------HighGUI图形界面初步

在OpenCV中生成一个png图片,并写入当前工程目录下

OpenCV的命名空间:using namespace cv;(可不用敲cv::)

Mat类:用于保存图像以及其他矩阵数据的数据结构,默认情况下其尺寸为0;

           Mat srcImage=imread("1.jpg");

imread()函数:图像的载入------Mat imread(const string& filename,int flags=1);

          参数一:需要载入的图片的路径

          参数二:为载入标识,它指定一个加载图像的颜色类型。(flags>0返回3通道彩色图像;=0返回灰度图像;<0返回包含Alpha通道的加载图像)

                       CV_LOAD_IMAGE_GRAYSCALE------等价取值0(图像转换成灰度图像);

                       CV_LOAD_IMAGE_COLOR--------等价取值为1(转换图像到彩色再返回);

                        CV_LOAD_IMAGE_ANYDEPTH-----等价取值为2(深度16,23位返回对应深度图像,否则转换为8位返回)。

imshow()函数:图像的显示-----void imshow(const string& winname,InputArray mat);

             参数一:需显示的窗口的名称

             参数二:填需要显示的图像

InputArray类型把它简单的看作Mat类型即可。

nameWindow()函数:创建窗口-----void nameWindow(const strin& winname,int flags=WINDOW_AUTOSIZE);

          参数一:窗口名称

          参数二:窗口的标识(WINDOW_AUTOSIZE窗口大小适应图像大小;WINDOW_NORMAL用户可以改变窗口的大小;WINDOW_OPENGL窗口创建支持OpenGL)

imwrite()函数:输出图像到指定的文件夹

函数原型:bool imwrite(const string& filename,InputArray img,const vector<int>& params=vector<int>());

        参数一:需要写入的文件名(带后缀)

        参数二:Mat类型的图像数据

        参数三:表示为特定格式保存的参数编码(JPEG(0-100)默认值95;PNG(0-9)默认值3;PPM,PGM,PBM(0或1)默认为1)

代码如下:

//------程序一:imwrite函数的用法--在opencv中生成一个PNG图片,并写入到当前工程目录下----

#include <opencv2/opencv.hpp>
#include <vector>

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_MAX;
			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);
	//copression_params.push_back(CV_IMWRITE_PNG_COMPRESSION);OPENCV2版本
	compression_params.push_back(9);

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

程序运行结果:

 初级图像混合

代码如下:

//------------程序二:图像的载入、显示与输出(初级图像混合)----------
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;

int main() {
	//-------图像的载入和显示---------
	//Mat girl = imread("lenna.jpg");
	//namedWindow("lenna图",WINDOW_NORMAL);
	//imshow("lenna图",girl);

	//--------初级图像混合-----------
	Mat image = imread("k.jpg",1);
	Mat logo = imread("1.png");
	namedWindow("原画图", WINDOW_NORMAL);
	imshow("原画图",image);

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

	//定义一个Mat类型,用于存放,图像的ROI
	Mat imageROI;
	//方法一
	imageROI = image(Rect(100,150,logo.cols,logo.rows));

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

	//将logo加到原图上
	addWeighted(imageROI,0.5,logo,0.3,0.0,imageROI);

	//显示结果
	namedWindow("原图+logo图", WINDOW_NORMAL);
	imshow("原图+logo图",image);

	//-----------图像的输出----------
	imwrite("imwrite生成的图片.jpg",image);

	waitKey();
	return 0;
}

运行结果:

滑动条的创建和使用

1.滑动条的创建和使用(createTrackbar()函数)

C++函数原型:int createTrackbar(conststring& trackbarname,conststring& winname,int* value,int count,TrackbarCallback onChange=0,void* userdata=0);
       参数一:轨迹条的名字
       参数二:轨迹条依附的窗口名称
       参数三:表示滑块的位置
       参数四:表示滑块可以达到的最大位置的值。最小值为0.
       参数五:(默认0)这是一个指向回调函数的指针,每次滑块位置改变时,这个函数会进行回调。
       参数六:(默认0)用户传给回调函数的数据,用来处理轨迹条事件

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

C++函数原型 :int getTrackbarPos(conststring& trackbarname,conststring& winname);
     参数一:轨迹条的名字
     参数二:轨迹条的父窗口的名称

3.SetMouseCallback()函数为指定的窗口设置鼠标回调函数
C++函数原型:void setMouseCallback(conststring& winname,MouseCallback onMouse,void* userdata=0);
      参数一:窗口名字
      参数二:窗口里每次鼠标事件发生的时候,被调用的函数指针。
      参数三:(默认值0)用户定义的传递到回调函数的参数。
onMouse函数原型:void Foo(int event,int x,int y,int flags,void*param);
      参数一:event-----EVENT_MOUSEMOVE:鼠标移动消息;
                                   EVENT_LBUTTONDOWN:鼠标左键按下消息。
      参数二:x,y:鼠标指针在图像坐标系中的坐标值(不是窗口坐标系)
      参数三:glags:EVENT_FLAG的组合
      参数四:param:用户定义的传到SetMouseCallback函数调用的参数

4.sprintf()函数的功能非常强大:效率比一些字符串操作函数要高;而且更具灵活性;可以将想要的结果输出到指定的字符串中,也可作为缓冲区,而printf只能输出到命令行上~
         函数功能:格式化字符串,将格式化的数据写入字符串中。

        函数原型:int sprintf(char *buffer, const char *format, [argument]...)

         参数:(1)buffer:是char类型的指针,指向写入的字符串指针;

                    (2)format:格式化字符串,即在程序中想要的格式;

                    (3)argument:可选参数,可以为任意类型的数据;

              函数返回值:buffer指向的字符串的长度;

              用处:(1)格式化数字字符串:在这点上sprintf和printf的用法一样,只是打印到的位置不同而已,
                        前者打印给buffer字符串,后者打印给标准输出,所以sprintf也可以用来将整型转化为字符串,
                        比如:sprintf(buffer, "%d", 123456);执行后buffer即指向字符串“123456”

                         (2)连接字符 
  代码如下:

//------------程序三:滑动条的创建和使用(createTrackbar()函数)----------

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>

using namespace cv;

#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;

//--------响应滑动条的回调函数-----------
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_dAlphaValue,0.0,g_dstImage);
	//显示效果图
	imshow( WINDOW_NAME , g_dstImage );
}

//--------控制台应用程序的入口函数,我们的程序从这里开始执行-------
int main(int argc,char** argv) {
	//加载图像(两图像的尺寸需相同)
	g_srcImage1 = imread("lenna.jpg");
	g_srcImage2 = imread("lenna.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,0);

	//在创建的窗体中创建一个滑动条控件
	char TrackbarName[50];
	sprintf_s(TrackbarName, "透明值%d", g_nMaxAlphaValue);
	
	createTrackbar(TrackbarName, WINDOW_NAME, &g_nAlphaValueSlider, g_nMaxAlphaValue, on_Trackbar);

	//结果在回调函数中显示
	on_Trackbar(g_nAlphaValueSlider,0);

	//按任意键退出
	waitKey(0);
	return 0;
}

 运行结果:(因运行时需两张相同大小的图片,所以用了两张lenna图)

         

鼠标交互

代码如下:

//---------程序四:鼠标交互-----------

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>

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;  //Rect矩阵类
bool g_bDrawingBox = false;
RNG g_rng(12345);  //RNG随机类:随机生成

//--------鼠标回调函数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;
	}
}
//--------自定义的矩形绘制函数---------
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)));//随机颜色
}

//--------控制台应用程序的入口函数-------
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;

	waitKey(0);
	return 0;
}

 运行结果:

猜你喜欢

转载自blog.csdn.net/qq_37894023/article/details/84374572