尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

UE5集成OpenCV完整指南:从编译配置到跨平台部署

UE5集成OpenCV完整指南:从编译配置到跨平台部署 1. 项目概述为什么要在虚幻引擎里搞计算机视觉如果你正在用虚幻引擎5开发一个需要“看懂”世界的项目比如一个能识别玩家手势的VR应用、一个能自动分析监控画面的数字孪生系统或者一个需要实时处理摄像头画面的AR游戏那你大概率绕不开一个名字OpenCV。这个开源计算机视觉库几乎是这个领域的“标准答案”提供了从图像读取、滤波、特征检测到目标识别等一整套强大的工具。但问题来了虚幻引擎5UE5是一个庞大的、自成体系的游戏引擎而OpenCV是一个用C写的、主要面向传统桌面应用和嵌入式系统的库。把它们俩撮合到一起就像让一个习惯在红毯上走秀的超模去泥地里开拖拉机——不是不行但得解决一堆水土不服的问题。我最近就在一个工业仿真项目里遇到了这个需求我们需要在虚幻引擎里实时处理来自多路工业相机的视频流识别特定的工件并测量其尺寸。市面上虽然有一些第三方插件但要么功能不全要么兼容性差要么就是收费昂贵。最终我决定直接集成官方的OpenCV插件并在此基础上进行深度定制。这个过程踩了不少坑也总结出了一套相对稳定可靠的集成方案。今天我就把这套从环境准备、编译配置、代码编写到问题排查的完整流程以及那些官方文档里不会写的“血泪教训”毫无保留地分享给你。无论你是想做人脸识别、二维码扫描、图像滤镜还是更复杂的视觉算法这篇文章都能帮你把OpenCV稳稳地“塞进”UE5的肚子里。2. 集成前的核心决策内置插件 vs 手动编译在动手之前你必须做一个关键选择是使用UE5引擎自带的OpenCV插件还是自己手动编译OpenCV库然后集成这个选择直接决定了后续90%的工作量和可能遇到的坑。2.1 内置插件快速启动但限制多UE5从某个版本开始在引擎插件目录Engine/Plugins/Runtime/OpenCV里自带了一个OpenCV插件。这听起来很美开箱即用。它的优点是省事无需自己下载、编译OpenCV引擎已经帮你准备好了预编译的二进制文件DLL和头文件。版本固定引擎团队测试过的版本理论上与当前引擎版本的兼容性最好。目前UE5.2/5.3内置的大多是OpenCV 4.5.x版本。但缺点同样明显而且往往是项目后期的“暗雷”版本老旧且不可控你被锁定在引擎提供的特定版本上。如果你的算法依赖OpenCV 4.7的某个新API或者你发现当前版本有某个影响你的Bug你将束手无策。功能可能不完整引擎内置的插件可能只编译了核心模块core,imgproc,highgui如果你需要videoio视频读写、dnn深度学习模块、features2d特征检测等很可能没有包含。平台支持局限这个预编译包通常只针对WindowsWin64平台。如果你的项目需要发布到Android、iOS或Linux这个内置插件基本没用你需要自己为这些平台交叉编译OpenCV。头文件包含的“坑”正如网络讨论中提到的直接使用#include opencv2/core.hpp可能会导致宏定义冲突比如Apple的check宏官方建议使用PreOpenCVHeaders.h和PostOpenCVHeaders.h来包裹OpenCV头文件这增加了代码的特定性。我的经验之谈对于快速原型验证、学习或者你的项目功能简单且仅面向Windows平台可以先用内置插件。但如果你要做严肃的商业项目或者有多平台需求我强烈建议你走第二条路。2.2 手动编译集成一次折腾终身受益自己下载OpenCV源码针对你的目标平台Windows, Android, iOS等进行编译然后将库和头文件集成到你的UE5项目中。这个过程更复杂但优势是决定性的版本自由你可以使用任何稳定版本如4.8.0, 4.9.0甚至最新的开发分支。功能定制在编译时你可以通过CMake选项精确控制需要哪些模块OPENCV_MODULES不需要的可以关掉减少打包体积。全平台支持你可以为Windows、Android、iOS等分别编译静态库或动态库实现真正的跨平台部署。深度控制你可以选择编译为静态库.lib/.a链接进你的插件或者动态库.dll/.so随项目分发控制更灵活。你需要付出的代价是需要一定的CMake和交叉编译知识。编译过程耗时较长尤其是带contrib模块时。需要手动管理不同平台的库文件路径。我的选择在经历了内置插件在Android平台上的“绝望”后我果断转向了手动编译。虽然前期花了大约两天时间搭建编译环境和调试但后续的项目开发、功能扩展和跨平台打包变得异常顺畅。下面的步骤详解我将以手动编译集成这条更通用、更强大的路径为主同时也会穿插说明如何使用内置插件以及如何避开它的坑。3. 环境准备与OpenCV编译这是整个流程中最需要耐心的一步。我们以最常用的Windows开发环境为例目标是编译出UE5项目能用的OpenCV库。3.1 工具链安装CMake前往 CMake官网 下载并安装最新版本。安装时记得勾选“Add CMake to the system PATH for all users”。Visual Studio 2022UE5主要支持VS2022。安装时在“工作负载”中务必勾选“使用C的桌面开发”“通用Windows平台开发”如果需要在右侧的“单个组件”中确保安装了Windows 10/11 SDK版本需与UE5兼容通常最新版即可和C CMake tools for Windows。Python 3.x可选如果你需要OpenCV的Python绑定或者某些脚本工具可以安装。但纯C集成不是必须的。OpenCV源码从 OpenCV GitHub Releases 下载你需要的版本例如opencv-4.9.0.zip。如果你需要额外功能如人脸识别、文本检测还需要下载同版本的opencv_contrib源码。3.2 使用CMake-GUI配置与编译不要直接用源码里的CMakeLists.txt在VS里打开那会处理很多UE5不需要的依赖。使用CMake-GUI是标准做法。设置源码和构建路径Where is the source code: 指向你解压的opencv-4.9.0文件夹。Where to build the binaries: 新建一个文件夹例如opencv-4.9.0/build_ue5。点击“Configure”。在弹出的对话框中选择生成器为“Visual Studio 17 2022”平台选择“x64”然后点击“Finish”。CMake会开始第一次配置。关键配置选项在配置后的红色列表中查找并修改BUILD_SHARED_LIBS:取消勾选。我们编译静态库.lib。动态库.dll在UE5插件中管理起来更麻烦容易引发DLL Hell即文章开头提到的0xc06d007e错误常常是因为DLL没找到或版本冲突。BUILD_opencv_world:取消勾选。这个选项会将所有模块打包成一个巨大的opencv_world450.lib。虽然链接简单但会极大增加最终可执行文件的大小。我们选择按模块链接只链接需要的。OPENCV_GENERATE_PKGCONFIG:取消勾选。这是给Linux系统用的Windows不需要。WITH_IPP、WITH_TBB、WITH_EIGEN等: 如果你不需要这些并行计算或数学库的加速可以取消勾选以简化依赖。OPENCV_ENABLE_ALLOCATOR_STATS:取消勾选。这个分配器统计可能与UE5的内存管理冲突导致崩溃。CMAKE_INSTALL_PREFIX: 设置一个安装路径如D:/Libraries/OpenCV_4.9.0_Static_ForUE5。编译安装后所有头文件和库文件都会整齐地放在这里方便UE5项目引用。如果你需要opencv_contrib在列表中找到OPENCV_EXTRA_MODULES_PATH将其值设置为你解压的opencv_contrib-4.9.0/modules文件夹路径。再次点击“Configure”直到所有红色条目消失。点击“Generate”。成功后点击“Open Project”会在VS2022中打开解决方案。3.3 在Visual Studio中编译与安装在VS2022中将顶部的解决方案配置从“Debug”切换到“Release”。UE5的Shipping和Development构建都是Release模式Debug库不兼容。在右侧解决方案资源管理器中找到名为CMakeTargets-INSTALL的目标右键点击它选择“生成”。重要提示不要直接生成ALL_BUILD。INSTALL目标会专门将编译好的库和头文件复制到我们之前设置的CMAKE_INSTALL_PREFIX目录下结构非常清晰。等待编译完成。这个过程可能比较长取决于你的电脑性能和选择的模块数量。编译安装完成后你的安装目录如D:/Libraries/OpenCV_4.9.0_Static_ForUE5下应该会有include和lib或x64/vc17/lib这样的文件夹里面就是我们需要集成到UE5的所有东西。4. 在UE5插件中集成OpenCV库我们不建议直接把OpenCV集成到游戏模块Game Module中。最佳实践是创建一个独立的“运行时插件”Runtime Plugin。这样做的隔离性好可以在多个项目中复用也符合UE5的模块化架构。4.1 创建UE5 C插件在UE5编辑器中打开你的项目。点击菜单栏的“工具(Tools)” - “新建插件(New Plugin...)”。选择“空白(Blank)”模板给它起个名字比如OpenCVIntegration类型确保是“运行时(Runtime)”然后点击“创建”。关闭编辑器。在项目目录的Plugins文件夹下你会找到新创建的OpenCVIntegration插件文件夹。4.2 配置插件的构建文件.Build.cs这是最关键的一步告诉UE5的构建系统在哪里找到OpenCV的头文件和库。打开你的插件源码目录YourProject/Plugins/OpenCVIntegration/Source/OpenCVIntegration/OpenCVIntegration.Build.cs。你需要修改PublicDependencyModuleNames和PrivateDependencyModuleNames但更重要的是要添加OpenCV的包含路径和库路径。using UnrealBuildTool; public class OpenCVIntegration : ModuleRules { public OpenCVIntegration(ReadOnlyTargetRules Target) : base(Target) { PCHUsage ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; // 1. 添加UE5模块依赖 PublicDependencyModuleNames.AddRange( new string[] { Core, CoreUObject, Engine, RHI, // 可能需要处理纹理数据 RenderCore } ); PrivateDependencyModuleNames.AddRange( new string[] { // 如果你的插件有Slate UI可以加Slate, SlateCore } ); // 2. 定义OpenCV的安装根目录根据你CMake安装的路径修改 string OpenCVBasePath D:\Libraries\OpenCV_4.9.0_Static_ForUE5; // 3. 添加OpenCV头文件包含路径 PublicIncludePaths.Add(Path.Combine(OpenCVBasePath, include)); // 4. 添加OpenCV库文件路径 string LibPath Path.Combine(OpenCVBasePath, x64, vc17, lib); // 注意你的lib文件夹结构 PublicAdditionalLibraries.Add(Path.Combine(LibPath, opencv_core490.lib)); PublicAdditionalLibraries.Add(Path.Combine(LibPath, opencv_imgproc490.lib)); PublicAdditionalLibraries.Add(Path.Combine(LibPath, opencv_highgui490.lib)); // 按需添加其他模块例如 // PublicAdditionalLibraries.Add(Path.Combine(LibPath, opencv_videoio490.lib)); // PublicAdditionalLibraries.Add(Path.Combine(LibPath, opencv_features2d490.lib)); // 5. 添加Windows系统库OpenCV静态库可能依赖这些 if (Target.Platform UnrealBuildPlatform.Win64) { PublicSystemLibraries.Add(vfw32.lib); PublicSystemLibraries.Add(comctl32.lib); } // 6. 定义预处理器宏防止Windows.h和OpenCV的min/max宏冲突 PublicDefinitions.Add(NOMINMAX); } }关键点解析PublicIncludePaths让插件内所有源码都能#include opencv2/...。PublicAdditionalLibraries这里链接的是我们编译的静态库.lib。你必须把你用到的所有OpenCV模块的.lib文件都加进来。注意库文件名后面的版本号如490要和你编译的版本对应。PublicSystemLibrariesvfw32.lib是Video for Windows库如果用了videoio模块可能需要。comctl32.lib是一些控件库。NOMINMAX这是一个至关重要的宏。Windows头文件Windows.h定义了min和max宏而OpenCV和C标准库的std::min/std::max模板函数会因此产生编译错误。定义这个宏可以禁用Windows的min/max宏。4.3 编写包装类与工具函数直接在游戏代码里调用OpenCV API不是好主意。我们应该创建一个包装类处理UE5数据类型如UTexture2D,TArrayuint8,FString和OpenCV数据类型如cv::Mat之间的转换并管理资源生命周期。在你的插件Private文件夹下创建一个类例如OpenCVHelper.h/.cpp。OpenCVHelper.h示例#pragma once #include CoreMinimal.h #include Engine/Texture2D.h #include OpenCVHelper.generated.h /** * 一个工具类用于桥接UE5和OpenCV的数据类型。 */ UCLASS() class OPENCVINTEGRATION_API UOpenCVHelper : public UObject { GENERATED_BODY() public: /** * 将UTexture2DRGBA8格式转换为OpenCV的cv::Mat (CV_8UC4)。 * param Texture 输入的UE5纹理。 * param OutMat 输出的OpenCV矩阵。需要确保Texture渲染线程资源已就绪。 * return 转换是否成功。 */ UFUNCTION(BlueprintCallable, Category OpenCV|Conversion) static bool Texture2DToMat(UTexture2D* Texture, cv::Mat OutMat); /** * 将cv::Mat (CV_8UC4) 转换为UTexture2D。 * param Mat 输入的OpenCV矩阵必须是CV_8UC4类型。 * return 新建的UTexture2D资源。调用者需管理其生命周期。 */ UFUNCTION(BlueprintCallable, Category OpenCV|Conversion) static UTexture2D* MatToTexture2D(const cv::Mat Mat); /** * 将UE5的TArrayuint8通常是JPEG/PNG的二进制数据解码为cv::Mat。 * param CompressedData 压缩的图像数据。 * param OutMat 输出的OpenCV矩阵。 * param Flags cv::imdecode的标志如cv::IMREAD_COLOR。 * return 解码是否成功。 */ UFUNCTION(BlueprintCallable, Category OpenCV|Conversion) static bool DecodeImage(const TArrayuint8 CompressedData, cv::Mat OutMat, int32 Flags cv::IMREAD_COLOR); // 可以继续添加其他工具函数如FString和std::string的转换等。 };OpenCVHelper.cpp实现要点#include OpenCVHelper.h // 注意这里直接包含OpenCV头文件因为.Build.cs已经配置了路径 #include opencv2/imgcodecs.hpp #include opencv2/imgproc.hpp bool UOpenCVHelper::Texture2DToMat(UTexture2D* Texture, cv::Mat OutMat) { if (!Texture || Texture-GetPixelFormat() ! PF_B8G8R8A8) { UE_LOG(LogTemp, Error, TEXT(Texture is null or not in PF_B8G8R8A8 format.)); return false; } FTexture2DMipMap* MipMap Texture-GetPlatformData()-Mips[0]; FByteBulkData* ImageData MipMap-BulkData; // 锁定数据 void* TextureData ImageData-Lock(LOCK_READ_ONLY); int32 Width Texture-GetSizeX(); int32 Height Texture-GetSizeY(); // 创建cv::Mat注意UE5的PF_B8G8R8A8是BGRA顺序对应OpenCV的CV_8UC4 OutMat cv::Mat(Height, Width, CV_8UC4, TextureData).clone(); // 使用clone进行深拷贝避免生命周期问题 // 解锁 ImageData-Unlock(); return true; } UTexture2D* UOpenCVHelper::MatToTexture2D(const cv::Mat Mat) { if (Mat.empty() || Mat.type() ! CV_8UC4) { UE_LOG(LogTemp, Error, TEXT(Input Mat is empty or not CV_8UC4 type.)); return nullptr; } // 创建UTexture2D UTexture2D* NewTexture UTexture2D::CreateTransient(Mat.cols, Mat.rows, PF_B8G8R8A8); if (!NewTexture) return nullptr; // 填充纹理数据 FTexture2DMipMap Mip NewTexture-GetPlatformData()-Mips[0]; void* Data Mip.BulkData.Lock(LOCK_READ_WRITE); FMemory::Memcpy(Data, Mat.data, Mat.total() * Mat.elemSize()); Mip.BulkData.Unlock(); // 更新资源 NewTexture-UpdateResource(); return NewTexture; }实操心得数据转换是性能瓶颈之一。Texture2DToMat中的clone()操作会进行一次完整的内存拷贝对于大纹理或高频调用如每帧处理开销很大。在性能敏感的场景可以考虑直接操作锁定的纹理内存但要小心线程安全和生命周期。另外UE5的纹理数据在GPU上而OpenCV在CPU上运算这个“GPU-CPU”的拷贝是无法避免的。5. 在游戏代码中调用OpenCV功能包装好工具类后在游戏代码中使用OpenCV就非常直观了。我们以一个简单的边缘检测Canny并显示结果的蓝图节点为例。首先在你的插件中创建一个蓝图函数库Blueprint Function Library例如OpenCVBPLibrary。OpenCVBPLibrary.h#pragma once #include Kismet/BlueprintFunctionLibrary.h #include OpenCVBPLibrary.generated.h UCLASS() class OPENCVINTEGRATION_API UOpenCVBPLibrary : public UBlueprintFunctionLibrary { GENERATED_BODY() public: /** * 对输入的UTexture2D进行Canny边缘检测并输出结果纹理。 * param InputTexture 输入纹理。 * param LowThreshold Canny低阈值。 * param HighThreshold Canny高阈值。 * param ReturnValue 输出的边缘检测结果纹理。 */ UFUNCTION(BlueprintCallable, Category OpenCV|Processing, meta (DisplayName Canny Edge Detection)) static void CannyEdgeDetection(UTexture2D* InputTexture, float LowThreshold, float HighThreshold, UTexture2D* ReturnValue); };OpenCVBPLibrary.cpp#include OpenCVBPLibrary.h #include OpenCVHelper.h // 我们之前写的工具类 #include opencv2/imgproc.hpp void UOpenCVBPLibrary::CannyEdgeDetection(UTexture2D* InputTexture, float LowThreshold, float HighThreshold, UTexture2D* ReturnValue) { ReturnValue nullptr; if (!InputTexture) return; cv::Mat SrcMat; // 1. 转换UE5纹理到OpenCV Mat if (!UOpenCVHelper::Texture2DToMat(InputTexture, SrcMat)) { UE_LOG(LogTemp, Error, TEXT(Failed to convert texture to Mat.)); return; } cv::Mat GrayMat, EdgeMat; // 2. 转换为灰度图 (Canny需要单通道输入) cv::cvtColor(SrcMat, GrayMat, cv::COLOR_BGRA2GRAY); // 3. 执行Canny边缘检测 cv::Canny(GrayMat, EdgeMat, LowThreshold, HighThreshold); // 4. 将单通道的边缘图转换回4通道BGRA以便显示 cv::Mat EdgeBGRAMat; cv::cvtColor(EdgeMat, EdgeBGRAMat, cv::COLOR_GRAY2BGRA); // 5. 转换回UTexture2D ReturnValue UOpenCVHelper::MatToTexture2D(EdgeBGRAMat); }编译你的插件。成功后在UE5编辑器的蓝图里你就能在函数列表里找到这个“Canny Edge Detection”节点连接上纹理和参数就能实时看到边缘检测的效果了。6. 跨平台部署与打包注意事项如果你的游戏需要发布到Windows以外的平台手动编译OpenCV的优势就体现出来了。6.1 为Android编译OpenCV这是最常见的移动端需求。你需要使用Android NDK和CMake进行交叉编译。准备环境安装Android NDK版本需与UE5的Android工具链兼容通常在Engine/Extras/Android下已有。设置ANDROID_NDK环境变量。使用CMake-GUI或命令行在配置时指定工具链文件Toolchain File。你需要一个Android的CMake工具链文件NDK里通常自带build/cmake/android.toolchain.cmake。关键CMake参数示例命令行cmake -DCMAKE_TOOLCHAIN_FILE%ANDROID_NDK%/build/cmake/android.toolchain.cmake \ -DANDROID_ABIarm64-v8a \ # 或 armeabi-v7a -DANDROID_PLATFORMandroid-24 \ -DBUILD_SHARED_LIBSOFF \ -DBUILD_ANDROID_EXAMPLESOFF \ -DBUILD_ANDROID_PROJECTSOFF \ -DANDROID_STLc_shared \ # 与UE5匹配通常是c_shared -DCMAKE_BUILD_TYPERelease \ ../opencv-4.9.0使用ninja或make进行编译然后make install。将编译好的.a静态库位于lib/arm64-v8a等和头文件像Windows那样配置到你的插件.Build.cs中但需要使用条件编译if (Target.Platform UnrealBuildPlatform.Win64) { // Windows库路径和库 string OpenCVPath ...Windows...; PublicAdditionalLibraries.Add(Path.Combine(OpenCVPath, opencv_core.lib)); } else if (Target.Platform UnrealBuildPlatform.Android) { // Android库路径和库 string OpenCVPath ...Android...; PublicAdditionalLibraries.Add(Path.Combine(OpenCVPath, libopencv_core.a)); // 添加Android NDK必要的系统库 PublicSystemLibraries.Add(log); PublicSystemLibraries.Add(android); }6.2 打包与依赖静态链接我们选择编译静态库.lib/.a并链接这意味着OpenCV的代码会被直接打包进你的插件DLL或游戏可执行文件中。这是最干净的方式没有额外的运行时依赖文件。动态库注意事项如果你必须使用动态库例如库文件太大你需要确保打包时这些DLLWindows、SOAndroid被正确复制到打包输出的Binaries目录下。这需要修改插件的.uplugin文件或构建脚本来处理。7. 常见问题与深度排坑指南集成过程中你几乎一定会遇到下面这些问题。我把它们和解决方案整理成了速查表。问题现象可能原因解决方案编译错误error C2589: ( : illegal token on right side of ::或error C2059: syntax error : ::Windows的min/max宏与C标准库冲突。在插件的.Build.cs文件中添加PublicDefinitions.Add(NOMINMAX);。这是最高频的编译错误。链接错误LNK2001: unresolved external symbol cv::...1. 库文件路径没找到。2. 需要的OpenCV模块.lib文件没有全部添加到PublicAdditionalLibraries。3. 库文件版本Debug/Release不匹配。1. 检查PublicAdditionalLibraries中的路径是否正确。2. 确保你代码中用到的每个OpenCV功能其所属模块的.lib都已添加。用Dependency Walker或dumpbin /exports查看库的导出函数。3. UE5使用Release模式链接确保你编译的OpenCV库也是Release版本。编辑器启动时崩溃错误码0xc06d007e这是典型的“模块加载失败”错误。如果你使用动态库DLL这个DLL没有放在编辑器能找到的位置。方案A推荐改用静态库链接一劳永逸。方案B将所需的opencv_world455.dll等文件复制到YourProject/Binaries/Win64目录下如网络讨论中所述。对于插件更规范的做法是在插件的.uplugin文件中配置LoadingPhase: Default并确保DLL在插件的Binaries/ThirdParty/Win64目录。运行时崩溃访问违例1.cv::Mat等OpenCV对象生命周期管理不当如使用了已释放的内存。2. 在多线程中不安全地使用OpenCV函数OpenCV部分函数非线程安全。3. 数据类型或通道数不匹配如把3通道图当成4通道处理。1. 确保所有cv::Mat在作用域内有效。在工具函数中对传入的纹理数据使用.clone()进行拷贝是安全的做法。2. 将OpenCV调用限制在游戏线程GameThread或使用锁进行保护。避免在渲染线程或AsyncTask中直接调用。3. 在调用cvtColor、resize等函数前用cv::Mat::type()和cv::Mat::channels()检查矩阵属性。Android打包失败或运行时找不到符号1. 没有为Android平台编译OpenCV库。2. 编译Android库时使用的STLc_shared与UE5不匹配。3. 库文件没有被打包进APK。1. 确保已按照6.1节为Android交叉编译了OpenCV。2. UE5通常使用c_shared。在CMake配置中务必设置-DANDROID_STLc_shared。3. 在插件的Build.cs中为Android平台正确添加库路径和.a文件后UE5的构建系统通常会将其自动打包。检查APK解压后的lib/arm64-v8a里是否有你的插件so文件。性能问题处理一帧图像很慢1. 每帧都在进行Texture2DToMat和MatToTexture2D的完整内存拷贝。2. 使用了复杂的OpenCV算法如SIFT、DNN推理。3. 没有利用OpenCV的IPP、TBB等优化编译时未开启。1. 考虑优化只在纹理更新时才进行转换使用cv::UMatOpenCL尝试GPU加速但需注意UE5的渲染线程冲突。2. 对算法进行性能剖析考虑降低图像分辨率、使用更快的算法ORB代替SIFT、或异步处理。3. 在编译OpenCV时开启WITH_IPPON和WITH_TBBON确保你的目标平台有这些库。最后再分享一个我踩过的大坑关于PreOpenCVHeaders.h和PostOpenCVHeaders.h。如果你坚持使用UE5内置的OpenCV插件那么在你的代码中包含OpenCV头文件时必须使用这种方式来避免宏冲突#include PreOpenCVHeaders.h #include opencv2/core.hpp #include opencv2/imgproc.hpp #include PostOpenCVHeaders.h但如果你像我一样选择手动编译集成就完全不需要这两个文件。直接#include opencv2/core.hpp即可。这两个头文件是Epic为了隔离其引擎宏与OpenCV宏而特意为内置插件准备的“补丁”。自己编译时通过定义NOMINMAX等宏已经解决了冲突再用这两个头文件反而可能引入不必要的依赖或问题。搞清楚你用的到底是“引擎的OpenCV”还是“你自己的OpenCV”这是避免很多诡异编译错误的关键。
返回列表