OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。

1、如果你是某BNUer,还在为某多媒体课的作业而烦恼,那么看看我这篇文章或许能够帮助你成功肝完DDL!
2、如果你只是想尝试一下Laplace做边缘检测,那么走过路过不要错过,看看我这篇文章真的是来对地方了!

文章内容:

    • 一、实验要求
    • 二、实验环境配置
      • 1、visual studio + OpenCV的配置
        • (1)环境说明
        • (2)OpenCV的下载
        • (3)OpenCV的配置
    • 三、运行源代码
      • 1、出现的问题及解决方法
        • (1)运行代码时出现了如下问题
        • (2)解决方法
      • 2、从AVI文件中得到视频流,进行laplace边缘检测的代码 :
      • 3、从摄像头中得到视频流进行laplace边缘检测的代码 :
    • 四、参考资料

一、实验要求

实验要求:
从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。
注:
1、Laplace边缘检测
在这里插入图片描述
OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第1张图片
2、主要思想OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第2张图片

实验环境: OpenCV2.4.13.6 + visual studio 2019

二、实验环境配置

1、visual studio + OpenCV的配置

(1)环境说明

笔者使用的实验环境visual studio 2019 + OpenCV 2.4.13.6。visual studio的安装教程网上有很多,在此就不多bb怎么安装了。这里主要以visual studio 2019为例来讲解如何配置OpenCV 2.4.13.6。各版本配置的方法都差不多,但是需要搜索和下载对应的OpenCV版本,不然的话容易出现一些问题。

如果是其他版本的VS和opencv可以参考一下这个链接https://blog.csdn.net/xinjiang666/article/details/80785210

(2)OpenCV的下载

方式1 :点击下载Opencv2.4.13.6安装包
方式2 :点击官网下载对应版本

(3)OpenCV的配置

1、双击下载好的OpenCV
在这里插入图片描述
2、选择好全英文路径并点击Extract
OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第3张图片
3、可以看到E:\OpenCV\路径下已经有了一个叫opencv的目录
OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第4张图片
4、点击进去可以看到opencv中包含的内容
OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第5张图片
5、添加系统环境变量(x64的版本)
此电脑(我的电脑)——>右键——>属性——>高级系统设置——>环境变量——>系统变量——>path——>编辑——>新建,然后添加刚才opencv目录下对应到bin的路径
OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第6张图片
6、打开visual studio 2019,点击创建新项目,新建C++控制台应用程序
OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第7张图片
OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第8张图片
OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第9张图片
7、将下图中的x86改为x64
OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第10张图片
8、视图–>其他窗口–>属性管理器。
OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第11张图片
9、Debug | x64 ——>右键——>添加新项目属性表
OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第12张图片
OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第13张图片
10、添加包含目录
右键刚才新建的属性表——>属性——>VC++目录——>包含目录
添加下面的三个路径(需要根据自己opencv路径自行修改):
OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第14张图片
OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第15张图片
OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第16张图片
11、添加库目录
VC++目录——>库目录——>编辑
OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第17张图片
OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第18张图片

12、添加附加依赖项
链接器——>输入——>附加依赖项,可以将下面的内容直接复制到附加依赖项中

opencv_calib3d2413d.lib
opencv_contrib2413d.lib
opencv_core2413d.lib
opencv_features2d2413d.lib
opencv_flann2413d.lib
opencv_gpu2413d.lib
opencv_highgui2413d.lib
opencv_imgproc2413d.lib
opencv_legacy2413d.lib
opencv_ml2413d.lib
opencv_nonfree2413d.lib
opencv_objdetect2413d.lib
opencv_ocl2413d.lib
opencv_photo2413d.lib
opencv_stitching2413d.lib
opencv_superres2413d.lib
opencv_video2413d.lib
opencv_videostab2413d.lib

OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第19张图片
OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第20张图片
OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第21张图片
好的,进行完这一步,说明已经将环境配置好了,接下来可以尝试运行代码了,nice!

三、运行源代码

1、出现的问题及解决方法

(1)运行代码时出现了如下问题

warning MSB8003: 未定义 WindowsSDKDir 属性。可能找不到某些生成工具

(2)解决方法

参考https://blog.csdn.net/dongbao520/article/details/117289543

用Visual Studio Installer进行修复
OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第22张图片
OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第23张图片

2、从AVI文件中得到视频流,进行laplace边缘检测的代码 :

/*
功能:从摄像头或者AVI文件中得到视频流,对视频流进行边缘检测,并输出结果。
*/

