【问题标题】:Trying to find a way to LOG Graphical data in OpenCV/BOOST试图找到一种在 OpenCV/BOOST 中记录图形数据的方法
【发布时间】:2017-09-18 14:47:40
【问题描述】:

首先:我正在使用 OpenCV C++ 进行图像处理。在 C++ 程序中加载 Mat 图像后,我使用 GNUPLOT 绘制了图像的图形。

现在,要求是记录 Mat 图像的图形数据。

为此,我通过包含所有 BOOST 库创建了一个 BOOST C++ 记录器。 BOOST 也是一个用于测试和记录数据的优秀库,但是它的 Log 的问题是它只能记录文本消息。如果我错了纠正我。

以下是我在 OpenCV 中使用 GNUPlot 绘制图形的代码

try
{
    Gnuplot g1("lines"); 

    std::vector<double> rowVector;
    std::vector<double> rowVectorExp;

    for (int i = 0; i < 50; i++)  
    {
        rowVector.push_back((double)i); 
        rowVectorExp.push_back((double)exp((float)i/10.0));

    }
    cout << "*** user-defined lists of doubles" << endl;
    g1 << "set term png";
    g1 << "set output \"test.png\"";

    //type of plot pattern
    g1.set_grid().set_style("lines"); 

    g1.plot_xy(rowVector, rowVectorExp, "user-defined points 2d");

    waitKey(0);
}
catch (GnuplotException ge)
{
    cout << ge.what() << endl;
}

cout << endl << "*** end of gnuplot example" << endl;

这是我的 BOOST 日志代码

namespace logging = boost::log;
void PlainGetEdgeVector::init()
{

 logging::add_file_log("sample%3N.log");

}

BOOST_LOG_TRIVIAL(info) << "This is my first Log line";

好消息是,我的 BOOST Logger 成功记录了短信。如果它也可以记录我的图形数据,那就太好了。

有什么建议吗?如果有人知道如何使用 BOOST 实现相同的功能,我将非常感激,或者如果有任何替代方案,也很高兴知道这一点。

【问题讨论】:

    标签: c++ opencv logging boost boost-log


    【解决方案1】:

    您的问题的解决方案很大程度上取决于数据的性质,您希望如何使用记录的数据。

    1。重新考虑将二进制数据转成文本

    出于调试目的,将二进制数据转换为文本通常更方便。即使处理大量数据,这种方法也很有用,因为用于文本处理的工具通常比处理任意二进制数据的工具多得多。例如,您可以将来自应用程序不同运行的两个日志与传统的合并/比较工具进行比较,以查看差异。文本日志也更容易使用 grepawk 等现成的工具过滤,而二进制数据则可能需要编写解析器。

    有很多方法可以将二进制数据转换为文本。最直接的方法是使用dump 操纵器,它将有效地生成原始二进制数据的文本视图。它也适合图形数据,因为它的数量往往相对较大,并且通常很容易在文本表示中进行比较(例如,当颜色样本适合一个字节时)。

    std::vector< std::uint8_t > image;
    // Outputs hex dump of the image
    BOOST_LOG_TRIVIAL(info) << logging::dump(image.data(), image.size());
    

    输出二进制数据的一种更结构化的方式是使用其他库,例如来自Boost.Rangeiterator_range。如果您的图形数据由比原始字节更复杂的内容组成,这将很有用。

    std::vector< double > image;
    // Outputs all elements of the image vector
    BOOST_LOG_TRIVIAL(info) << boost::make_iterator_range(image);
    

    您还可以编写自己的操纵器,以您想要的方式格式化数据,例如按行拆分输出。

    2。对于二进制数据,使用属性和自定义接收器后端

    如果您打算通过更专业的软件(例如图像查看器或编辑器)处理记录的数据,您可能希望以二进制形式保存数据。这可以通过 Boost.Log 完成,但需要更多的努力,因为库提供的接收器是面向文本的,您无法将二进制数据按原样保存到文本文件中。您必须编写一个 sink 后端,它将以您想要的格式写入二进制数据(例如,如果您计划使用图像编辑器,您可能希望以该编辑器支持的格式写入文件)。有一个教程here,它显示了你必须实现的接口和一个示例实现。重要的一点是后端的consume 函数,它将接收包含您的数据的日志记录视图。

    typedef boost::iterator_range< const double* > image_data;
    BOOST_LOG_ATTRIBUTE_KEYWORD(a_image, "Image", image_data)
    
    class image_writer_backend :
        public sinks::basic_sink_backend< sinks::synchronized_feeding >
    {
    public:
        void consume(logging::record_view const& rec)
        {
            // Extract the image data from the log record
            if (auto image = rec[a_image])
            {
                image_data const& im = image.get();
    
                // Write the image data to a file
            }
        }
    };
    

    为了将图像二进制数据传递到接收器,您需要将其作为属性附加到日志记录。有多种方法可以做到这一点,但假设您不打算根据图像过滤日志记录,最简单的方法是使用add_value 操纵器。

    std::vector< double > image;
    BOOST_LOG_TRIVIAL(info) << logging::add_value(a_image, image) << "Catch my image";
    

    警告:为了避免复制可能很大的图像数据,我们将传递一个轻量级的iterator_range 作为属性值。这仅适用于同步日志记录,因为在处理日志记录时image 向量需要保持活动状态。对于异步日志记录,您必须按值传递图像或使用引用计数。

    如果您确实想对图像数据应用过滤器,则可以使用scoped attributes 或将属性添加到logger

    请注意,通过添加用于写入二进制数据的新接收器,您并不排除与其他接收器一起写入文本日志,以便文本接收器可以处理“Catch my image”消息。通过使用其他属性,如日志记录counters,您可以关联不同接收器生成的不同文件中的日志记录。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-25
      • 2013-10-21
      • 1970-01-01
      • 1970-01-01
      • 2017-07-30
      • 2016-03-13
      相关资源
      最近更新 更多