1、2024-8-212024-8-21第第1 1页页#include opencv2/core/core.hppusing namespace cv;/Mat H=imread(“lena.jpg”);#include opencv2/core/core.hpp/cv:Mat H=imread(“lena.jpg”);2024-8-212024-8-21第第2 2页页类型名含义等价类型类型名含义等价类型CV_8U 8bit无符号字符型ucharCV_32S32bit有符号整型intCV_8S8bit有符号整型scharCV_32F32bit浮点类型floatCV_16U 16bit无符号整型us
2、hortCV_64F64bit浮点类型doubleCV_16S 16bit有符号整型short注:可以用于定义多通道数据类型注意注意:其中使用最多的是类型是:其中使用最多的是类型是CV_8U_C1CV_8U_C1和和CV_8U_C3CV_8U_C3,分别为分别为单通道单通道和和三通道三通道的的8 8位无符号整型位无符号整型2024-8-212024-8-21第第3 3页页注意注意:其中常用的是类型是:其中常用的是类型是PointPoint、SizeSize、PtrPtr、RectRect和和ScalarScalar。2024-8-212024-8-21第第4 4页页2024-8-212024-
3、8-21第第5 5页页(1)(1)矩阵的创建方法矩阵的创建方法2024-8-212024-8-21第第6 6页页【例【例.1.1】:Mat M(7,7,CV_32FC2,Scalar(1,3);/Mat M(7,7,CV_32FC2,Scalar(1,3);/创建创建7 77 7的复数矩阵,并用的复数矩阵,并用1+3j1+3j填充填充M.create(M.create(100,60100,60,CV_8UC(15);/,CV_8UC(15);/创建创建1001006060的的1515通道的通道的8bit8bit无符号字符型矩阵无符号字符型矩阵M.create(M.create(Size(6Si
4、ze(60,0,10100 0),CV_8UC(15);,CV_8UC(15);/与上一与上一行代码等价行代码等价int sz=100,100,100;int sz=100,100,100;Mat bigCube(3,sz,CV_8U,Scalar:all(0);Mat bigCube(3,sz,CV_8U,Scalar:all(0);2024-8-212024-8-21第第7 7页页【例【例.2 2】:继上例,欲将矩阵:继上例,欲将矩阵M M的第的第7 7列列拷贝拷贝给第给第1 1列列Mat M1=M.col(1);Mat M1=M.col(1);M.col(7).M.col(7).copy
5、TocopyTo(M1);(M1);注意注意:矩阵的拷贝:矩阵的拷贝(copyTo(copyTo方法方法)拷贝的只是矩阵头拷贝的只是矩阵头并修改源矩阵的并修改源矩阵的refcounterrefcounter指针,并不将源矩阵的指针,并不将源矩阵的实际数据拷贝至目的矩阵,实际数据拷贝至目的矩阵,故上例目的不能达到故上例目的不能达到。(2)(2)矩阵的拷贝矩阵的拷贝2024-8-212024-8-21第第8 8页页【例【例.3 3】:新建一个三通道图像:新建一个三通道图像imgimg,并将,并将(10,10,100,100)(10,10,100,100)的矩形区域置为绿色的矩形区域置为绿色Mat
6、img(Size(320,240),CV_8UC3);Mat img(Size(320,240),CV_8UC3);Mat roi(img,Rect(10,10,100,100);Mat roi(img,Rect(10,10,100,100);roi=Scalar(0,255,0);roi=Scalar(0,255,0);【例【例.4 4】:利用数组初始化矩阵:利用数组初始化矩阵M M,再将矩阵,再将矩阵M M克隆克隆至矩阵至矩阵N Ndouble m33=1,2,3,4,5,6,7,8,9;double m33=1,2,3,4,5,6,7,8,9;Mat M=Mat(3,3,CV_64F,m
7、);Mat M=Mat(3,3,CV_64F,m);Mat N=M.clone();Mat N=M.clone();矩阵矩阵N N的内容将和矩阵的内容将和矩阵M M的完全一致,且都独立分配内存空间。的完全一致,且都独立分配内存空间。(3)(3)矩阵的克隆矩阵的克隆【建议使用】【建议使用】2024-8-212024-8-21第第9 9页页(4)(4)矩阵的初始化矩阵的初始化【例【例.6 6】:产生:产生“0”/“1”“0”/“1”矩阵矩阵Mat A;Mat A;A=Mat:A=Mat:zeroszeros(3,3,CV_32F);(3,3,CV_32F);Mat B=Mat:Mat B=Mat:
8、onesones(100,100,CV_8U)(100,100,CV_8U)*3 3【例【例.5 5】:int m33=1,2,3,4,5,6,7,8,9;int m33=1,2,3,4,5,6,7,8,9;Mat M=Mat(3,3,CV_8U,m);Mat M=Mat(3,3,CV_8U,m);2024-8-212024-8-21第第1010页页(5)(5)矩阵的存取矩阵的存取【例【例.7 7】:atat方法方法Mat H(100,100,CV_64F);Mat H(100,100,CV_64F);for(int i=0;i H.rows;i+)for(int i=0;i H.rows;i
9、+)for(int j=0;j H.cols;j+)for(int j=0;j H.cols;j+)H.H.atat(i,j)=255.H.at(i,j);(i,j)=255.H.at(i,j);(6)(6)矩阵的运算矩阵的运算 点积点积:要求两个矩阵:要求两个矩阵(M M、N N)的大小、类型相同的大小、类型相同M.dot(N);M.dot(N);2024-8-212024-8-21第第1111页页 叉积叉积:要求两个矩阵必须为相同大小、类型的三元组浮:要求两个矩阵必须为相同大小、类型的三元组浮点类型点类型M.cross(N);M.cross(N);乘除乘除:multiply(M,N,D,0
10、.8);/multiply(M,N,D,0.8);/点乘点乘divide(M,N,D);/divide(M,N,D);/点除点除M.mul(5/N);/M.mul(5/N);/等价于等价于 divide(M,N,5);divide(M,N,5);D=MD=M*N;/N;/两个矩阵相乘两个矩阵相乘 加减加减add(M,N,D);/D=M+Nadd(M,N,D);/D=M+Nsubtract(M,N,D);/D=M.Nsubtract(M,N,D);/D=M.N2024-8-212024-8-21第第1212页页 求逆求逆N=M.inv();N=M.inv();转置转置N=M.t();N=M.t(
11、);OpenCVOpenCV提供了非常丰富的矩阵操作的提供了非常丰富的矩阵操作的APIAPI函数,函数,几乎囊括了所有必需的几乎囊括了所有必需的基本矩阵运算基本矩阵运算,这些函数,这些函数包括:包括:绝对值绝对值、绝对差绝对差、求逆求逆、对数运算对数运算、指数指数运算运算、模运算模运算、特征值求解特征值求解、最大最大(小小)值值、转置转置、归一化归一化、奇异值分解奇异值分解等等,详见等等,详见OpenCVOpenCV参考手册。参考手册。2024-8-212024-8-21第第1313页页MatMat imreadimread(const string&(const string&filenam
12、e,intfilename,int flags=1flags=1););/适用于适用于C+C+2024-8-212024-8-21第第1414页页boolbool imwriteimwrite(const string&(const string&filename,filename,InputArray InputArray image,image,const vector&const vector¶ms=vector()params=vector()2024-8-212024-8-21第第1515页页 单通道图像:单通道图像:Scalar intensity=img.Scalar i
13、ntensity=img.atat(x,y);(x,y);三通道图像:三通道图像:按按B B、G G、R R排列排列Vec3bVec3b intensity=img.at(x,y);intensity=img.at(x,y);uchar blue=intensity.val0;uchar blue=intensity.val0;uchar green=intensity.val1;uchar green=intensity.val1;uchar red=intensity.val2;uchar red=intensity.val2;Vec3fVec3f intensity=img.at(x,y
14、);intensity=img.at(x,y);float blue=intensity.val0;float blue=intensity.val0;float green=intensity.val1;float green=intensity.val1;float red=intensity.val2;float red=intensity.val2;2024-8-212024-8-21第第1616页页img.at(x,y)=128;img.at(x,y)=128;注注:中的类型须与图像数据的实际类型一致。中的类型须与图像数据的实际类型一致。Img=Scalar(0)Img=Scalar
15、(0);Rect r(10,10,100,100);Rect r(10,10,100,100);Mat smallImg=img(r);Mat smallImg=img(r);(img,grey,CV_BGR2GRAY);(img,grey,CV_BGR2GRAY);2024-8-212024-8-21第第1717页页Mat img=Mat img=imreadimread(image.jpg);(image.jpg);namedWindownamedWindow(image,CV_WINDOW_AUTOSIZE);(image,CV_WINDOW_AUTOSIZE);(image,img);
16、(image,img);waitKeywaitKey();();medianFilter,GaussianFilter,bilateralFilter,medianFilter,GaussianFilter,bilateralFilter,blur,blur,boxFilterboxFilter,filter2Dfilter2D,GaussianBlurGaussianBlur,Smooth,Smooth,medianBlur,Laplacian,medianBlur,Laplacian,SobelSobel,imdilateimdilate,imerodeimerode2024-8-2120
17、24-8-21第第1818页页invertAffineTransform,invertAffineTransform,warpAffinewarpAffine,warpPerspective,warpPerspective,LogPolar,LogPolar,resizeresize,dct,dct,dftdft,adaptiveThreshold,adaptiveThreshold,cvtColorcvtColor,floodFill,integral,watershed,floodFill,integral,watershed calcHistcalcHist,equalizeHisteq
18、ualizeHist,NormalizeHist,ThreshHist,NormalizeHist,ThreshHist moments,HuMoments,moments,HuMoments,findContoursfindContours,drawContoursdrawContours,contourAreacontourArea,ApproxChains,ApproxChains,boundingRectboundingRect,CannyCanny,HoughCirclesHoughCircles,HoughLinesHoughLines,MatchTemplate,MatchTem
19、plateVideoCapture:open,isOpened,release,grab,VideoCapture:open,isOpened,release,grab,VideoWriter:open,isOpened,writeVideoWriter:open,isOpened,write2024-8-212024-8-21第第1919页页给图像添加噪声,实际上就是对图像中像素点的灰度值给图像添加噪声,实际上就是对图像中像素点的灰度值进行随机修改,通过随机数产生函数取得像素点的行、进行随机修改,通过随机数产生函数取得像素点的行、列坐标,然后对该像素点的灰度值按照事先约定的方式列坐标,然后对
20、该像素点的灰度值按照事先约定的方式置为置为0 0或或255255的过程;的过程;图像平滑的方式,按照数字图像处理的理论有多种方式,图像平滑的方式,按照数字图像处理的理论有多种方式,如均值滤波、中值滤波、高斯平滑滤波等等,这些基本如均值滤波、中值滤波、高斯平滑滤波等等,这些基本的图像处理算法在的图像处理算法在OpenCVOpenCV中都提供了相应的中都提供了相应的APIAPI函数。本函数。本例采用中值滤波进行平滑处理。例采用中值滤波进行平滑处理。2024-8-212024-8-21第第2020页页(1)(1)包含所需的头文件包含所需的头文件#include /#include /标准输入标准输入
21、/输出流输出流#include#include/矢量矢量/OpenCV/OpenCV图像处理包图像处理包#include opencv2/imgproc/imgproc.hpp#include opencv2/imgproc/imgproc.hpp/OpenCV/OpenCV高层高层GUIGUI包包#include opencv2/highgui/highgui.hpp#include opencv2/highgui/highgui.hpp/OpenCV/OpenCV二维特征检测与描述包二维特征检测与描述包#include opencv2/features2d/features2d.hpp#i
22、nclude opencv2/features2d/features2d.hpp(2)(2)声明命名空间声明命名空间using namespace std;using namespace std;/C+/C+标准标准stdstd命名空间命名空间using namespace cv;using namespace cv;/OpenCV/OpenCV命名空间命名空间 2024-8-212024-8-21第第2121页页(3)(3)自定义函数原型声明自定义函数原型声明(可选可选)void void addNoiseaddNoise(Mat&image,int n,int noise);(Mat&im
23、age,int n,int noise);/图像加噪自定义函数图像加噪自定义函数(4)main(4)main函数:函数:主函数主函数int main(void)int main(void)/建立三个窗口,分别用于显示源图像、加噪后图像和平滑后的图像建立三个窗口,分别用于显示源图像、加噪后图像和平滑后的图像 namedWindownamedWindow(Source,CV_WINDOW_AUTOSIZE);(Source,CV_WINDOW_AUTOSIZE);namedWindow(Noised,CV_WINDOW_AUTOSIZE);namedWindow(Noised,CV_WINDOW_
24、AUTOSIZE);namedWindow(Smoothed,CV_WINDOW_AUTOSIZE);namedWindow(Smoothed,CV_WINDOW_AUTOSIZE);/定义图像容器定义图像容器srcsrc,并加载图像,并加载图像lena.pnglena.png Mat src=Mat src=imreadimread(lena.png,CV_BGR2GRAY);(lena.png,CV_BGR2GRAY);if(src.empty()return 1;/if(src.empty()return 1;/判断是否加载成功判断是否加载成功 imshowimshow(Source,s
25、rc);(Source,src);/显示源图像显示源图像 addNoiseaddNoise(src,2000,255);/(src,2000,255);/给图像加入随机噪声给图像加入随机噪声 imshow(Noised,src);imshow(Noised,src);/显示加噪后的图像显示加噪后的图像 medianBlurmedianBlur(src,src,3);/(src,src,3);/对加噪后的图像进行中值滤波平滑处理对加噪后的图像进行中值滤波平滑处理 imshow(Smoothed,src);imshow(Smoothed,src);/显示平滑后的图像显示平滑后的图像 waitKey
26、();waitKey();/等待用户按键等待用户按键 2024-8-212024-8-21第第2222页页(5)addNoise(5)addNoise函数:用于对图像函数:用于对图像添加随机噪声添加随机噪声/入口参数:入口参数:imageimage待添加噪声的源图像待添加噪声的源图像;n;n加入噪声点个数加入噪声点个数;noise;noise噪声类型噪声类型/出口参数:无出口参数:无void addNoise(Mat&image,int n=1000,int noise=0)void addNoise(Mat&image,int n=1000,int noise=0)srand(getTick
27、Count();srand(getTickCount();/产生随机数种子产生随机数种子 if(image.empty()return;/if(image.empty()return;/判断源图像是否有效判断源图像是否有效 for(int l=0;ln;l+)for(int l=0;l=3)if(image.channels()=3)/图像通道数判断图像通道数判断 for(int k=0;kimage.channels();k+)/for(int k=0;kimage.channels();k+)/多通道多通道 image.image.atat(i,j)k=noise;/(i,j)k=nois
28、e;/添加噪声添加噪声 else else /单通道单通道 image.at(i,j)=noise;/image.at(i,j)=noise;/添加噪声添加噪声 2024-8-212024-8-21第第2323页页 图图16.1 16.1 加噪后的图像加噪后的图像 图图16.2 16.2 中值滤波平滑后的图像中值滤波平滑后的图像2024-8-212024-8-21第第2424页页按照按照15.215.2节的方法,节的方法,(1)(1)在在Code:BlocksCode:Blocks中新建工程中新建工程;(2)(2)工程模板选择工程模板选择“wxWidgets Projects”“wxWidge
29、ts Projects”;(3)(3)GUIGUI界面设计器选择界面设计器选择“wxFormbuilder”“wxFormbuilder”;(4)(4)应用程序类型选择应用程序类型选择“Frame Based”“Frame Based”;(5)(5)其余页面选项可根据实际情况确定,如其余页面选项可根据实际情况确定,如wxWidgetswxWidgets是以动态链接库还是静态链接库等等。是以动态链接库还是静态链接库等等。关键步骤关键步骤如图如图16.316.3和图和图16.16.4 4所示。所示。2024-8-212024-8-21第第2525页页图图16.3 GUI16.3 GUI设计器及应用
30、程序类型选择设计器及应用程序类型选择 图图16.4 wxWidgets16.4 wxWidgets库设置库设置wxSmithwxSmith、wxFormbuilderwxFormbuilder分别分别是是Code:BlocksCode:Blocks自带的设计器自带的设计器插件插件和和为外部为外部GUIGUI设计器。设计器。建议建议初学者使用初学者使用wxFormbuilderwxFormbuilder。【Use wxWidgets DLLUse wxWidgets DLL】:勾选:勾选表示使用表示使用DLLDLL方式。方式。【Enable unicodeEnable unicode】:勾选表:
31、勾选表示支持示支持UnicodeUnicode字符编码。字符编码。2024-8-212024-8-21第第2626页页本本GUIGUI案例采用如案例采用如表表16.416.4所示的所示的wxWidgetswxWidgets组件来组件来设计完成,设计完成,GUIGUI界面的外观如界面的外观如图图16.516.5所示。所示。组件类功能在本案例中用途wxFrame框架窗口GUI顶层窗口wxMenuBar菜单提供菜单操作wxSizer布局容器提供GUI界面中各组件的布局功能wxStaticLine静态线条用于GUI界面不同区域的分割线wxStaticText静态文本用于显示字符信息wxTextCtrl
32、文本控件用于接收用户输入数据wxChoice选项控件提供用户选择(噪声类型、平滑算法)wxButton按钮执行某种操作(如加噪、平滑滤波)表表16.4 16.4 所用到的所用到的wxWidgetswxWidgets组件组件2024-8-212024-8-21第第2727页页图图16.5 wxFormbuilder16.5 wxFormbuilder下的下的GUIGUI界面外观界面外观2024-8-212024-8-21第第2828页页(1)(1)菜单处理菜单处理:本例只为:本例只为“F“F文件文件”菜单中的菜单中的“O“O打开打开”命命令项的令项的OnMenuSelectionOnMenuSe
33、lection事件添加处理函数事件添加处理函数“OnFileopen”“OnFileopen”处理函数,完成打开一个图像文件的操作。其余菜单项的处理函数,完成打开一个图像文件的操作。其余菜单项的事件处理采用系统生成的默认操作。事件处理采用系统生成的默认操作。(2)(2)命令按钮命令按钮:分别为:分别为“加噪加噪”、“平滑平滑”两个按钮的两个按钮的“OnButtonClick”“OnButtonClick”和和“OnUpdateUI”“OnUpdateUI”事件添加处理函数:事件添加处理函数:OnBtnAddNoiseOnBtnAddNoise、OnUpdateUIAddnoiseOnUpdat
34、eUIAddnoise、OnBtnSmoothOnBtnSmooth和和OnUpdateUISmoothOnUpdateUISmooth。按按15.315.3的方法,点击工具栏的方法,点击工具栏“Generate Code”“Generate Code”按钮和菜按钮和菜单单“ToolsGenerate Inherited Class”“ToolsGenerate Inherited Class”生成生成GUIGUI界面的界面的C+C+代码和派生类,并将派生类中事件处理函数的声明和代码和派生类,并将派生类中事件处理函数的声明和实现代码框架拷贝到设计主文件,修改并完善相关代码。实现代码框架拷贝到设
35、计主文件,修改并完善相关代码。2024-8-212024-8-21第第2929页页本例的源代码包含三个类和一个资源文件:应用程序类本例的源代码包含三个类和一个资源文件:应用程序类ImageSmoothAppImageSmoothApp、GUIGUI界面类界面类GUIFrameGUIFrame、resource.rcresource.rc和和ImageSmoothMainImageSmoothMain。(1)(1)应用程序类应用程序类ImageSmoothAppImageSmoothApp类类2024-8-212024-8-21第第3030页页2024-8-212024-8-21第第3131页页
36、(2)(2)设计主文件设计主文件ImageSmoothFrameImageSmoothFrame类类2024-8-212024-8-21第第3232页页2024-8-212024-8-21第第3333页页2024-8-212024-8-21第第3434页页2024-8-212024-8-21第第3535页页2024-8-212024-8-21第第3636页页2024-8-212024-8-21第第3737页页2024-8-212024-8-21第第3838页页2024-8-212024-8-21第第3939页页2024-8-212024-8-21第第4040页页2024-8-212024-8-
37、21第第4141页页2024-8-212024-8-21第第4242页页2024-8-212024-8-21第第4343页页2024-8-212024-8-21第第4444页页2024-8-212024-8-21第第4545页页(3)(3)GUIFrameGUIFrame类类GUIFrameGUIFrame是是wxFormbuilderwxFormbuilder根据用户根据用户GUIGUI设计的布局设计的布局自动自动生成生成的代码,并作为类的代码,并作为类ImageSmoothFrameImageSmoothFrame的父类加以继的父类加以继承。关于承。关于GUIFrameGUIFrame类的
38、代码解析,此处从略。类的代码解析,此处从略。(1)(1)右键点击右键点击【ImageSmoothImageSmooth】【】【Build optionsBuild options】如如图图16.616.6所示;所示;(2)(2)相关选项相关选项的的配置配置如如图图16.16.7 7所示所示2024-8-212024-8-21第第4646页页图图16.6 16.6 工程构建选项工程构建选项2024-8-212024-8-21第第4747页页注意注意:在指定:在指定wxWidgetswxWidgets链接链接库的时候,不仅库的时候,不仅要保证选中的库要保证选中的库与当前工程的类与当前工程的类型是型
39、是一致一致的的(动动态库或静态库态库或静态库),而且库的而且库的排列顺排列顺序序也有先后之分。也有先后之分。具体可以参考具体可以参考wxWidgetswxWidgets自带自带的的samplessamples。图图16.7 16.7 工程构建选项配置对话框工程构建选项配置对话框2024-8-212024-8-21第第4848页页 编译、链接成功后,点击工具栏运行按钮,待程序启编译、链接成功后,点击工具栏运行按钮,待程序启动后通过动后通过“文件文件”菜单菜单打开一个图像文件,打开一个图像文件,添加噪声添加噪声,然,然后进行后进行平滑处理平滑处理,结果如图,结果如图16.81216.812所示。所
40、示。图图16.8 16.8 为加载图像时的界面为加载图像时的界面2024-8-212024-8-21第第4949页页图图16.9 16.9 打开打开lena.pnglena.png图像图像2024-8-212024-8-21图图16.10 16.10 添加椒盐噪声和平滑效果添加椒盐噪声和平滑效果第第5050页页2024-8-212024-8-21第第5151页页图图16.11 16.11 添加高斯噪声和平滑效果添加高斯噪声和平滑效果2024-8-212024-8-21图图16.12 Linux16.12 Linux环境下运行效果环境下运行效果第第5252页页2024-8-212024-8-21
41、第第5353页页(1)(1)讲述了讲述了OpenCVOpenCV使用的使用的初步知识初步知识,介绍了,介绍了OpenCVOpenCV的基础数据结构、数据类型、的基础数据结构、数据类型、MatMat类型图像容器、类型图像容器、OpenCVOpenCV图像操作的常用图像操作的常用APIAPI函数等。函数等。(2)(2)重点讲述了在重点讲述了在Code:BlocksCode:Blocks环境下如何利用环境下如何利用OpenCVOpenCV进行图像处理,并以图像加噪与平滑处理为进行图像处理,并以图像加噪与平滑处理为例介绍了两种不同的设计模式:例介绍了两种不同的设计模式:控制台模式控制台模式和和GUIGUI界面模式界面模式,给出了具体的设计过程、测试结果,特,给出了具体的设计过程、测试结果,特别是如何结合案例要求进行别是如何结合案例要求进行GUIGUI界面的设计和代码界面的设计和代码的编写,从而进一步掌握利用的编写,从而进一步掌握利用OpenCVOpenCV进行数字图像进行数字图像处理的实际工程应用奠定必要的基础。处理的实际工程应用奠定必要的基础。