Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.71/41: Рейтинг темы: голосов - 41, средняя оценка - 4.71
9 / 9 / 4
Регистрация: 25.09.2011
Сообщений: 23

Выравнивание освещения (Retinex)

25.09.2011, 10:14. Показов 7610. Ответов 8
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Доброго времени суток. Требуется реализовать метод, который выравнивает освещение на входной картинке по методу single scale retinex. Проблема в том, что я никак не могу понять сам алгоритм. Применяю фнч (использую фильтр Гаусса с сигмой 5, шириной 10) чтобы получить "освещенность" картинки. Что делать дальше? В интернете нашел только формулы I'=logI-log(G*I) , где I-исходное изображение, G*I - это, как я понял, изображение после размытия гауссом, I' результат. Только вот если применять эти формулы поканально, типа I'(x,y)=logI(x,y)-log(G*I(x,y)) для r,g,b, получается ерунда.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
25.09.2011, 10:14
Ответы с готовыми решениями:

Устранение неравномерности освещения на изображении
Всем добра! Столкнулся со следующей проблемой. Есть изображение... Работаю на шарп+OpenCv, но знаний библиотеки не хватает. ...

Регулятор освещения
Добрые люди, здравствуйте! Очень понравился сайт и форум, прочитал почти все, до чего до брался...получил "просвящение" :) ...

Убрать освещения
Доброго времени суток, как можно убрать освещения, т.е. что бы блок был со всех сторон одинаково светлый, что бы не было темных мест...

8
5 / 5 / 2
Регистрация: 31.07.2010
Сообщений: 62
13.10.2011, 05:59
Если решил проблему - дай знать. Буду очень признателен.
0
1 / 1 / 1
Регистрация: 04.12.2010
Сообщений: 67
06.04.2012, 14:43
привет если проблема решена, буду тоже очень признателен если напишите или в личку или тут каким образом удалось
0
5 / 5 / 2
Регистрация: 31.07.2010
Сообщений: 62
06.04.2012, 17:47
Цитата Сообщение от ProgRoman Посмотреть сообщение
привет если проблема решена, буду тоже очень признателен если напишите или в личку или тут каким образом удалось
проблема решена. алгоритм применяется к яркостным компонентам для выравнивания освещения.
I'(x, y) = 255*log10( I(x, y)/G(x, y) ) + 127.5

I - яркость пикселя
G - значение Гауссиана в пикселе
I' - новая яркость пикселя

Яркостную компоненту можно получить при переводе изображения в пространство YCrCb
0
1 / 1 / 1
Регистрация: 04.12.2010
Сообщений: 67
07.04.2012, 00:21
Большое спасибо перешёл из RGB в YCrCb выбрал только канал Y и работал с ним получилось следующее ниже прикреплены картинки не совсем ясно почему такие эффекты возникают...
Изображения
  
