Перейти к содержимому
Compvision.ru
ProgRoman

Retinex

Recommended Posts

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

Лекции по обработке изображений


Mat msRetinex(const Mat &img)

{	

	Mat ims = img.clone();

	Mat t1,t2,t3;


	int sm = MIN(ims.size().height,ims.size().width);

	if(!(sm%2))sm--;


	GaussianBlur(ims,t1,Size(sm,sm),sm/1);

	GaussianBlur(ims,t2,Size(sm,sm),sm/2);

	GaussianBlur(ims,t3,Size(sm,sm),sm/3);


	Mat l1,l2,l3,l4;

	log(ims,l1);log(t1,l2);log(t2,l3);log(t3,l4);


	Mat tr = (3*l1 - l2-l3-l4)/3;


	return tr;

}

возможно надо применять другие размеры ядра или sigma брать другую...

ниже прикреплены фото с результатами работы алгоритма 1-ое фото оригинальное изображение затем фото обработанное Single Retinex и 3-тье обработанное Multi Retinex... визуально 2-ое и 3-тье изображение везде похоже... хотя должно быть лучше...

post-2515-0-13536400-1332502830_thumb.jp

post-2515-0-12407300-1332502852_thumb.jp

post-2515-0-56034400-1332502862_thumb.jp

post-2515-0-88044700-1332502872_thumb.jp

post-2515-0-18969600-1332502947_thumb.jp

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Может с типами матриц проблема.

Если там тип элемента целое, тем более если 8-ми битное целое то значения могут отсекаться.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

изображения переводятся в вещественный тип

img.convertTo(ts,CV_64FC3,1.0/255.0);

и все действия происходят уже в нём...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

кстати, обратите внимание на

if(!(sm%2))sm--;

и

GaussianBlur(ims,t1,Size(sm,sm),sm/1);

GaussianBlur(ims,t2,Size(sm,sm),sm/2);

GaussianBlur(ims,t3,Size(sm,sm),sm/3);

остальное похоже верно

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

что-то странно... изменил

GaussianBlur(ims,t1,Size(sm,sm),sm/1);

GaussianBlur(ims,t2,Size(sm,sm),sm/2);

GaussianBlur(ims,t3,Size(sm,sm),sm/3);

на

GaussianBlur(ims,t1,Size(sm,sm),sm/1);

GaussianBlur(ims,t2,Size(sm,sm),sm/3);

GaussianBlur(ims,t3,Size(sm,sm),sm/5);

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Может размер ядра поменять, а не дисперсию?

Или вручную ядро соорудить?

PS^ Кстати четные лучше :) это у меня опечатка была.(я бы поставил 2,4,8)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

изменил на

GaussianBlur(ims,t1,Size(sm/2,sm/2),sm/2);

GaussianBlur(ims,t2,Size(sm/2,sm/2),sm/4);

GaussianBlur(ims,t3,Size(sm/2,sm/2),sm/8);

поменял и размер ядра.. ну в два раза меньший стал...

вроде бы есть проясненья лучше ли стало пока не знаю... но откуда-то возникает чёрная полоса... непонятно...

может у этого алгоритма область применения есть ну где-то он не работает...

post-2515-0-37559300-1332509479_thumb.jp

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

А если размер ядра равным сигме устанавливать?

Что касается полосы, то похоже там краевые эффекты возникают.

И еще, можно попробовать весовые коэффициенты поменять.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

А если размер ядра равным сигме устанавливать?

стало лучше, но почему то иногда теряется информация о цвете...изображение в каких-то областях становится чёрным..

ниже пример потери цвета

изменения в коде такие

int sm1 = MIN(ims.size().height,ims.size().width);

int sm2 = sm1/2,sm3=sm1/4;

if(!(sm1%2))sm1--;

if(!(sm2%2))sm2--;

if(!(sm3%2))sm3--;

GaussianBlur(ims,t1,Size(sm1,sm1),sm1);

GaussianBlur(ims,t2,Size(sm2,sm2),sm2);

GaussianBlur(ims,t3,Size(sm3,sm3),sm3);

post-2515-0-68977500-1332514401_thumb.jp

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Ну, вероятно надо преобразовать в HSV и работать с плоскостью интенсивности, тогда цвет должен сохраниться.

А может эквализацией гистограммы можно обойтись.

Вот что ориентировочно получится:

post-1-0-59119100-1332523041_thumb.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Ну, вероятно надо преобразовать в HSV и работать с плоскостью интенсивности, тогда цвет должен сохраниться.

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

post-2515-0-37499800-1332845426_thumb.jp

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Может часть значений в отрицательную область уходят?

Надо попробовать нормировать и сдвинуть значения. Чтобы все были в диапазоне от 0.0 до 1.0.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

ts.convertTo(ims,CV_64FC3,1.0/255.0);

так вроде бы это и переводит в диапазон от 0 до 1 в вещественные числа

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

не а, это умножает все на 1/255

получается

-x*1/255=-x/255;

отрицательная часть отсекается.

ЗЫ: Кажется, из-за непонимания этого преобразования картинки такие темные :)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

нормировать и сдвигать как я понимаю надо уже

Mat tr = (3*l1 - l2-l3-l4)/3;

сам tr.. как сдвинуть пусть у нас есть отрицательные элементы в матрице находим максимальное отклонение от 0 и сдвигаем всю матрицы на это значение тогда самое минимальное значение в матрице будет 0 так вроде бы...

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

tr'=(tr-min)/(max-min)

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
tr'=(tr-min)/(max-min)

Реализовал это преобразование качество действительно повысилось, но есть некие выбросы..

post-2515-0-29562400-1333014922_thumb.jp

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Картинка красивая, яркая, но неправильная :)

log(0) - не есть хорошо, надо обрабатывать это как особый случай.

Да, и еще наверное логично было бы, преобразовать изображение обратно, а Вы так и оперируете логарифмами.

Сделайте pow(I,tr); может и приводить к диапазону 0-1 не понадобится, хотя скорее всего, придется конечный результат приводить к диапазону 0-1.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

log(0) это да я что-то не подумал, а почему изображение в степень возводить ну каждый элемент изображения мы же по алгоритму логарифм брали.. для обратного преобразования как я понимаю нужна экспонента... pow(I,tr); не совсем понятно в какую степень возводить надо

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

так если Log (логарифм по основанию 10), то 10 в степень tr.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

получилось следующее в общем качество улучшилось... но есть интересное вот для улучшения качества после степени пришлось закомментировать

tr'=(tr-min)/(max-min)

//dx - максимум dm - минимум

/*etr = etr - Mat::ones(etr.size(),CV_64FC1)*dm;

etr = etr/(dx-dm);*/

и получил следующие не странности.. 1-ое изображение это оригинал, затем второе с закоментированной частью tr'=(tr-min)/(max-min) а третье когда комментарий убирал...

в 3-их изображениях фон более детальный что ли... хотя качество в общем хуже... а во 2-ых более контрастный наверно... яркий.. но детали что некоторые теряются не такие чёткие как раньше... а 3-тье изображение вообще почему то белое практически всё..

post-2515-0-17985300-1333114489_thumb.jp

post-2515-0-58059200-1333114501_thumb.jp

post-2515-0-72425800-1333114519_thumb.jp

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Все правильно, степени незачем приводить к интервалу 0-1.

К интервалу 0-1 надо привести результат (10^tr), возможно поэтому на последнем все белое, там все значения больше 1.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Думаю эти ссылки будут интересны: https://mywebspace.wisc.edu/acahn/cs534webpage/dir/retinex.html

http://cgm.computergraphics.ru/content/view/118

Матлабовский исходник с первой ссылки:

% An implementation of the Retinex algorithm baised off a paper by Robert Sobol (2004). 
% It aproximates an ever decreasing spiral by moving in alternatingly horizontal and vertical
% steps. This implementation goes arround five times at each level of the
% spiral. The outer levels actualy represent closer relationships, as the
% spiral tightens, because the mask values have propegated inwards, it
% represents a more global operator ie longer distance relations.

% Because our goal was to normalize images for facial recognition, not
% preserve exact perception baised relationships for a human. Not much care
% was put into the paramiters used. We simply tried a couple values and
% used one that was "good enough". Similarly, not all of the math is
% exactly faithful to the algorithm described by Sobol, some of it is
% "pretty much right" and seems to give good results. This is particularly
% true with rescaling the Retinex back to normal color space (from log
% space). We simply "undid" the log operation and the results seemed good
% in the grey space of images we are working on.

