首页 > 解决方案 > 如何使用所有额外文件信息(如 Haar Cascade 训练权重的 XML 文件)编译代码?

问题描述

我正在尝试使用 Microsoft Visual Studio 2017 在 C++ 中构建完全独立的 DLL。通常我将 c++ 与 OpenCV 和 LabVIEW 额外库一起使用,一切都很好,直到我尝试在 LabVIEW 中的外部机器上运行它。

我构建了自己的环境,用于将我的机器视觉方法链接为 LabVIEW 的实时应用程序。我的 DLL 一次只分析一个图像/帧。在我开始使用基于 Haar Cascade Classifier (HCC) 的新方法之前,一切都运行良好,这需要额外的带有权重的 XML 文件。我训练自己的 HCC 权重,并将它们保存为 XML 文件,在编译期间必须由代码读取。不幸的是,DLL 在每台机器上都需要该文件的路径,这使得使用它变得困难。是否有任何选项可以将此 XML 内容永久导入 DLL?我不想每次运行 DLL 时都提供此路径。在下面的代码中,我粘贴了我的问题的一些片段。在编译之前,我必须将级联 XML 文件的路径作为 HaarPathXML 变量。我认为这就是我的代码在其他机器上崩溃的原因 - 它看不到这条路径。在编译期间是否有硬编码此文件数据的选项?

// ========================
// === SOME HEADER CODE ===
// ========================

// === Dll entry point ===
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    UNREFERENCED_PARAMETER(hModule);
    UNREFERENCED_PARAMETER(lpReserved);
    switch (ul_reason_for_call)
    {
        case DLL_PROCESS_ATTACH:
        case DLL_THREAD_ATTACH:
        case DLL_THREAD_DETACH:
        case DLL_PROCESS_DETACH:
            break;
    }
    return TRUE;
}

// === Function to export as DLL ===
extern "C" __declspec(dllexport) char* PupilData(
                                                 const uint8_t *__arr[], 
                                                 const uint16_t __img_rows,
                                                 const uint16_t __img_cols,
                                                 uint8_t __GB,
                                                ) // Describe inputs
{
    // === Define the data ===
    string HaarPathXML = "C:\\Users\\path_to_file\\cascade.xml";

        // ====================================================================
        // === SOME MAIN CODE, WHICH GIVES out VARIABLE WITH CALCULATED DATA ===
        // ====================================================================

    // === Change out string to char table and return it as an DLL output ===
    char* C_pupil_data = new char[out.size() + 1];
    copy(out.begin(), out.end(), C_pupil_data);
    C_pupil_data[out.size()] = '\0';

    return C_pupil_data;
}

我认为我可以将路径作为另一个变量并为此准备 LabVIEW 代码。但我正在寻找更简单的方法来处理它。此外 - 连续读取 XML 文件可能会减少我的代码的每秒帧数。

标签: c++opencvdllcompilationhaar-classifier

解决方案


第一次我会回答我自己的问题;)根据 SO 中的一个答案,我制作了 .h 文件,其中包含 XML 内容,但手动(但只有一次)转换为字符串。这就是XML2Str.h 的外观:

#pragma once
#include <string>

static inline string StringXML()
{
    string xml;
    xml =  "<\?xml version=\"1.0\"\?>\n";
    xml += "<opencv_storage>\n";
    xml += "<cascade>\n";
    xml += ...
    xml += "</opencv_storage>";

    return xml
}

在此之后,我调用上述方法来获取 OpenCV字符串对象,并使用方法FileStorage读取(不加载)转换和硬编码的 XML。

#include "XML2Str.h"

CascadeClassifier cascade;
String HaarPathXML_h = StringXML();
FileStorage fs(HaarPathXML_h, FileStorage::MEMORY);
cascade.read(fs.getFirstTopLevelNode());

在这些操作之后,everythink 在 .exe 和 .dll 文件中运行良好,无需额外的带有模型的 XML 文件。


推荐阅读