0
5 / 5 / 2
Регистрация: 31.07.2010
Сообщений: 62
07.04.2012, 08:21
Явная ошибка в реализации. Исходное изображение у нас grayscale, при переводе в YCrCb хроматические компоненты должны равняться 0. Ретинекс работает только с Y, значит после обратного преобразования изображения в RGB. оно тоже должно быть grayscale.
Скорее всего при реализации вы использовали opencv и забыли сделать обратное преобразование в RGB
0
1 / 1 / 1
Регистрация: 04.12.2010
Сообщений: 67
07.04.2012, 19:32
что-то пока всё равно не понимаю где ошибка... пишу действительно с применением OpenCV и работаю только с одним каналом..
ниже код
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
Mat Retinex(const Mat &img)
{
    Mat im;
    Mat t1,t2,t3,t4,t5,res,tm1,tm2;
 
    cvtColor(img,im,CV_BGR2YCrCb);
    
    Mat i3[3];
    split(im,i3);
    Mat ims1 = i3[0].clone();
    Mat ims;
    ims1.convertTo(ims,CV_64FC1,1.0);
 
    //
    for(int i=0; i<ims.rows; i++)
    {
        for(int j=0; j<ims.cols; j++)
        {
            double d = ims.at<double>(i,j); 
            if(d==0)
            {
                ims.at<double>(i,j) +=0.00001;
            }
        }
    }
    //
 
    int sm1 = MIN(ims.size().height,ims.size().width);
    int sm2 = sm1/2;
    int sm3=sm1/4;
 
    if(!(sm1%2))sm1--;
    if(!(sm2%2))sm2--;
    if(!(sm3%2))sm3--;
 
    if(sm1==0)sm1=1;
    if(sm2==0)sm2=1;
    if(sm3==0)sm3=1;
 
    GaussianBlur(ims,t1,Size(sm1,sm1),sm1);
    GaussianBlur(ims,t2,Size(sm2,sm2),sm2);
    GaussianBlur(ims,t3,Size(sm3,sm3),sm3);
 
    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;
 
    Mat etr;
    exp(tr,etr);
 
    double dm=10000000,dx=-100000000;
 
    for(int i=0; i<etr.rows; i++)
    {
        for(int j=0; j<etr.cols; j++)
        {
            double d = etr.at<double>(i,j);
            if(d<dm)dm=d;
            if(d>dx)dx=d;
        }
    }       
 
    etr = etr - Mat::ones(etr.size(),CV_64FC1)*dm;
    etr = etr/(dx-dm);
    etr = etr*255;
    //etr+=127.5;
 
    etr.convertTo(tm2,CV_8UC1,1.0);
    i3[2]=tm2.clone();
    
    merge(i3,3,tm1);
    cvtColor(tm1,res,CV_YCrCb2BGR);
 
    return res;
}
0
5 / 5 / 2
Регистрация: 31.07.2010
Сообщений: 62
09.04.2012, 08:59
Отправляю свой код
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#region Single Scale Retinex
 
        public static Image<Bgr, byte> SingleScaleRetinex(this Image<Bgr, byte> img, int gaussianKernelSize, double sigma)
        {
            var radius = gaussianKernelSize / 2;
            var kernelSize = 2 * radius + 1;
 
            var ycc = img.Convert<Ycc, byte>();
 
            // Формируем ядро Гауссиана
            var sum = 0f;
            var gaussKernel = new float[kernelSize * kernelSize];
            for (int i = -radius, k = 0; i <= radius; i++, k++)
            {
                for (int j = -radius; j <= radius; j++)
                {
                    var val = (float)Math.Exp(-(i * i + j * j) / (sigma * sigma));
                    gaussKernel[k] = val;
                    sum += val;
                }
            }
            for (int i = 0; i < gaussKernel.Length; i++)
                gaussKernel[i] /= sum;
 
            // Работаем только с яркостным каналом
            var gray = new Image<Gray, byte>(ycc.Size);
            CvInvoke.cvSetImageCOI(ycc, 1);
            CvInvoke.cvCopy(ycc, gray, IntPtr.Zero);
 
            // Размеры изображения
            var width = img.Width;
            var height = img.Height;
 
            var bmp = gray.Bitmap;
            var bitmapData = bmp.LockBits(new Rectangle(Point.Empty, gray.Size), ImageLockMode.ReadWrite, PixelFormat.Format8bppIndexed);
 
            unsafe
            {
                for (var y = 0; y < height; y++)
                {
                    var row = (byte*)bitmapData.Scan0 + y * bitmapData.Stride;
                    for (var x = 0; x < width; x++)
                    {
                        var color = row + x;
 
                        float val = 0;
 
                        for (int i = -radius, k = 0; i <= radius; i++, k++)
                        {
                            var ii = y + i;
                            if (ii < 0) ii = 0; if (ii >= height) ii = height - 1;
 
                            var row2 = (byte*)bitmapData.Scan0 + ii * bitmapData.Stride;
                            for (int j = -radius; j <= radius; j++)
                            {
                                var jj = x + j;
                                if (jj < 0) jj = 0; if (jj >= width) jj = width - 1;
 
                                val += *(row2 + jj) * gaussKernel[k];
 
                            }
                        }
 
                        var newColor = 127.5 + 255 * Math.Log(*color / val);
                        if (newColor > 255)
                            newColor = 255;
                        else if (newColor < 0)
                            newColor = 0;
                        *color = (byte)newColor;
                    }
                }
            }
            bmp.UnlockBits(bitmapData);
 
            CvInvoke.cvCopy(gray, ycc, IntPtr.Zero);
            CvInvoke.cvSetImageCOI(ycc, 0);
 
            return ycc.Convert<Bgr, byte>();
 
        }
 
        #endregion
