高通sensor坐标轴的转换

本文介绍高通sensor系统中坐标系转换方法。可在adsp或dd driver里转换,转换信息存于nv。文中给出转换对应关系、代码示例,还提及sensor(加速度、陀螺仪和地磁)坐标系转换参数存储位置,以及如何请求读取这些nv参数。

原文:https://blog.youkuaiyun.com/ranfei_870406/article/details/17762251 

高通的sensor系统中,可以让我们在adsp中转换sensor的坐标系。由于sensor贴的位置,可能与我们的android要求的坐标系不同,那么需要转换,有的芯片可以向里面写寄存器,让芯片来帮我们转换,高通的也可以在dd driver里面来进行转换。
这里转换坐标系的信息,我们可以保存到nv里面,也就是那个sns_reg文件里面,在初始化的时候会通过init函数传递进来:
sns_ddf_status_e (*init)(
        sns_ddf_handle_t*         dd_handle_ptr,
        sns_ddf_handle_t         smgr_handle,
        sns_ddf_nv_params_s*   nv_params,
        sns_ddf_device_access_s   device_info[],
        uint32_t                 num_devices,
        sns_ddf_memhandler_s*     memhandler,
        sns_ddf_sensor_e**       sensors,
        uint32_t*                 num_sensors
);
我们先讲讲使用情况,是如何对应的。
传递进来的参数如下:{1, 2, 3},那么raw data就按照x,y,z 传递上去;
如果传递进来的参数是:{-1, 2, -3}, 那么raw data 就按照 -x, y, -z传递上去;
如果传递进来的参数是:{-2, 3, -1}, 那么 x 对应的是raw数据的 -y, y 对应的是raw数据的 z, 在对应的是raw数据的 -x
总结一下他们的对应关系是, 数字代表的是raw数组里面的索引,正负符号代表了数据是否反向。

下面看看代码:

void sns_ddf_axes_map_init(sns_ddf_axes_map_s* axes_map, uint8_t* registry_data)
{
    const int8_t* registry_axes_map = (int8_t*)registry_data;

    if(!sns_ddf_axes_map_is_reg_data_valid(registry_axes_map))
    {
        // Default to no change in orientation.
        axes_map->indx_x = 0;
        axes_map->indx_y = 1;
        axes_map->indx_z = 2;
        axes_map->sign_x = 1;
        axes_map->sign_y = 1;
        axes_map->sign_z = 1;
        return;
    }

    axes_map->sign_x = SIGN_OF_INT8(registry_axes_map[0]);
    axes_map->indx_x = registry_axes_map[0] * axes_map->sign_x - 1;

    axes_map->sign_y = SIGN_OF_INT8(registry_axes_map[1]);
    axes_map->indx_y = registry_axes_map[1] * axes_map->sign_y - 1;

    axes_map->sign_z = SIGN_OF_INT8(registry_axes_map[2]);
    axes_map->indx_z = registry_axes_map[2] * axes_map->sign_z - 1;
}
// Return -1 if an int8_t is negative, or +1 otherwise.
#define SIGN_OF_INT8(x) (1 | ((x) >> 7))
这个宏定义就只是取出了符号,代表正负,后面使用。
所以如果传递的是 -3,那么 axes_map->sign_x = -1;
这些索引index呢,我们可以算算,如果是 -1或者1, 就是 (1*1) - 1 = 0;或者 (-1 * -1) - 1 = 0;
同样的道理,如果是 -3或者3,那么就是 (3 * 1) - 1 = 2;或者 (-3 * -1) - 1 = 2;
这些index就是将来在raw数组里面寻找数据的数组下标了。

那我们在传递数据的时候,在调用了如下的函数:

void sns_ddf_map_axes(sns_ddf_axes_map_s* axes_map, q16_t* device_data)
{
    static q16_t tmp[3];

    SNS_OS_MEMCOPY(tmp, device_data, sizeof(tmp));
    device_data[0] = tmp[axes_map->indx_x] * axes_map->sign_x;
    device_data[1] = tmp[axes_map->indx_y] * axes_map->sign_y;
    device_data[2] = tmp[axes_map->indx_z] * axes_map->sign_z;
}
device_data是从sensor寄存器里面读取出来的数据,那么我们把上面计算出来的index作为下标,来进行对应,是否反向就用sign来相乘,这就这样我们的坐标系就完成了转换了。


原理很简单,我们的sensor包括加速度,陀螺仪和地磁都需要坐标轴的转换,前面讲到是把这些nv参数传递进来初始化的。那么他们存在nv的那个位置呢,在sns_reg_api_v02.h这个文件中,我们定义了如下的一下宏定义:

/**  Item ID's corresponding to group SNS_REG_DRIVER_GROUP_ACCEL (Group Id: 1000)  */
#define SNS_REG_DRIVER_ACCEL_X_ORIENT_V02 700
#define SNS_REG_DRIVER_ACCEL_Y_ORIENT_V02 701
#define SNS_REG_DRIVER_ACCEL_Z_ORIENT_V02 702

/**  Item ID's corresponding to group SNS_REG_DRIVER_GROUP_GYRO (Group Id: 1010)  */
#define SNS_REG_DRIVER_GYRO_X_ORIENT_V02 800
#define SNS_REG_DRIVER_GYRO_Y_ORIENT_V02 801
#define SNS_REG_DRIVER_GYRO_Z_ORIENT_V02 802

/**  Item ID's corresponding to group SNS_REG_DRIVER_GROUP_MAG (Group Id: 1020)  */
#define SNS_REG_DRIVER_MAG_X_ORIENT_V02 900
#define SNS_REG_DRIVER_MAG_Y_ORIENT_V02 901
#define SNS_REG_DRIVER_MAG_Z_ORIENT_V02 902

这些地址里面,存储的就是对应senosr的坐标系转换参数,我们可以用QSensorTest.apk这个程序来读取一下,刚好就是传递进dsps的nv参数。那么就有两个问题了,这些nv参数是哪里写入的呢,驱动里面又是哪里请求的这些nv项呢。

我们先来看后面一个问题,我们按照这些group ID 进行寻找,发现在sns_smgr_sensor_config.h这个文件中,最每一个sensor的相关信息进行了定义,也包括了需要的nv参数的信息,下面是一个加速度的信息摘取:

#ifdef CONFIG_USE_LIS3DH
  #define SNS_SMGR_SENSOR_0_ENUM_CODE                   SNS_SMGR_ID_ACCEL_V01
  #define SNS_SMGR_SENSOR_0_DD_FN_LIST_PTR              &sns_dd_acc_lis3dh_if
  #define SNS_SMGR_SENSOR_0_DEVICE_ID                   0
  #define SNS_SMGR_SENSOR_0_BUS_ADDRESS                 0x19 /* 0x1D alternative I2C address. ranfei modify */
  #define SNS_SMGR_SENSOR_0_DATA_TYPE_1                 SNS_DDF_SENSOR_ACCEL
  #define SNS_SMGR_SENSOR_0_DATA_TYPE_2                 SNS_DDF_SENSOR__NONE
  #define SNS_SMGR_SENSOR_0_RANGE_TYPE                  SNS_SMGR_DATA_TYPE_PRIMARY_V01
  #define SNS_SMGR_SENSOR_0_SENSITIVITY_DEFAULT         1 /* 16g fixed. */
  #define SNS_SMGR_SENSOR_0_FLAGS                       SNS_SMGR_NO_SENSITIVITY //RK check this with SMGR requirements
  #define SNS_SMGR_SENSOR_0_OFF_TO_IDLE                 1000 /* usec */ // RK check this with data sheet
  #define SNS_SMGR_SENSOR_0_IDLE_TO_READY               100000 /* usec */
  #define SNS_SMGR_SENSOR_0_REG_ITEM_TYPE               SNS_SMGR_REG_ITEM_TYPE_GROUP
  #define SNS_SMGR_SENSOR_0_REG_ITEM_ID                 SNS_REG_DRIVER_GROUP_ACCEL_V02
  #define SNS_SMGR_SENSOR_0_CAL_PRI_TYPE                SNS_SMGR_REG_ITEM_TYPE_GROUP
  #define SNS_SMGR_SENSOR_0_CAL_PRI_ID                  SNS_REG_SCM_GROUP_ACCEL_FAC_CAL_PARAMS_V02  /* 0=SNS_REG_SMGR_GROUP_ACCEL_V02 in sns_reg_api_v02.h */
  #define SNS_SMGR_SENSOR_0_GPIO_FIRST                  61    //ranfei modify
  #define SNS_SMGR_SENSOR_0_GPIO_SECOND                 0xffff
#endif /* CONFIG_USE_LIS3DH */
可以看到 #define SNS_SMGR_SENSOR_0_REG_ITEM_ID                 SNS_REG_DRIVER_GROUP_ACCEL_V02