function y = Retinex(inImage)

inImage = double(inImage);

[m,n] = size(inImage);


for j=1:n % create a log version of input image
for i=1:m
if inImage(i,j) == 0 % aproximate 0 with a small number to avoid NaN issues
L(i,j) = 0.00001;
else
L(i,j)=log(inImage(i,j));
end
end
end

imCopy = L;
Maximum = max(L(:)); % maximum intensity value in the image
[sRow, sCol] = size(L);
shift = 2^(fix(log2(min(sRow, sCol)))-1); % initial place to begin
lastProduct = Maximum*ones(sRow, sCol); % initialize Last Product
while (abs(shift) >= 1) % iterate intil spiral is one unit large
for i = 1:5
currRow = 0; % move horizontaly
currCol = shift;
interProduct = lastProduct;
if (currRow + currCol > 0) % bottom right spiral part
interProduct((currRow+1):end, (currCol+1):end) = lastProduct(1:(end-currRow), 1:(end-currCol)) + imCopy((currRow+1):end, (currCol+1):end) - imCopy(1:(end-currRow), 1:(end-currCol)); % propigate inward (adding is log mulitply)
else
interProduct(1:(end+currRow), 1:(end+currCol)) = lastProduct((1-currRow):end, (1-currCol):end) + imCopy(1:(end+currRow),1:(end+currCol)) - imCopy((1-currRow):end, (1-currCol):end); % propigate inward (adding is log mulitply)
end
interProduct(interProduct > Maximum) = Maximum; % % if values excede the max image value, rescale
product = (interProduct + lastProduct)/2; % average with the previous Product
lastProduct = product;

currRow = shift; % move verticly
currCol = 0;
interProduct = lastProduct;
if (currRow + currCol > 0) % bottom right spiral part
interProduct((currRow+1):end, (currCol+1):end) = lastProduct(1:(end-currRow), 1:(end-currCol)) + imCopy((currRow+1):end, (currCol+1):end) - imCopy(1:(end-currRow), 1:(end-currCol)); % propigate inward (adding is log mulitply)
else
interProduct(1:(end+currRow), 1:(end+currCol)) = lastProduct((1-currRow):end, (1-currCol):end) + imCopy(1:(end+currRow),1:(end+currCol)) - imCopy((1-currRow):end, (1-currCol):end); % propigate inward (adding is log mulitply)
end

interProduct(interProduct > Maximum) = Maximum; % if values excede the max image value, rescale

product = (interProduct + lastProduct)/2; % average with the previous Product
lastProduct = product;

end
shift = -shift/2; % tighten spiral
end
y = product;

for j=1:n
for i=1:m
y(i,j)=exp(y(i,j)); % rescale output to be non logerithmic
end
end
maxVal = max(max(y));
for j=1:n
for i=1:m
y(i,j)= y(i,j)/ maxVal;
end
end

y = uint8(round(y * 255));

%figure, imshow(uint8(round(inImage))); This commented code shows the input
%figure, imshow(y); and output images in the acgoritm

[/code]

  • Like 1

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

задам тут вопрос, что если у меня есть N изображений(типа панорама) и мне надо выровнять между ними яркость и контраст?

допустим одно можно взять за основу или как то на автомате.

cvEqualizeHist кстати работает плохо на отдельном взятом изображении, так что просто применить это ко всем не подходит.

тут еще стандартные фотографии для тестов,хотя возможно где то они есть в большем разрешении.

http://www.cs.utah.edu/~sbasu/ipprojects/project1/

http://www.sci.utah.edu/~cscheid/spr05/imageprocessing/project1/

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Создайте учётную запись или войдите для комментирования

Вы должны быть пользователем, чтобы оставить комментарий

Создать учётную запись

Зарегистрируйтесь для создания учётной записи. Это просто!

Зарегистрировать учётную запись

Войти

Уже зарегистрированы? Войдите здесь.

Войти сейчас


  • Сейчас на странице   0 пользователей

    Нет пользователей, просматривающих эту страницу

×