cv::VideoCapture 在 C# 项目中从 DLL 使用时不会打开文件或流

Posted

技术标签:

【中文标题】cv::VideoCapture 在 C# 项目中从 DLL 使用时不会打开文件或流【英文标题】:cv::VideoCapture doesn't open a file or stream when using it from DLL in C# project 【发布时间】:2019-01-24 02:09:30 【问题描述】:

我通过 DllImports 在 C++ 中使用 Unity 的 C# 脚本和 OpenCV。我的目标是在 Unity 场景中创建来自 OpenCV 的视频流。 Unity 加载包含 OpenCV 函数的库。 问题是cv::VideoCapture().open("path_to_file_or_stream") 在从 dll(来自 Unity)调用时总是返回 false。

当我将我的 C++ 代码构建为可执行文件时,一切都很完美。我正在使用 CMAKE 构建我的项目。

# Build exe
ADD_EXECUTABLE($PROJECT_NAME $SRCS_DIR $INCL_DIR)

# Build lib
ADD_LIBRARY($PROJECT_NAME SHARED $SRCS_DIR $INCL_DIR)

# OpenCV
FIND_PACKAGE(OpenCV)
IF(OpenCV_FOUND)
  TARGET_LINK_LIBRARIES($PROJECT_NAME PUBLIC $OpenCV_LIBS)
    MESSAGE(STATUS "[OpenCV_LIBS] " $OpenCV_LIBS)
ENDIF()

但是,当从 dll 运行时,cv::VideoCapture() 没有打开。

这是我目前掌握的一些代码:

C++/ImageProviderAPI.h

#define IMAGE_API __declspec(dllexport)
extern "C"

    ...
    IMAGE_API ImageProviderAPI* InitProvider(const char* url);
    IMAGE_API void StartProvider(ImageProviderAPI* api);
    ...


class ImageProviderAPI 

public:

    ImageProviderAPI(std::string url);
    ~ImageProviderAPI();

    void start();

private:

    std::string m_url;
    cv::VideoCapture* p_videoCapture;
;

C++/ImageProviderAPI.h

IMAGE_API ImageProviderAPI* InitProvider(const char* url) 
    return new ImageProviderAPI(std::string(url));


IMAGE_API void StartProvider(ImageProviderAPI* api) 
    api->start();


ImageProviderAPI::ImageProviderAPI(std::string url) : 
m_url(url), p_videoCapture(nullptr) 



void ImageProviderAPI::start() 
    p_videoCapture = new cv::VideoCapture();
    bool res = p_videoCapture->open(m_url);     // m_url - path to file or stream url
                                                // Always false if called from dll 
    // or this way

    p_videoCapture = new cv::VideoCapture(m_url);
    bool res = p_videoCapture->isOpened();      // Always false if called from dll

C#/MyScript.cs

public class MyScript: MonoBehaviour 
    ...
    [DllImport("ImageProviderAPI.dll", CharSet = CharSet.Unicode)]
    private static extern IntPtr InitProvider(string url);

    [DllImport("ImageProviderAPI.dll", CharSet = CharSet.Unicode)]
    private static extern void StartProvider(IntPtr api);

    private IntPtr API;

    void Start() 
        API = InitProvider("path_to_file_or_stream_url");
        StartProvider(API);
    

    void Update() 
        // Do stuff
    

例如,其他一些 OpenCV 函数,如 cv::imreadcv::resizecv::cvtColor 在从 dll 调用时可以工作。我用std::ofstream记录了VideoCapture打开结果。

我没想到以 exe 或 dll 运行时有任何区别。也许我在 dll 导入/导出过程中遗漏了一些东西。

【问题讨论】:

我的错误是我忘记检查传递给cv::VideoCapture 的文件路径或流url 字符串。删除CharSet = CharSet.Unicode 即可解决问题。 【参考方案1】:

问题是DllImportAttribute,尤其是CharSet = CharSet.Unicode

要解决它,只需删除 CharSet = CharSet.Unicode

[DllImport("ImageProviderAPI.dll")]

【讨论】:

以上是关于cv::VideoCapture 在 C# 项目中从 DLL 使用时不会打开文件或流的主要内容,如果未能解决你的问题,请参考以下文章

cv::VideoCapture 适用于网络摄像头,但不适用于 IP 摄像头?

cv2.videoCapture.release() 是啥意思?

无法在 Android 手机中使用 cv2.VideoCapture(0) 打开相机

模块“cv2”没有“VideoCapture”成员

4.OpenCV视频处理

Opencv python| cv. VideoCapture.get() 参数介绍