第3章 HighGUI图形用户界面初步
3.1 图像的载入、显示和输出到文件
1.OpenCV命名空间2种访问方法
(1)代码开头加:usingnamespace cv;
(2)每个类或函数前加:cv::
2.Mat类
(1)Mat类用于保存图像及其他矩阵数据,默认尺寸0
(2)定义Mat对象: cv::Mat pic(320,640,cv::Scalar(100));
3.图像载入:imread()函数
函数原型:Mat imread(const string& filename, intflags=1);
(1)const string& filename : 载入图片路径名,Windows系统下,OpenCV的imread函数支持类型:
(2)int flags:载入标识,制定加载图像的颜色类型:
· 取值0,CV_LOAD_IMAGE_GRAYSCALE,始终将图像转换成灰度再返回
· 取值1,CV_LOAD_IMAGE_COLOR,总是转换图像到彩色再返回
· 取值2,CV_LOAD_IMAGE_ANYDEPTH,载入图像深度为16位或32位,就返回对应深度图像,否则转换为8位图像再返回
通常:
·flags>0返回一个3通道彩色图像
·flags=0返回灰度图像
·flags<0返回包含Alpha通道的加载图像
4.图像显示:imshow()函数
函数原型:void imshow(const string& winname,InputArray mat);
(1)const string&类型的winname,填需要显示的窗口标识名称
(2)InputArray类型的mat,填需要显示的图像
(3)imshow默认窗口(CV_WINDOW_AUTOSIZE)显示图像原始大小,否则缩放以适合窗口,缩放取决于图像深度:
·8位无符号类型图像,显示原始大小
·16位无符号或32位整型,像素值除以256,即[0,255*256]->[0,255]
·32位浮点数,像素值乘以255,即[0,1]->[0,255]
5.nameWindow()函数
函数原型:void nameWindow(const string& winname,int flas=EINDOW_AUTOSIZE);
(1)参数说明:1)窗口名2)窗口标识(WINDOW_NORMAL:可改变窗口大小;WINDOW_AUTOSIZE:窗口自动调整大小;WINDOW_OPENGL:窗口创建时支持OpenGL)
(2)作用:创建窗口
6. imwrite函数
函数原型:bool imwrite(const string& fliename,InputArray img,const vector& params=vector());
(1)参数说明:
文件名;
Mat类型的图像数据;
特定格式保存的参数编码(默认vector()):JPEG格式图片,参数表示0-100的图片质量(默认值95);PNG格式图片,参数表示0-9压缩级别(默认值3);PPM\PGM\PB,格式图片,参数表示0或1二进制格式标志(默认值1)
(2)作用:输出到文件
(3)示例:在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);
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;
}
7.图像载入、混合、显示、输出到文件综合示例
#include<opencv2/opencv.hpp>
#include<opencv2/highgui/highgui.hpp>
using namespace cv;
int main()
{
//1.图像的载入和显示
Mat girl = imread("girl.jpg");
namedWindow("[1]动漫图"); //创建一个名为“【1】动漫图”的窗口
imshow("[1]动漫图", girl);
//2.初级图像混合
Mat image = imread("cat.jpg");
Mat logo = imread("dog.jpg");
namedWindow("[2]原画图");
imshow("[2]原画图", image);
namedWindow("[3]logo图");
imshow("[3]logo图", logo);
Mat imageROI;//定义一个Mat类型,用于存放,图像的ROI
imageROI = image(Rect(800, 300, logo.cols, logo.rows));//方法一
//imageROI = image(Range(350, 350 + logo.rows), Range(800, 800 + logo.cols));//方法二
addWeighted(imageROI, 0.5, logo, 0.3, 0.0, imageROI);//将logo加到原图上
namedWindow("[4]原画+logo图");
imshow("[4]原画+logo图", image);
//3.图像输出
//imwrite("由imwrite生成的图片", image);
waitKey(0);
return 0;
}
3.2 滑动条的创建和使用
3.2.1 创建滑动条:createTrackbar()函数
函数原型:int createTrackbar(conststring& trackbarname,conststring& winname,int* value,int count,TrackbarCallback onChange=0,void* userdata=0);
(1)参数说明:轨迹条名字 ,依附窗口名 , 滑块初始位置 ,滑块可以到达的最大位置, 指向回调函数指针(每当滑块改变时函数都会回调), 用户传给回调函数的数据
(2)函数作用:创建一个具有特定名称和范围的轨迹条
(3)示例:用轨迹条控制两幅图像的Alpha混合
#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_dAlphValue;
double g_dBetaValue;
//声明存储图像的变量
Mat g_srcImage1;
Mat g_srcImage2;
Mat g_dstImage;
//响应滑动条的回调函数,第一个参数是轨迹条位置,第二个参数是用户数据
void on_Teackbar(int, void*)
{
//求出当前alpha值相对于最大值的比例
g_dAlphValue = (double)g_nAlphaValueSlider / g_nMaxAlphaValue;
//则beta值为1减去alpha值
g_dBetaValue = (1.0 - g_dAlphValue);
//根据alpha和beta值进行线性混合
addWeighted(g_srcImage1, g_dAlphValue, g_srcImage2, g_dBetaValue, 0.0, g_dstImage);
//显示效果图
imshow(WINDOW_NAME, g_dstImage);
}
int main()
{
//加载图像(两图像尺寸需要相同)
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_s(TrackbarName, "透明值 %d", g_nMaxAlphaValue);
createTrackbar(TrackbarName, WINDOW_NAME, &g_nAlphaValueSlider, g_nMaxAlphaValue,on_Teackbar);
//结果在回调函数中显示
on_Teackbar(g_nAlphaValueSlider, 0);
//按任意键退出
waitKey(0);
return 0;
}
3.2.2 getTrackbarPos()函数
函数原型:int getTrackbarPos(conststring& trackbarname,conststring& winname);
(1)参数说明: 轨迹条名字 , 窗口名
(2)作用:获取当前轨迹条位置
3.3 鼠标操作
SetMouseCallback()函数:void setMouseCallback(conststring& winname,MouseCallback onMouse,void* userdata=0)
(1)参数说明:窗口名字,指定窗口里每次鼠标事件发生的时候被调用的函数指针,用户定义的传递到回调函数的参数(默认0)
(2)作用:为指定的窗口设置鼠标消息回调函数
(3)示例:
#include<opencv2/opencv.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;
bool g_bDrawingBox = false; //是否进行绘制
RNG g_rng(12345);
int main()
{
//[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);
cvSetMouseCallback(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;
}
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)));
}