長曝光拍照,一般指曝光時間大於0.5s 的拍照,現在的 sensor 支持的長曝光時間都比較長了,比如 imx380 ,能支持到 64s。參考一般的手機一般會有 1s 2s 5s 10s 30s 等。
下面先說明下sensor 曝光時間。一般的單位是 多少行,所以設置下面的曝光時間是 linecount, 行數。
下面是高通平台的代碼中關於曝光時間的計算:
這個宏定義了 1s 中有多少個像素,那么一個像素的時間就是 1/vt_pik_clk
#define SENSOR_GET_VT_PIK_CLK(out_info) \
(uint32_t)((out_info)->line_length_pclk * (out_info)->frame_length_lines \
* (out_info)->max_fps)
1行的曝光時間
Tline = line_length_pclk * 1 / vt_pik_clk
那么設置下來的 linecount 表示的時間就是:
Tline * linecount
那么如果設置下來的曝光時間是 5s, 那換算能 linecount
5s = Tline * linecount
linecount = 5s / Tline
但是這個 linecout 在 sensor 的 spec 中有規定的, 比如 imx380 最大就是 16位數(兩個字節表示) 65535, 最大的 Tline 數 是 65535 - 22, 這個22 是sensor 定義的。
那么如果需要實現長曝光, 比如 5s ,用上面的公式計算出來(原創mojl)得到的 linecount 數就超過 65513 了,所以sensor 有了另外一個寄存器,是這樣定義的:
0x3100 CIT_LSHIFT //range 0 - 7 0: 表示非長曝光功能,
exposure_time = coarse_integ_time << LSHIFT
這樣同樣的 linecount , 曝光時間就被放大到原來的 2,4, 8, 16, 32, 64, 128 倍。
這樣我們就可以實現我們的長曝光功能了, 我們先設置一個 base 曝光時間,比如 0.5s, 其它的曝光時間是 這個 base 的倍數,然后結合上面的 LSHIFT 設置,就可以實現
任意大小的曝光時間了。舉個例子:
比如 設置 2s 曝光時間, 那么 2s/0.5s = 4 , 這樣 LSHIFT 正好設置能 2
那么 設置為 1.2s 怎么(原創mojl)計算呢, 1.2s / 0.5s = 2.4, 可以 通過 lshift = log2(2.4) 向上取整,然后在用原來的 linecount 除以 pow(2, lshift), 我設計了下面的代碼
base_linecount 對應 0.5s 時的 linecount,這個 0.5s 可以用換成其它值
div = (1.0 * current_linecount) / base_linecount;
lshift = (log2(div) + 0.9999);
current_linecount /= pow(2, lshift);
通過這幾行代碼,就把 長曝光對應的 很大的 linecount 值,分解成了一個合適的linecount 值 和 LSHIFT 的組合。在高通的代碼中,我們只要把 current linecount 值臨時修改掉,然后再把 0x3100 寫成
剛才計算出來的 LSHIFT。 記得 要把 那個原始的 linecount 值提前保存(原創mojl)出來,設置完sensor 之后還要恢復回去,因為在 照片的曝光信息中計算曝光時間需要那個原始的linecount 才能算出來長曝光的值的。
