Конференция "Media" » Принцип работы инструментов автокоррекции изображений
 
  • leonidus © (07.08.07 14:35) [0]
    В гугловской Picasa, и кажется в ACDSee, есть инструмент с помошью которого можно автоматически поднять якрость/контратность фотографии. Т.е. просто одним кликом программа осветляет фотографию, причем для разных фоток уровень осветления будет разный, в связи с чем вопрос, как программа понимает до какого уровня необходимо осветлить фотку, что бы и не пересветить ее и темного тоже небыло?
  • MBo © (07.08.07 15:16) [1]
    например, выравниванием гистограммы
  • leonidus © (07.08.07 15:23) [2]
    это как?
  • DVM © (07.08.07 15:29) [3]

    > это как?

    1) делаешь массив из 256 ячеек.
    2) Проходишь по пикселам и узнаешь яркость каждого.
    3) Заносишь  +1 в ячейку массива под тем номером какую яркость ты получил.
    4) После прохода по картинке у тебя будет массив с количествами пикселов по каждой величине яркости от 0 до 255.

    Этот массив - и есть гистограмма
  • DVM © (07.08.07 15:32) [4]
    на хорошей фотке гистограмма должна быть более-менее равномерной или хотя бы не напоминать букву U. U-образную гистограмму имеет слишком контрастная фотка.
  • Sdubaruhnul (07.08.07 16:34) [5]
    Вот небольшая брошюрка об инструменте Curves в Photoshop, на русском.
    http://upload2.net/page/download/HJqvQJZznrZOHt2/UsingCurvesInPS.rar.html
  • leonidus © (07.08.07 20:14) [6]
    ссылка битая
  • Sdubaruhnul (07.08.07 21:36) [7]
    >leonidus ©   (07.08.07 20:14) [6]

    Да нет, работает. Там внизу секундомер. Но если настаиваешь, то зеркало:
    http://www.speedyshare.com/557836353.html
  • leonidus © (08.08.07 00:35) [8]
    >DVMА что есть яркость?

    Я вот делаю так:

    var
    btm:tbitmap;
    color:tcolor;
    r,g,b:integer;
    ...

     for x:=0 to btm.Width-1 do
      begin
       sum_l:=0;

       for y:=0 to btm.Height-1 do
        begin
         color:=btm.Canvas.Pixels[x,y];
         r:=GetRValue(color);
         g:=GetGValue(color);
         b:=GetBValue(color);

         sum_l:=sum_l+(r+g+b);
        end;

      end;

    будет ли в конце каждого цикла "for y", значение sum_l равное высоте столбца гистограммы цветов, или гистограмма строится как-то иначе?
  • pavia © (08.08.07 03:10) [9]
    Для того чтобы произвести корекцию изоброжения нужно выровнить по трем уровням R,G,B. Припомощи линейного растяжения интенсивностий.
    Делается это так ищем минимумы и максимумы по трем состовляющим.
    RMin, RMax, GMin, GMax, BMin, BMax

    (R-RMin)*(255-0)/(RMax-RMin)
    (G-GMin)*(255-0)/(GMax-GMin)
    (B-BMin)*(255-0)/(BMax-BMin)

    R,G,B -знначение в точке

    Насчет гистограммы.
    Гистограмма - представления распределения частот выбранных переменных.
    Тоесть то сколько раз встеречается значения переменных.

    К примеру можно иметь три гистограммы интенсивнистей R,G,B.
    Или одну по яркости, чаще всего пользуются ей. Где яркость можно считать так I=(R+G+B)/3 или  как опишу ниже.

    Выравнивание идет также.  
    (I-IMin)*(255-0)/(IMax-IMin)
    А вообще можно добавить перемещение мыши тогда выравнивание  вести соответственно.

    Для того чтобы провести корекцию изоброжения по яркости нужно
    1. Перейти из цветового пространства в другое RGB -> YUV
    2. Сделать корекцию
    3. Сделать обратное преобразование YUV->RGB
    Цветовая модель YUV состоит из
    яркостную компоненты Y и двумя цветоразностныых компонентами U и V

    Преобразование идет по следующим формулам

    Y = 0.299R + 0.587G + 0,114B
    U = – 0.147R – 0.289G + 0,436B
    V = 0.615R + 0.515G + 0,100B = 0,877(R – Y)

    R = Y + 1.140V
    G = Y – 0.395U – 0.581V
    B = Y + 2.032U

    Насчет программирования используй ScanLine


    Const
    RY=0.2989;
    GY=0.5866;
    BY=0.1144;
    Var
    Hist:Array [0..255] of Byte;
    Bp:TBitmap;
    p:PByteArray;
    R,G,B:Byte;

    // Картинка должна быть в формате 24бита елси нет нужно привести
    bp.PixelFormat:=pf24Bit;

    FillCher(Hist[0],255,0);
    if bp <> nil then
    begin
    for i:=0 to bp.Height-1 do
     begin
     p:=bp.ScanLine[i];
     for j:=0 to bp.Width-1 do
      begin
      B:=p[j*3+0];
      G:=p[j*3+1];
      R:=p[j*3+2];
      Inc(Hist[Round(RY*R+GY*G+BY*B)]);
      end;
     end;



    Код писал прямо сдесь без проверки, думаю что работает.
  • Pavia © (08.08.07 03:20) [10]

    > Sdubaruhnul   (07.08.07 21:36) [7]
    > >leonidus ©   (07.08.07 20:14) [6]
    >
    > Да нет, работает. Там внизу секундомер. Но если настаиваешь,
    >  то зеркало:
    > http://www.speedyshare.com/557836353.html

    Интерестная ссылка. Я и так знаю все это так как хорошо представляю что происходит.
    Там идет замена одних цветов другими.
    Строются три таблицы или одна общая замены.

    NewR,NewG,NewB:Array [0..255] of Byte;

    И поомеру заменяются
    R:=NewR[R];

    В фотошопе просто есть поле через которое удобно задовать эти таблицы.
    Там либы каждая точка задается как точка поставленная карандошем. Или как крявая. В качестве формылы для кривой новерно используются безье кривые.
  • leonidus © (08.08.07 09:43) [11]
    >pavia спасибо за инфу и код, но есть несколько вопросов:

    1. Полученный массив содержит гистограмму яркости, я правильно понял?
    2. Не понятно что делает функция Inc(Hist[Round(RY*R+GY*G+BY*B)]);
    3. после получения
    Y = 0.299R + 0.587G + 0,114B (ваш код это делает), нужно продолжить вычисления:

    U = – 0.147R – 0.289G + 0,436B
    V = 0.615R + 0.515G + 0,100B = 0,877(R – Y)
    R = Y + 1.140V
    G = Y – 0.395U – 0.581V
    B = Y + 2.032U

    верно?
    4. Как реализовать после этого коррекцию изображения в bp ?
  • DVM © (08.08.07 10:42) [12]

    > leonidus ©   (08.08.07 00:35) [8]
    > >DVM А что есть яркость?

    Y = 0.299R + 0.587G + 0,114B


    > 1. Полученный массив содержит гистограмму яркости, я правильно
    > понял?

    да
  • leonidus © (08.08.07 11:43) [13]
    Хорошо, я получил массив яркостей, а как теперь провести коррекцию над исходным изображением?
  • Pavia © (08.08.07 13:14) [14]
    1. Да
    2. Вычесляет гистограмму.
    Находим яркость Round(RY*R+GY*G+BY*B)
    И увиличиваем на еденицу значение ячейки равной яркосости по номеру.
    Inc(x) все равно что x:=x+1;
    3. Мой код делает только вычислении гистограммы. А вот преобразования он не делает. Посмотрел что делает фотошо. Автоконтраст не заморачивается с расчетами. Просто считает что все состовляющии R,G,B равны. И гистограмму строит в соответствии с равенством каналов.

    for i:=0 to bp.Height-1 do
    begin
    p:=bp.ScanLine[i];
    for j:=0 to bp.Width*3-1 do
     begin
     Inc(Hist[p[j]]);
     end;



    p:=bp.ScanLine[0];
    Y:=p[0];
    YMax:= Y;
    YMin:= Y;

    for i:=0 to bp.Height-1 do
    begin
    p:=bp.ScanLine[i];
    for j:=0 to bp.Width*3-1 do
     begin
     Y:=p[j];
     if Y>YMax then YMax:=Y;
     if Y<YMin then YMin:=Y;
     end;
    end;

    for i:=0 to bp.Height-1 do
    begin
    p:=bp.ScanLine[i];
    for j:=0 to bp.Width-1 do
     begin
     B:=Round((p[j*3+0]-YMin)*255 / (YMax-YMin));
     G:=Round((p[j*3+1]-YMin)*255 / (YMax-YMin));
     R:=Round((p[j*3+2]-YMin)*255 / (YMax-YMin));
     p[j*3+0]:=B;
     p[j*3+1]:=G;
     p[j*3+2]:=R;
     end;
    end;




    4. К примеру как сделано выше.
    Гистограмма служит для других целий отоброжает сколько в картине светлых а сколько темных цветов. Можно к графику гистограммы добаить два ползунка левый и правый конец. С помощью них буде происходить вычисление насколько нужно сжать растянуть или сместить состовляющии цветов.
  • Pavia © (08.08.07 13:20) [15]
    Имея гистограмму в распоряжении найти Min и Max можно так

    Это значительно быстрее нежели чем пробигать всю картинку.

    for i:=0 to 255 do
    if Hist[i]>0 then
     begin
     YMin:=i;
     YMax:=i;
     Break;
     end;
    for i:=0 to 255 do
    if Hist[i]>0 then
     begin
     if Hist[i]>Hist[YMax] then YMax:=i;
     if Hist[i]<Hist[YMin] then YMin:=i;
     end;

  • Pavia © (08.08.07 13:25) [16]
    Я там выше писал

    > Hist:Array [0..255] of Byte;

    Надо так Hist:Array [0..255] of DWord;
    И соответственно FillCher(Hist[0],256*4,0);
  • leonidus © (08.08.07 14:18) [17]
    Приведенный код почему-то совршенно не увеличивает яркость картинки...

    >Pavia пожалуйста ответьте еще не несколько вопросов:
    1. В чем так сказалть физический смысл массива яркостей, почему в нем 256 символов и что значит если первый символ скажем равен 800, а 37 - нулю?
    2. В чем смысл цикла:
    for i:=0 to bp.Height-1 do
    begin
    p:=bp.ScanLine[i];
    for j:=0 to bp.Width*3-1 do
    begin
    Inc(Hist[p[j]]);
    end;
    end;

    что здесь делается с гистограммой?

    3. Кусок
    p:=bp.ScanLine[0];
    Y:=p[0];
    YMax:= Y;
    YMin:= Y;

    for i:=0 to bp.Height-1 do
    begin
    p:=bp.ScanLine[i];
    for j:=0 to bp.Width*3-1 do
    begin
    Y:=p[j];
    if Y>YMax then YMax:=Y;
    if Y<YMin then YMin:=Y;
    end;
    end;

    ищет в bp масимальный и минимальный элементы, но откуда bp.Width*3-1, и почему YMax всегда рано 255, а YMin = 0 ?
  • Pavia © (08.08.07 14:35) [18]

    > Приведенный код почему-то совршенно не увеличивает яркость
    > картинки...

    Насчет яркости не знаю, а вот контрасность должен увеличивать.
    Изменения могут быть и не заметны глазу, поэтому сделай вывод гистограммы. Ты сможешь увидить как она растягивается и заполняет весь диапозон частот.

    1. 256 потому что нам так захотелось. Просто мы имеем три состовляющих цвеа R,G,B каждая варируется от 0 до 255, так почемумы яркость тоже не варьировать в этих приделах поэтому Значение яркости может принемать только 256 значений.
    Это значит что на всей картинке яркость со значением 0 встретилась 800 раз, а со значением 37 вообще не встретилась. Если построить график, то ты увидишь где столбики выше(их больше) слева тоесть ближе к нулю значит картинка темная. Если столбики выше справа то картинка светлая.
    Если столбики разраяжены. Тоесть встречаются 0 элименты. Значит увеличивали контрасность картинки. Если к примеру заполненна середина гистограммы а покраям нет, то значит нужно увеличить контрасность. И тд.

    2.  Вычисляется гистограма по RGB, такую обычно выводит фотошоп.

    3.  bp.Width*3-1 так как у нас три состовляющих R,G,B

    > почему YMax всегда рано 255, а YMin = 0 ?

    Не всегда просто тебе повезло у тебя есть и "белый" цвет на кортинке и "черный". Вернее есть цвет у которого одна из состовляющих равна 255 и есть другой у которого есть 0 значение одного из цветов R,G,B
    Для такой картинке автокантраст не нужен.
  • leonidus © (08.08.07 14:49) [19]
    Ок, картина проясняется - Pavia большое спасибо. Но все же еще вопрос, а как быть с автояркостью, ее как реализовать?
 
Конференция "Media" » Принцип работы инструментов автокоррекции изображений
Есть новые Нет новых   [134431   +10][b:0][p:0.002]