Blog. Just Blog

Оценка резкости изображения через оператор Лапласа

Версия для печати Добавить в Избранное Отправить на E-Mail | Категория: Web-мастеру и не только | Автор: ManHunter
Оценка резкости изображения через оператор Лапласа
Оценка резкости изображения через оператор Лапласа

Попробовал решить задачу для автоматической оценки резкости изображения через оператор Лапласа. Зачем это нужно? Я фотографирую каждый кадр по несколько раз, чтобы потом выбрать лучший из серии. Из нескольких похожих файлов надо оставить по одному, а дубли и мусор удалить. Это занимает много времени, да и место на дисках быстро заканчивается, если не чистить. В результате почитал теорию, потестировал код, а потом сделал решение на PHP. Алгоритм можно использовать для автоматической очистки больших массивов фото - например, после поездки или мероприятия. Смазанные кадры удаляются, а резкие остаются.

Немножко теории. В основе алгоритма лежит оператор Лапласа - это штука (другими словами не назвать, слишком мудрено), которая находит на картинке места, где цвет резко меняется, например края предметов. Чем больше таких мест, тем выше число на выходе. Если усреднить это число по всей картинке, получится объективная оценка: чем оно больше, тем фото резче. Однако у этого подхода есть слабое место - зависимость от яркости кадра. Пересвеченное или слишком темное фото дает заниженные значения даже при идеальном фокусе, потому что контраст на границах падает. Поэтому нужна нормировка. В моем коде она есть: алгоритм считает не только резкость, но и среднюю яркость кадра. Итоговая оценка вычисляется как отношение одного к другому с поправкой на максимум. Простыми словами - резкость считается относительно освещенности. Это позволяет сравнивать снимки с разной экспозицией: темные и светлые кадры больше не страдают.
  1. // Дополнительная функция, получить сумму RGB пикселя
  2. function get_gray($img$x$y) {
  3.     $rgb=imagecolorat($img$x$y);
  4.     return (($rgb>>16) & 0xFF)+(($rgb>>8) & 0xFF)+($rgb 0xFF);
  5. }
  6.  
  7. // Оценка резкости изображения через оператор Лапласа
  8. // с нормированием по яркости
  9. function laplacian_sharpness($path) {
  10.     // Загружаем исходное изображение
  11.     $src=imagecreatefromjpeg($path);
  12.     $w=imagesx($src);
  13.     $h=imagesy($src);
  14.  
  15.     // Ресайз до 1024 пикселей, иначе большие фото считаются долго
  16.     $max_size=1024;
  17.     if ($w>$max_size || $h>$max_size) {
  18.         $ratio=min($max_size $w$max_size $h);
  19.         $new_w=$w*$ratio;
  20.         $new_h=$h*$ratio;
  21.         // Рабочее изображение
  22.         $img=imagecreatetruecolor($new_w$new_h);
  23.         imagecopyresampled(
  24.             $img$src0,0,0,0$new_w$new_h$w$h
  25.         );
  26.         // Оригинал больше не нужен
  27.         imagedestroy($src);
  28.     }
  29.     else {
  30.         // Рабочее изображение
  31.         $img=$src;
  32.         $new_w=$w;
  33.         $new_h=$h;
  34.     }
  35.  
  36.     // Сумма модулей лапласиана
  37.     $score=0;
  38.     // Сумма яркостей всех пикселей
  39.     $brightness_total=0;
  40.     // Количество обработанных пикселей
  41.     $count=0;
  42.  
  43.     // Проходим по всем пикселям, кроме границ
  44.     for($x=1$x<($new_w-1); $x++) {
  45.         for($y=1$y<($new_h-1); $y++) {
  46.             // Яркость текущего пикселя
  47.             $gray=get_gray($img$x$y);
  48.             $brightness_total+=$gray;
  49.  
  50.             // Центр и сумма соседей точек. Чем больше перепад
  51.             // яркости с соседями, тем выше значение
  52.             $lap=-4*$gray +
  53.                 get_gray($img$x+1$y) +
  54.                 get_gray($img$x-1$y) +
  55.                 get_gray($img$x$y+1) +
  56.                 get_gray($img$x$y-1);
  57.             $score+=abs($lap);
  58.             $count++;
  59.         }
  60.     }
  61.  
  62.     imagedestroy($img);
  63.  
  64.     // Средняя резкость на пиксель
  65.     $avg_score=$count?($score/$count) : 0;
  66.     // Средняя яркость на пиксель (0-765)
  67.     $avg_brightness=$count?($brightness_total/$count) : 1;
  68.  
  69.     // Нормирование. Умножаем на 765 (максимальная яркость)
  70.     // и делим на среднюю яркость, это компенсирует
  71.     // занижение оценки на темных и светлых фото
  72.     return round($avg_score*(765/$avg_brightness), 2);
  73. }
Я постарался добавить все нужные комментарии. На входе в функцию laplacian_sharpness - файл с картинкой, на выходе число, которое оценивает резкость. Числовая оценка резкости сама по себе мало что говорит без контекста, а дальше уже решается конкретная задача.
  1. // Настройки порогов
  2. $bad_sharpness=20;
  3. // Ниже этого - "мыло" (BAD)
  4. $good_sharpness=70;
  5. // Выше этого - отличная резкость (GOOD)
  6.  
  7. // Путь к папке с фото
  8. $directory='foto/test';
  9. // Поиск нужного формата файлов
  10. $files=glob($directory.'/*.jpg');
  11.  
  12. foreach ($files as $file) {
  13.     // Считаем резкость
  14.     $sharpness=laplacian_sharpness($file);
  15.  
  16.     // Определяем порогов
  17.     if ($sharpness<$bad_sharpness) {
  18.         // Мусор
  19.         $res='<b style="color:#FF0000;">BAD</b>';
  20.     }
  21.     elseif ($sharpness>$good_sharpness) {
  22.         // Отличное качество
  23.         $res='<b style="color:#208F20;">GOOD</b>';
  24.     }
  25.     else {
  26.         // Требуется ручная проверка
  27.         $res='<b>CHECK</b>';
  28.     }
  29.  
  30.     echo '<div>'.basename($file).' : '.$sharpness.' : '.$res'</div>';
  31. }
Главное, что метод дает стабильную и повторяемую метрику, которую можно настраивать под себя. Настройки пороги резкости меняются в переменных $bad_sharpness и $good_sharpness, соответственно, у меня значение 20 - ниже этого будет "мыло", и 70 - выше них отличные фото. То, что попадает в середину, скорее всего, требует ручной проверки. Границы подбираются опытным путем под конкретную камеру и стиль съемки.

Поделиться ссылкой ВКонтакте
Просмотров: 111 | Комментариев: 0

Комментарии

Отзывы посетителей сайта о статье
Комментариeв нет

Добавить комментарий

Заполните форму для добавления комментария
Имя*:
Текст комментария (не более 2000 символов)*:

*Все поля обязательны для заполнения.
Комментарии, содержащие рекламу, ненормативную лексику, оскорбления и т.п., а также флуд и сообщения не по теме, будут удаляться. Нарушителям может быть заблокирован доступ к сайту.
Наверх
Powered by PCL's Speckled Band Engine 0.2 RC3
© ManHunter / PCL, 2008-2026
При использовании материалов ссылка на сайт обязательна
Время генерации: 0.09 сек. / MySQL: 2 (0.0039 сек.) / Память: 4.5 Mb
Наверх