【问题标题】:How to read data from a text file at compile time in this case? [duplicate]在这种情况下,如何在编译时从文本文件中读取数据? [复制]
【发布时间】:2015-08-11 21:39:15
【问题描述】:

我知道问题的标题可能使它看起来是一个重复的问题,但事实并非如此。我已经尝试了 stackoverflow 上给出的几乎所有解决方案..A way to read data out of a file at compile time to put it somewhere in application image files to initialize an array.

我的问题是我正在使用 C++ 代码,并且我也在使用一些开放的 cv 库和函数。我有一个主函数 OsiMain.cpp,它的代码为

我的代码:

int main (int argc, char * argv[])
{
try
{
    OsiManager osi ;        
    osi.loadConfiguration(argv[1]) ;
    osi.showConfiguration() ;        
    osi.run() ;
}
catch ( std::exception & e )
{
        std::cout << e.what() << std::endl ;
    }

return 0 ;

OsiManager 是另一个类。该类管理所有文件、配置、保存和加载选项。它使用 OsiEye 类来执行技术处理。

在 OsiManager 构造函数中,我们初始化代码需要的一些参数的值。下面给出OsiManager代码的构造函数部分

// Default constructor
OsiManager::OsiManager ( )
{
    mMapInt["Minimum diameter for pupil"] = &mMinPupilDiameter ;
    mMapInt["Maximum diameter for pupil"] = &mMaxPupilDiameter ;
    mMapInt["Minimum diameter for iris"] = &mMinIrisDiameter ;
    mMapInt["Maximum diameter for iris"] = &mMaxIrisDiameter ;
    mMapInt["Width of normalized image"] = &mWidthOfNormalizedIris ;
    mMapInt["Height of normalized image"] = &mHeightOfNormalizedIris ;
    mMapString["Gabor filters"] = &mFilenameGaborFilters ;
    mMapString["Application points"] = &mFilenameApplicationPoints ;


    // Initialize all parameters
    initConfiguration() ;     
}

void OsiManager::initConfiguration ( )
{
    mMinPupilDiameter = 50;
    mMaxPupilDiameter = 160; 
    mMinIrisDiameter = 160; 
    mMaxIrisDiameter = 280; 
    mWidthOfNormalizedIris = 512; 
    mHeightOfNormalizedIris = 64; 
    mFilenameGaborFilters = "/home/Iris_Osiris_v4.1/OsirisParam/filters.txt" ;
    mFilenameApplicationPoints = "/home/Iris_Osiris_v4.1/OsirisParam/points.txt" ;
   mGaborFilters.clear();
   mpApplicationPoints = 0 ;

}

这些值在构造函数中被初始化。在函数initconfiguration中我们可以看到mfilenameGaborFilter和mfilenameApplication点两个文件路径。这些给出了两个文件名的路径。这些文件基本上有巨大的矩阵,如 9 x 15 、 9 x 25。这些矩阵被读入变量 mGaborFilters 和 mpApplicationPoints ,它们分别是 vectorCvMat* 和 CvMat* 类型。用于将这些文件读入变量的函数如下所示分别为 loadGaborFilters 和 loadApplicationPoints。

void OsiManager::loadGaborFilters( )
{
    // Open text file containing the filters
    ifstream file(mFilenameGaborFilters.c_str(),ios::in) ;
    if ( ! file )
    {
        throw runtime_error("Cannot load Gabor filters in file " + mFilenameGaborFilters) ;
    }

    // Get the number of filters
    int n_filters ;
    file >> n_filters ;
    mGaborFilters.resize(n_filters) ;

    // Size of filter
    int rows , cols ;

    // Loop on each filter
    for ( int f = 0 ; f < n_filters ; f++ )
    {    
        // Get the size of the filter
        file >> rows ;
        file >> cols ;

        // Temporary filter. Will be destroyed at the end of loop
        mGaborFilters[f] = cvCreateMat(rows,cols,CV_32FC1) ;            

        // Set the value at coordinates r,c
        for ( int r = 0 ; r < rows ; r++ )
        {
            for ( int c = 0 ; c < cols ; c++ )
            {
                file >> mGaborFilters[f]->data.fl[r*cols+c] ;
            }
        }

    } // Loop on each filter

    // Close the file
    file.close() ;

} // end of function





// Load the application points (build a binary matrix) from a textfile
void OsiManager::loadApplicationPoints ( )
{
    // Open text file containing the filters
    ifstream file(mFilenameApplicationPoints.c_str(),ios::in) ;
    if ( ! file )
    {
        throw runtime_error("Cannot load the application points in " + mFilenameApplicationPoints) ;
    }

    // Get the number of points
    int n_points = 0 ;
    file >> n_points ;

    // Allocate memory for the matrix containing the points
    mpApplicationPoints = cvCreateMat(mHeightOfNormalizedIris,mWidthOfNormalizedIris,CV_8UC1) ;

    // Initialize all pixels to "off"
    cvSet(mpApplicationPoints,cvScalar(0)) ;        

    // Local variables
    int i , j ;

    // Loop on each point
    for ( int p = 0 ; p < n_points ; p++ )
    {    
        // Get the coordinates
        file >> i ; file >> j ;

        // Set pixel to "on"
        if ( i < 0 || i > mpApplicationPoints->rows-1 || j < 0 || j > mpApplicationPoints->cols-1 )
        {
            cout << "Point (" << i << "," << j << ") " ;
            cout << "exceeds size of normalized image : " ;
            cout << mpApplicationPoints->rows << "x" << mpApplicationPoints->cols ;
            cout << " while loading application points" << endl ;
        }
        else
        {
            mpApplicationPoints->data.ptr[(i)*mpApplicationPoints->cols+j] = 255 ;
        }
    }

    // Close the file
    file.close() ;

} // end of function

以上两个函数是OsiManager类的成员函数loadConfiguration的一部分,在main函数中被调用。

我的问题是我希望在编译时将这些文件 Gabor 过滤器和应用程序点读入变量中,因为我们不想将文件与可执行文件或构建一起上传到集群。

【问题讨论】:

  • 特别没有必要用不相关的代码混淆每个人。在编译时不可能读取任何额外的初始化数据,除非它以可以通过#include 语句有效注入的格式给出。
  • 链接到的问题是关于二进制数据的,不允许我的解决方案是将文本配置数据放入静态初始化 std::istringstream 对象的初始化字符串中。
  • 此技术可能满足您的需求:stackoverflow.com/a/31953006/3807729
  • @Galik 我想知道是否可以让预处理器在原始字符串文字中注入文本(使其他编译指示(如#ifdef 等)的优势可用)。字符串文字延续之类的诡计?
  • @πάνταῥεῖ 我只是管理它,但我不得不将原始字符串分隔符 R"~()~"; 放在外部文本文件中。

标签: c++ opencv compilation


【解决方案1】:

您不能在编译时执行运行时文件 IO,但由于源数据只是文本,您可以使用这些文件的内容初始化 const char* 字符串(使用 C++11 原始字符串文字和复制和粘贴很容易)和将 init 函数中的 ifstream 替换为使用字符串文字初始化的 std::stringstream

【讨论】:

  • 感谢您的回答,但我怎样才能用这些文件的内容初始化 const char * 字符串。我只知道文件的位置。我认为那是我的问题。如何在编译时复制这些内容并使用这些内容初始化该变量对不起,我对 c++ 的这些高级概念太天真了。你能举个例子吗?
  • 复制并粘贴恐怕...在某些情况下,您可以#include 文件的内容,但我认为不可能将文本文件转换为字符串方式。
  • 如果您想自动读取文件,您可以使用一些简单的脚本或 xxd 之类的工具通过构建系统进行设置。
  • 事实上我确实尝试过 xxd 并尝试 #include xxd 生成的头文件,例如 mGaborFIlters={#include "filters.h"}...但我不确定给了我很多编译时错误,我认为我做的不对
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-06
  • 1970-01-01
相关资源
最近更新 更多