Написание файла JPEG с Boost :: Gil - PullRequest
1 голос
/ 24 апреля 2020

Я пытаюсь прочитать файл jpeg, выполнить простое преобразование и записать его, используя библиотеку boost :: gil. Прямо сейчас я застрял, поскольку даже считывание файла, извлечение небелых точек (он содержит только красные и белые точки) и запись их в другой файл дает совершенно неожиданные результаты. Я хочу, чтобы изображения были одинаковыми, но вот что происходит:

Это входное изображение. Original Picture

И это изображение на выходе: enter image description here

Вот как я читаю небелые координаты:

vector<Point2D> points;
//load points from file
rgb8_image_t img;
jpeg_read_image(in_file_path, img );

assert( 2 == img._view.num_dimensions );
const auto dimensions = img._view.dimensions();
assert( 2 == dimensions.num_dimensions );

row_width = dimensions.x;
col_height = dimensions.y;

size_t white_cnt = 0;
size_t non_white_cnt = 0;
for ( uint32_t x = 0; x < dimensions.x; ++x ){
    for ( uint32_t y = 0; y < dimensions.y; ++y ){
        const rgb8_pixel_t& pix = const_view(img)( rgb8_image_t::point_t(x,y) );
        if ( !is_white(pix) ){
            points.push_back( Point2D {x,y} );
        }
    }
}

И вот как пишут те же самые пункты

rgb8_image_t img(row_width,col_heigth);

rgb8_pixel_t white(255,255,255);
rgb8_pixel_t red(255,0,0);
rgb8_pixel_t blue(0,0,255);

fill_pixels( view(img), white );

cout << "printing " << points.size() << "points" << std::endl;
for ( Point2D p : points ){
        const auto x = p[0];
        const auto y = p[1];
        cout << x <<"," << y << endl;
        view(img)( rgb8_image_t::point_t( x,y ) ) = red;
}

jpeg_write_view( out_file_path, const_view(img));

Для полноты, это проверка is_white:

bool is_white( const boost::gil::rgb8_pixel_t& pix ){
    const auto r = boost::gil::at_c<0>(pix);
    const auto g = boost::gil::at_c<1>(pix);
    const auto b = boost::gil::at_c<2>(pix);
    constexpr auto MAX_VAL = std::numeric_limits<decltype(r)>::max();
    return ( MAX_VAL == r ) && ( MAX_VAL == g ) && ( MAX_VAL == b );
}

Любая идея, что я делаю неправильно ?

Спасибо

1 Ответ

1 голос
/ 27 апреля 2020

Из-за артефактов JPEG в исходных данных у вас есть много небелых пикселей, которые на самом деле не красные:

enter image description here

Вам необходимо сравнить цвета с порогом. Я решил, что для ваших текущих данных было бы более эффективно обнаруживать небелость в оттенках серого, поэтому вся программа фактически становится такой:

gil::transform_pixels(
        const_view(input),
        view(output),
        [](auto& pix) { return pix<200? blue : white; });

Вот модифицированный дубль:

#include <boost/gil.hpp>
#include <boost/gil/color_convert.hpp>
#include <boost/gil/extension/io/jpeg.hpp>
#include <boost/gil/io/io.hpp>
#include <iostream>
namespace gil = boost::gil;

int main() {
    static const gil::rgb8_pixel_t
        white(255, 255, 255),
        red(255, 0, 0),
        blue(0, 0, 255);

    // load points from file
    gil::gray8_image_t input;
    read_and_convert_image("input.jpg", input,
            gil::image_read_settings<gil::jpeg_tag>{});

    auto dimensions = input._view.dimensions();
    gil::rgb8_image_t output(dimensions.x, dimensions.y, white);

    gil::transform_pixels(
            const_view(input),
            view(output),
            [](auto& pix) { return pix<200? blue : white; });

    write_view("output.jpg", const_view(output), gil::jpeg_tag());
}

Примечание

  • есть несколько упрощений
  • Я использую новый интерфейс ввода-вывода
  • Я выбрал случайное пороговое значение в сером канале (200) для определить белизну, которая была моим первым порогом, и она, кажется, работает достаточно хорошо, но вы можете настроить ее для своих входных данных
  • Я изменил цвет выходного пикселя на синий, чтобы «доказать», что я не просто показывает входное изображение:)

Здесь чередуются вход и выход:

enter image description here

...