В первая часть статьи Мы рассмотрели аппаратные блоки, из которых состоит видеопроцессор TI DM368, а теперь переходим к обзору наших алгоритмов и кода.
Весь аппаратный конвейер камеры работает в потоковом режиме, то есть сразу после обработки пикселя одним из блоков он передается следующему.
При включении программное обеспечение видеопроцессора устанавливает параметры и инициализирует все конвейеры, затем входит в непрерывный цикл обработки каждого кадра.
Если частота кадров сенсора составляет 30 кадров в секунду, то все необходимые функции будут вызываться 30 раз в секунду.
Теперь о принципах работы алгоритмов.
Суть алгоритма AE (автоэкспонирования) заключается в установке значений экспозиции, коэффициента умножения (усиления) и сдвига (сдвига) таким образом, чтобы на выходе была картинка с минимальным количеством переэкспонированных и затемненных участков.
Экспозиция или электронный затвор отвечает за количество света, попадающего на сенсор.
В современных датчиках оно может варьироваться от 1 000 000 до 1 микросекунды, поэтому нет необходимости использовать апертуру для ограничения интенсивности света.
Усиление и смещение служат для преобразования 12-битного формата в 8-битный и выбираются так, чтобы максимально использовать скудный 8-битный динамический диапазон.
Как правильно определить величину экспозиции? Мы попробовали несколько вариантов: ограничили сверху, то есть изменили экспозицию так, чтобы максимальное значение гистограммы было ниже определенного порога, и понизили нижнюю границу гистограммы до определенного значения.
Оба метода максимально используют весь динамический диапазон, но имеют один недостаток – в яркий солнечный день объекты в тени практически не видны.
Таким образом, чтобы увидеть тени, иногда лучше переэкспонировать определенные участки сцены.
Поэтому мы позволяем максимуму гистограммы свободно плавать и выбираем экспозицию так, чтобы среднее значение Y совпадало с выбранным нами значением.
Пришло время перейти к алгоритмам, начнем с автоэкспозиции:
1. Алгоритм начинается с получения статистических данных от Boxcar.
2. Затем по этим данным строится гистограмма и рассчитывается среднее значение Y.Uint32 w, h; Uint16 *box; status = DRV_ipipeGetBoxcarBuf(&bufId, 0); if(status!= OSA_SOK) { OSA_ERROR("ERROR: DRV_ipipeGetBoxcarBuf()\n"); return status; } pBufInfo = DRV_ipipeGetBoxcarBufInfo(bufId); DRV_ipipePutBoxcarBuf(bufId); box = pBufInfo->virtAddr; w = gDRV_ipipeObj.boxcarInfo.width; //Boxcar width h = gDRV_ipipeObj.boxcarInfo.height; // Boxcar height
Uint32 sz = w*h, sz4 = sz*4, hsz = 512;
Uint32 hist[hsz];
int GN[3] = { -16, 0, 16};
memset(hist, 0, sizeof(Uint32)*hsz);
//AE and WB
for(i=0; i < sz4; i+=4) {
r = box[i+2]>>2;
g = box[i+1]>>2;
b = box[i ]>>2;
RR += r; GG += g; BB += b;
Y += ((117*b + 601*g + 306*r)>>10);
hist[r>>3]++;
hist[g>>3]++;
hist[b>>3]++;
for(j=0; j < ns; j++) {
GB[j] += abs(g - (b*(512 + GN[j])>>9));
GR[j] += abs(g - (r*(512 + GN[j])>>9));
}
}
Y = Y/sz;
hn->Y.New = Y;
RR = RR/sz; GG = GG/sz; BB = BB/sz;
3. Найдите минимальное значение гистограммы.
//Find histogram min
sum = 0;
for(i=0; sum < hn->SatTh; i++) sum += hist[i];
hn->Hmin.New = i;
//Find histogram max
sum = 0;
for(i=hsz-1; sum < hn->SatTh; i--) sum += hist[i];
hn->Hmax.New = i;
4. Измените значение экспозиции.
Если среднее значение Y в два раза больше или меньше нашего порога YAE, то шаг изменения увеличивается, а если изменение Y меньше 20%, то экспозиция не меняется.
if(hn->Y.New) tmp = (hn->Y.New > hn->YAE) ? hn->Y.New*100/hn->YAE : hn->YAE*100/hn->Y.New;
if(tmp > 200){
if(hn->Y.New) hn->Exp.New = hn->Exp.Old*(hn->Y.New*2 + hn->YAE)/(hn->Y.New*3);
} else if(tmp > 20){
if(hn->Y.New > hn->YAE) hn->Exp.New = hn->Exp.Old*99/100;
else hn->Exp.New = hn->Exp.Old*100/99;
}
if(hn->Exp.New > hn->Exp.Range.max) hn->Exp.New = hn->Exp.Range.max;
5. Для плавного изменения изображения видеопотока усредняем несколько последних значений величин, используемых в алгоритме А?: #define HISTORY 30
int history = 0;
typedef struct IAEWBF_Param{
XDAS_Int32 Old; //Old value
XDAS_Int32 New; //New value
XDAS_Int32 Step; //The step of changing
XDAS_Int32 Avrg; //Sum of all history value
XDAS_Int32 Change; //Need for smooth change
XDAS_Int32 Hist[HISTORY]; //History array
XDAS_Int32 HistC; //History count
XDAS_Int32 NewA; //Avarage of value
IAEWBF_Range Range; //The range of value changes
}IAEWBF_Param;
int add_history(IAEWBF_Param *p)
{
int diff = 0;
p->Avrg += p->New;
p->Avrg -= p->Hist[p->HistC];
if(p->New) diff = abs(p->Hist[p->HistC] - p->New)*100/p->New;
p->Hist[p->HistC] = p->New;
p->HistC = (p->HistC == (HISTORY - 1)) ? 0 : p->HistC + 1;
p->NewA = (history < HISTORY) ? p->Avrg/history : p->Avrg/HISTORY;
return diff;
}
history++;
add_history(&hn->Hmax);
add_history(&hn->Hmin);
add_history(&hn->Y);
6. И наконец, последний этап А? – настройка усиления и смещения.
На выходе мы ориентируемся на то, чтобы среднее значение Y попадало примерно в середину выходного диапазона HmaxTh. С учетом гамма-коррекции и эксперимента это значение равно hn-> HmaxTh/4. //Change the offset and gain
hn->Offset.New = hn->Hmin.NewA;
if(hn->Y.NewA - hn->Offset.New) hn->GIFIF.New = ((hn->HmaxTh/4)*512)/(hn->Y.NewA - hn->Offset.New);
up = hn->Hmax.NewA*hn->GIFIF.New>>9;
if((up < hn->HmaxTh) && (hn->Y.NewA - hn->Offset.New))
if(hn->Y.NewA - hn->Offset.New) hn->GIFIF.New = (((hn->HmaxTh*2 - up)/4)*512)/(hn->Y.NewA - hn->Offset.New);
//Check gain range
hn->GIFIF.New = hn->GIFIF.New > hn->GIFIF.Range.max ? hn->GIFIF.Range.max : hn->GIFIF.New;
hn->GIFIF.New = hn->GIFIF.New < hn->GIFIF.Range.min ? hn->GIFIF.Range.min : hn->GIFIF.New;
Теперь давайте перейдем к баланс белого (ВБ).
Существует множество алгоритмов его настройки; мы используем 2 из них в нашей камере.
В дневном режиме минимизируем локальные отклонения цвета по всей картинке.
Поскольку белый, черный и серый имеют R = G = B, а белый также является самым ярким в сцене, его минимизация вносит наибольший вклад в общую энергию.
Ночью при открытом инфракрасном фильтре используем серый мир алгоритм, то есть мы просто выравниваем средние значения цвета.
В основном цикле при заполнении гистограмм ищем значения суммарных отклонений красного GR[j] и синего GB[j] от зеленого и находим направление движения к минимуму: if(IRcutClose){
min = GR[0]; minr = 0;
for(j=1; j < ns; j++){
if(GR[j] < min) { min = GR[j]; minr = j; }
}
min = GB[0]; minb = 0;
for(j=1; j < ns; j++){
if(GB[j] < min) { min = GB[j]; minb = j; }
}
if(minr != 1) hn->Rgain.New = hn->Rgain.Old + (GN[minr]*hn->Rgain.Old/512);
if(minb != 1) hn->Bgain.New = hn->Bgain.Old + (GN[minb]*hn->Bgain.Old/512);
} else {
//Night AW mode
if(RR) hn->Rgain.New = GG*hn->Rgain.Old/RR;
if(BB) hn->Bgain.New = GG*hn->Bgain.Old/BB;
}
У разных сенсоров совершенно разные отклонения цвета, но алгоритм всегда работает корректно в течение дня, пример сенсора SONY IMX136 до и после баланса белого:
Давайте остановимся немного на гамма-коррекция , это необходимо для того, чтобы уравнять чувствительность камеры и человеческого глаза.
Как правило, функция преобразования имеет степенную зависимость, но мы используем другую; по нашим субъективным ощущениям, оно лучше отражает реальность:
gam[i] = out*((log(i + in*a) - log(in*a))/(log(in + in*a) - log(in*a)));
где in — максимум входного диапазона,
out - максимальный выходной диапазон,
а — коэффициент кривизны (в нашем случае 0,05 лучше всего подходит для разных сцен)
При инициализации системы мы загружаем эту кривую в таблицу LUT и каждый кадр проходит через нее.
Пример того, как гамма-коррекция меняет картинку:
Отдельно хотелось бы отметить возможности наших камер, которые встречаются не очень часто.
Во-первых, переход на меньшую частоту кадров при уменьшении освещенности, во-вторых, в ночном режиме, когда инфракрасный фильтр убран, камера может оставаться в цвете.
Исходный код прошивки для наших камер доступен через систему контроля версий Git по адресу: git://sigrand.ru/sigticam.git .
Чтобы загрузить исходный код, вы можете использовать следующую команду: git clone git://sigrand.ru/sigticam.git .
Вышеуказанные алгоритмы расположены в каталоге sigticam/sigticam/platform/ti_dm368/appro2/av_capture/framework/alg/src/aewbf_sig. Вы можете посмотреть прямую трансляцию с наших, и не только наших, камер.
Здесь .
В следующей статье мы рассмотрим, как реализован автофокус в наших камерах.
и что такое широкий динамический диапазон HDR или WDR. .
Теги: #видеонаблюдение #Алгоритмы #DM368 #автоэкспозиция #баланс белого #Автофокус #3А #гамма-коррекция #hdr #wdr #Алгоритмы
-
Генерация Раскладов Для Карточных Игр
19 Oct, 24 -
Бесплатный Редактор Шрифтов Html5.
19 Oct, 24