#include "cv.h"
#include "highgui.h"
#include 
#include 
int main(int argc, char** argv)
{
	IplImage* laplace = 0;
	IplImage* colorlaplace = 0;
	IplImage* planes[3] = { 0, 0, 0 };  // 多个图像面
	CvCapture* capture = 0;//初始化为0,若在后面不对capture的值做修改,则从摄像头获得视频流
	//CvCapture
	//视频获取结构
	//typedef struct CvCapture CvCapture;
	/*结构CvCapture 没有公共接口,它只能被用来作为视频获取函数的一个参数。
	下面的语句说明在命令行执行程序时,如果指定AVI文件,那么处理从
	 AVI文件读取的视频流,如果不指定输入变量,那么处理从摄像头获取的视频流*/
	 /*
	 if (argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
		 capture = cvCaptureFromCAM(argc == 2 ? argv[1][0] - '0' : 0);
	 else if (argc == 2)
		 capture = cvCaptureFromAVI(argv[1]);
	 */
	 //获取视频,不需要上面的if...else语句,需要改为自己电脑上对应的路径
	capture = cvCaptureFromAVI( "E://1qq document//bsd.avi" );
	
	if (!capture) //获取视频失败
	{
		fprintf(stderr, "Could not initialize capturing.../n");
		return -1;
	}
	cvNamedWindow("Laplacian", 0);
	// 循环捕捉,直到用户按键跳出循环体
	for (;;)
	{
		IplImage* frame = 0;
		int i;
		//cvQueryFrame
		//
		//从摄像头或者文件中抓取并返回一帧
		//IplImage* cvQueryFrame( CvCapture* capture );
		//capture 
		//视频获取结构。
		//函数cvQueryFrame从摄像头或者文件中抓取一帧,然后解压并返回这一帧。
		//这个函数仅仅是函数cvGrabFrame和函数cvRetrieveFrame在一起调用的组合。
		//返回的图像不可以被用户释放或者修改。 抓取后,capture被指向下一帧,
		//可用cvSetCaptureProperty调整capture到合适的帧。
		//
		//注意: cvQueryFrame返回的指针总是指向同一块内存。建议cvQueryFrame后拷贝一份
		//。而且返回的帧需要FLIP后才符合OPENCV的坐标系。 若返回值为NULL,说明到了视频的最后一帧。
		frame = cvQueryFrame(capture);
		if (!frame)
			break;
		if (!laplace)
		{
			for (i = 0; i < 3; i++)
				planes[i] = cvCreateImage(cvSize(frame->width, frame->height), 8, 1);
			//CreateImage
			/*
			创建头并分配数据
			IplImage* cvCreateImage( CvSize size, int depth, int channels );
			size
			图像宽、高.
			depth 
			图像元素的位深度,可以是下面的其中之一:
			IPL_DEPTH_8U - 无符号8位整型
			IPL_DEPTH_8S - 有符号8位整型
			IPL_DEPTH_16U - 无符号16位整型
			IPL_DEPTH_16S - 有符号16位整型
			IPL_DEPTH_32S - 有符号32位整型
			IPL_DEPTH_32F - 单精度浮点数
			IPL_DEPTH_64F - 双精度浮点数
			channels 
			每个元素(像素)的颜色通道数量.可以是 1, 2, 3 或 4.通道是交叉存取的,例如通常的彩色图像数据排列是:
			b0 g0 r0 b1 g1 r1 ...
			虽然通常 IPL 图象格式可以存贮非交叉存取的图像,并且一些OpenCV 也能处理他, 但是这个函数只能创建交叉存取图像.
			函数 cvCreateImage 创建头并分配数据,这个函数是下列的缩写型式
			header = cvCreateImageHeader(size,depth,channels);
			cvCreateData(header); //只是创建空间,并不会初始化空间内的数据
			*/

			laplace = cvCreateImage(cvSize(frame->width, frame->height),
				IPL_DEPTH_16S, 1);
			colorlaplace = cvCreateImage(cvSize(frame->width, frame->height), 8, 3);
		}
		//cvCvtPixToPlane
		/*
		  openCV里面的一个函数
		  可以看作cvSplit是他的宏:
		  #define cvCvtPixToPlane cvSplit
		  void cvSplit( const CvArr* src, CvArr* dst0, CvArr* dst1,CvArr* dst2, CvArr* dst3 );
		  作用是:分割多通道数组成几个单通道数组或者从数组中提取一个通道
		  一般用法是cvCvtPixToPlane(IplImage * src,IplImage * dst1,IplImage *dst2,IplImage * dst3,IplImage *dst4)
		  第一个参数是源图像,后面是分离出来每个通道的目标图像,如果圆筒到时3通道的,可以把最后一个参数设置为空。
		  例如cvCvtPixToPlane(IplImage * src,IplImage * dst1,IplImage *dst2,IplImage * dst3,NULL)
		*/
		cvCvtPixToPlane(frame, planes[0], planes[1], planes[2], 0);
		for (i = 0; i < 3; i++)
		{
			//			Laplace
			//计算图像的 Laplacian 变换
			//void cvLaplace( const CvArr* src, CvArr* dst, int aperture_size=3 );
			//src
			//输入图像.
			//dst
			//输出图像.
			//aperture_size
			//核大小 (与 cvSobel 中定义一样).
			//在每个通道内进行Laplace变换,计算图像的边缘信息
			cvLaplace(planes[i], laplace, 3); // 3: aperture_size
			//ConvertScaleAbs
			//使用线性变换转换输入数组元素成8位无符号整型
			//void cvConvertScaleAbs( const CvArr* src, CvArr* dst, double scale=1, double shift=0 );
			//#define cvCvtScaleAbs cvConvertScaleAbs
			//src
			//原数组
			//dst
			//输出数组 (深度为 8u).
			//scale
			//比例因子.
			//shift
			//原数组元素按比例缩放后添加的值。
			//函数 cvConvertScaleAbs 与前一函数是相同的,但它是存贮变换结果的绝对值:
			//dst(I)=abs(src(I)*scale + (shift,shift,...))
			//函数只支持目标数数组的深度为 8u (8-bit 无符号) , 对于别的类型函数仿效于cvConvertScale 和 cvAbs 函数的联合
			cvConvertScaleAbs(laplace, planes[i], 1, 0);  // planes[] = ABS(laplace)
		}
		//cvCvtPixToPlane是cvCvtPlaneToPix的逆函数,恢复多通道图像并显示
		cvCvtPlaneToPix(planes[0], planes[1], planes[2], 0, colorlaplace);
		//IplImage
		//	IPL 图像头
		//	typedef struct _IplImage
		//{
		//	int  nSize;         /* IplImage大小,=sizeof(IplImage)*/
		//	int  ID;            /* 版本 (=0)*/
		//	int  nChannels;     /* 大多数OPENCV函数支持1,2,3 或 4 个通道 */
		//	int  alphaChannel;  /* 被OpenCV忽略 */
		//	int  depth;         /* 像素的位深度: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U,
		//						IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F 可支持 */
		//	char colorModel[4]; /* 被OpenCV忽略 */
		//	char channelSeq[4]; /* 被OpenCV忽略 */
		//	int  dataOrder;     /* 0 - 交叉存取颜色通道,对三通道RGB图像,像素存储顺序为BGR BGR BGR ... BGR;
		//						1 - 分开的颜色通道,对三通道RGB图像,像素存储顺序为RRR...R GGG...G BBB...B。
		//						cvCreateImage只能创建交叉存取图像 */
		//	int  origin;        /* 0 - 顶—左结构,
		//						1 - 底—左结构 (Windows bitmaps 风格) */
		//	int  align;         /* 图像行排列 (4 or 8). OpenCV 忽略它,使用 widthStep 代替 */
		//	int  width;         /* 图像宽像素数 */
		//	int  height;        /* 图像高像素数*/
		//	struct _IplROI *roi;/* 图像感兴趣区域. 当该值非空只对该区域进行处理 */
		//	struct _IplImage *maskROI; /* 在 OpenCV中必须置NULL */
		//	void  *imageId;     /* 同上*/
		//	struct _IplTileInfo *tileInfo; /*同上*/
		//	int  imageSize;     /* 图像数据大小(在交叉存取格式下imageSize=image->height*image->widthStep),单位字节*/
		//	char *imageData;  /* 指向排列的图像数据 */
		//	int  widthStep;   /* 排列的图像行大小,以字节为单位 */
		//	int  BorderMode[4]; /* 边际结束模式, 被OpenCV忽略 */
		//	int  BorderConst[4]; /* 同上 */
		//	char *imageDataOrigin; /* 指针指向一个不同的图像数据结构(不是必须排列的),是为了纠正图像内存分配准备的 */
		//}
		//    IplImage;
		//IplImage结构来自于 Intel Image Processing Library(是其本身所具有的)。OpenCV 只支持其中的一个子集:
		//alphaChannel 在OpenCV中被忽略。
		//colorModel 和channelSeq 被OpenCV忽略。OpenCV颜色转换的唯一函数 cvCvtColor把原图像的颜色空间的目标图像的颜色空间作为一个参数。
		//dataOrder 必须是IPL_DATA_ORDER_PIXEL (颜色通道是交叉存取),然而平面图像的被选择通道可以被处理,就像COI(感兴趣的通道)被设置过一样。
		//align 是被OpenCV忽略的,而用 widthStep 去访问后继的图像行。
		//不支持maskROI 。处理MASK的函数把他当作一个分离的参数。MASK在 OpenCV 里是 8-bit,然而在 IPL他是 1-bit。
		//tileInfo 不支持。
		//BorderMode和BorderConst是不支持的。每个 OpenCV 函数处理像素的邻近的像素,通常使用单一的固定代码边际模式。
		//除了上述限制,OpenCV处理ROI有不同的要求。要求原图像和目标图像的尺寸或 ROI的尺寸必须(根据不同的操作,
		//例如cvPyrDown 目标图像的宽(高)必须等于原图像的宽(高)除以2 ±1)精确匹配,而IPL处理交叉区域,如图像的大小或ROI大小可能是完全独立的。
		colorlaplace->origin = frame->origin;   //让他们结构一致
		cvShowImage("Laplacian", colorlaplace);
		if (cvWaitKey(10) >= 0)
			break;
	}
	cvReleaseCapture(&capture);//释放视频
	cvDestroyWindow("Laplacian");//关掉视频播放窗口
	return 0;
}

