【问题标题】:Reading RAW MAPIR images in MATLAB在 MATLAB 中读取 RAW MAPIR 图像
【发布时间】:2017-03-27 13:43:22
【问题描述】:

我有一个来自 MAPIR NDVI 相机的原始图像,我想将其加载到 MATLAB 中并将所需的两个波段(NIR、红边)导出为 tif。

根据制造商的说法,NIR 数据存储在蓝色通道中,可见光(红色边缘)存储在红色通道中,为 16 位。

我尝试使用以下代码读取文件 “How can I read in a RAW image in MATLAB?”但它创建了这些fragments,我不确定为什么会这样。要么我读错了文件,要么是因为 NIR 通道的分辨率较低。

Here 是指向使用的 RAW 图像的链接。

【问题讨论】:

  • RAW 表示没有格式,所以是 RAW。 RAW格式不是一种格式,而是缺少一种格式,世界上每一种设备都可能有不同的RAW写入方式。当您说 RAW 时,它的意思是“无论设备测量什么,一点一点”。因此,只有您(或制造商)知道如何准确读取您的 RAW 数据。只需按照说明进行操作
  • 制造商的说明是:“使用 QGIS 插件”,不幸的是,它不适用于 OSX。
  • 好吧,要么弄清楚运行QGID插件的方式(可能是虚拟机),要么让制造商告诉你文件到底是怎么写的。没有其他选择,无法猜测原始文件包含什么
  • 你知道图片的尺寸吗?宽 x 高像素?
  • 好的,那我就可以了——我想它看起来像这样thesetchells.com/a.jpg 我的代码有点杂乱,我有点忙,但我稍后应该为您提供解决方案。

标签: image matlab image-processing


【解决方案1】:

看起来“碎片”的原因是CFA (color filter array)
像素排列类似于拜耳马赛克:

不清楚什么是 CFA 对齐。

您发布了:

根据制造商的说法,NIR 数据存储在蓝色通道中,可见光(红色边缘)存储在红色通道中

但是拜耳对齐有 4 种可能的组合。
在 Matlab 中,demosaic function documentation 组合称为'gbrg''grbg''bggr''rggb'

我不知道最常见的对齐方式是什么。
我不能说哪个通道应该是“蓝色通道”,哪个是“红色通道”。 (我们所知道的是它们位于对角线)。
我也无法在 Google 中找到对齐信息。

由于我不知道哪个是哪个,我提取了所有 4 个可能的通道:

srcN = 4608; %Raw image width (number of columns).
srcM = 3456; %Raw image height (number of rows).

%Open raw image for reading.
f = fopen('2017_0321_134045_015.RAW', 'r');

%Read raw data into matrix I (use '*uint16' for keeping data in uint16 - no conversion to double).
I = fread(f, [srcN, srcM], '*uint16');

fclose(f);

%Transpose I, because RAW image format is row-major, and Matlab matrix format is column-major.
I = I';


%Assume Bayer mosaic sensor alignment.
%Seperate to mosaic components.
J1 = I(1:2:end, 1:2:end);
J2 = I(1:2:end, 2:2:end);
J3 = I(2:2:end, 1:2:end);
J4 = I(2:2:end, 2:2:end);

figure;imshow(J1);title('J1');
figure;imshow(J2);title('J2');
figure;imshow(J3);title('J3');
figure;imshow(J4);title('J4');

%Save all 4 images as tif
imwrite(J1, 'J1.tif');
imwrite(J2, 'J2.tif');
imwrite(J3, 'J3.tif');
imwrite(J4, 'J4.tif');

这是四张图片(缩小了 x4 倍):

J1:

J2:

J3:

J4:


更新:

Emotional_Cabbage 发布了以下参考图片:

我尝试将原始图像作为参考,但无法正确获取。

我认为 CFA 对齐方式是:
J1 - 红色通道。
J2J3 - 单色而不是绿色通道。
J4 - 近红外颜色通道。

插图:

我使用了如下处理代码:

J = demosaic(I, 'rggb');
J = imadjust(J, [0.02, 0.98], [], 0.45); %Adjust image intensity, and use gamma value of 0.45
J(:,:,2) = J(:,:,2)*0.75; %Reduce the green by factor of 0.75
figure;imshow(J);

结果:

仍然缺少一些获得正确结果的信息......

【讨论】:

  • 感谢您的帮助!但遗憾的是,它似乎并不完全正确。该图像应该看起来像this。而且无论我尝试哪种组合,我都无法得到相同的结果。显然,图像存储为 16 位 word 中的 12 位块。所以前 12 位是一个像素,剩下的 4 位和后面的 8 位是下一个像素。
  • @Emotional_Cabbage 这不可能是正确的,Cabbage 先生。 4,032 像素 x 3,024 像素产生 15,925,248 像素,而您的文件正好是字节数的两倍,因此每个像素有 2 个字节,即 1 个字节用于红色,1 个字节用于 NIR,而不是 12 位红色和 12 位 NIR。
  • 所有 16 位都被 RAW 格式使用,但像素被分块,使得每个像素的一些数据重叠到下一个单词中。所以第一个字的前 12 位将是一个像素,然后该字的下 4 位将是下一个像素,然后下一个字的前 8 位将是第二个像素的其余部分,依此类推。 i> 是支持人员告诉我们的。
  • @Emotional_Cabbage 这不可能是正确的。如果是这样,您将需要 3 个字节(24 位)来存储 2 个像素(每个 12 位),因此您的文件需要为 4608*3456*3 或 47775744 字节,但它只有 31850496 字节。
  • @Emotional_Cabbage 另外,你说的“正确”的图像有三个通道,它们都是唯一的,但是RAW图像有2个通道,那么第三个通道是从哪里来的从?它不是任何其他通道的副本,因为这 3 个通道都有不同的均值和标准差。
