实现过程

  1. 获取分块亮度统计数据

    – 用的memcp,是否可以直接用指针获取,用const保护;

  2. 计算分块亮度

    –用RGGB的平均亮度代替一个块的亮度

  3. 进行排序

    –是否会出现totalblockNum比总数大的问题

  4. 求平均亮度

  5. 设置亮度阈值

    –根据level获取相应百分比的块的亮度和序号

  6. 如果检测到当前亮度大于亮度阈值,CurFrameAvgLuma加上该分块的亮度

  7. 求亮区的平均亮度

  8. 将分块亮度统计数据乘以(亮区亮度和平均亮度的比值)

初步实现

原有的背光补偿等级仅仅调节的是亮区的范围,而亮区的程度并不能调节。
而且如果没有强光,也会对普通场景的亮度降低。为了不影响普通场景的亮度,可以采用对强光进行识别的算法。

首先用执法仪对强光和普通场景的直方图进行分析,场景1-3是普通场景,场景4-6是强光场景。发现强光场景的共同点是256的值很大,而255或者254却很小。同时要对RGB都进行分析,有的时候可能有一种光很亮,会误判成强光场景。
注意:可能不能直接用比例的方式去减小曝光时间,可能会出现不收敛的情况,导致上下波动。
强光和普通场景直方图

由于AE统计信息是将图像分块统计,也相当于一个缩小的直方图数据。
如果分块数据的话,强光场景下应该是强光区域有不少,同时暗光很多,由于成对数关系,因此区分应该很明显。
亮度在最大值亮度的50%-90%区间内,比例很少。
同时可以判断亮区的边界,如果边界大于一定的范围,则进行调整。

获取分块数据

static uint8_t aec_get_status = 0;
static int histo_count = 0;
if (property_get("persist.liqinxing.aec_stats.get", value, "") > 0){
if (strcmp("0", value) == 0){
aec_get_status = 1;
}
else{
if(aec_get_status){
aec_get_status = 0;
FILE *fp;
fp = fopen("/data/aec_stats.txt","a");
if(fp == NULL){
LOGE("cannot open file aec_stats.txt,please create it");
return false;
}
fprintf(fp, "No.%d sence h_num:%d v_num:%d",
histo_count++, aec_stats->bayer_stats.p_q3a_bg_stats->bg_region_h_num,
aec_stats->bayer_stats.p_q3a_bg_stats->bg_region_v_num);
fprintf(fp,"channel-r:\n");
for(int i = 0; i < 3888; i++)
fprintf(fp,"%d ", aec_stats->bayer_stats.p_q3a_bg_stats->bg_r_sum[i]);
fprintf(fp,"\n");
fprintf(fp,"channel-gr:\n");
for(int i = 0; i < 3888; i++)
fprintf(fp,"%d ", aec_stats->bayer_stats.p_q3a_bg_stats->bg_gr_sum[i]);
fprintf(fp,"\n");
fprintf(fp,"channel-gb:\n");
for(int i = 0; i < 3888; i++)
fprintf(fp,"%d ", aec_stats->bayer_stats.p_q3a_bg_stats->bg_gb_sum[i]);
fprintf(fp,"\n");
fprintf(fp,"channel-b:\n");
for(int i = 0; i < 3888; i++)
fprintf(fp,"%d ", aec_stats->bayer_stats.p_q3a_bg_stats->bg_b_sum[i]);
fprintf(fp,"\n");
//free point p
fclose(fp);
if(fp!=NULL)
fp=NULL;
}
}
}

但是出现问题,没有将数据打印出来
发现没有进入这个mask中,函数没有执行
因此放在aec_biz_stats_map中,这里是将stats数据map进aec算法模块的地方。
先用matlab进行处理;本文用的python处理

强光场景识别

  1. 计算相比于最强光强的比例

分为三个区间,暗区,中间区间,亮区,阈值为30%和80%

可以看到强光场景下暗区比例很大,中间区间较小,亮区类似

中位数

  1. 打印stats其他参数,了解参数的意义

    1. rmax,grmax,gbmax,bmax是一样的16383,是一个像素上最大亮度(14位)

    2. region_pixel_cnt=bg_region_height*bg_region_width 660=22*30

      1920/64=30 1080/48=22 因此总共的最大亮度为1e7 单体最大亮度为2703195,这符合实验得出的结论

    3. 直方图数据长度不一致,原来是4096,后来变成了256

      if (CAM_HISTOGRAM_STATS_SIZE == bhist_stats->num_bins) {
      memcpy(hist_data->hist_buf, stats_ptr,
      sizeof(hist->bayer_stats.r_stats.hist_buf));
      } else if (bhist_stats->num_bins > CAM_HISTOGRAM_STATS_SIZE &&
      bhist_stats->num_bins % CAM_HISTOGRAM_STATS_SIZE == 0) {
      /* Stats from HW have more bins and is a multiple of output bin size */
      /* scale bins by collapsing */
      uint32_t factor = bhist_stats->num_bins / CAM_HISTOGRAM_STATS_SIZE;
      uint32_t i, j;
      for (i = 0; i < CAM_HISTOGRAM_STATS_SIZE; i++) {
      for (j = 0; j < factor; j++) {
      hist_data->hist_buf[i] +=
      stats_ptr[i * factor + j];
      }
      }
      } else {
      ISP_ERR("CHANNEL_Y Size mismatch error bhist_stats->num_bins %d",
      bhist_stats->num_bins);
      return;
      }

num_bins是实际直方图数据的长度,由于这个长度是256的倍数,aec模块中的统计数据其实是将num_bins的直方图数据进行了压缩

这里用goto语句防止打开文件错误,没有执行下面原有的程序

