Очистить картинку от шума. GD. Возможно?

  • Автор темы Автор темы ksnk
  • Дата начала Дата начала

ksnk

прохожий
При загрузке картинок, иногда, требуется очистить картинку от артефактов пережатия jpeg, которые выглядят как шум. Картинки небольшого размера, превьюшки и накладные расходы даже на попиксельный просмотр картинки будут не очень страшны.
Выглядит это как дополнительный сервис в админке, когда после загрузки превьюшки, будет предложено пользователю выбрать наиболее удачный вариант обработки.
По идее, любой фильтр для очистки шума с этим справляется относительно разумно, однако потребовалось это сделать на сервере, без Image Magick.
Возможно ли это сделать с помощью фильтров GD или как нибудь еще?
 
не знаю как на счет jpeg шум но подход такой,
1. копия -> ч/б
2. все что черное уменьшить на 1px
3. все что черное увеличить на 1px
4. использовать как маску для оригинала
 
@WMix, маска в каком смысле, все что вне маски - выкидываем? При этом фон со светлым рисунком потеряется. Или я что-то не понял?
 
O! Все что вне маски делаем размытым... Вроде так более разумно выглядит. Правда что делать со светлым рисунком на темном фоне - нипанятна...
Спасибо за идею, буду думать.
 
Правда что делать со светлым рисунком на темном фоне
можно и инвертить, а вообще внутри как и снаружи... но яб на твоем месте не парился с попиксельной обработкой... не тот язык, долго будет
 
На первый взгляд - конволюшн с гауссовой матрицей дал неплохой результат.

PHP:
$img=imagecreatefromjpeg($imgfile);
$emboss = array(array(1/16, 1/8, 1/16), array(1/8, 1/4, 1/8), array(1/16, 1/8, 1/16));
        // calculate the sharpen divisor
$divisor = array_sum(array_map('array_sum', $emboss));
imageconvolution($img, $emboss, $divisor, 0);
В общем-то, практически блур, но для грязных и небольших превьюшек получается неплохо.

Хотя я уже почти созрел для вычисления маски по IMG_FILTER_EDGEDETECT, потом зарядить там контраст, результирующую картинку заблурить и по маске, там где пиксели достаточно черные или белые - скопировать старое изображение... Может еще доделаю :)
 
Хотя я уже почти созрел для вычисления маски по IMG_FILTER_EDGEDETECT, потом зарядить там контраст, результирующую картинку заблурить и по маске, там где пиксели достаточно черные или белые - скопировать старое изображение... Может еще доделаю :)
Там по идее в более качественных фильтрах так и делают, low pass + high pass + всякие угадайки
 
Да, как и ожидалось, решение с попиксельной работой оказалось медленным. Впрочем вся работа с GD не быстра...
Вдруг кому понадобится - тут есть некоторые цифры и слова.
PHP:
    /**
     * шумодав на коленке для маленьких жипегчиков .
     * @param file $imgfile :select[~dir(*.jpg)]  имя файла для обработки
     * @param string $tmpname :text имя файла с результатом, без расширения
     */
    function do_convert($imgfile,$tmpname='tmp'){
        $orig=imagecreatefromjpeg($imgfile);
        $width = imagesx($orig);
        $height = imagesy($orig);
        $mask=imagecreatetruecolor($width,$height);
        $img=imagecreatetruecolor($width,$height);
        // копируем оригинал
        imagecopy($mask,$orig,0,0,0,0,$width,$height);
        imagecopy($img,$orig,0,0,0,0,$width,$height);
        // делаем маску
        imagefilter($mask,IMG_FILTER_EDGEDETECT);
        imagefilter($mask,IMG_FILTER_GRAYSCALE);
        // imagefilter($img,IMG_FILTER_CONTRAST,-100); // не надо, становится хуже :(

        // Гаусс блур для  $img
        //imagefilter($img,IMG_FILTER_GAUSSIAN_BLUR);
        // или сильный блур для остальной картинки
        imagefilter($img,IMG_FILTER_SELECTIVE_BLUR);

        for($i=0;$i<$width;$i++)for($j=0;$j<$height;$j++){
            $rgb=imagecolorat($mask,$i,$j);
            $r = ($rgb >> 16) & 0xFF;
            $g = ($rgb >> 8) & 0xFF;
            $b = $rgb & 0xFF;
            $col=abs(128-($r+$g+$b)/3);
            if($col>110){
                $c=imagecolorat($orig,$i,$j);
                imagesetpixel($img,$i,$j,$c);
            }
        }
        // $img - готовая картинка с уменьшеным шумом
        imagepng($img,dirname($imgfile).'/'.$tmpname.'.png');
        imagedestroy($mask);
        imagedestroy($orig);
        imagedestroy($img); // порядок прежде всего
        //echo dirname($imgfile).'/'.$tmpname.'.png';
    }
Не то, что он убирает артефакты на картинке, но делает их не такими заметными. На первый взгляд, получился почти обычный мыльный шумодав...
 
Эх, попьет из тебя крови твой шумодав, говнецо еще то! Чес слово простой exec для imagic логичнее и проще поддерживаемо! Ну поиграйся... Задачка для понимания мира больше
 
  • Like
Реакции: ksnk
Сверху