0
0 / 0 / 0
Регистрация: 05.07.2012
Сообщений: 7
06.11.2013, 18:45
dr.kernel, попробовал вашу функцию, не работает
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
06.11.2013, 18:45
Помогаю со студенческими работами здесь

Сложение освещения
Как в пиксельном шейдере сложить освещение от нескольких источников света ? по классике: ... float4 main(PS_INPUT In): COLOR ...

ON/OFF наружного освещения
Доброго времени суток :) Есть желание сделать включение/выключение наружного освещения дома от времени суток. На сколько будет...

Настройка освещения
Всем привет.Столкнулся с проблемой освещения.В помещении у меня есть 3 источника света.Они светят очень тускло и если увеличить радиус...

Неправильный расчет освещения
Хотел разобраться самостоятельно, но видимо не удастся. Пытался реализовать систему множественного освещения. Оно считается неправильно....

Вычисление карты освещения
Приветствую. Имеется следующая задача - необходимо вычислить карту освещения. На входе мы получаем квадратную матрицу чисел, где 0 -...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
9
Ответ Создать тему
Новые блоги и статьи
Блокировка документа от изменений, если он открыт у другого пользователя
Maks 08.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа, разработанного в конфигурации КА2. Задача: запретить редактирование документа, если он открыт у другого пользователя. / / . . .
Система безопасности+живучести для сервера-слоя интернета (сети). Двойная привязка.
Hrethgir 08.04.2026
Далее были размышления о системе безопасности. Сообщения с наклонным текстом - мои. А как нам будет можно проверить, что ссылка наша, а не подделана хулиганами, которая выбросит на другую ветку и. . .
Модель ЗдрввоСохранения 7: больше работников, больше ресурсов.
anaschu 08.04.2026
работников и заданий может быть сколько угодно, но настроено всё так, что используется пока что только 20% kYBz3eJf3jQ
Дальние перспективы сервера - слоя сети с космологическим дизайном интефейса карты и логики.
Hrethgir 07.04.2026
Дальнейшее ближайшее планирование вывело к размышлениям над дальними перспективами. И вот тут может быть даже будут нужны оценки специалистов, так как в дальних перспективах всё может очень сильно. . .
Горе от ума
kumehtar 07.04.2026
Эта мне ментальная установка, что вот прямо сейчас, мол, мне для полного счастья не хватает (нужное вписать), и когда я этого достигну - тогда и полный кайф. Одна из самых сильных ловушек на пути. . . .
Использование значений реквизитов справочника в документе, с определенными условиями и правами
Maks 07.04.2026
1. Контроль срока действия договора Алгоритм из решения ниже реализован на примере нетипового документа "ЗаявкаНаРаботу", разработанного в конфигурации КА2. Задача: уведомлять пользователя, если. . .
Доступность команды формы по условию
Maks 07.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: сделать доступной кнопку (команда формы "ЗавершитьСписание") при. . .
Уведомление о неверно выбранном значении справочника
Maks 06.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "НарядПутевка", разработанного в конфигурации КА2. Задача: уведомлять пользователя, если в документе выбран неверный склад. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru