Автор Тема: коррекция яркость/контраст  (Прочитано 1752 раз)

0 Пользователей и 1 Гость просматривают эту тему.

dramster

  • Герой форума
  • *****
  • Сообщений: 1104
    • Просмотр профиля
коррекция яркость/контраст
« : Февраль 17, 2016, 01:53:01 am »
 по сути это продолжение из темы http://crapware.aidf.org/forum/index.php?topic=2390.msg14982#msg14982 . но я там размечтался насчет мегафункционала по обработке изображения  :D. да, всё это будет лишним, и врядли ктото будет пользоваться всякими сепиями, чернобелым и тп.
но всеже есть процедура коррекции, которая значительно бы помогла в множестве ситуаций, и это какраз таки контраст. сильно не вникал как он там должен работать, прочитал пару статей, в редакторах както это всё сложно, и по сути нам ведь не нужно чтобы картинка стала красивее, нам нужно как можно точнее выделить нужные нам цвета в изображении.
немного поэкспериментировал, остановился на примитивном изменении контраста и яркости. меняя 2 параметра $mid и $k можно как увеличивать\уменьшать контраст, так и увеличивать\уменьшать яркость. $mid - это та середина яркости, от которой скрипт будет повышать яркость пикселей которые светлее этого самого $mid. и понижать яркость тех пикселей, которые темнее $mid. его значение от 0 до 255. $k - это то значение , на которое будет повышаться или уменьшаться (при отрицательном значении) яркость.
Код: Clickermann
  1. $x1=903
  2. $y1=956
  3. $x2=968
  4. $y2=1003
  5.  
  6.  
  7. $mid=147
  8. $k=40
  9. //=========================
  10. print("start")
  11. GETSCREEN($x1,$y1,$x2,$y2)
  12. SCREENSHOTEX($x1,$y1,$x2,$y2)
  13. FOR($y=$y1,$y<$y2+1)
  14.   FOR($x=$x1,$x<$x2+1)
  15.      $c= pxl($x,$y)
  16.      IF(((colorr($c)+colorg($c)+colorb($c))/3) > $mid)
  17.         $outr=colorr($c)+$k
  18.         $outg=colorg($c)+$k
  19.         $outb=colorb($c)+$k
  20.         IF($outr < $mid)
  21.            $outr=$mid
  22.         END_IF
  23.         IF($outg < $mid)
  24.            $outg=$mid
  25.         END_IF
  26.         IF($outb < $mid)
  27.            $outb=$mid
  28.         END_IF
  29.      else
  30.         $outr=colorr($c)-$k
  31.         $outg=colorg($c)-$k
  32.         $outb=colorb($c)-$k
  33.         IF($outr > $mid)
  34.            $outr=$mid
  35.         END_IF
  36.         IF($outg > $mid)
  37.            $outg=$mid
  38.         END_IF
  39.         IF($outb > $mid)
  40.            $outb=$mid
  41.         END_IF
  42.      END_IF
  43.      IF($outr < 0)
  44.         $outr=0
  45.      END_IF
  46.      IF($outg < 0)
  47.         $outg=0
  48.      END_IF
  49.      IF($outb < 0)
  50.         $outb=0
  51.      END_IF
  52.      IF($outr > 255)
  53.         $outr=255
  54.      END_IF
  55.      IF($outg > 255)
  56.         $outg=255
  57.      END_IF
  58.      IF($outb > 255)
  59.         $outb=255
  60.      END_IF
  61.      PXLREPLACE($x,$y,$x,$y,$c,COLORGEN($outr,$outg,$outb))
  62.   END_CYC
  63. END_CYC
  64. print("fin")
  65.  
  66. SCREENSHOTEX($x1,$y1,$x2,$y2)
  67. halt
как это работает, примеры:

исходное изображение

 [spoiler=немного больше яркости $mid=0 $k=40][/spoiler]
 [spoiler=немного меньше яркости $mid=255 $k=50 (или $mid=0 $k=-50)][/spoiler]
 [spoiler=немного больше контраста $mid=147 $k=25][/spoiler]
 [spoiler=немного меньше контраста $mid=147 $k=-25][/spoiler]

так для чего же это всё нужно? покажу пару примеров.
пример Vint'a:


$mid=160 $k=255
$mid=170 $k=255

примеры с распознаванием чисел, не охота было искать где это применять, но вспоминаю, что часто отказывался от распознавания, в силу того, что колормид не мог отделить сами цифры от фона. но, как пример, покажу на капче, где кокраз таки при колормод 8, встречались иногда прострелы в контурах цифр.
капча
колормод 8
$mid=170 $k=255
$mid=190 $k=255

ну и применение без разделения на 2 цвета также должно помоч в некоторых ситуациях. например в игре "мастер гитары 2" (если ктото встречался с этой игрой), до того как ввели цвета грифов, оранжевая дорожка по цвету почти совпадала с движущейся фишкой. а когда всунули динамические изменения цветов грифа, никакой колормод не мог справится. я уверен, что данная процедура помогла бы в этой ситуации.

некоторые скажут - "так написал же скрипт, всунь в подпрограмму и пользуйся". но хотелось бы чтоб эта коррекция работала также быстро как и существующий колормод. изменение поочереди каждого пикселя это оооочень долго.


что думаете? поможет на деле чтото этоковое, или это снова я размечтался  :D ?

по сути, правильно чередуя колормод яркость и контраст, можно выделить любой искомый цвет или диапазон цветов в картинке.


