请帮忙查找opencvsharp编译后测试输出错误的原因。C++测试程序显示编译后的Opencv可在GPU正常工作,但C#测试程序显示工作异常。
背景:
上位机软件为使用visual stuido 2022 c#编写的winform程序,其中使用到了opencvsharp,应用的功能包括videocapture、mat、roi、circle等,因为图像采集、裁剪后的是给推理线程使用,推理线程是在GPU上,为了避免CPUD到GPU传输开销,现在想把图像采集、裁剪、标记等工作放到GPU上进行。需要 使用cmake重新编译opencv,使opencvsharp 支持cuda。
现阶段是在cmake上编译完成,并对编译后的文件使用vs2022进行allbuild、install生成。使用cmake先后编译了2次,第一次启用了build_opencv_world,vs2022生成后得到opencv_world4130.lib、以及opencv_world4130.dll。第二次关闭build_opencv_world,得到其他的dll文件,如opencv_ccalib4130.dll、
opencv_core4130.dll、opencv_videoio_ffmpeg4130_64.dll、opencv_cudaarithm4130.dll等。将第一次得到的opencv_world4130.dll和第二次的dll文件放到一起,放到文件夹C:\Users\zhang\source\repos\WinFormsApp5zmotion\OpenCvSharp\opencv_files\opencv4120_win_64\vc17\bin中。
新建了一个C++控制台程序,对编译的内容进行验证。main.cpp代码如下:
#include <opencv2/opencv.hpp>
#include <opencv2/cudaarithm.hpp>
#include <iostream>
int main()
{
// 1) 设备计数
int n = cv::cuda::getCudaEnabledDeviceCount();
std::cout << "CUDA devices = " << n << std::endl;
if (n <= 0)
{
std::cerr << "No CUDA device or OpenCV built without CUDA support.\n";
return -1;
}
// 2) 选 0 号设备并打印信息
cv::cuda::setDevice(0);
cv::cuda::printShortCudaDeviceInfo(0);
// 3) 准备 4×4 float 矩阵
cv::Mat hA = cv::Mat::ones(4, 4, CV_32F);
cv::Mat hB = cv::Mat::ones(4, 4, CV_32F) * 3;
// 4) 搬到 GPU
cv::cuda::GpuMat dA, dB, dC;
dA.upload(hA);
dB.upload(hB);
// 5) 做一次加法
cv::cuda::add(dA, dB, dC);
// 6) 拷回 CPU
cv::Mat hC;
dC.download(hC);
std::cout << "A = \n" << hA << "\nB = \n" << hB
<< "\nA+B = \n" << hC << std::endl;
return 0;
}
运行后输出:
CUDA devices = 1
Device 0: "NVIDIA GeForce RTX 4060 Laptop GPU" 8188Mb, sm_89, Driver/Runtime ver.12.70/12.60
A =
[1, 1, 1, 1;
1, 1, 1, 1;
1, 1, 1, 1;
1, 1, 1, 1]
B =
[3, 3, 3, 3;
3, 3, 3, 3;
3, 3, 3, 3;
3, 3, 3, 3]
A+B =
[4, 4, 4, 4;
4, 4, 4, 4;
4, 4, 4, 4;
4, 4, 4, 4]
之后使用vs2022对Opencvsharp进行生成,得到OpenCvSharp.dll和OpenCvSharpExtern.dll。编译过程中,配置全部选release,平台全选X64.对OpenCvSharp属性>生成>条件编辑符,都启用了ENABLED_CUDA。在OpenCvSharpExtern属性中,设置与C++测试程序设置相同。设置如下:
①.C/C++ >常规>附加包含目录中
C:\Users\zhang\source\repos\WinFormsApp5zmotion\OpenCvNewBuild\install\include
此文件夹下有opencv2文件夹。
②.链接器 >常规>附加库目录
C:\Users\zhang\source\repos\WinFormsApp5zmotion\OpenCvNewBuild\install\x64\vc17\lib
此目录下包含76个lib文件,包括opencv_world4130.lib、opencv_cudaarithm4130.lib等
③.链接器 >输入>附加依赖项
opencv_world4130.lib
%(AdditionalDependencies)
④.调试>环境
PATH=%PATH%;C:\Users\zhang\source\repos\WinFormsApp5zmotion\OpenCvSharp\opencv_files\opencv4120_win_64\vc17\bin
得到的OpenCvSharp.dll和OpenCvSharpExtern.dll以及C:\Users\zhang\source\repos\WinFormsApp5zmotion\OpenCvSharp\opencv_files\opencv4120_win_64\vc17\bin中的其他dll文件放置到一起,共70个dll文件。
新建C#测试程序WinFormsApp1OpenCvSharpCUDAtest,将所有dll文件(70个),放置到该项目下的输出目录下,C:\Users\zhang\source\repos\WinFormsApp1OpenCvSharpCUDAtest\bin\x64\Release\net8.0-windows。
同时,在C:\Users\zhang\source\repos\WinFormsApp1OpenCvSharpCUDAtest\lib目录下 放置了OpenCvSharp.dll和OpenCvSharpExtern.dll,并把其余的dll如 opencv_world4130.dll、opencv_cudaarithm4130.dll等包括cuda\bin下的dll共98个dll都放到了
C:\Users\zhang\source\repos\WinFormsApp1OpenCvSharpCUDAtest\lib\native目录下
在测试程序中,编辑添加项目文件,如下:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0-windows7.0</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
<Platforms>x64</Platforms>
<NuGetAuditMode>direct</NuGetAuditMode>
</PropertyGroup>
<!-- 1. 引用你自己编译的 OpenCvSharp(本地 DLL) -->
<ItemGroup>
<!-- 如果你把 OpenCvSharp.dll 放在 lib 文件夹 -->
<Reference Include="OpenCvSharp">
<HintPath>lib\OpenCvSharp.dll</HintPath>
</Reference>
<!-- 如有 Extensions、WpfExtensions 等也同理 -->
<Reference Include="OpenCvSharp.Extensions">
<HintPath>lib\OpenCvSharpExtern.dll</HintPath>
</Reference>
</ItemGroup>
<!-- 2. 将本地 native DLL 一并复制到输出目录 -->
<ItemGroup>
<None Include="native\*.dll" LinkBase="." CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>
<ItemGroup>
<Compile Remove="lib\**" />
<EmbeddedResource Remove="lib\**" />
<None Remove="lib\**" />
</ItemGroup>
<ItemGroup>
</ItemGroup>
<ItemGroup>
<Compile Update="Properties\Settings.Designer.cs">
<DesignTimeSharedInput>True</DesignTimeSharedInput>
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<None Update="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
</Project>
测试程序中,报错如下,同时从解决方案资源管理器中可以看到,依赖项\程序集\ OpenCvSharp.Extensions前有黄色叹号,这是什么原因?
严重性 代码 说明 项目 文件 行 抑制状态 详细信息
错误(活动) CS0246 未能找到类型或命名空间名“GpuMat”(是否缺少 using 指令或程序集引用?) WinFormsApp1OpenCvSharpCUDAtest C:\Users\zhang\source\repos\WinFormsApp1OpenCvSharpCUDAtest\Form1.cs 33
错误(活动) CS0234 命名空间“OpenCvSharp”中不存在类型或命名空间名“Cuda”(是否缺少程序集引用?) WinFormsApp1OpenCvSharpCUDAtest C:\Users\zhang\source\repos\WinFormsApp1OpenCvSharpCUDAtest\Form1.cs 7
错误(活动) CS0117 “Cv2”未包含“GetCudaEnabledDeviceCount”的定义 WinFormsApp1OpenCvSharpCUDAtest C:\Users\zhang\source\repos\WinFormsApp1OpenCvSharpCUDAtest\Form1.cs 28
C#测试程序代码如下:
using System;
using System.Diagnostics;
using System.Drawing;
using System.Windows.Forms;
using OpenCvSharp;
using OpenCvSharp.Cuda;
using Size=OpenCvSharp.Size;
namespace WinFormsApp1OpenCvSharpCUDAtest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void btnTestCuda_Click(object sender, EventArgs e)
{
try
{
// 只做最简单的设备检查
int cudaDeviceCount = Cv2.GetCudaEnabledDeviceCount();
AddLog($"找到 {cudaDeviceCount} 个CUDA设备");
// 如果上面成功了,再尝试创建一个GpuMat
using (var gpuMat = new GpuMat())
{
AddLog("GpuMat创建成功");
}
}
catch (Exception ex)
{
AddLog($"错误: {ex.Message}");
AddLog($"堆栈: {ex.StackTrace}");
}
}
private TimeSpan MeasureTime(Action action)
{
var stopwatch = Stopwatch.StartNew();
action();
stopwatch.Stop();
return stopwatch.Elapsed;
}
private void AddLog(string message)
{
if (txtLog.InvokeRequired)
{
txtLog.Invoke(new Action<string>(AddLog), message);
}
else
{
txtLog.AppendText($"{DateTime.Now:HH:mm:ss} - {message}{Environment.NewLine}");
txtLog.ScrollToCaret();
}
}
}
}
问题:
1.测试程序从解决方案资源管理器中可以看到,依赖项\程序集\ OpenCvSharp.Extensions前有黄色叹号,这是什么原因?
2.测试程序报错的原因?
3.如果想要实现GPU上运行opencv的采集、裁剪、画圆命令,是否需要对Opencvsharp项目中 手写 对应的NativeMethods_cuda.cs + GpuMat.cs 等方法??