一、基本概念
- 壞點:在sensor的制造過程中儡羔,無法保證每個sensor中的像素點都是完好的。一半會存在較少的一些像素會存在損壞的情況。
- 壞點的一些類型:
2.1 亮度 -- 一直保持高亮的點
2.2 暗點 -- 一直保持黑暗的點
2.3 灰點 -- 在一定的范圍內(nèi)正常场梆,但是超過一定的閾值即無法顯示正常 - 處理的方法
3.1 靜態(tài)壞點標(biāo)定法
即在全亮的環(huán)境中把暗點標(biāo)記出來,在全黑的環(huán)境下把亮點標(biāo)記出來纯路。用靜態(tài)表把壞點存放起來或油,再進行標(biāo)定。
好處是精確感昼,壞處是需要每個批次都需要校準(zhǔn)以及需要比較大的空間來放靜態(tài)表装哆。
3.2 動態(tài)壞點標(biāo)定法
即動態(tài)的識別判斷出壞點,然后進行矯正定嗓。好處是不用進行每個sensor進行標(biāo)定蜕琴。往往通過以下兩種方式進行對壞點的識別。1. 梯度的方式宵溅,通過當(dāng)前點像素的與附近同色像素的梯度差異來判斷出是否為壞點凌简。 2.色差的方式,根據(jù)一般現(xiàn)實世界中的顏色過渡比較平緩恃逻,所以有一些會根據(jù)g/r,g/b的比例或者差值來進行判別出壞點雏搂。
二藕施、一個簡單的動態(tài)壞點標(biāo)定法
- CN103297717B上的插值方法
1. 使用5*5的區(qū)域來獲取差異性,T值為區(qū)域中相同元素的值,g為菱形凸郑,r/b為正方形裳食。
dN = |T1 - T2| + |T2 - T3| + ... + |Tn - T1|
2. 計算壞點的門限閾值,DPC與拍攝中的感光度有關(guān)
DPC_TH= dN * DPC
3. 計算當(dāng)前值與領(lǐng)域的值的差異
DIFF = dC = |T - T1| + |T - T2| + ... + |T - Tn|
4. 如果DIFF大于DPC_TH則為壞點芙沥,進入5
5. 計算出邊緣的梯度诲祸,計算出水平和垂直的梯度以下圖G為中心來示例。
VG=|G3-G7|+|R0-R1|
HG=|G1-G5|+|B0-B1|
6. 根據(jù)梯度來計算出待插值的方向
6.1 如果VG<HG×DR,DR為預(yù)設(shè)的邊緣補償?shù)谋壤? AVG_V=(G3+G7)/2
6.2 如果HG<VG×DR
AVG_H=(G1+G5)/2
6.3 如果VG≧HG×DR&HG≧VG×DR
AVG_T=(G1+G2+G3+G4+G5+G6+G7+G8)/8
void xxx_dpc_lianyong_run(void* handle)
{
if (NULL == handle)
{
printf("xxx_dpc_chen_run handle is null! \n");
return;
}
xxx_isp_handle* isp_handle = (xxx_isp_handle*)handle;
u16 Width = isp_handle->raw_handle.raw_wide;
u16 Height = isp_handle->raw_handle.raw_high;
const u8 Green = 1 - ((isp_handle->demosaic_handle.red_x + \
isp_handle->demosaic_handle.red_y) & 1);
u16* data = isp_handle->raw_handle.data;
u16 search_step = isp_handle->dpc_handle.dpc_chan_handle.search_step;
u16* ptr;
ptr = (u16*)malloc(Width * Height * sizeof(u16));// 全部按16位讀出來
if (ptr == NULL) return ;
memcpy(ptr, data, Width * Height * sizeof(u16));
u16 x, y;
u16 dN,dpc_th,diff;
u16 vg, hg;
u32 hist_g = 0;
u32 hist_g_v = 0;
u32 hist_g_h = 0;
u32 hist_g_t = 0;
u32 hist_rb_v = 0;
u32 hist_rb_h = 0;
u32 hist_rb_t = 0;
u32 hist_rb = 0;
// 暫時先不管最外層的問題而昨,不考慮邊界
for (y = search_step + 1; y < Height - search_step - 1; y++)
{
for (x = search_step + 1; x < Width - search_step - 1; x++)
{
// green取菱形
if (((x + y) & 1) == Green)
{
dN = abs(data[y * Width + x - 2] - data[(y - 1) * Width + x - 1]) + \
abs(data[(y - 1) * Width + x - 1] - data[(y - 2) * Width + x]) + \
abs(data[(y - 2) * Width + x] - data[(y - 1) * Width + x + 1]) + \
abs(data[(y - 1) * Width + x + 1] - data[(y)*Width + x + 2]) + \
abs(data[(y)*Width + x + 2] - data[(y + 1) * Width + x + 1]) + \
abs(data[(y + 1) * Width + x + 1] - data[(y + 2) * Width + x]) + \
abs(data[(y + 2) * Width + x] - data[(y + 1) * Width + x - 1]) + \
abs(data[(y + 1) * Width + x - 1] - data[(y)*Width + x - 2]);
diff = abs(data[y * Width + x] - data[(y - 1) * Width + x - 1]) + \
abs(data[y * Width + x] - data[(y - 2) * Width + x]) + \
abs(data[y * Width + x] - data[(y - 1) * Width + x + 1]) + \
abs(data[y * Width + x] - data[(y)*Width + x + 2]) + \
abs(data[y * Width + x] - data[(y + 1) * Width + x + 1]) + \
abs(data[y * Width + x] - data[(y + 2) * Width + x]) + \
abs(data[y * Width + x] - data[(y + 1) * Width + x - 1]) + \
abs(data[y * Width + x] - data[(y)*Width + x - 2]);
dpc_th = dN * isp_handle->dpc_handle.dpc_lianyong_handle.dpc;
if (diff > dpc_th)
{
hist_g++;
vg = abs(data[(y - 2) * Width + x] - data[(y + 2) * Width + x]) + \
abs(data[(y - 1) * Width + x] - data[(y + 1) * Width + x]);
hg = abs(data[(y) * Width + x - 2] - data[(y ) * Width + x + 2]) + \
abs(data[(y ) * Width + x - 1] - data[(y) * Width + x] + 1);
if (vg * 100 < hg * isp_handle->dpc_handle.dpc_lianyong_handle.dr)
{
hist_g_v++;
ptr[(y)*Width + x] = (data[(y - 2) * Width + x] + data[(y + 2) * Width + x]) / 2;
}
else if (hg * 100 < vg * isp_handle->dpc_handle.dpc_lianyong_handle.dr)
{
hist_g_h++;
ptr[(y)*Width + x] = (data[(y)*Width + x - 2] + data[(y)*Width + x + 2]) / 2;
}
else
{
hist_g_t++;
ptr[(y)*Width + x] = (data[y * Width + x - 2] + data[(y - 1) * Width + x - 1] + \
data[(y - 2) * Width + x] + data[(y - 1) * Width + x + 1] + \
data[(y)*Width + x + 2] + data[(y + 1) * Width + x + 1] + \
data[(y + 2) * Width + x] + data[(y + 1) * Width + x - 1])/8;
}
}
}// r/b取正方形
else
{
dN = abs(data[y * Width + x - 2] - data[(y - 2) * Width + x - 2]) + \
abs(data[(y - 2) * Width + x - 2] - data[(y - 2) * Width + x]) + \
abs(data[(y - 2) * Width + x] - data[(y - 2) * Width + x + 2]) + \
abs(data[(y - 2) * Width + x + 2] - data[(y)*Width + x + 2]) + \
abs(data[(y)*Width + x + 2] - data[(y + 2) * Width + x + 2]) + \
abs(data[(y + 2) * Width + x + 2] - data[(y + 2) * Width + x]) + \
abs(data[(y + 2) * Width + x] - data[(y + 2) * Width + x - 2]) + \
abs(data[(y + 2) * Width + x - 2] - data[(y)*Width + x - 2]);
diff = abs(data[y * Width + x] - data[(y - 2) * Width + x - 2]) + \
abs(data[y * Width + x] - data[(y - 2) * Width + x]) + \
abs(data[y * Width + x] - data[(y - 2) * Width + x + 2]) + \
abs(data[y * Width + x] - data[(y)*Width + x + 2]) + \
abs(data[y * Width + x] - data[(y + 2) * Width + x + 2]) + \
abs(data[y * Width + x] - data[(y + 2) * Width + x]) + \
abs(data[y * Width + x] - data[(y + 2) * Width + x - 2]) + \
abs(data[y * Width + x] - data[(y)*Width + x - 2]);
dpc_th = dN * isp_handle->dpc_handle.dpc_lianyong_handle.dpc;
if (diff > dpc_th)
{
hist_rb++;
vg = abs(data[(y - 2) * Width + x] - data[(y + 2) * Width + x]) + \
abs(data[(y - 1) * Width + x] - data[(y + 1) * Width + x]);
hg = abs(data[(y)*Width + x - 2] - data[(y)*Width + x + 2]) + \
abs(data[(y)*Width + x - 1] - data[(y)*Width + x] + 1);
if (vg * 100 < hg * isp_handle->dpc_handle.dpc_lianyong_handle.dr)
{
hist_rb_v++;
ptr[(y)*Width + x] = (data[(y - 2) * Width + x] + data[(y + 2) * Width + x]) / 2;
}
else if (hg * 100 < vg * isp_handle->dpc_handle.dpc_lianyong_handle.dr)
{
hist_rb_h++;
ptr[(y)*Width + x] = (data[(y)*Width + x - 2] + data[(y)*Width + x + 2]) / 2;
}
else
{
hist_rb_t++;
ptr[(y)*Width + x] = (data[(y - 2) * Width + x - 2] + data[(y - 2) * Width + x] + \
data[(y - 2) * Width + x + 2] + data[(y)*Width + x + 2] + \
data[(y + 2) * Width + x + 2] + data[(y + 2) * Width + x] + \
data[(y + 2) * Width + x - 2] + data[(y)*Width + x - 2]) / 8;
}
}
}
}
}
memcpy(data, ptr, Width * Height * sizeof(u16));
printf("hist_g = %d;hist_rb = %d\n", hist_g, hist_rb);
printf("hist_g_v = %d;hist_g_h = %d;hist_g_t = %d\n", hist_g_v, hist_g_h, hist_g_t);
printf("hist_rb_v = %d;hist_rb_h = %d;hist_rb_t = %d\n", hist_rb_v, hist_rb_h, hist_rb_t);
}
感覺整體效果還可以,基本上該去的壞點都去掉了,邏輯簡單救氯,看起來很舒服。
修改DR和DPC的強度值就可以調(diào)整效果了歌憨。DPC越小着憨,可以檢測到越多的壞點。DR越小則越容易做中值濾波务嫡,可以應(yīng)對多個壞點的簇甲抖,也會帶來一些細(xì)節(jié)的模糊。
待完成的植袍。色比的方式惧眠。多幀的時候,防止壞點閃爍于个。
多說一句氛魁,在對于tone_curve等提亮之后會存在一部分的壞點出來,所以去壞點放的位置是不是在提亮之后會合適一點呢厅篓?