Pull to refresh

Comments 26

Смотря на примеры, кажется, что агрессивое распределение ошибки хорощо работает на планых переходах, когда как распередение только на соседние пиксели — при сложной картинке. Может быть переключаться или динамически генерировать матрийцу в зависимости от того, насколько «детализирован» регион? (средний модуль разницы с соседними пикселями, как вариант)?

Ещё, как гипотеза, от паттернов может помочь добавление некоторой доли случайности в матрицу распределения ошибки
Еще можно специально подготовленный использовать. Вот тут есть 4 варианта такой добавки.
    case 1: mask = ((x ^ y * 149) * 1234& 511)/511.0; break;
    case 2: mask = (((x+c*17) ^ y * 149) * 1234 & 511)/511.0; break;
    case 3: mask = ((x + y * 237) * 119 & 255)/255.0; break;
    case 4: mask = (((x+c*67) + y * 236) * 119 & 255)/255.0; break;

image

Вычисление матрицы дизеринга - сама по себе непростая и интересная задача. Алгоритм Noise shaping должен удовлетворять двум противоречивым требованиям: максимальное подавление нижних частот и равномерность распределения значений в интервале [0; 1). Если просто поочерёдно применять операции highpass и remap, то профиль шума может всё равно получиться неоднородным (см. статью). Хороший шум можно получить только путём параметрической оптимизации.

Приведу примеры дизеринга последовательностью R2 (той, что по вашей ссылке)

Код
use image::io::Reader as ImageReader;
use image::Pixel;

fn main() {
    for path in ["1.png", "2.png"] {
        let img = ImageReader::open(path).unwrap().decode().unwrap();
        let mut imgbuf = img.to_luma8();
        for (x, y, pixel) in imgbuf.enumerate_pixels_mut() {
            pixel.apply(|v| {
                let value = (v as f32) / 255.0;
                let linear = value * value;
                if linear < r2(x, y) {
                    0
                } else {
                    255
                }
            });
        }
        let name = format!("{path}_golden.png");
        imgbuf.save(name).unwrap();
    }
}

fn r2(x: u32, y: u32) -> f32 {
    let a1 = 0.7548776662;
    let a2 = 0.56984029;
    let t = (x as f32 * a1 + y as f32 * a2).fract();
    if t < 0.5 {
        2.0 * t
    } else {
        2.0 - 2.0 * t
    }
}

Дизеринг до сих пор актуален для E-Ink экранов. Не помню точно какой алгоритм использовали в YotaPhone 2, но на нём можно было вполне комфортно работать в Android приложениях и даже смотреть youtube!

Превосходно! Помнится одно время игрался с GameBoy Camera, был такой девайс:

Меня всегда завораживали получаемые картинки, вот тут есть немного моего творчества.

Хотя конкретно эти фотки сделаны не на GameBoy Camera, а на уже поздней Nintendo DS с дополнительным фильтром.

классные фотки у вас, атмосферные

Мне однажды дизеринг пригодился в рендеренге VR для животных, а именно для фруктовых мух: используемый дисплей умел выдавать больше кадров в секунду в режиме два цвета (ч/б), с оттенками серого FPS снижался вдвое, что было нежелательно. С дизерингом получилось выторговать временное разрешение в обмен на пространственное — у насекомых оно все равно неважное, а вот реакция очень быстрая, поэтому FPS важней.

Прочитал комментарий два раза, долго пытался понять, что такое VR для животных. В голову лезли мысли про игры для кошек на планшетах и воспоминания про черно-белое зрение у собак.
Похоже, пора завязывать читать статьи месячной давности в 5 утра и идти спать.

Интересная статья. Немного перекликается с полиграфической темой. Там рипы решают аналогичные задачи. И например изображение по алгоритму Аткинсона очень похоже на стохастическое растрирование (так оно у полиграфистов называется). Еще есть интересные растры - например линейный. Думаю на экране он бы смотрелся очень интересно.

по роду службы часто необходим дизеринг и я использую отличный сервис dither me.

единственное что могу отмеить - независимо от алгоритма, изображение всегда приходится притемнять. (я обычно использую палитру из 3 или 4х цветов)

при разглядывании картинок возникал эффект догрузки изображения: к примеру градиент вначале статьи. Через секунду после втыкания в градиент, при движении глаз вдоль по полоске, он скачкообразно становился более размытым и появлялись границы рисунка. Аналогично с остальными картинками из статьи - они как-то пляшут. Скажите, это только я вижу или кто-то еще?

я не вижу. единственный эффект странный — это мерцание при скролле

Дайте угадаю: у вас плоский монитор?

Это та статья о дизеренге которую я давно хотел почитать. Спасибо!

интересно, понятно, познавательно. большое спасибо за труд!

Еще есть такой инструмент как pixelator, который тоже умеет в дизеринг.

Вот такое:

image

Превращает в такое:

image

Количество цветов и размер пикселей тоже можно варьировать.

Мне больше нравится телеграм-бот @ZXRasterBot от камрада @Error1024 делающий вот такое прекрасное. Там можно часами подбирать подходящие под конкретную картинку параметры.

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

Познакомился с ними еще давно благодаря Corel Photo-Paint. Жаль, что про мой любимый алгоритм - Stucki - не написали.

Да, приятная симметричная матрица. Ещё хорош Sierra Lite своим минимализмом и хорошими результатами.

Не очень понял пассаж про sRGB и RGB. Особенно в контексте ч/б. RGB - пространство цветное и аппаратно-зависимое. Любое RGB устройство не способно отображать внеохватные цвета. sRGB-то в полном объеме далеко не все экраны поддерживают, я уж молчу про AdobeRGB и ProPhotoRGB.

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

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

Картинки градиентов из публикации проверяют как хорошо откалиброван ваш монитор по гамме, ха.
Но, на самом деле, тут есть и палка о двух концах. С гамма-коррекцией дизеринг сохраняет яркость, но теряет в детализации темных областей и визуальной равномерности (простыми словами - редкие белые точки в тенях становятся ещё более редкими).

Из собственной практики (подготовка изображений для лазерной гравировки или текстур для фрезерования) могу добавить, что собственно dithering, как его ни крути, очень редко дает действительно хороший результат. Весьма часто приходится сначала довольно сильно искажать изображение путем wavelet-фильтрации, имитируя довольно агрессивный tone mapping, добиваясь более высокого локального контраста вместо глобального.

Sign up to leave a comment.