关于当前raw数据处理的几种方法

1. 数据介绍

目前做实验的raw数据有两种类型,一种是通过尼康数码相机拍摄的,12位,后缀名为.nef的raw;另一种是此前使用tx2摄像头拍摄的,16 位,raw文件,后缀名命名为.raw。前者包含有数码相机处理raw文件的元(meta)数据,如曝光时间、白平衡、ISO值等,后者包含的是非数码相机拍摄的文件数据。二者数据结构不同,故处理方式也存在差异。

2. 处理方式

  • 针对.nef文件,目前的处理方式是通过libraw进行软件isp处理,支持坏死像素点的修复,gamma校正,相机白平衡,曝光补偿等操作,支持导出处理后的可视化的tif文件。
  • 调用libraw接口,打开数码相机raw文件的参考代码如下所示:
LibRaw RawProcessor; /// 创建libraw类的一个实例
RawProcessor.imgdata.params /// 根据处理需求配置,处理参数,如白平衡,gamma校正等操作
ret = RawProcessor.open_file(argv[arg]); /// @brief 1. open raw file
if (ret != LIBRAW_SUCCESS)
{
    fprintf(stderr, "Cannot open %s: %s\n", argv[arg], libraw_strerror(ret));
    continue; // no recycle b/c open_file will recycle itself
}
if ((ret = RawProcessor.unpack()) != LIBRAW_SUCCESS) /// @brief 2. unpack
{
  fprintf(stderr, "Cannot unpack %s: %s\n", argv[arg], libraw_strerror(ret));
    continue;
}
if (LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_process())) /// @brief 3.dcraw_process
{
    fprintf(stderr, "Cannot do postprocessing on %s: %s\n", argv[arg],
              libraw_strerror(ret));
    if (LIBRAW_FATAL_ERROR(ret))
        continue;
}
if (LIBRAW_SUCCESS != (ret = RawProcessor.dcraw_ppm_tiff_writer(outfn))) /// @brief 4. write tiff format file in disk.
{
    fprintf(stderr, "Cannot write %s: %s\n", outfn, libraw_strerror(ret));
}

/// @brief 5. recycle handle.
RawProcessor.recycle(); // just for show this call

效果图如下所示:

左图是相机原始nef文件使用本机照片查看软件打开的效果,右图是经过libraw处理后的结果,设置了自动白平衡,输出tiff文件。

左图是相机导出的jpg文件使用本机照片查看软件打开的效果,右图是经过libraw处理后的结果,设置了自动白平衡,输出tiff文件。

  • 针对.raw文件,目前只能对tx2摄像头拍摄的raw文件进行处理,因为了解raw文件数据结构,图像真实宽高以及meta数据的位置和长度,故可以直接通过二进制的方式进行读取,将RAW图像数据转到RGB域(去马赛克处理,rggb转rgb)内,再利用opencv对RGB域的图像进行软件ISP处理,如自动白平衡,亮度提升,对比度增强,gamma校正,饱和度增强等操作。
    使用二进制方式处理已知数据结果的raw文件代码,如下所示:
FILE *fp = nullptr;
fp = fopen(input_path,"r");
fseek(fp,0L,SEEK_END);
int size = ftell(fp);
std::cout<<"input size lenght is "<<size<<std::endl;
fseek(fp,0L,SEEK_SET);

ushort *data = (ushort *)malloc(width*height * sizeof(ushort));
fread(data, sizeof(unsigned short), width*height, fp);
cv::Mat img_raw;
const int new_w = img_w;
const int new_h = img_h;
int bufLen = new_h * new_w;
img_raw.create(new_h, new_w, CV_16UC1);
memcpy(img_raw.data, data, bufLen * sizeof(ushort));
cv::normalize(img_raw, img_raw, 0, 255, cv::NORM_MINMAX);
cv::cvtColor(img_raw, img_raw, CV_BayerRG2RGB);//CV_BayerRG2BGR
img_raw.convertTo(img_raw, CV_8UC3);

注意:只介绍c++代码的处理方式。

3. 参考资料

  • libraw介绍
  • 用于读取和处理RAW相机图像的库,github链接;
  • libraw库可以从数码相机生成的RAW文件中提取以下内容:
  • RAW数据(像素值)
  • 处理RAW所需的元数据(几何、CFA/拜耳模式、黑电平、白平衡等)
  • 嵌入式预览/缩略图