Vint

  • Супермодератор
  • Герой форума
  • *
  • Сообщений: 3756
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • Просмотр профиля
Re: коррекция яркость/контраст
« Ответ #1 : Февраль 17, 2016, 11:46:05 am »
Хорошая мысль. Я полностью ЗА.

Я вот только не понял назначение вот этого:
Код: Clickermann
  1.         IF($outr < $mid)
  2.            $outr=$mid
  3.         END_IF
  4.         IF($outg < $mid)
  5.            $outg=$mid
  6.         END_IF
  7.         IF($outb < $mid)
  8.            $outb=$mid
  9.         END_IF

Зачем эта обрезка? Почему низ каждого канала подтягивается к $mid если при прибавлении $k он $mid не привысил?
Какой в этом сакральный смысл?
Добовлено: аааа, понял. Это только для отрицательных $k. Когда если яркость больше средней мы уменьшаем, но если изменение перешло через $mid, Чтобы не попали в зону где мы яркость увеличиваем. А то получается что прибрежный диапазон +$k -$k вылазит навстречу друг другу и выходит не очень хорошо.
Диапазоны для верхней части получаются $mid...255, для нижней 0...$mid, а не 0...255, как в других режимах.


P.S. И почему при всех этих манипуляциях средняя яркость считается как 1:1:1, а не как более правильное/красивое применённое ранее 0.299:0.587:0.114
« Последнее редактирование: Февраль 17, 2016, 12:34:59 pm от Vint »


dramster

  • Герой форума
  • *****
  • Сообщений: 1104
    • Просмотр профиля
Re: коррекция яркость/контраст
« Ответ #2 : Февраль 17, 2016, 08:01:29 pm »
 если уж делать правильно, то насколько я понял, яркость должна увеличиваться на значение, зависящее от удаления от значения $mid. и и значение яркости (далее $k_res) должно увеличиваться не линейно, а по логарифмической кривой. но так как я ничегошеньки не помню про логорифмы, то попробуем увеличивать тот самый $k_res линейно, в зависимости от разница между $mid и средним значением начального цвета.в этоге у нас получится очень даже приличный корректор контраста.
добавил $k_res = int((($color_mid - $mid)/128)*$k), не уверен что так правильно, но результаты, визуально, намного лучше чем те, что в предыдущем варианте с статичным увеличением яркости.
оригинал

$mid=147 $k=50

$mid=147 $k=-50

Код: Clickermann
  1. $x1=2681
  2. $y1=1173
  3. $x2=2815
  4. $y2=1316
  5.  
  6.  
  7. $mid=147
  8. $k=50
  9.  
  10. print("start")
  11. GETSCREEN($x1,$y1,$x2,$y2)
  12. SCREENSHOTEX($x1,$y1,$x2,$y2)
  13. FOR($y=$y1,$y<$y2+1)
  14.   FOR($x=$x1,$x<$x2+1)
  15.      $c= pxl($x,$y)
  16.      $color_mid = (colorr($c)+colorg($c)+colorb($c))/3
  17.      IF($color_mid  > $mid)
  18.         $k_res = int((($color_mid - $mid)/128)*$k)
  19.  
  20.         $outr=colorr($c)+$k_res
  21.         $outg=colorg($c)+$k_res
  22.         $outb=colorb($c)+$k_res
  23.         IF($outr < $mid)
  24.            $outr=$mid
  25.         END_IF
  26.         IF($outg < $mid)
  27.            $outg=$mid
  28.         END_IF
  29.         IF($outb < $mid)
  30.            $outb=$mid
  31.         END_IF
  32.      else
  33.         $k_res = int((($mid-$color_mid)/128)*$k)
  34.  
  35.         $outr=colorr($c)-$k_res
  36.         $outg=colorg($c)-$k_res
  37.         $outb=colorb($c)-$k_res
  38.         IF($outr > $mid)
  39.            $outr=$mid
  40.         END_IF
  41.         IF($outg > $mid)
  42.            $outg=$mid
  43.         END_IF
  44.         IF($outb > $mid)
  45.            $outb=$mid
  46.         END_IF
  47.      END_IF
  48.      IF($outr < 0)
  49.         $outr=0
  50.      END_IF
  51.      IF($outg < 0)
  52.         $outg=0
  53.      END_IF
  54.      IF($outb < 0)
  55.         $outb=0
  56.      END_IF
  57.      IF($outr > 255)
  58.         $outr=255
  59.      END_IF
  60.      IF($outg > 255)
  61.         $outg=255
  62.      END_IF
  63.      IF($outb > 255)
  64.         $outb=255
  65.      END_IF
  66.      PXLREPLACE($x,$y,$x,$y,$c,COLORGEN($outr,$outg,$outb))
  67.   END_CYC
  68. END_CYC
  69. print("fin")
  70.  
  71. SCREENSHOTEX($x1,$y1,$x2,$y2)
  72. halt



но всеже я думаю, что первый вариант на практике поможет лучше, не красота нам нужна. тем более, что изменение яркости (без контраста) в этом случае будет работать не корректно. при увеличении/уменьшении яркости $mid=0 $k=+-0...255 у нас всеравно будет немного применяться эффект контрастности изза $k_res = int((($mid-$color_mid)/128)*$k)




немного подредактировал, накосячил в вычислениях $k_res
« Последнее редактирование: Февраль 18, 2016, 12:09:13 am от dramster »