Kithara使用 OpenCV 库
目录
- [Kithara使用 OpenCV 库](#Kithara使用 OpenCV 库)
- [OpenCV 构建实例 (采用可视化操作的方式)](#OpenCV 构建实例 (采用可视化操作的方式))
-
- [1. 准备工作](#1. 准备工作)
- [2. OpenCV构建](#2. OpenCV构建)
简介
这些指南将帮助您学习如何使用 OpenCV 3.0、3.4 和 4.1 库在内核模式下进行实时图像处理。我们假设您基本上已经知道如何设置项目并打开驱动程序以开始您的工作。如果你对此不熟悉,你应该看看第一个项目 教程。
OpenCV 使用我们的实时 Windows 虚拟化。这种虚拟化在实时环境中模拟 Windows API 的最重要部分。只有在无法进行仿真或不合理的情况下,虚拟化才会离开实时环境并依赖于 Windows。此外,这种虚拟化是有限的,因此在实时使用OpenCV时存在一些限制。
需求和支持的环境
OpenCV 严重依赖标准的 C++ 库。这意味着与 OpenCV 和 OpenCV 库本身交互的代码必须使用完全相同的 C/C++ 运行时库 (CRT) 实例。Kithara不支持任何DLL版本的CRT用于内核模式。因此,要在 Kithara 中使用 OpenCV 库,它们必须使用静态链接运行时构建为静态库。不能使用 OpenCV 的 DLL 版本,因为这需要 OpenCV 使用 CRT 的 DLL 版本。此外,当将 CRT 的调试版本用于其中一个构建配置时,您还需要链接到静态 OpenCV 库的调试版本(它们的名称后面附加了一个"d")。
Windows虚拟化仅适用于Kithara实时任务和作为DLL加载到内核模式的代码。(Kithara还允许通过其他方式将代码加载到内核模式并实时执行,但它们不适合运行OpenCV代码)。对于Kithara RealTime Suite 10.11,我们已经使用以下Visual Studio平台工具集(包括静态CRT)成功测试了OpenCV 4.1:
-
Visual Studio 2017 (vc14.16) (Visual Studio 2017 版本 15.9.11,更新 9)
-
Visual Studio 2015 (vc14.00) (Visual Studio 2015 版本 14.0.25,更新 3)
我们还对 OpenCv 3.0 和 3.4 进行了等效测试:
-
Visual Studio 2017 (vc14.16) (Visual Studio 2017 版本 15.9.11,更新 9)
-
Visual Studio 2015 (vc14.00) (Visual Studio 2015 版本 14.0.25,更新 3)
-
Visual Studio 2013 (vc12.00) (Visual Studio 2013 版本 12.0.40,Update 5)
-
Visual Studio 2010 (vc10.00) (Visual Studio 2010 版本 10.0.30)
Kithara RealTime Suite 10.11之前的驱动程序(不包括在内)支持OpenCv 3.0,并在上述版本的Visual Studio 2013和2010中进行了测试。
这些测试是通过在实时环境中运行所有 OpenCV 3.0、3.4 和 4.1 准确性测试来执行的。OpenCV 是使用默认静态库构建。测试是使用源代码中的 OpenCV 3.0、3.4 和 4.1 构建执行的,如下所述。请注意,OpenCv 4 使用了 C++11 标准功能,这些功能仅在 Visual Studio 2015 之后才得到充分实现。
构建 OpenCV 库
OpenCV 附带了用于不同版本的 Visual Studio(2015 和 2017)的库构建,这些库已经可以使用。但是,我们建议您使用将要用于自己的项目的编译器重新构建 OpenCV 库。这不仅减少了出现兼容性问题的机会,而且还让您有机会从 OpenCV 构建中完全删除一些不需要或不可用的功能。
OpenCV 依赖于工具"CMake"为不同的编译器和 IDE 生成项目文件。请参阅 OpenCV 文档,了解如何将 CMake 与 OpenCV 一起使用。CMake 允许您配置构建并禁用对第三方库和 API 的特定依赖项。
使用 CMake 进行配置以与 Kithara 一起工作
最重要的配置步骤是将 BUILD_SHARED_LIBS 设置为禁用,因为它默认设置为"启用"。此外,请确保已启用 BUILD_WITH_STATIC_CRT。
我们还建议禁用有关 OpenCL、OpenGL、CUDA 和 Windows Media(DirectShow、VFW 等)的所有条目。这些 API 不能在内核模式下使用。如果您没有禁用它们,OpenCV 将在运行时将缺少依赖项。但是,在这种情况下,OpenCV 应该仍然可以使用。
请使用 Windows 平台的默认并行化框架(Microsoft 并发运行时,它包含在 CRT 中)。这意味着,WITH_OPENMP 和 WITH_TBB 都应该被禁用,这已经是默认设置。否则,这些框架的 DLL 将存在依赖性,这些 DLL 无法加载到内核模式,从而可能导致错误。
建议启用 INSTALL_CREATE_DISTRIB,尤其是在处理我们的示例时。它将生成一个目标项目"INSTALL",在构建时,它将把库和包含文件放在一个共享的根目录下。然后,您应该创建一个指向该目录的环境变量 OPENCV_DIR。我们的示例使用此环境变量,因此它们能够找到要链接到的包含文件和库。
这可以通过 CMakeGUI 或命令行完成,如下所示:
cmake -Bbuild
-DBUILD_SHARED_LIBS=false
-DBUILD_WITH_STATIC_CRT=true
-DWITH_OPENCL=false
-DWITH_OPENGL=false
-DWITH_DIRECTX=false
-DWITH_VFW=false
-DWITH_CUDA=false
-DWITH_MSMF=false
-DWITH_IPP=true
-DWITH_OPENCLAMDBLAS=false
-DWITH_OPENCLAMDFFT=false
-DBUILD_TESTS=false
-DBUILD_PERF_TESTS=false
-DBUILD_opencv_world=false
-G "Visual Studio 15 2017" --arch x64 .\\sources\\
OpenCv 在从主要版本 3 过渡到 4 的过程中,已将其一些以前的核心模块移动到 contrib 存储库中。这些是 shape、superres 和
videostab,它们与它们的构建依赖项 ximgproc 和 optflow 一起出现。4.1 也支持所有这些功能。要获取这些内容,请参阅 他们的文档。
使用 OpenCV 库设置项目
除了设置内核模式DLL项目的默认方法外,您还需要将OpenCV构建的包含目录添加到编译器设置的包含目录中,并将静态库的路径以及要使用的库添加到链接器设置中。包含文件将在" ( O P E N C V D I R ) / i n c l u d e " 下找到。库路径取决于使用的实际 C R T 和目标体系结构。通用路径为 " (OPENCV_DIR)/include"下找到。库路径取决于使用的实际 CRT 和目标体系结构。通用路径为" (OPENCVDIR)/include"下找到。库路径取决于使用的实际CRT和目标体系结构。通用路径为"(OPENCV_DIR)///staticlibs",其中是目标架构(x86 或 x64)和使用的 CRT 版本(vc10、vc11、vc12、vc14 或 vc15)。例如,在 Visual Studio 2013 中使用 64 位版本会导致其他链接器目录为"$(OPENCV_DIR)/x64/vc12/staticlibs"。请注意,CRT 是以增量方式进行版本控制的,而不是像 Visual Studio 产品命名所建议的那样按年份进行版本控制(即 Visual Studio 2013 使用 vc12,Visual Studio 2017 使用 vc15)。实际需要哪些库取决于您正在使用的 OpenCV 部分。在下文中,列出了所需的可能库。请将 XXX 替换为您想要的不带点的 OpenCv 版本,例如 340 或 410。另请注意,Debug 版本将附加字母"d"):
-
opencv_calib3dXXX.lib
-
opencv_coreXXX.lib
-
opencv_features2dXXX.lib
-
opencv_flannXXX.lib
-
opencv_halXXX.lib
-
opencv_highguiXXX.lib
-
opencv_imgcodecsXXX.lib
-
opencv_imgprocXXX.lib
-
opencv_mlXXX.lib
-
opencv_objdetectXXX.lib
-
opencv_photoXXX.lib
-
opencv_shapeXXX.lib
-
opencv_stitchingXXX.lib
-
opencv_superresXXX.lib
-
opencv_videoXXX.lib
-
opencv_videoioXXX.lib
或者,也可以使用 opencv_worldXXX.lib,这是一个将所有其他库捆绑到一个库中的库。
OpenCV 库大多还依赖于第三方库,这些库随 OpenCV 一起构建,并且与 OpenCV 构建同时构建。包括 IPP 库、图像编解码器和压缩(调试版本将附加字母"d"):
-
IlmImfd.lib
-
ippiwd.lib
-
ittnotifyd.lib
-
libjasperd.lib
-
libjpeg-turbod.lib
-
libpngd.lib
-
libprotobufd.lib
-
libtiffd.lib
-
libwebpd.lib
-
quircd.lib
-
zlibd.lib文件
某些代码路径还需要更多的 Windows 库。它主要但不仅占模块"highgui"。请注意,此列表不完整,并考虑推荐的设置。在 OpenCV 中包含对视频格式的支持也会创建对其他库的依赖性。
-
user32.lib
-
gdi32.lib
-
advapi32.lib
-
comctl32.lib
如果代码未使用某些模块,则这些列表可能会缩短。请参考 OpenCV 文档来确定模块的依赖关系。如果遇到来自链接器的有关缺少函数的错误消息,请首先检查此列表以查找缺少的依赖项。
请不要忘记仍然链接到Kithara图书馆!如果您查看我们的示例,OpenCV 的项目配置是通过使用属性表来解决的。这些设置将放入属性表中,实际项目将继承这些属性表,并且在 Visual Studio UI 中可能不可见。这为配置阶段提供了一些模块化。
运行 OpenCV 代码
使用Kithara RealTime Suite实时运行OpenCV代码需要两个主要步骤。首先,您需要将包含代码的DLL加载到内核模式。其次,您将需要一个实际运行代码的任务。
打开Kithara驱动程序后,可以立即加载DLL。必须使用专用函数 KS_loadVisionKernel,而不是通常的函数 KS_loadKernel。它将加载 DLL 并在适当的环境中执行其入口点。这是正确初始化 CRT 所必需的。
KSHandle hKernel;
KS_loadVisionKernel(&hKernel, "myDll.dll", 0, 0, KSF_KERNEL_EXEC);
下一步是创建一个任务,为此,我们首先需要在加载的DLL内部创建一个函数的回调,其中包含任务的代码。
KSHandle hCallBack;
KS_createKernelCallBack(&hCallBack, hKernel, "myFunction", 0,
KSF_DIRECT_EXEC |KSF_SAVE_FPU, 0);
DLL 中的函数在此处称为"myFunction"。必须使用标志 KSF_DIRECT_EXEC,以便在触发回调的同一上下文中运行回调。标志 KSF_SAVE_FPU 是必需的,用于在上下文切换上保存 FPU 和 SSE 寄存器的状态。
关于结构包装和对齐的重要通知 |
---|
如果不使用默认结构打包,请确保包含具有相同结构打包效果的 OpenCV 标头,就像用于构建 OpenCV 一样(通常具有 8 个字节的默认打包)。OpenCV 头文件不强制执行特定的结构打包。结构打包不匹配将导致二进制文件不兼容,从而在运行时导致各种错误。 |
一个例子是我们的样本。它们使用与默认结构打包不同的结构打包,因此需要包含 OpenCV 标头,并恢复默认结构打包。 |
在现在实际创建任务之前,我们还必须提高为其分配的堆栈空间。默认情况下,Windows 为每个线程保留 1 MB 的堆栈空间。Kithara 只保留 3 KB,这对于像 OpenCV 这样的库来说是不够的。因此,我们将 KS_setTaskStackSize 的大小提高到 Windows 线程的典型大小。
KS_setTaskStackSize(0x100000, 0);
最后,我们创建任务。必须使用标志 KSF_CUSTOM_STACK_SIZE 创建任务,才能使用我们刚刚设置的更大的堆栈大小。
KSHandle hTask;
KS_createTask(&hTask, hCallBack, 250, KSF_CUSTOM_STACK_SIZE);
有关任务的更多信息,请参见 任务模块。
请注意,只有实际调用 OpenCV 函数的函数才能作为任务执行。处理程序等的其他回调可以正常使用,并同时驻留在同一个 DLL 中。
图像采集和 OpenCV
由于无法实时使用OpenCV附带的图像捕捉功能,因此必须使用相机模块进行图像采集。使用相机模块中的函数 KS_recvCameraImage,您可以检索指向图像数据的指针以及有关宽度、高度、像素格式和行填充的信息。像素格式是 像素格式命名约定 (PFNC) 中定义的格式之一。有了这些信息,您可以使用 OpenCV 函数来创建 OpenCV 图像 (cv::Mat),您可以进行处理。请注意,并非所有格式都适合转换,例如几种不同的包装类型。如果没有适合转换的函数组合,则必须自行提供转换函数。
cv::Mat 的构造函数非常灵活,因为它允许直接使用几种不同的图像格式而无需复制。此外,cv::cvtColor 和 cv::mixChannels 可用于demosaic 、从不同的颜色空间转换和重新排序通道,或合并来自不同图像的通道。cv::Mat 构造函数的一个重要参数是参数"step",它描述了 to 行之间的字节计数。它取决于像素格式的单个像素的位大小和图像的行填充。该步骤的计算方式如下:
step = 宽度 * bitSize / 8 + linePadding
如果行填充为零,则可以使用自动步骤。
以下是 PFNC 像素格式和匹配的 OpenCV 类型的映射:
PFNC | OpenCV Type | bitSize | bits/Channel | 备注 |
---|---|---|---|---|
Mono8 | CV_8UC1 | 8 | 8 | |
Mono8s | CV_8SC1 | 8 | 8 | |
Mono10 | CV_16UC1 | 16 | 10 | |
Mono12 | CV_16UC1 | 16 | 12 | |
Mono14 | CV_16UC1 | 16 | 14 | |
Mono16 | CV_16UC1 | 16 | 16 | |
BayerGR8, BayerBG8, BayerRG8, BayerGB8 | CV_8UC1 | 8 | 8 | 1) |
BayerGR10, BayerBG10, BayerRG10, BayerGB10 | CV_16UC1 | 16 | 10 | 1) |
BayerGR12, BayerBG12, BayerRG12, BayerGB12 | CV_16UC1 | 16 | 12 | 1) |
BayerGR16, BayerBG16, BayerRG16, BayerGB16 | CV_16UC1 | 16 | 16 | 1) |
YUV8_UYV, YCbCr_8_CbYCr, YCbCr601_8_CbYCr, YCbCr709_8_CbYCr | CV_8UC3 | 24 | 8 | 2) 4) |
RGB8, BGR8 | CV_8UC3 | 24 | 8 | 2) |
RGB10, BGR10 | CV_16UC3 | 48 | 10 | 2) |
RGB12, RGB12 | CV_16UC3 | 48 | 12 | 2) |
RGB16, RGB16 | CV_16UC3 | 48 | 16 | 2) |
RGBa8, BGRa8 | CV_8UC4 | 32 | 8 | 2) |
RGB565p, BGR565p | CV_16UC1 | 16 | 5, 6 | 3) |
-
使用 cv::cvtColor demosaic 为 3 通道图像。
-
使用 cv::cvtColor 转换为不同的颜色空间和/或 cv::mixChannels 对组件进行重新排序。
-
使用 cv::cvtColor 转换为 3 通道图像。
-
对于 YUV 和相关类型,luma 通道始终是第二个通道,因此要转换为更常见的格式,其中 luma 是第一个通道,您必须交换通道。
平面RGB格式('RGB8_Planar'、'RGB10_Planar'、'RGB12_Planar'、'RGB16_Planar')应被视为'单声道'格式,创建三个图像,然后可以将其组合成具有_cv::mixChannels_的多通道图像。
自动并行化
我们的软件支持 OpenCV 使用的 Microsoft 并发运行时。不支持其他并行化框架(如 OpenMP)。
自动并行化会在其他 CPU 上启动其他任务,这可能会与您的实时应用程序设计冲突。如果没有明确需要,我们建议通过调用 cv::setNumThreads(0) 来禁用自动并行化。
自动并行化任务从创建它们的任务继承实时优先级。它们大多是在首次使用时或更新线程数时创建的。因此,显式调用 cv::setNumThreads 以受控方式创建任务可能很有用。任务以循环方式分发到可用的 CPU,同时遵循 Windows 虚拟化中的进程关联掩码。Windows 函数 SetProcessAffinityMask、GetProcessAffinityMask 和 GetCurrentProcess 在实时上下文中可用,使你能够控制允许启动哪些 CPU 新任务。
限制和局限性
1.系统建议
由于所有分配都在非分页池中,因此内核级别的内存资源受到限制,而非分页池本身在 Windows 中是有限的资源。此问题对于 32 位 Windows XP 尤其适用,对于非分页池,其最大大小为 256 MBytes。对于 64 位版本或高于 XP 的版本,这些限制设置得更高,如果您安装了足够的物理内存,则不会造成问题。另请注意,许多数据结构需要连续内存。这在 32 位平台上可能很少见。
2.实时限制
某些 OpenCV 操作无法实时执行,因为它们需要与 Windows 系统交互。这些是文件处理和用户交互(Windows、输入)等功能。这些操作需要与用户模式线程进行通信,但用户模式线程的优先级很高,但当然无法满足内核模式实时任务的实时约束。
3.不支持的功能和缺失的功能
以下功能不能在内核模式下使用:
-
除 Microsoft 并发运行时以外的并行化框架
-
GPU 加速(OpenGL、OpenCL、CUDA、IPP Async、DirectX) 1)
-
任何用于图像捕获和视频解码的第三方库(DirectShow、VfW、FFMpeg、相机 API) 2)
-
OpenCV 模块 HighGUI 3)
-
目前没有计划支持 GPU 加速。我们计划支持将基于 CPU 的加速与 IPP 一起使用,包括 AVX 和 AVX2。
-
您可以使用我们的 相机模块 从 GigE Vision® 和 USB 3 VisionTM 相机采集图像。
-
对模块"HighGUI"功能的基本子集只有基本的支持。我们不建议使用内核模式中的任何 GUI 元素(另请参阅下一段)。
4.显示 OpenCV 对象
尽管您可以从内核级别使用简单的 HighGUI 窗口,但不建议从内核级别打开窗口。显示 OpenCV 对象的假定方法是使用共享内存区域将序列化的 OpenCV 项复制到其中,从而使用到用户模式的进程间通信。
OpenCV 构建实例 (采用可视化操作的方式)
不想动手的话,也能获取我们编译好的资源: OpenCV - 4.1.0 静态库下载
1. 准备工作
- 下载源码:OpenCV官网 OpenCV - 4.1.0 下载
- 安装 Visual Studio 2017 (参考第一个项目中 Visual Studio 2022 C++ 开发环境安装)
Visual Studio Community 2017 (version 15.7) (x86 and x64) - (Multiple Languages)
文件名: mu_visual_studio_community_2017_version_15.3_x86_x64_11100062.exe
SHA1: EC5E128EDC90FAC0BBADECD6DB32F8F008A4D669
文件大小: 1.02GB
发布时间 : 2017-08-14
方法: 复制ed2k链接,打开eMule或迅雷,新建下载,粘贴链接,开始下载
cpp
ed2k://|file|mu_visual_studio_community_2017_version_15.3_x86_x64_11100062.exe|1069960|5984B3CD547F9F213DE21EFE5887F08D|
- 安装CMake CMake下载 CMake 使用教程
2. OpenCV构建
-
解压OpenCV4.1.0的源码后,打开源码目录创建 【build】 文件夹
-
打开【cmake-gui.exe】开始构建项目,选择源码路径,选择构建目录(使用创建的build目录),点击【Configure】
-
选择构建的版本(推荐 Visual Studio 2017) ,选择构建平台,点击 【Finished】,等待配置完成
-
根据上文中的一些说明进行配置
配置选项:
选项 | 操作 |
---|---|
BUILD_SHARED_LIBS | false |
BUILD_WITH_STATIC_CRT | true |
WITH_OPENCL | false |
WITH_OPENGL | false |
WITH_DIRECTX | false |
WITH_CUDA | false |
WITH_MSMF | false |
WITH_IPP | true |
WITH_OPENCLAMDBLAS | false |
WITH_OPENCLAMDFFT | false |
BUILD_TESTS | false |
BUILD_PERF_TESTS | false |
BUILD_opencv_world | false |
- 配置完成后点击【Generate】生成Visual Studio 2017项目,等待执行完成
- 执行成功后,点击打开项目【Open Project】
- 选择构建版本,全部构建后,再点击安装,Release切换构建版本后同样操作。
-
全部构建完成后,再【build】->【install】 目录中就是已经编译后的程序,你可以把他保存到你电脑的任意位置,以方便你在程序中调用;
-
注意: 生成的库 后缀中【d】结尾代表debug版本。
现在,你可以尝试运行一些Kithara执行OpenCV的一些示例了
smp\LibraryOpenCV smp\LibraryOpenCVDisplay smp\LibraryOpenCVWithCamera