1. 图像的载入、显示和输出到文件
1.1 OpenCV的命名空间
OpenCV中的C++类和函数都是定义在命名空间 cv 之内的,在访问时可以:
- 在代码开头加上 using namespace cv; (推荐这种方法)
- 每一次在使用OpenCV相关类和函数时,前面加上 cv:: ,例如:cv::imread()。
1.2 Mat类简析
OpenCV中Mat用于保存图像以及其他矩阵数据的数据结构。
例如:
Mat img=imread("1.jpg");
这里就是将图片中的信息读取保存在名为img的Mat变量里面。
1.3 图像的载入:imread( )函数
imread( )函数原始定义:
Mat imread( const String& filename, int flags = IMREAD_COLOR );
格式:imread(参数1,参数2)
- 参数1:const String&类型的filename,指载入图片的路径名。
例如:Mat img = imread("D:/practice/opencv3/imge/2.jpg");
在Windows系统下,OpenCV的imread( )函数支持的图像类型:
- 参数2:int类型的flags,为载入标识,它指定加载图像的颜色类型。该参数常常忽略,其默认为1(IMREAD_COLOR ),表示加载三通道的彩色图像。
其他的有:
对应的解释:
注意:当以彩色模式载入图像时,解码后的图像会以BGR的通道顺序进行存储,即蓝、绿、红的顺序。
1.4 图像的显示:imshow( )函数
imshow( )函数用于在指定窗口显示一副图像,函数的原始定义为:
void imshow(const String& winname, InputArray mat);
格式:imshow(参数1,参数2);
- 参数1:const String&类型的winname,填需要显示的窗口名称。
- 参数2:InputArray 类型的mat,填需要显示的图像。
例如:imshow("原始图片", img);
1.5 创建窗口:namedWindow( )函数
namedWindow( )函数,用于创建一个窗口。一般用于在显示窗口之前就需要用到窗口名这种情况,否则直接用imshow( )就好。
原始定义:
void namedWindow(const String& winname, int flags = WINDOW_AUTOSIZE);
格式:namedWindow(参数1,参数2);
例如:namedWindow("WIN1", WINDOW_NORMAL);
- 参数1:const String&类型的name,填写窗口的名称;
- 参数2:int类型的flags,窗口的标识,有以下选择:
可以调用 destroyWindow( )或者destroyAllWindow( )函数来关闭窗口。
1.6 输出图像到文件:imwrite( )函数
imwrite( )函数用于将图像输出到文件中去,原始定义为:
bool imwrite( const String& filename, InputArray img,
const std::vector<int>& params = std::vector<int>());
格式:imwrite(参数1,参数2,参数3);
例如:imwrite("D:/imge/test123.jpg", img);
- 参数1:const String& 类型的filename,填写需要写入的文件名字,注意要加后缀,例如”img.jpg"。
- 参数2:InputArray 类型的img,一般填一个Mat类型的图像数据。
- 参数3:const vector&类型的params,表示特定格式保存的参数编码。默认值为vector( ),一般情况不需要填写。
综合示例:图像的载入、显示与输出
目标:读入两张图片,并且将这两张图片进行混合,最后将其保存输出。
示例代码:
#include<opencv2/opencv.hpp>
using namespace cv;
int main()
{
//-------------------- 图像的载入和显示 ---------------
Mat img = imread("D:/practice/opencv3/imge/2.jpg");//载入原始图片
namedWindow("【原始图像】");//创建原始图片窗口
imshow("【原始图像】", img);//显示原始图片
//-------------------- 初级图像混合 ------------------
Mat cat = imread("D:/practice/opencv3/imge/mao.jpg");//载入猫咪的图片
namedWindow("【猫咪的图片】");
imshow("【猫咪的图片】", cat);
//定义一个Mat类型,用于存放图像的ROI
Mat imgeROI;
imgeROI = cat(Rect(10, 50, img.cols, img.rows));
//将原图加到猫咪上(因为这里原图尺寸比猫咪小很多)
addWeighted(imgeROI, 0.5, img, 0.6, 0., imgeROI);
//显示结果
namedWindow("【混合后】");
imshow("【混合后】", cat);
//--------------------- 图像的输出 ----------------
imwrite("D:/practice/opencv3/imge/混合图片.jpg",cat);
waitKey(0);
system("pasue");
}
运行结果:
2. 滑动条的创建和使用
2.1 创建滑动条:createTrackbar( )函数
createTrackbar( )函数用于创建一个调整数值的滑动条,该滑动条依附在指定的窗口上。该函数常常和一个回调函数配合起来使用。
原始定义:
int createTrackbar(const String& trackbarname, const String& winname,
int* value, int count,
TrackbarCallback onChange = 0,
void* userdata = 0);
格式:createTrackbar(参数1,参数2,参数3,参数4,参数5,参数6);
- 参数1:const String&类型的trackbarname,我们创建的滑动条的名字。
- 参数2:const String&类型的winname,滑动条所依附窗口的名字,即对应nameWindow( )函数创建窗口时填入的窗口名字。
- 参数3:int*类型的value,一个指向整型的指针,表示滑动条上滑块的位置。在创建时,滑块的初始位置就是该变量当前的值。
- 参数4:int类型的count,表示滑块可以达到的最大位置的值。滑块的最小位置的值始终是0。
- 参数5:TrackbarCallback类型的onChange ,它有默认值为0。具体介绍如下:
参数6:void*类型的userdata,也有默认值0。具体介绍如下:
示例:利用滑动条来控制两个图像的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_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);
}
//-------------------------- mian()函数 ————————————
// 描述:控制台应用程序的入口函数,我们的程序从这里开始i执行
//-------------------------------------------------------------------------
int main(int argc,char** argv)
{
//加载图像(两图像的尺寸需要相同)
g_srcImage1 = imread("D:/practice/opencv3/imge/1.jpg");
g_srcImage2 = imread("D:/practice/opencv3/imge/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_Trackbar);
//结果在回调函数中显示
on_Trackbar(g_nAlphaValueSlider, 0);
//按任意键退出
waitKey(0);
system("pause");
return 0;
}
运行结果:
2.2 获取当前滑动条的位置:getTrackbarPos( )函数
getTrackbarPos( )函数,用于获取当前滑动条的位置。原始定义:
int getTrackbarPos(const String& trackbarname, const String& winname);
格式:getTrackbarPos(参数1,参数2);
- 参数1:const String&类型的trackbarname,表示滑动条的名字;
- 参数2:const String&类型的winname,表示滑动条父窗口的名字。
3. 鼠标操作
setMouseCallback( )函数,为指定的窗口设置鼠标回调函数,原始定义如下:
void setMouseCallback(const String& winname, MouseCallback onMouse, void* userdata = 0);
格式:setMouseCallback(参数1,参数2,参数3);
参数1:const String&类型的winname,窗口的名字;
参数2:MouseCallback类型的onMouse,指定窗口每次鼠标时间发生的时候,被调用的函数指针。具体介绍如下:
参数3: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 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)
{
//准备参数
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;//按下ESC键,程序退出
}
return 0;
//system("pasue");
}
//--------------------------- 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)
{
rectangle(img, box.tl(),box.br(), Scalar(g_rng.uniform(0, 255), g_rng.uniform(0, 255), g_rng.uniform(0, 255)));//随机颜色
}
运行结果: