#matlab #image-processing #dithering
#matlab #обработка изображений #сглаживание
Вопрос:
Я пытаюсь реализовать сглаживание Флойда Стейнберга в MATLAB, используя псевдокод на странице Википедии https://en.wikipedia.org/wiki/Floyd–Steinberg_dithering
Мой код приведен ниже
image = double(imread("dithering.jpg")) ./ 255;
levels = 2;
image_quantised = round(image .* (levels - 1)) ./ (levels - 1);
error = image - image_quantised;
height = size(image(:, :, 1), 1);
width = size(image(:, :, 1), 2);
image_dithered = image_quantised;
for y = 1:height - 1
for x = 2:width - 1
image_dithered(y , x 1, :) = image_dithered(y , x 1, :) error(y, x, :) .* 7 / 16;
image_dithered(y 1, x - 1, :) = image_dithered(y 1, x - 1, :) error(y, x, :) .* 3 / 16;
image_dithered(y 1, x , :) = image_dithered(y 1, x , :) error(y, x, :) .* 5 / 16;
image_dithered(y 1, x 1, :) = image_dithered(y 1, x 1, :) error(y, x, :) .* 1 / 16;
end
end
imshow(image_dithered) % Image 1
imshow(dither(mean(image, 3))) % Image 2
Изображение 1
Изображение 2
Я ожидаю результата на изображении 2, но получаю изображение 1. Похоже, что алгоритм ничего не делает. Есть идеи? 🙂
Редактировать: я пробовал инициализацию image_dithered
с разными значениями; все нули, квантованное изображение и исходное изображение. Ни один из них не работает правильно
Редактирование 2: я приближаюсь к вычислению ошибки и квантованию в цикле. Однако все еще не на месте.
for y = 1:height - 1
for x = 2:width - 1
new_pixel = round(image_dithered(y, x, :) .* (levels - 1)) ./ (levels - 1);
image_dithered(y, x, :) = new_pixel;
error = image(y, x, :) - new_pixel;
image_dithered(y , x 1, :) = image_dithered(y , x 1, :) error .* 7 / 16;
image_dithered(y 1, x - 1, :) = image_dithered(y 1, x - 1, :) error .* 3 / 16;
image_dithered(y 1, x , :) = image_dithered(y 1, x , :) error .* 5 / 16;
image_dithered(y 1, x 1, :) = image_dithered(y 1, x 1, :) error .* 1 / 16;
end
end
Редактировать 3: Спасибо за @saastn и @Cris Luengo, оба ответа помогли мне понять, где я ошибался, и, похоже, теперь все работает так, как ожидалось!
Исправленный код приведен ниже для полноты.
height = size(image(:, :, 1), 1);
width = size(image(:, :, 1), 2);
image_dithered = image;
for y = 1:height - 1
for x = 2:width - 1
old_pixel = image_dithered(y, x, :);
new_pixel = round(image_dithered(y, x, :) .* (levels - 1)) ./ (levels - 1);
image_dithered(y, x, :) = new_pixel;
error = old_pixel - new_pixel;
image_dithered(y , x 1, :) = image_dithered(y , x 1, :) error .* 7 / 16;
image_dithered(y 1, x - 1, :) = image_dithered(y 1, x - 1, :) error .* 3 / 16;
image_dithered(y 1, x , :) = image_dithered(y 1, x , :) error .* 5 / 16;
image_dithered(y 1, x 1, :) = image_dithered(y 1, x 1, :) error .* 1 / 16;
end
end
imshow(image_dithered)
imshow(dither(mean(image, 3)))
Ответ №1:
Проблема в том, что вы пытались улучшить псевдокод и удалить oldpixel
! Обратите внимание, что алгоритм вычисляет не ошибку между квантованным пикселем и его соответствующим значением в исходном изображении, а скорее ошибку между квантованным пикселем и предыдущим значением в искаженном изображении, которое могло быть обновлено при сканировании предыдущих пикселей. oldpixel
Вернитесь и просмотрите весь алгоритм еще раз.
Но даже после внесения изменений вы не можете ожидать, что результаты будут соответствовать выводам MATLAB, что может быть результатом различий в деталях двух реализаций.
Ответ №2:
Вы распространяете ошибки в image_quantized
, а не в исходном изображении. Удалите это квантованное изображение, оно не является частью алгоритма.
Вам нужно квантовать один пиксель, затем найти разницу с исходным значением и распространить эту ошибку на будущие пиксели.
Обратите внимание, что псевдокод Википедии делает это на месте, существует только одна копия изображения, которая работает как для ввода, так и для вывода.
В этом моем старом сообщении в блоге есть код MATLAB для сглаживания Флойда-Стейнберга.
Ответ №3:
Предполагая, что вы сначала следуете ответу saastn (и отвечаете на то, что в нем говорится о различиях между этими изображениями): я бы сказал, что, просто взглянув на них на изображении saastn, шаблоны Matlab выглядят так, как будто они представляют собой боковую версию Floyd-Steinberg здесь, либо путем поворота, либо, что более вероятно, с помощьютранспозиция (поменяйте местами x с y, что является отражением по диагональной оси x y). Это нельзя имитировать, просто изменяя коэффициенты, изображение должно обрабатываться по столбцам («для x» за пределами «для y» И т. Д.).