【解决方案2】:

虽然您已经接受了另一个答案,但我想在这里保存我的努力结果,以防其他人遇到类似问题。根据原始问题,此代码在 Mac 或 Linux 上运行。

////////////////////////////////////////////////////////////////////////////////
// raw2tif.c
// Mark Setchell
//
// Reads a RAW file from a MAPIR NDVI camera and converts it to a TIF
//
// Usage:
// raw2tif RAWfile result.tif
////////////////////////////////////////////////////////////////////////////////
#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <string.h>
#include "tiffio.h"

#define WIDTH   4608
#define HEIGHT  3456
#define RAW_BITSPERSAMPLE   8
#define RAW_SAMPLESPERPIXEL 2
#define TIF_BITSPERSAMPLE   8
#define TIF_SAMPLESPERPIXEL 3

int main(int argc,char* argv[])
{
   char ifilename[128];
   char ofilename[128];
   unsigned char inrow[WIDTH*RAW_BITSPERSAMPLE*RAW_SAMPLESPERPIXEL/8];
   FILE* in;

   // Check input and output file names supplied
   if(argc!=3){
      fprintf(stderr,"Usage: raw2tif RAWfile TIFfile");
      exit(EXIT_FAILURE);
   }

   // Pick up arguments - infile (RAW) and outfile (TIF)
   strcpy(ifilename,argv[1]);
   strcpy(ofilename,argv[2]);

   // Open input file
   in=fopen(ifilename,"rb");
   if(in==NULL){
      fprintf(stderr,"ERROR: Unable to open RAW input file");
      exit(EXIT_FAILURE);
   }

   // Open output file
   TIFF *tif= TIFFOpen(ofilename, "w");
   if(tif==NULL){
      fprintf(stderr,"ERROR: Unable to open output file");
      exit(EXIT_FAILURE);
   }

   // Set baseline tags
   TIFFSetField(tif,TIFFTAG_IMAGEWIDTH,WIDTH);
   TIFFSetField(tif,TIFFTAG_IMAGELENGTH,HEIGHT);
   TIFFSetField(tif,TIFFTAG_BITSPERSAMPLE,TIF_BITSPERSAMPLE);
   TIFFSetField(tif,TIFFTAG_SAMPLESPERPIXEL,TIF_SAMPLESPERPIXEL);
   TIFFSetField(tif,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT);
   TIFFSetField(tif,TIFFTAG_COMPRESSION,COMPRESSION_LZW);
   TIFFSetField(tif,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG);
   TIFFSetField(tif,TIFFTAG_PHOTOMETRIC,PHOTOMETRIC_MINISBLACK);

   uint32  rowsPerStrip;
   rowsPerStrip = HEIGHT;
   rowsPerStrip = TIFFDefaultStripSize(tif, rowsPerStrip);
   TIFFSetField(tif, TIFFTAG_ROWSPERSTRIP, rowsPerStrip);
   TIFFSetupStrips(tif);

   // Line buffer
   int scanlineSize = TIFFScanlineSize(tif);
   unsigned char* scanline = (unsigned char*) _TIFFmalloc(scanlineSize);

   // Iterate over rows of RAW file writing rows of TIF file
   for(int row=0;row<HEIGHT;row++)
   {
      if(fread(inrow,WIDTH*RAW_BITSPERSAMPLE*RAW_SAMPLESPERPIXEL/8,1,in)!=1){
         fprintf(stderr,"ERROR: Error reading input file at row %d\n",row);
         exit(EXIT_FAILURE);
      }
      // Following few lines need correcting when input file format is known
      unsigned char* ip=inrow;
      unsigned char* op=scanline;
      for(int col=0;col<WIDTH;col++){
         *op++=*ip++;  // Write RAW red to TIF red
         *op++=0;      // Set TIF green to 0
         *op++=*ip++;  // Write RAW NIR to TIF blue
      }
      if(TIFFWriteScanline(tif,scanline,row,0) != 1){
         fprintf(stderr,"ERROR: Error writing output file at row %d\n",row);
         exit(EXIT_FAILURE);
      }
   }

   // Clean up
   _TIFFfree(scanline);
   TIFFClose(tif);
}

一个合适的Makefile是:

CC=clang -Wall -pedantic
TIF_INC=-I/usr/include -I/usr/local/include
TIF_LIB=-L/usr/lib -L/usr/local/lib -ltiff

raw2tif: raw2tif.c
    $(CC) raw2tif.c $(TIF_INC) $(TIF_LIB) -o raw2tif

【讨论】:

    猜你喜欢
    • 2014-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多