《Opencv3编程入门》学习笔记
记录一下在学习《Opencv3编程入门》这本书时遇到的问题或重要的知识点。
第一章 邂逅opencv
参考推荐软件版本:visual studio2010 opencv2.4.9
- visual studio安装教程:
https://blog.csdn.net/qq_45768871/article/details/108178858
- opencv2.4.9下载:(解压到指定文件夹就行)
https://sourceforge.net/projects/opencvlibrary/files/opencv-win/2.4.9/opencv-2.4.9.exe/download
-
配置环境变量:将
opencv解压路径/build/x64/vc10/bin
添加到Path中 -
Visual studio新建项目配置(参考书p17-p21)
注意:我这里选择和书上一样使用Win32编译器+x86:
附1:opencv附加依赖项
opencv_calib3d249.lib
opencv_contrib249.lib
opencv_core249.lib
opencv_features2d249.lib
opencv_flann249.lib
opencv_gpu249.lib
opencv_highgui249.lib
opencv_imgproc249.lib
opencv_legacy249.lib
opencv_ml249.lib
opencv_nonfree249.lib
opencv_objdetect249.lib
opencv_ocl249.lib
opencv_photo249.lib
opencv_stitching249.lib
opencv_superres249.lib
opencv_ts249.lib
opencv_video249.lib
opencv_videostab249.lib
opencv_calib3d249d.lib
opencv_contrib249d.lib
opencv_core249d.lib
opencv_features2d249d.lib
opencv_flann249d.lib
opencv_gpu249d.lib
opencv_highgui249d.lib
opencv_imgproc249d.lib
opencv_legacy249d.lib
opencv_ml249d.lib
opencv_nonfree249d.lib
opencv_objdetect249d.lib
opencv_ocl249d.lib
opencv_photo249d.lib
opencv_stitching249d.lib
opencv_superres249d.lib
opencv_ts249d.lib
opencv_video249d.lib
opencv_videostab249d.lib
问题:运行报错如下图所示
解决:这是因为文件路径错误,特别要注意反斜杠(因为直接放在源文件下的图片,无法读取到,所以选择使用文件的绝对路径)
Mat img = imread("D://lili/Desktop/2.jpg");
测试:载入并显示一张图片到窗口中
#include <opencv2\opencv.hpp>
using namespace cv;
int main(){
//1、读入一张图片
Mat img = imread("D://lili/Desktop/jpg/opencv/2.jpg");
//2、在窗口中现实载入的图片
imshow("【载入的图片】",img);
//3、等待6000ms后窗口自动关闭
waitKey(6000);
}
快速上手
(一)图像显示
#include <opencv2\opencv.hpp>
using namespace cv; //包含cv命名空间
void main(){
Mat srcImage = imread("D://lili/Desktop/jpg/opencv/2.jpg");
imshow("【原始图】",srcImage);
waitKey(0); //等待任意键按下
}
(二)图像腐蚀
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
using namespace cv;
int main(){
Mat srcImage = imread("D://lili/Desktop/jpg/opencv/2.jpg");
imshow("【原图】腐蚀操作",srcImage);
//拓展1:返回指定形状和尺寸的结构元素
Mat element = getStructuringElement(MORPH_CROSS,Size(12,12));
Mat distImage;
//拓展2
erode(srcImage,distImage,element);
imshow("【效果图】腐蚀操作",distImage);
waitKey(0);
return 0;
}
拓展1:getStructuringElement函数
形态学处理函数:获取结构化元素,会返回指定形状和尺寸的结构元素。 (类似卷积核)
Mat getStructuringElement(int shape, Size esize, Point anchor =Point(-1, -1));
-
参数1: 表示内核的形状,有三种: 矩形:MORPH_RECT; 交叉形:MORPH_CROSS; 椭圆形:MORPH_ELLIPSE;
-
参数2: 表示内核的尺寸。
-
参数3: 表示锚点的位置。对于锚点的位置,有默认值Point(-1,-1),表示锚点位于中心点。element形状唯一依赖锚点位置,其他情况下,锚点只是影响了形态学运算结果的偏移。
拓展2:erode函数
CV_EXPORTS_W void erode( InputArray src, OutputArray dst, InputArray kernel,
Point anchor = Point(-1,-1), int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue() );
参数描述
-
参数1: src 输入图像;通道的数量可以是任意的,但是深度值应该是以下之一: CV_8U, CV_16U, CV_16S, CV_32F,CV_64F.
-
参数2:dst 和源图像同样大小和类型的输出图像。
-
参数3:kernel 用于腐蚀的结构元素;如果element=Mat(),是一个3 x 3的矩形结构元素. Kernel可以通过使用getStructuringElement来创建。
-
参数4:anchor 素中的锚点的位置,默认是值(-1,-1),也就是说锚点在元素的中心位置。
-
参数5:iterations 腐蚀的迭代次数。
-
参数6:borderType像素外推方法。参见#BorderTypes, BORDER_WRAP不支持。
-
参数7:borderValue 固定边缘的情况下的边缘值。
(三)图像模糊
#include <opencv2\highgui\highgui.hpp>
#include <opencv2\imgproc\imgproc.hpp>
using namespace cv;
int main(){
Mat srcImage = imread("D://lili/Desktop/jpg/opencv/2.jpg");
imshow("均值滤波【原图】",srcImage);
Mat distImage;
blur(srcImage,distImage,Size(11,11));
imshow("均值滤波【效果图】",distImage);
waitKey(0);
return 0;
}
拓展1:blur函数
void blur(InputArray src, OutputArray dst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT )
参数描述
- 参数1:InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。该函数对通道是独立处理的,且可以处理任意通道数的图片,但需要注意,待处理的图片深度应该为CV_8U, CV_16U, CV_16S, CV_32F 以及 CV_64F之一。
- 参数2:OutputArray类型的dst,即目标图像,需要和源图片有一样的尺寸和类型。比如可以用Mat::Clone,以源图片为模板,来初始化得到如假包换的目标图。
- 参数3:Size类型(对Size类型稍后有讲解)的ksize,内核的大小。一般这样写Size( w,h )来表示内核的大小( 其中,w 为像素宽度, h为像素高度)。Size(3,3)就表示3x3的核大小,Size(5,5)就表示5x5的核大小
- 参数4:Point类型的anchor,表示锚点(即被平滑的那个点),注意他有默认值Point(-1,-1)。如果这个点坐标是负值的话,就表示取核的中心为锚点,所以默认值Point(-1,-1)表示这个锚点在核的中心。
- 参数5:int类型的borderType,用于推断图像外部像素的某种边界模式。有默认值BORDER_DEFAULT,我们一般不去管它。
(四)canny边缘检测
操作步骤:将原图像转为灰度图——》降噪——》运行canny算子
#include <opencv2\opencv.hpp>
#include <opencv2\imgproc\imgproc.hpp>
using namespace cv;
int main(){
Mat srcImage = imread("D://lili/Desktop/jpg/opencv/2.jpg");
imshow("【原图】Canny边缘检测",srcImage);
Mat distImage,edge,grayImage;
//1、创建与src同类型和大小的矩阵
distImage.create(srcImage.size(),srcImage.type());
//2、将原图像转为灰度图
cvtColor(srcImage,grayImage,CV_BGR2GRAY);
//3、3*3内核降噪 模糊去噪:噪声会影响边缘检测的准确性,因此首先要将噪声过滤掉
blur(grayImage,edge,Size(3,3));
//4、运行canny算子
Canny(edge,edge,3,9,3);
//5、显示效果
imshow("【效果图】Canny边缘检测",edge);
waitKey(0);
return 0;
}
拓展1:cvtColor函数:图像空间色彩转换
void cvtColor( InputArray src, OutputArray dst, int code, int dstCn = 0 );
函数参数解释
-
参数1:src(source):输入的源图像。为矩阵形式。
-
参数2:dst(destination):输出的目标图像,即经过色彩转后我们需要得到的图像。也为矩阵形式。
-
参数3:code:颜色空间转换的标识符,表示我们所要进行空间转换的结果。
code的参数多达200多,在此列举一些常用的参数,更多参数请查阅opencv官方文档
注意!在opencv中彩色图像(RGB图像)按照BGR顺序进行存储。所以以彩色图像为源图像进行颜色空间转换时,注意是“BGR2” -
参数4:dstCn:目标图像的通道数。 默认值为0,表示目标图像取源图像的通道数 。
拓展2:Canny边缘检测—Canny函数
void Canny(InputArray image, OutputArray edges, double threshold1, double threshold2, int apertureSize=3, bool L2gradient=false)
参数详解:
- 第一个参数:InputArray类型的image,输入图像,Mat对象节课,需为单通道8位图像。
- 第二个参数:OutputArray类型的edges,输出的边缘图,需要和输入图像有相同的尺寸和类型。
- 第三个参数:double类型的threshold1,第一个滞后性阈值。
- 第四个参数:double类型的threshold2,第二个滞后性阈值。
- 第五个参数:int类型的apertureSize,表示算子的孔径的大小,默认值时3.
- 第六个参数:bool类型的L2gradient,一个计算图像梯度复制的标识,默认false。
(五)opencv视频操作基础—读取并播放视频
#include <opencv2\opencv.hpp>
using namespace cv;
int main(){
//1、读入视频 或者写成:VideoCapture capture;capture.open("XXX.avi");
VideoCapture capture("D://lili/Desktop/jpg/opencv/1.avi");
//2、循环显示每一帧
while(1){
Mat frame; //定义一个Mat对象,用于存储每一帧的图像
capture >> frame; //读取当前帧
imshow("读取视频",frame); //显示当前帧
waitKey(30);
}
return 0;
}
注意:当视频播放结束以后,报如下图的错误,问题待解决。
(六)opencv视频操作基础—调用摄像头采集图像
注:这里由于电脑摄像头不好使,并没有效果图
1、调用摄像头
将指定的视频文件名替换为0,即表示调用摄像头
#include <opencv2\opencv.hpp>
using namespace cv;
int main(){
//1、读入视频
VideoCapture capture(0);
//2、循环显示每一帧
while(1){
Mat frame; //定义一个Mat对象,用于存储每一帧的图像
capture >> frame; //读取当前帧
imshow("读取视频",frame); //显示当前帧
waitKey(30);
}
return 0;
}
2、canny边缘检测摄像头采集视频
即对每一帧(frame)执行canny边缘检测操作
#include <opencv2\opencv.hpp>
using namespace cv;
int main(){
//读入视频
VideoCapture capture(0);
Mat edges;
//循环显示每一帧
while(1){
//1、读入图像
Mat frame;
capture >> frame;
//2、将图像转为灰度图像
cvtColor(frame,edges,CV_BGR2GRAY);
//3、降噪
blur(edges,edges,Size(7,7));
//4、canny边缘检测
Canny(edges,edges,0,30,0);
imshow("被canny后的视频",edges);
waitKey(30);
}
return 0;
}