试图在OpenCV / BOOST

时间:2017-09-18 14:47:40

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

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

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

要做到这一点,我通过包含所有BOOST库创建了一个BOOST C ++ Logger。 BOOST也是用于测试和记录数据的优秀库,但是它的日志问题是它只能记录文本消息。如果我错了,请纠正我。

下面是我使用在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实现相同的功能,我将非常感激,或者如果有其他选择,那么也很高兴知道。

1 个答案:

答案 0 :(得分:2)

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

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());

输出二进制数据的更有条理的方法是使用其他库,例如来自iterator_rangeBoost.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

请注意,通过添加用于编写二进制数据的新接收器,您不必排除使用其他接收器编写文本日志,以便&#34;捕获我的图像&#34;消息可以由文本接收器处理。通过使用其他属性,例如日志记录counters,您可以将日志记录关联到由不同接收器生成的不同文件中。