详见《OpenCV3编程入门(毛星云、冷雪飞)》
2.1 图像的载入、显示和输出到文件
OpenCV的命名空间
在使用OpenCV每一类的函数,都要加入cv::命名空间,推荐在代码开头加上
using namespace cv;
写简单程序时
# include <opencv2/core/core.hpp>
# include <opencv2/highgui/highgui.hpp>
using namespace cv;
Mat类图像操作
默认情况下尺寸为0,也可以指定初始尺寸,比如定义一个Mat类对象cv::Mat pic(320, 640, cv::Scalar(100));
图像的载入:imread()函数:
Mat imread(const string& filename, intflags=1);
intflags为载入标识,flags>0 返回一个3通道的彩色图像,flags=0返回灰度图像,flags<0返回包含Alpha通道的加载图像。若以彩色模式载入图像,解码后的图像会以BGR通道顺序存储。
Mat image0=imread("1.jpg",2|4); //载入无损的源图像
Mat image1=imread("1.jpg",0); //载入灰度图
Mat image2=imread("1.jpg",199); //载入3通道彩色图像
图像显示:imshow()函数:
void imshow(const string& winname, InputArray mat);
- const string&类型的winname:填需要显示的窗口标识名称
- InputArray类型mat:填需要显示的图像
如果载入的图像是8bit unsigned,显示图像本来的样子;如果是16bit unsigned或32bit integer,像素值除以256,将值的范围[0, 255×256]映射到[0.255]。如果图像是32bit floating-point,像素值要乘以255,将值的范围是[0,1]映射到[0.255]。
在窗口创建的时候,如果设定了支持OpenGL(WINDOW_OPENGL),那么imshow还支持ogl::Buffer, ogl::Texture2D以及gpu::GpuMat作为输入。
IntputArray/OutputArray类型:简单当成Mat类即可。
创建窗口:namedWindow():
void nameWindow(const string& winname, int flags=WINDOW_AUTOSIZE);
- const string&类型的winname:填写被用作窗口的标识符的窗口名称
- int类型的flags:窗口的标识,WINDOW_NORMAL-用户可以改变窗口大小;WINDOW_AUTOSIZE-窗口大小会自动调整来适应所显示的图像;WINDOW_OPENGL,设置这个值,窗口创建时会支持OpenGL。
调用destroyWindow()
或destroyAllWindows()
函数来关闭窗口。
输出图像到文件:imwrite()函数
bool imwrite(const string& filename, InputArray img, const vector<int>& params=vector<int>());
- const string& 类型的filename:填需要写入的文件名
- InputArray类型的img:填一个Mat类型的图像数据
- const vector()&类型的params:表示特定格式保存的参数编码。对于JPEG格式图片,这个参数表示0-100的图像质量(CV_IMWRITE_JPEG_QUALITY),默认值是95;
PNG格式的图片,这个参数表示压缩级别从0-9(CV_IMWRITE_PNG_COMPRESSION),较高的值意味着更小的尺寸和更长的压缩时间;
PPM, PGM, PBM格式图片,这个参数表示一个二进制格式标志(CV_IMWRITE_PXM_BINARY),取值为0或1,默认是1。
2.2 滑动条的创建和使用
创建一个滑动条:creatTrackbar
滑动条需要一个回调函数配合起来使用
int creatTrackbar(conststring& trackbarname, conststring& winname, int* value, int count, TrackbarCallback onChange=0, void* userdata=0);
- const string&类型的trackbarname:轨迹条的名字
- const string&类型的winname:窗口的名字
- int*类型的value:指向整型的指针,表示滑块的位置。创建时,滑块的初始位置就是该变量当前的值
- int类型的count:滑块可以达到的最大位置的值。最小位置的值始终为0
- TrackbarCallback类型的onChange,回调函数的函数名,有默认值0。指向回调函数的指针,每次滑块位置改变时该函数都会进行回调,并且这个函数的原型必须是void XXX(int, void*),第一个参数是轨迹条的位置,第二个位置是用户数据。如果回调是NULL指针,则表示没有回调函数的调用,仅第三个参数value有变化
- void*类型的userdata,有默认值0。是用户传给回调函数的数据,用来处理轨迹条事件。如果使用的第三个参数value实参是全局变量,可以不管userdata参数。
获取当前轨迹条的位置:getTrackbarPos()函数
int getTrackbarPos(conststring& trackbarname, conststring& winname);
- const string&类型的trackbarname,表示轨迹条的名字
- const string&类型的winname,表示轨迹条的父窗口的名称
例:两幅图像指定透明的混合
#include <opencv2/opencv.hpp>
#include "opencv2/highgui/highgui.hpp"
using namespace cv;
#define WINDOR_NAME "[线性混合示例]"
Mat g_srcImage1;
Mat g_srcImage2;
Mat g_dstImage;
//on_Trackerbar()滑动条回调函数
void on_Trackbar(int, void*)
{
g_dAlphaValue = (double)g_nAlphaValueSlider/g_nMaxAlphaValue;
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);
}
int main(int argc, char** argv)
{
g_srcImage1 = imread("1.jpg");
g_srcImage2 = imread("2.jpg"):
if(!g_srcImage1.data){printf("读取第一幅图片错误,请确定目录下是否有imread函数指定图片存在~!\n"); return -1;}
if(!g_srgImage2.data){printf("读取第二幅图片错误,请确认目录下是否有imread函数指定图片存在~!\n");return -1;}
//设置滑动条初值为70
g_nAlphaValueSlider = 70;
//创建窗体
nameWindow(WINDOW_NAME,1);
//在窗体中创建一个滑动条 控件
char TrackbarNme[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;
}
2.3 鼠标操作
与滑动条的消息映射方向类似,都是通过一个中介函数配合一个回调函数实现的。
指定鼠标操作消息回调函数SetMouseCallbck
void setMouseCallback(const string& winname, MouseCallback onMouse, void* userdata=0)
- const string&类型的winname:窗口的名字
- MouseCallback类型的onMouse:指定窗口里每次鼠标发生的时候,被调用的函数指针。函数原型是void Foo(int event, int x, int y, int flags, void* param),event是EVENT_+变量之一,x,y是鼠标指针在图像坐标系中的坐标值,flags是EVENT_FLAG的组合,param是用户定义的传递到SetMouseCallback函数调用的参数。如EVENT_MOUSEMOVE为鼠标移动消息,EVENT_LBUTTONDOWN为鼠标左键按下消息。
- void*类型的userdata,用户定义的传递到回调函数的参数,有默认值0。
例:使用鼠标左键按下和松开在黑色窗口中绘制出一个一个彩色的矩形
# include <opencv2/opencv.hpp>
using namespace cv;
#define WINDOR_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_bDrawimgBox=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);
srcImage = Scalar::all(0);
//设置鼠标操作回调函数
nameWindow(WINDOR_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;
}
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){
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;
DrawRectangle(image, g_rectangle);
}
break;
}
}
void DrawRectangle(cv::Mat& img, cv::Rect box){
rectangle(img, box.t1(), box.br(), Scalar(g_rng.uniform(0,255), g_rng.uniform(0,255),g_rng.uniform(0,255)));//随机颜色
}