Author Topic: коррекция яркость/контраст  (Read 4702 times)

0 Members and 1 Guest are viewing this topic.

dramster

  • Герой форума
  • *****
  • Posts: 1134
    • View Profile
коррекция яркость/контраст
« on: February 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 - это то значение , на которое будет повышаться или уменьшаться (при отрицательном значении) яркость.
Code: (clickermann) [Select]
$x1=903
$y1=956
$x2=968
$y2=1003


$mid=147
$k=40
//=========================
print("start")
GETSCREEN($x1,$y1,$x2,$y2)
SCREENSHOTEX($x1,$y1,$x2,$y2)
FOR($y=$y1,$y<$y2+1)
   FOR($x=$x1,$x<$x2+1)
      $c= pxl($x,$y)
      IF(((colorr($c)+colorg($c)+colorb($c))/3) > $mid)
         $outr=colorr($c)+$k
         $outg=colorg($c)+$k
         $outb=colorb($c)+$k
         IF($outr < $mid)
            $outr=$mid
         END_IF
         IF($outg < $mid)
            $outg=$mid
         END_IF
         IF($outb < $mid)
            $outb=$mid
         END_IF
      else
         $outr=colorr($c)-$k
         $outg=colorg($c)-$k
         $outb=colorb($c)-$k
         IF($outr > $mid)
            $outr=$mid
         END_IF
         IF($outg > $mid)
            $outg=$mid
         END_IF
         IF($outb > $mid)
            $outb=$mid
         END_IF
      END_IF
      IF($outr < 0)
         $outr=0
      END_IF
      IF($outg < 0)
         $outg=0
      END_IF
      IF($outb < 0)
         $outb=0
      END_IF
      IF($outr > 255)
         $outr=255
      END_IF
      IF($outg > 255)
         $outg=255
      END_IF
      IF($outb > 255)
         $outb=255
      END_IF
      PXLREPLACE($x,$y,$x,$y,$c,COLORGEN($outr,$outg,$outb))
   END_CYC
END_CYC
print("fin")

SCREENSHOTEX($x1,$y1,$x2,$y2)
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

  • Супермодератор
  • Герой форума
  • *
  • Posts: 3935
  • Лечу куда хочу. cman 4.13.014x32, 4.14.003 W10
    • View Profile
Re: коррекция яркость/контраст
« Reply #1 on: February 17, 2016, 11:46:05 AM »
Хорошая мысль. Я полностью ЗА.

Я вот только не понял назначение вот этого:
Code: (clickermann) [Select]
         IF($outr < $mid)
            $outr=$mid
         END_IF
         IF($outg < $mid)
            $outg=$mid
         END_IF
         IF($outb < $mid)
            $outb=$mid
         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
« Last Edit: February 17, 2016, 12:34:59 PM by Vint »


dramster

  • Герой форума
  • *****
  • Posts: 1134
    • View Profile
Re: коррекция яркость/контраст
« Reply #2 on: February 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

Code: (clickermann) [Select]
$x1=2681
$y1=1173
$x2=2815
$y2=1316


$mid=147
$k=50

print("start")
GETSCREEN($x1,$y1,$x2,$y2)
SCREENSHOTEX($x1,$y1,$x2,$y2)
FOR($y=$y1,$y<$y2+1)
   FOR($x=$x1,$x<$x2+1)
      $c= pxl($x,$y)
      $color_mid = (colorr($c)+colorg($c)+colorb($c))/3
      IF($color_mid  > $mid)
         $k_res = int((($color_mid - $mid)/128)*$k)
         
         $outr=colorr($c)+$k_res
         $outg=colorg($c)+$k_res
         $outb=colorb($c)+$k_res
         IF($outr < $mid)
            $outr=$mid
         END_IF
         IF($outg < $mid)
            $outg=$mid
         END_IF
         IF($outb < $mid)
            $outb=$mid
         END_IF
      else
         $k_res = int((($mid-$color_mid)/128)*$k)
         
         $outr=colorr($c)-$k_res
         $outg=colorg($c)-$k_res
         $outb=colorb($c)-$k_res
         IF($outr > $mid)
            $outr=$mid
         END_IF
         IF($outg > $mid)
            $outg=$mid
         END_IF
         IF($outb > $mid)
            $outb=$mid
         END_IF
      END_IF
      IF($outr < 0)
         $outr=0
      END_IF
      IF($outg < 0)
         $outg=0
      END_IF
      IF($outb < 0)
         $outb=0
      END_IF
      IF($outr > 255)
         $outr=255
      END_IF
      IF($outg > 255)
         $outg=255
      END_IF
      IF($outb > 255)
         $outb=255
      END_IF
      PXLREPLACE($x,$y,$x,$y,$c,COLORGEN($outr,$outg,$outb))
   END_CYC
END_CYC
print("fin")

SCREENSHOTEX($x1,$y1,$x2,$y2)
halt



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




немного подредактировал, накосячил в вычислениях $k_res
« Last Edit: February 18, 2016, 12:09:13 AM by dramster »