OpenCV+visual studio 2019 实现对avi视频或摄像头 laplace边缘检测。从AVI文件( bsd.avi)中得到视频流,对视频流进行Laplace边缘检测,并输出结果。_第24张图片

3、从摄像头中得到视频流进行laplace边缘检测的代码 :

/*
功能:从摄像头或者AVI文件中得到视频流,对视频流进行边缘检测,并输出结果。
*/

#include "cv.h"
#include "highgui.h"
#include 
#include 
int main(int argc, char** argv)
{
	IplImage* laplace = 0;
	IplImage* colorlaplace = 0;
	IplImage* planes[3] = { 0, 0, 0 };  // 多个图像面
	CvCapture* capture = 0;//初始化为0,若在后面不对capture的值做修改,则从摄像头获得视频流
	//CvCapture
	//视频获取结构
	//typedef struct CvCapture CvCapture;
	/*结构CvCapture 没有公共接口,它只能被用来作为视频获取函数的一个参数。
	下面的语句说明在命令行执行程序时,如果指定AVI文件,那么处理从
	 AVI文件读取的视频流,如果不指定输入变量,那么处理从摄像头获取的视频流*/
	 
	 if (argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
		 capture = cvCaptureFromCAM(argc == 2 ? argv[1][0] - '0' : 0);
	 else if (argc == 2)
		 capture = cvCaptureFromAVI(argv[1]);
	 
	//获取视频,不需要上面的if...else语句,需要改为自己电脑上对应的路径
	//capture = cvCaptureFromAVI( "E://1qq document//bsd.avi" );
	
	if (!capture) //获取视频失败
	{
		fprintf(stderr, "Could not initialize capturing.../n");
		return -1;
	}
	cvNamedWindow("Laplacian", 0);
	// 循环捕捉,直到用户按键跳出循环体
	for (;;)
	{
		IplImage* frame = 0;
		int i;
		//cvQueryFrame
		//
		//从摄像头或者文件中抓取并返回一帧
		//IplImage* cvQueryFrame( CvCapture* capture );
		//capture 
		//视频获取结构。
		//函数cvQueryFrame从摄像头或者文件中抓取一帧,然后解压并返回这一帧。
		//这个函数仅仅是函数cvGrabFrame和函数cvRetrieveFrame在一起调用的组合。
		//返回的图像不可以被用户释放或者修改。 抓取后,capture被指向下一帧,
		//可用cvSetCaptureProperty调整capture到合适的帧。
		//
		//注意: cvQueryFrame返回的指针总是指向同一块内存。建议cvQueryFrame后拷贝一份
		//。而且返回的帧需要FLIP后才符合OPENCV的坐标系。 若返回值为NULL,说明到了视频的最后一帧。
		frame = cvQueryFrame(capture);
		if (!frame)
			break;
		if (!laplace)
		{
			for (i = 0; i < 3; i++)
				planes[i] = cvCreateImage(cvSize(frame->width, frame->height), 8, 1);
			//CreateImage
			/*
			创建头并分配数据
			IplImage* cvCreateImage( CvSize size, int depth, int channels );
			size
			图像宽、高.
			depth 
			图像元素的位深度,可以是下面的其中之一:
			IPL_DEPTH_8U - 无符号8位整型
			IPL_DEPTH_8S - 有符号8位整型
			IPL_DEPTH_16U - 无符号16位整型
			IPL_DEPTH_16S - 有符号16位整型
			IPL_DEPTH_32S - 有符号32位整型
			IPL_DEPTH_32F - 单精度浮点数
			IPL_DEPTH_64F - 双精度浮点数
			channels 
			每个元素(像素)的颜色通道数量.可以是 1, 2, 3 或 4.通道是交叉存取的,例如通常的彩色图像数据排列是:
			b0 g0 r0 b1 g1 r1 ...
			虽然通常 IPL 图象格式可以存贮非交叉存取的图像,并且一些OpenCV 也能处理他, 但是这个函数只能创建交叉存取图像.
			函数 cvCreateImage 创建头并分配数据,这个函数是下列的缩写型式
			header = cvCreateImageHeader(size,depth,channels);
			cvCreateData(header); //只是创建空间,并不会初始化空间内的数据
			*/

			laplace = cvCreateImage(cvSize(frame->width, frame->height),
				IPL_DEPTH_16S, 1);
			colorlaplace = cvCreateImage(cvSize(frame->width, frame->height), 8, 3);
		}
		//cvCvtPixToPlane
		/*
		  openCV里面的一个函数
		  可以看作cvSplit是他的宏:
		  #define cvCvtPixToPlane cvSplit
		  void cvSplit( const CvArr* src, CvArr* dst0, CvArr* dst1,CvArr* dst2, CvArr* dst3 );
		  作用是:分割多通道数组成几个单通道数组或者从数组中提取一个通道
		  一般用法是cvCvtPixToPlane(IplImage * src,IplImage * dst1,IplImage *dst2,IplImage * dst3,IplImage *dst4)
		  第一个参数是源图像,后面是分离出来每个通道的目标图像,如果圆筒到时3通道的,可以把最后一个参数设置为空。
		  例如cvCvtPixToPlane(IplImage * src,IplImage * dst1,IplImage *dst2,IplImage * dst3,NULL)
		*/
		cvCvtPixToPlane(frame, planes[0], planes[1], planes[2], 0);
		for (i = 0; i < 3; i++)
		{
			//			Laplace
			//计算图像的 Laplacian 变换
			//void cvLaplace( const CvArr* src, CvArr* dst, int aperture_size=3 );
			//src
			//输入图像.
			//dst
			//输出图像.
			//aperture_size
			//核大小 (与 cvSobel 中定义一样).
			//在每个通道内进行Laplace变换,计算图像的边缘信息
			cvLaplace(planes[i], laplace, 3); // 3: aperture_size
			//ConvertScaleAbs
			//使用线性变换转换输入数组元素成8位无符号整型
			//void cvConvertScaleAbs( const CvArr* src, CvArr* dst, double scale=1, double shift=0 );
			//#define cvCvtScaleAbs cvConvertScaleAbs
			//src
			//原数组
			//dst
			//输出数组 (深度为 8u).
			//scale
			//比例因子.
			//shift
			//原数组元素按比例缩放后添加的值。
			//函数 cvConvertScaleAbs 与前一函数是相同的,但它是存贮变换结果的绝对值:
			//dst(I)=abs(src(I)*scale + (shift,shift,...))
			//函数只支持目标数数组的深度为 8u (8-bit 无符号) , 对于别的类型函数仿效于cvConvertScale 和 cvAbs 函数的联合
			cvConvertScaleAbs(laplace, planes[i], 1, 0);  // planes[] = ABS(laplace)
		}
		//cvCvtPixToPlane是cvCvtPlaneToPix的逆函数,恢复多通道图像并显示
		cvCvtPlaneToPix(planes[0], planes[1], planes[2], 0, colorlaplace);
		//IplImage
		//	IPL 图像头
		//	typedef struct _IplImage
		//{
		//	int  nSize;         /* IplImage大小,=sizeof(IplImage)*/
		//	int  ID;            /* 版本 (=0)*/
		//	int  nChannels;     /* 大多数OPENCV函数支持1,2,3 或 4 个通道 */
		//	int  alphaChannel;  /* 被OpenCV忽略 */
		//	int  depth;         /* 像素的位深度: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U,
		//						IPL_DEPTH_16S, IPL_DEPTH_32S, IPL_DEPTH_32F and IPL_DEPTH_64F 可支持 */
		//	char colorModel[4]; /* 被OpenCV忽略 */
		//	char channelSeq[4]; /* 被OpenCV忽略 */
		//	int  dataOrder;     /* 0 - 交叉存取颜色通道,对三通道RGB图像,像素存储顺序为BGR BGR BGR ... BGR;
		//						1 - 分开的颜色通道,对三通道RGB图像,像素存储顺序为RRR...R GGG...G BBB...B。
		//						cvCreateImage只能创建交叉存取图像 */
		//	int  origin;        /* 0 - 顶—左结构,
		//						1 - 底—左结构 (Windows bitmaps 风格) */
		//	int  align;         /* 图像行排列 (4 or 8). OpenCV 忽略它,使用 widthStep 代替 */
		//	int  width;         /* 图像宽像素数 */
		//	int  height;        /* 图像高像素数*/
		//	struct _IplROI *roi;/* 图像感兴趣区域. 当该值非空只对该区域进行处理 */
		//	struct _IplImage *maskROI; /* 在 OpenCV中必须置NULL */
		//	void  *imageId;     /* 同上*/
		//	struct _IplTileInfo *tileInfo; /*同上*/
		//	int  imageSize;     /* 图像数据大小(在交叉存取格式下imageSize=image->height*image->widthStep),单位字节*/
		//	char *imageData;  /* 指向排列的图像数据 */
		//	int  widthStep;   /* 排列的图像行大小,以字节为单位 */
		//	int  BorderMode[4]; /* 边际结束模式, 被OpenCV忽略 */
		//	int  BorderConst[4]; /* 同上 */
		//	char *imageDataOrigin; /* 指针指向一个不同的图像数据结构(不是必须排列的),是为了纠正图像内存分配准备的 */
		//}
		//    IplImage;
		//IplImage结构来自于 Intel Image Processing Library(是其本身所具有的)。OpenCV 只支持其中的一个子集:
		//alphaChannel 在OpenCV中被忽略。
		//colorModel 和channelSeq 被OpenCV忽略。OpenCV颜色转换的唯一函数 cvCvtColor把原图像的颜色空间的目标图像的颜色空间作为一个参数。
		//dataOrder 必须是IPL_DATA_ORDER_PIXEL (颜色通道是交叉存取),然而平面图像的被选择通道可以被处理,就像COI(感兴趣的通道)被设置过一样。
		//align 是被OpenCV忽略的,而用 widthStep 去访问后继的图像行。
		//不支持maskROI 。处理MASK的函数把他当作一个分离的参数。MASK在 OpenCV 里是 8-bit,然而在 IPL他是 1-bit。
		//tileInfo 不支持。
		//BorderMode和BorderConst是不支持的。每个 OpenCV 函数处理像素的邻近的像素,通常使用单一的固定代码边际模式。
		//除了上述限制,OpenCV处理ROI有不同的要求。要求原图像和目标图像的尺寸或 ROI的尺寸必须(根据不同的操作,
		//例如cvPyrDown 目标图像的宽(高)必须等于原图像的宽(高)除以2 ±1)精确匹配,而IPL处理交叉区域,如图像的大小或ROI大小可能是完全独立的。
		colorlaplace->origin = frame->origin;   //让他们结构一致
		cvShowImage("Laplacian", colorlaplace);
		if (cvWaitKey(10) >= 0)
			break;
	}
	cvReleaseCapture(&capture);//释放视频
	cvDestroyWindow("Laplacian");//关掉视频播放窗口
	return 0;
}

四、参考资料

  1. https://blog.csdn.net/lzheng012019/article/details/121531472
  2. https://blog.csdn.net/jishijian7408/article/details/100690253?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522163806819216780271992167%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=163806819216780271992167&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v1~rank_v31_ecpm-4-100690253.first_rank_v2_pc_rank_v29&utm_term=vs2010%E9%85%8D%E7%BD%AEopencv2.4&spm=1018.2226.3001.4449
  3. https://blog.csdn.net/xinjiang666/article/details/80785210?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_utm_term~default-0.no_search_link&spm=1001.2101.3001.4242.1
  4. https://www.cnblogs.com/gao-hongxiang/p/12342419.html
  5. https://blog.csdn.net/dongbao520/article/details/117289543

你可能感兴趣的:(laplace边缘检测,边缘检测,opencv,visual,studio,音视频)