![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Принцип работы инструментов автокоррекции изображений
leonidus © (2007-08-07 14:35:00)В гугловской Picasa, и кажется в ACDSee, есть инструмент с помошью которого можно автоматически поднять якрость/контратность фотографии. Т.е. просто одним кликом программа осветляет фотографию, причем для разных фоток уровень осветления будет разный, в связи с чем вопрос, как программа понимает до какого уровня необходимо осветлить фотку, что бы и не пересветить ее и темного тоже небыло?
Ricks (2007-08-16 19:18:00) [1]только код почти весь в моих типах, догадайся сам :)
var
HIST : ImageHistogram;
HISR : ImageHistogram;
HISG : ImageHistogram;
HISB : ImageHistogram;
...
var D : PRGBAArray;
V : array [0..2] of PRGBAArray;
H : tagBITMAPINFO;
B : TBitmap;
N : Cardinal;
J : Cardinal;
L : TLabRec;
A : TRGBARec;
lMin, lMax : single;
hMean : array [0..3] of single;
sMean : array [0..2] of single;
begin
N:=ExtractImageData(SourceImage.Picture.Bitmap.Handle, H, D);
V[0]:=AllocMem( N * 4 );
V[1]:=AllocMem( N * 4 );
V[2]:=AllocMem( N * 4 );
lMax:=0;
lMin:=255;
FillChar(HIST, SizeOf(HIST), 0);
for J:=0 to pred(N) do begin
L:=RGBAtoLab( D^[J] );
if L.L > lMax then lMax:=L.L;
if L.L < lMin then lMin:=L.L;
Inc(HIST[ Round(L.L) ]);
Inc(HISR[ D^[J].Red ]);
Inc(HISG[ D^[J].Green ]);
Inc(HISB[ D^[J].Blue ]);
end;
FillChar(hMean, SizeOf(hMean), 0);
FillChar(sMean, SizeOf(sMean), 0);
for J:=0 to 255 do begin
hMean[0]:=hMean[0] + j * HISR[J]; sMean[0]:=sMean[0] + HISR[J];
hMean[1]:=hMean[1] + j * HISG[J]; sMean[1]:=sMean[1] + HISG[J];
hMean[2]:=hMean[2] + j * HISB[J]; sMean[2]:=sMean[2] + HISB[J];
end;
hMean[0]:=hMean[0] / sMean[0];
hMean[1]:=hMean[1] / sMean[1];
hMean[2]:=hMean[2] / sMean[2];
hMean[3]:=(hMean[0] + hMean[1] + hMean[2]) / 3;
for J:=0 to pred(N) do begin
V[0]^[J]:=D^[J];
A.Blue:= ByteLim( D^[J].Blue - (hMean[2] - hMean[3]) );
A.Green:=ByteLim( D^[J].Green - (hMean[1] - hMean[3]) );
A.Red:= ByteLim( D^[J].Red - (hMean[0] - hMean[3]) );
V[1]^[J]:=A;
end;
for J:=0 to pred(N) do begin
L:=RGBAtoLab( V[1]^[J] );
if L.L > lMax then lMax:=L.L;
if L.L < lMin then lMin:=L.L;
end;
for J:=0 to pred(N) do begin
A.Blue:= ByteLim( 255 * (V[1]^[J].Blue - lMin) / (lMax - lMin) );
A.Green:=ByteLim( 255 * (V[1]^[J].Green - lMin) / (lMax - lMin) );
A.Red:= ByteLim( 255 * (V[1]^[J].Red - lMin) / (lMax - lMin) );
V[2]^[J]:=A;
end;
.....
leonid (2007-08-14 17:20:00) [2]Ricks а можно код глянуть?
leonid (2007-08-14 17:18:00) [3]Ricks большое спасибо за потраченное время, сейчас буду смотреть.
Ricks (2007-08-12 21:11:00) [4]
> во втором проходе выравниваются контраст (наверное ;))
для чего находим минимум и максимум "светлоты" и для каждого
канала
загнался :)
находим не для каждого канала min и max светлоты (т.к это бред :)), а просто минимум и максимум светлоты изображения
Ricks (2007-08-12 21:09:00) [5]Помучался я над вашей проблемой и вот что получилось:
http://www.ricks.pisem.net/test.zip
улучшал в два прохода.
в первом выравниваются цвета, для чего по каждому каналу находиться среднее значение (можно и с помощью гистограммы), потом находится общее среднее mean = (meanR + meanG + meanB) / 3 и для каждого канала
делаем
new[R, G, B]:=old[R, G, B] - (mean[R, G, B] - mean)
(на моем тестовом рисунке убирается излишек синего цвета)
во втором проходе выравниваются контраст (наверное ;))
для чего находим минимум и максимум "светлоты" и для каждого канала
new[R, G, B]:=255 * (old[R, G, B] - minL) / (maxL - minL)
формулу эту спер отсюда же, у Pavia :)
вроде бы неплохо выравнивает :)
leonid (2007-08-11 18:01:00) [6]>Pavia сейчас экспериментировал с фотошоповским инструментом "автоконтраст", и как вы верно заметили автоконтраст делается за счет равномерного растяжения гистограммы и заполнения нулевых или близким к нулю элементов гистограммы. Однако я сейчас сверил фотошопом картинку до преобразования вашим кодом и после, гистограмма практически одинаковая, хотя сам фотошоп на тойже картинке автоконтраст не сильный но делает, и гистограмма там явно смещается. Гдеже загвоздка? Фотку могу выложить на которой проводил эксперимент.
leonid (2007-08-09 22:39:00) [7]>А вообще там нет проверки выхода за границу
Где нету проверки?
Pavia (2007-08-09 19:56:00) [8]А вообще там нет проверки выхода за границу если меньше 0 то пишем 0 если больше 255 то 255
Pavia (2007-08-09 19:44:00) [9]Реально, просто я тогда малость ошибся.
s:=0;
HMean:=0;
for i:=0 to 255 do
begin
HMean:=HMean+i*Hist[i];
s:=s+Hist[i];
end;
HMean:=Round(HMean/S);
Но вот насчет осветления. Осветление не обязана быть линейной операцией. Почитай про гаммо коррекцию.
leonid (2007-08-09 17:25:00) [10]А какие еще приемлемые способы существуют?
DVM (2007-08-09 17:00:00) [11]
> Как вы считаете это реально?
Реально, но что будет в результате сказать сложно.
leonid (2007-08-09 16:47:00) [12]сделал так:
//считаем ср. арифм. по гистограмме
for i:=0 to 255 do HMean:=HMean+i*Hist[i];
HMean:=HMean div 255;
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]-(127-HMean));
G:=Round(p[j*3+1]-(127-HMean));
R:=Round(p[j*3+2]-(127-HMean));
p[j*3+0]:=B;
p[j*3+1]:=G;
p[j*3+2]:=R;
end;
end;
end;
но почему-то вместо осветления получил какое-то странное смещение цветов. Но в общем сам аглоритм осветления или затемнения всей фотографии я нашел, вопрос в другом, как принять решении о применеии того или иного алгоритма, и насколько именно затемнять или осветлять фотку... а что если гистограммы разделить на две части и посчитать среднее значение слева и справо, соотв. если слева значение больше, то фотка темная, если справа больше - то светлая. Как вы считаете это реально?
DVM (2007-08-08 15:12:00) [13]
> а как быть с автояркостью, ее как реализовать?
В отличии от контраста, с яркостью не все так просто. Нет четкого определения достаточно или недостаточно яркого изображения. В том же фотошопе нет такого действия автояркость, но есть автоконтраст.
Поэтому надо определиться сначала с нижней и верхней границей яркости и потом двигать яркость изображения в зону между этими границами.
Pavia (2007-08-08 15:10:00) [14]Хотя чето с вычислением HMean я напутал,
Pavia (2007-08-08 15:05:00) [15]При изменении контрасности яркость не должна меняться. Но когда мы делаем автоконтраст яркость у нас тоже меняется.
Если уж не терпиться просто вычти из R,G,B значение 127-HMean. HMean - средне арефметическое по гистограмме.
for i:=0 to 255 do HMean:=HMean+i*Hist[i];
HMean:=HMean div 255;
Есть еще выравнивание освещенности. Тут если не в доваться в теорию. То делаем размытие по некоторому радиусу. И делим исходное изоброжение на размытое. Есть и более сложные мотоды.
leonidus (2007-08-08 14:49:00) [16]Ок, картина проясняется - Pavia большое спасибо. Но все же еще вопрос, а как быть с автояркостью, ее как реализовать?
Pavia (2007-08-08 14:35:00) [17]
> Приведенный код почему-то совршенно не увеличивает яркость
> картинки...
Насчет яркости не знаю, а вот контрасность должен увеличивать.
Изменения могут быть и не заметны глазу, поэтому сделай вывод гистограммы. Ты сможешь увидить как она растягивается и заполняет весь диапозон частот.
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 (2007-08-08 14:18:00) [18]Приведенный код почему-то совршенно не увеличивает яркость картинки...
>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 (2007-08-08 13:25:00) [19]Я там выше писал
> Hist:Array [0..255] of Byte;
Надо так Hist:Array [0..255] of DWord;
И соответственно FillCher(Hist[0],256*4,0);
Pavia (2007-08-08 13:20:00) [20]Имея гистограмму в распоряжении найти 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;