通过控制增益的方式来控制图像的过曝和正常情况,对两种情况进行对比。

从过曝到正常,中位数降低很明显

可以看梯度–直方图或者分块亮度数据的梯度

注意:写入txt数据的时候不要连续写入两个\n,如果这样readlines的时候第一个字符会为空

可以以梯度来衡量

我只要找到强光的特点就行了,

首先有值很大的,直方图中255的值很大,而254的值很小

直方图后面160-254之间几乎是平的

检测到如果大于一定的值如80%的最大值,则进行权重的增大或者,或者直接对AE进行调整

原来的方法不行,因为亮的区域亮度已经满了,再增大也改变不了多少AE的效果,可以修改测光表的权重

框架式构图 –人手搭框架、框架拍景物

搜查AEC chromatix数据的调用位置

prase

自动调节可以算最高点80%和40%面积的比值作为他们的梯度

如果是sink端口,则不需要查看事件,取而代之的,只需转发事件并让下游模块处理它们并采取相应的行动

MCT_EVENT_DOWNSTREAM是接受上游的数据,向下游传递

chromatix数据是在stats模块进行最先一步的加载,分发给下游进行处理

PROBLEM:究竟什么算是下游模块?

动态修改权重:两种方案,去修改chromatix文件,让它重新加载一次;在chromatix数据向下发的时候修改它的值;由于第一种方法存在一个数据大量赋值的过程,可能会降低速度,甚至导致一大堆赋值问题,因此采用第二种方案。

想法:修改reload应该就可以让chromatix文件重载,这样不就不需要重启设备调参数了么

sensor_util_post_chromatix_event_downstream

cached

macro:宏指令

PROBLEM:只搜索到了event_module->module_event_data给其他模块赋值,没有搜索到谁赋值给它的?void*难道就是这么神奇?难道是在framework层进行赋值的?

func_tbl有三个方法:open/process/close 可以对chromatix进行操作

process中可以选择

SENSOR_SUB_MODULE_PROCESS_EVENT对sensor的每个子模块进行处理,chromatix也是在其中 如果要搜索子模块的处理函数可以搜索process的类型,如CHROMATIX_GET_PTR

第二个参数是对那个模块生效

PROBLEM:为什么加载chromatix的时候还要加载一堆模块

lru页面置换算法(Least Recently Used)

关于操作系统的内存管理,如何节省利用容量不大的内存为最多的进程提供资源,一直是研究的重要方向。而内存的虚拟存储管理,是现在最通用,最成功的方式—— 在内存有限的情况下,扩展一部分外存作为虚拟内存,真正的内存只存储当前运行时所用得到信息。这无疑极大地扩充了内存的功能,极大地提高了计算机的并发度。虚拟页式存储管理,则是将进程所需空间划分为多个页面,内存中只存放当前所需页面,其余页面放入外存的管理方式。

然而,有利就有弊,虚拟页式存储管理增加了进程所需的内存空间,却也带来了运行时间变长这一缺点:进程运行过程中,不可避免地要把在外存中存放的一些信息和内存中已有的进行交换,由于外存的低速,这一步骤所花费的时间不可忽略。因而,采取尽量好的算法以减少读取外存的次数,也是相当有意义的事情。

我的理解:这个算法就是去决定哪些数据该放在内存里,哪些数据该放在外存里。

PROBLEM:为什么替换了动态库文件,chromatix数据依旧没有生效

ANSWER: so文件是位于外存之中,而程序运行会先检测所需的数据内存中是否存在,如果存在就加载内存中的数据,如果不存在再去加载位于外存的数据。虚拟内存可以虚拟的扩大程序的内存空间,但是会出现一个问题,

BIZ:business model ,实际上就是控制层(业务逻辑层)。
解释:控制层的主要作用就是协调model层和view层直接的调用和转换。能够有效的避免请求直接进行数据库内容调用,而忽略了逻辑处理的部分。
实际上biz就起到了一个server服务的角色,很好的沟通了上层和下层直接的转换,避免在model层进行业务处理(代码太混乱,不利于维护)

由于每次reload的时候都要先查找hash值以及lru,不会重新重新读取动态库数据,因此在读取hash值的位置加一个函数,不进行hash值的读取

PROBLEM:为何直接用eztune中的代码可以生效

方法一:由于在reload chromatix文件的时候,会首先查找是否存在hash值以及lru;当程序运行时会将so文件中的数据加载到内存中,因此我们要删去原来的hash值和lru,重新load chromatix。

方法二:移植extune的代码

PROBLEM:没有对指针进行malloc,可以进行赋值么

由于测光权重表和bg_stats(grid)不是一一对应的关系,

还可以判断是否是运动光源

如果想要降低AE,有下面几种方法:

  1. 提升cur_luma:
  • 增加测光权重:但是不知道在哪一帧生效

  • 增大输入的stats —— aec使用bg_stats和直方图数据进行统计

  1. 减少target_luma

  2. 直接对写入寄存器的值进行操作

  • 对index进行操作

对光晕的检测;如果正常曝光,应该不会存在过大的光晕

设置两个阈值,饱和亮度和较亮的亮度。用饱和亮度的块数除较亮的亮度的块数得到ratio,可以得出光晕的比例。ratio越大,光晕越小。

但是实际上发现,普通场景较亮亮度色块很多,而很亮的很少;强光场景中,ratio反而大——解释:由于强光场景亮度区分的很大,较亮的色块就比较少,因此ratio值就比较大

难道说ratio值越小越正常?理论上如果光晕少的话,应该是较亮的区域很少,饱和的区域很多,理论上数字很大呀

直方图更加精确一点,为何不用直方图呢 –转用直方图

发现直方图更逼近想象中的曲线,光晕越小,ratio越大,但是不太好判断