Попытка найти способ LOG графических данных в OpenCV/BOOST

Начнем с того, что я работаю над обработкой изображений с помощью OpenCV C++. После загрузки изображения Mat в программу на C++ я построил график изображения с помощью GNUPLOT.

Теперь Требование — регистрировать графические данные изображения Mat.

Для этого я создал регистратор BOOST C++, включив в него все библиотеки BOOST. BOOST также является отличной библиотекой для тестирования и регистрации данных, но проблема с ее журналом заключается в том, что она может регистрировать только текстовые сообщения. Поправьте меня если я ошибаюсь.

Ниже приведен мой КОД для построения графика с использованием GNUPlot в OpenCV:

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, я был бы очень признателен, или если есть какие-либо альтернативы, это тоже полезно знать.


person DivyaMaheswaran    schedule 18.09.2017    source источник


Ответы (1)


Решение вашей проблемы во многом зависит от характера данных, как вы хотите использовать зарегистрированные данные.

1. Пересмотрите возможность преобразования двоичных данных в текст

В целях отладки часто удобнее преобразовать двоичные данные в текст. Даже при больших объемах данных этот подход может быть полезен, поскольку инструментов для обработки текста обычно намного больше, чем для работы с произвольными двоичными данными. Например, вы можете сравнить два журнала из разных запусков вашего приложения с помощью обычных инструментов слияния/сравнения, чтобы увидеть разницу. Текстовые журналы также легче фильтровать с помощью таких инструментов, как grep или awk, которые легко доступны, в отличие от двоичных данных, для которых вам, вероятно, придется писать анализатор.

Есть много способов преобразовать двоичные данные в текст. Самый прямой подход — использовать dump манипулятор, который будет эффективно создавать текстовое представление необработанных двоичных данных. Он также подходит для графических данных, потому что они, как правило, относительно велики по объему, и их часто достаточно легко сравнивать в текстовом представлении (например, когда образец цвета соответствует байту).

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

Более структурированный способ вывода двоичных данных — использование других библиотек, таких как iterator_range из Boost.Range. Это может быть полезно, если ваши графические данные состоят из чего-то более сложного, чем необработанные байты.

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

Вы также можете написать свой собственный манипулятор, который будет форматировать данные так, как вы хотите, например. разбить вывод по строкам.

2. Для двоичных данных используйте атрибуты и пользовательский бэкенд приемника.

Если вы намерены обрабатывать зарегистрированные данные с помощью более специализированного программного обеспечения, такого как средство просмотра изображений или редактор, вы можете сохранить данные в двоичной форме. Это можно сделать с помощью Boost.Log, но это потребует больше усилий, потому что приемники, предоставляемые библиотекой, ориентированы на текст, и вы не можете сохранить двоичные данные в текстовый файл как есть. Вам нужно будет написать серверную часть приемника, которая будет записывать двоичные данные в нужном вам формате (например, если вы планируете использовать редактор изображений, вы можете захотеть записывать файлы в формате, поддерживаемом этим редактором). Существует руководство здесь, где показан интерфейс, который необходимо реализовать, и пример реализации. Важным битом является функция 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 должен оставаться активным, пока обрабатывается запись журнала. Для асинхронного ведения журнала вам придется передавать изображение по значению или использовать подсчет ссылок.

Если вы хотите применить фильтры к данным изображения, вы можете использовать атрибуты с областью действия или добавьте атрибут в регистратор.

Обратите внимание, что, добавляя новый приемник для записи двоичных данных, вы не исключаете записи текстовых журналов с другими приемниками, чтобы сообщение «Catch my image» могло быть обработано текстовым приемником. Используя другие атрибуты, такие как запись журнала счетчики вы можете связать записи журнала в разных файлах, созданных разными приемниками.

person Andrey Semashev    schedule 18.09.2017