这个正是前面定义的加速度坐标系矫正的nv group ID了。在smgr里面调用 sns_err_code_e sns_smgr_req_reg_data( const uint16_t Id, const uint8_t Type );就可以请求读取相应的nv参数了;
 

<think>嗯,用户问的是关于halFDDO、halFDGetFaceResult和convertResult这三个函数的功能、参数差异,以及坐标转换的流程,特别是涉及到TG crop、Active array crop这些参数的区别。首先,我需要回忆一下这些函数可能属于哪个平台或框架。看起来像是摄像头或者图像处理相关的模块,可能是安卓HAL层或者某个相机驱动库里的函数。 根据用户提供的引用内容,里面有提到EEPROM格式化白平衡数据、AF校准等,这可能与相机模块的校准有关。所以这些函数可能属于相机硬件抽象层(HAL)中的面部检测相关功能。接下来需要分析每个函数的作用: halFDDO可能是指面部检测的初始化或配置函数,比如设置参数、启动检测引擎。halFDGetFaceResult可能是获取检测结果,而convertResult可能负责将原始坐标转换为不同坐标系,比如从传感器坐标系到显示坐标系。 接下来是参数差异,用户提到的TG crop、Active array crop可能涉及图像传感器的不同裁剪区域。TG可能指Target,即目标裁剪区域,而Active array是传感器实际有效的像素区域。坐标转换流程需要了解如何从原始检测结果转换到不同的裁剪区域,可能涉及缩放、平移等操作。 需要确认这些参数的具体含义,比如Active array是传感器的物理感光区域,而TG crop可能是后续处理中选取的区域,比如用于预览或拍照的裁剪区域。坐标转换时需要考虑两者的比例和偏移量。 可能用户在实际开发中遇到了坐标转换的问题,比如人脸检测的结果在预览画面上的位置不正确,需要明确各个函数如何传递参数,以及不同crop区域的关系。需要解释清楚每个函数的输入输出参数,特别是坐标的参考系,以及转换过程中使用的缩放因子和偏移量。 另外,用户提到的平台算法可能指的是不同硬件平台(如高通、MTK)在坐标转换处理上的差异,需要比较这些平台的具体实现方式。例如,某些平台可能使用不同的校准数据结构,或者在坐标转换时应用不同的补偿参数。 最后,要确保回答结构清晰,分点说明每个函数的功能、参数差异,以及坐标转换的详细步骤,引用提供的代码片段中的相关函数作为参考,帮助用户理解整个流程。</think>### HAL接口功能解析及坐标转换流程 根据代码片段中涉及的EEPROM校准数据结构和命名规范分析,这三个接口属于摄像头HAL层的人脸检测功能模块[^1]。 #### 一、核心接口功能对比 | 接口名称 | 功能定位 | 输入参数示例 | 输出参数特征 | |---------------------|----------------------------|--------------------------------|-------------------------| | **halFDDO** | 人脸检测算法初始化 | 图像尺寸/传感器模式/校准参数 | 返回算法句柄 | | **halFDGetFaceResult** | 获取原始检测数据 | 算法句柄/图像buffer指针 | 包含原始坐标的face结构体| | **convertResult** | 坐标系转换 | 原始坐标/转换矩阵 | 适配显示界面的最终坐标 | #### 二、坐标转换核心流程 1. **坐标系基准定义**: - **Active Array**:传感器物理有效像素区域(如4032x3024) - **TG Crop**:图像信号处理(ISP)输出的目标尺寸(如1600x1200) 2. **转换公式示例**: $$ x_{display} = (x_{sensor} - crop_{left}) \times \frac{displayWidth}{cropWidth} $$ $$ y_{display} = (y_{sensor} - crop_{top}) \times \frac{displayHeight}{cropHeight} $$ 3. **典型转换场景**: ```cpp // 示例转换伪代码 void convertResult(FaceResult* raw, Rect activeArray, Rect targetCrop) { float scaleX = targetCrop.width / activeArray.width; float scaleY = targetCrop.height / activeArray.height; raw->left = (raw->left - activeArray.left) * scaleX; raw->top = (raw->top - activeArray.top) * scaleY; // 处理边界溢出和比例补偿... } ``` #### 三、平台算法差异要点 1. **高通平台**: - 要求额外补偿镜头畸变参数 - 使用QCOM_AF_CALIBRATION_DATA结构体 2. **MTK平台**: - 采用MTK_LSC_CALIBRATION_DATA格式 - 需要处理旋转镜像标志位 3. **三星平台**: - 强制校验AE同步状态 - 需要传入3A锁定标记
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值