ProgRoman 9 Жалоба Опубликовано March 23, 2012 Добрый день разбираюсь с алгоритмом 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-тье изображение везде похоже... хотя должно быть лучше... Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано March 23, 2012 Может с типами матриц проблема. Если там тип элемента целое, тем более если 8-ми битное целое то значения могут отсекаться. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ProgRoman 9 Жалоба Опубликовано March 23, 2012 изображения переводятся в вещественный тип img.convertTo(ts,CV_64FC3,1.0/255.0); и все действия происходят уже в нём... Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано March 23, 2012 кстати, обратите внимание на 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); остальное похоже верно Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ProgRoman 9 Жалоба Опубликовано March 23, 2012 что-то странно... изменил 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); ну все нечётные... и тоже ничего не изменилось... очень странно... почему так вроде бы должно меняться в зависимости от ядра гаусса... Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано March 23, 2012 Может размер ядра поменять, а не дисперсию? Или вручную ядро соорудить? PS^ Кстати четные лучше это у меня опечатка была.(я бы поставил 2,4,8) Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ProgRoman 9 Жалоба Опубликовано March 23, 2012 изменил на 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); поменял и размер ядра.. ну в два раза меньший стал... вроде бы есть проясненья лучше ли стало пока не знаю... но откуда-то возникает чёрная полоса... непонятно... может у этого алгоритма область применения есть ну где-то он не работает... Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано March 23, 2012 А если размер ядра равным сигме устанавливать? Что касается полосы, то похоже там краевые эффекты возникают. И еще, можно попробовать весовые коэффициенты поменять. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ProgRoman 9 Жалоба Опубликовано March 23, 2012 А если размер ядра равным сигме устанавливать? стало лучше, но почему то иногда теряется информация о цвете...изображение в каких-то областях становится чёрным.. ниже пример потери цвета изменения в коде такие 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); Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано March 23, 2012 Ну, вероятно надо преобразовать в HSV и работать с плоскостью интенсивности, тогда цвет должен сохраниться. А может эквализацией гистограммы можно обойтись. Вот что ориентировочно получится: Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ProgRoman 9 Жалоба Опубликовано March 27, 2012 Ну, вероятно надо преобразовать в HSV и работать с плоскостью интенсивности, тогда цвет должен сохраниться. перевёл, но что-то особо ничто не поменялось... уж не знаю как у авторов статей такие хорошие результаты выходят... Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано March 27, 2012 Может часть значений в отрицательную область уходят? Надо попробовать нормировать и сдвинуть значения. Чтобы все были в диапазоне от 0.0 до 1.0. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ProgRoman 9 Жалоба Опубликовано March 28, 2012 ts.convertTo(ims,CV_64FC3,1.0/255.0); так вроде бы это и переводит в диапазон от 0 до 1 в вещественные числа Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано March 28, 2012 не а, это умножает все на 1/255 получается -x*1/255=-x/255; отрицательная часть отсекается. ЗЫ: Кажется, из-за непонимания этого преобразования картинки такие темные Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ProgRoman 9 Жалоба Опубликовано March 28, 2012 нормировать и сдвигать как я понимаю надо уже Mat tr = (3*l1 - l2-l3-l4)/3; сам tr.. как сдвинуть пусть у нас есть отрицательные элементы в матрице находим максимальное отклонение от 0 и сдвигаем всю матрицы на это значение тогда самое минимальное значение в матрице будет 0 так вроде бы... Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано March 28, 2012 tr'=(tr-min)/(max-min) Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ProgRoman 9 Жалоба Опубликовано March 29, 2012 tr'=(tr-min)/(max-min) Реализовал это преобразование качество действительно повысилось, но есть некие выбросы.. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано March 29, 2012 Картинка красивая, яркая, но неправильная log(0) - не есть хорошо, надо обрабатывать это как особый случай. Да, и еще наверное логично было бы, преобразовать изображение обратно, а Вы так и оперируете логарифмами. Сделайте pow(I,tr); может и приводить к диапазону 0-1 не понадобится, хотя скорее всего, придется конечный результат приводить к диапазону 0-1. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ProgRoman 9 Жалоба Опубликовано March 29, 2012 log(0) это да я что-то не подумал, а почему изображение в степень возводить ну каждый элемент изображения мы же по алгоритму логарифм брали.. для обратного преобразования как я понимаю нужна экспонента... pow(I,tr); не совсем понятно в какую степень возводить надо Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано March 29, 2012 так если Log (логарифм по основанию 10), то 10 в степень tr. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ProgRoman 9 Жалоба Опубликовано March 29, 2012 ой точно что-то я сегодня туплю))) сейчас попробую)) Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
ProgRoman 9 Жалоба Опубликовано March 30, 2012 получилось следующее в общем качество улучшилось... но есть интересное вот для улучшения качества после степени пришлось закомментировать 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-тье изображение вообще почему то белое практически всё.. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано March 30, 2012 Все правильно, степени незачем приводить к интервалу 0-1. К интервалу 0-1 надо привести результат (10^tr), возможно поэтому на последнем все белое, там все значения больше 1. Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
Smorodov 579 Жалоба Опубликовано March 30, 2012 Думаю эти ссылки будут интересны: 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] 1 Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах
mrgloom 242 Жалоба Опубликовано April 2, 2012 задам тут вопрос, что если у меня есть N изображений(типа панорама) и мне надо выровнять между ними яркость и контраст? допустим одно можно взять за основу или как то на автомате. cvEqualizeHist кстати работает плохо на отдельном взятом изображении, так что просто применить это ко всем не подходит. тут еще стандартные фотографии для тестов,хотя возможно где то они есть в большем разрешении. http://www.cs.utah.edu/~sbasu/ipprojects/project1/ http://www.sci.utah.edu/~cscheid/spr05/imageprocessing/project1/ Поделиться сообщением Ссылка на сообщение Поделиться на других сайтах