实现包含GStreamer库的OpenCV库文件编译

最近需要实现在Windows环境下使用GStreamer库使用VisualStudio读取水下机器人BlueROV2摄像头的图像。经尝试,在Ardusub相关资料(http://www.ardusub.com/)中包含的Windows下读取ROV视频流的C++代码(http://www.ardusub.com/developers/opencv.html)并不能稳定的获取视频,而且C++的程序过于冗长不易理解(经实验验证,在 Ubuntu 16.04 下,使用python的代码可以获取流畅的视频流,而Windows需要结合GStreamer与python的绑定库,且最终获取的图像会出现花屏)。通过笔者在网上查找的资料,最终确定了较为简单的解决方案:使用包含GStreamer库的OpenCV库进行水下机器人视频读取。本文介绍如何在 Windows10 (64-bit) + VS2017 + Gstreamer1.18.2 + opencv 4.40 (含contribute模块)的配置环境下实现BlueROV2视频流的稳定读取。

参考博文(需要):

1. Compile Opencv with GStreamer for Visual Studio 2019 on windows 10 with and contribution modules

2. How to compile OpenCV with Gstreamer [Ubuntu&Windows]

一.需要准备的原材料:

1. Opencv源码 下载对应版本源码,分别点进opencv和opencv_contrib的资源库, 选右侧relase选择对应版本的源码

实现包含GStreamer库的OpenCV库文件编译_第1张图片              实现包含GStreamer库的OpenCV库文件编译_第2张图片

下载页面(Windows下选择Source code.zip):

opencv https://github.com/opencv/opencv/releases/tag/4.4.0

opencv_contrib https://github.com/opencv/opencv_contrib/releases/tag/4.4.0

2. GStreamer1.18.2 库文件 (GStreamer官网)

两个文件(下载页面):

3. CMake Binary Distribution (下载页面)

实现包含GStreamer库的OpenCV库文件编译_第3张图片

4. VS2017下载及安装,选择 community-简体中文-exe 版本下载(该版本无需key)

下载页面 https://my.visualstudio.com/Downloads?q=visual%20studio%202017&wt.mc_id=o~msft~vscom~older-downloads

注意安装时需要附加勾选以下的安装选项,否则CMake可能无法找到VS2017编译器(Visual Studio 15 2017)  

参考自 https://stackoverflow.com/questions/42701019/problems-generating-solution-for-vs-2017-with-cmake

实现包含GStreamer库的OpenCV库文件编译_第4张图片

二. CMake编译OpenCV + contrib + GStreamer 设置:

1. 首先安装GStreamer,分别运行 gstreamer-1.0-msvc-x86_64-1.18.2.msi 及 gstreamer-1.0-devel-msvc-x86_64-1.18.2.msi (会安装于同一目录下),安装后加入以下 windows 环境变量:

  • xxx\1.0\msvc_x86_64\bin
  • xxx\1.0\msvc_x86_64\lib
  • xxx\1.0\msvc_x86_64\lib\gstreamer-1.0

其中 xxx 为GStreamer库的安装目录。

2. 将opencv与opencv_contrib分别解压,打开CMake,设置opencv解压后所在的目录为source code路径,创建一个空的build目录用于存放生成的项目文件(build the binaries)。 

点configure 配置,选择Visual Studio 15 2017编译器,之后会进行编译,编译后会在显示区出现configuring done。拉动下方滚动条,可能会发现如下报错:

实现包含GStreamer库的OpenCV库文件编译_第5张图片

这是由于网络问题,无法连接服务器而不能下载。解决方案:https://www.jianshu.com/p/52de9de70891

根据CMakeDownloadLog.txt的信息,手动从网上下载补全文件,并放入目的目录(xxx\opencv-4.4.0\.cache\ippicv)。

并且有部分选项显示红色,此时需要进行如下配置:

  • OPENCV_EXTRA_MODULES_PATH:填写opencv_contrib/modules所在目录,注意路径中的斜杠需要使用反斜杠"/"分隔,否则报错。同时勾选OPENCV_ENABLE_NONFREE选项。

  • GStreamer 路径配置 (也可参考博文链接中的配置)

实现包含GStreamer库的OpenCV库文件编译_第6张图片

勾选Non_free_module。

再次点configure 配置,有时出现JAVA与VTK相关的报错,由于并不会在后续使用这两个模块,笔者选择直接取消勾选与JAVA与VTK相关的编译内容,调整后点configure 配置。接下来可能依然存在由于网络问题造成的下载报错问题,依次将文件手动下载后放入目的目录中 (xxx\build) ,这些文件包括:

  • xxx\build\downloads\xfeatures2d 文件夹下:

实现包含GStreamer库的OpenCV库文件编译_第7张图片

  • xxx\build\testdata\cv\face 文件夹下:face_landmark_model.dat

若上述路径中某一级文件夹不存在,需要手动创建。

再次点击configure,无红色区域且下方显示框无红色错误提示。确认GStreamer被包含。

实现包含GStreamer库的OpenCV库文件编译_第8张图片

此外,有时会遇到 OPENCV_GENERATE_SETUPVARS 的相关错误,取消勾选该选项即可。

三.  VS2017生成库文件

点generate在build目录下生成VS2017项目文件

打开build目录下OpenCV.sln文件,选择生成release版本,x64的库,也可生成debug版本。两种版本的库分别用于属性为release和debug的x64项目中:

右键ALL_BUILD,生成库文件。

漫长等待......

实现包含GStreamer库的OpenCV库文件编译_第9张图片

确保最终输出结果为全部成功,0失败,0跳过。生成成功总个数依据在CMake的配置项中勾选项目个数的不同而不同。

右键INSTALL,生成。这一步将生成的库文件拷贝至xxx\build\install文件夹下。

为了便于配置VS项目的库文件属性,需要使用以下批处理命令获取生成的库文件命并存入名为Filename-list的txt文件中:

DIR *.* /B>Filename-list.txt

生成后,选择后缀为.dll的文件名,打开需要使用OpenCV库的 VS项目,将库名称复制到  属性-连接器-输入-附加依赖项 中。

四. 使用VS编写的C++项目读取BLUEROV2摄像机视频

在VS项目中加入包含以下代码的cpp文件:

#include 
#include 
#include 
#include 


void videoShow(cv::Mat &frame, int &pingNumber, double &timeStampUTC, int &keyframe_new, int &stopflag, int &aloneFlag)
{
	std::string str;
	int frameCount = 0;
	//cv::namedWindow("Sender", cv::WINDOW_NORMAL);
	while (true) 
	{
		if (keyframe_new)
		{
			cv::imshow("Sender", frame);
			keyframe_new = 0;
		}
		stopflag = cv::waitKey(1);
		if (stopflag == 'y')
		{
			//ping_num = ping_total_number;	
			if(!aloneFlag)
				str = ".\\capturedImageSet\\ping_" + std::to_string(pingNumber-1) + "_"+ std::to_string(timeStampUTC) + ".bmp";
			else
				str = ".\\saveFrames\\img_" + std::to_string(frameCount++) + ".bmp";
			cv::imwrite(str, frame);
		}
		else if (stopflag == 's')
		{
			std::cout << "video show stop" << std::endl;
			break;
		}
	}
	cv::destroyWindow("Sender");
}

int main()
{
	int alongFlag = 1;
	cv::VideoCapture cap("udpsrc port=5600 ! application/x-rtp,payload=96,encoding-name=H264,latency = 30 ! rtpjitterbuffer mode=1 !\
						  rtph264depay ! h264parse ! avdec_h264 ! decodebin ! videoconvert ! video/x-raw,format=(string)BGR !\
                          videoconvert! appsink sync = false", cv::CAP_GSTREAMER);
	cv::Mat frame;
	int getframe_flag = 0;
	int keyframe_new = 0;
	int keyValue = 0;
	int initialFalg = 1;
	double timeStampUTC;
	int pingNumber = 0;
	while (true)
	{
		cap.read(frame);
		if (frame.empty())
		{
			break;
		}
		keyframe_new = 1;
		if (initialFalg)
		{
			initialFalg = 0;
			std::thread displayThread(videoShow, std::ref(frame), std::ref(pingNumber), std::ref(timeStampUTC), std::ref(keyframe_new), std::ref(keyValue), std::ref(alongFlag));
			displayThread.detach();
		}
		if (keyValue == 's')
		{
			std::cout << "video stop" << std::endl;
			break;
		}
	}
    return 0;
}

可以看到,由于该OpenCV库包含了GStreamer库,因此可以使用VedioCapture实现网络摄像头的视频流读取。显示读取画面如下:

至此,实现了win10下使用VS调用 OpenCV + GStreamer 库实现BlueROV2视频流读取及显示的全部工作。

你可能感兴趣的:(编程环境配置,opencv,python,windows)