Jump to content
Compvision.ru
Sign in to follow this  
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

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites

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

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

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

Share this post


Link to post
Share on other sites

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

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);

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

Share this post


Link to post
Share on other sites

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

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);

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

Share this post


Link to post
Share on other sites

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

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

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

Share this post


Link to post
Share on other sites

изменил на

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

Share this post


Link to post
Share on other sites

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

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

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

Share this post


Link to post
Share on other sites

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

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

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

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

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

Share this post


Link to post
Share on other sites

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

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

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

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

Share this post


Link to post
Share on other sites
Ну, вероятно надо преобразовать в HSV и работать с плоскостью интенсивности, тогда цвет должен сохраниться.

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

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

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites

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

получается

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

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

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

Share this post


Link to post
Share on other sites

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

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

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites
tr'=(tr-min)/(max-min)

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

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

Share this post


Link to post
Share on other sites

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

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

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

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites

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

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

Share this post


Link to post
Share on other sites

Думаю эти ссылки будут интересны: 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

Share this post


Link to post
Share on other sites

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

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

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

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

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

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

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

×