Image 在MATLAB中读取原始MAPIR图像
我有一个来自MAPIR NDVI相机的原始图像,希望将其加载到MATLAB中,并将所需的两个波段(NIR、红色边缘)导出为tif 根据制造商的说法,NIR数据以16位的形式存储在蓝色通道中,而可见光(红色边缘)存储在红色通道中 我试着从中读取带有代码的文件 “但是它创造了这些,我不知道为什么会发生这种情况。要么我读错了文件,要么是因为NIR通道的分辨率较低Image 在MATLAB中读取原始MAPIR图像,image,matlab,image-processing,Image,Matlab,Image Processing,我有一个来自MAPIR NDVI相机的原始图像,希望将其加载到MATLAB中,并将所需的两个波段(NIR、红色边缘)导出为tif 根据制造商的说法,NIR数据以16位的形式存储在蓝色通道中,而可见光(红色边缘)存储在红色通道中 我试着从中读取带有代码的文件 “但是它创造了这些,我不知道为什么会发生这种情况。要么我读错了文件,要么是因为NIR通道的分辨率较低 是指向所用原始图像的链接 看起来“碎片”的原因是。 像素排列类似于拜耳马赛克,如下所示: 目前还不清楚CFA的定位是什么 您发布了: 根据
是指向所用原始图像的链接 看起来“碎片”的原因是。
像素排列类似于拜耳马赛克,如下所示: 目前还不清楚CFA的定位是什么 您发布了: 根据制造商的说法,近红外数据存储在蓝色通道中,可见光(红边)存储在红色通道中 但拜耳校准有4种可能的组合。
在Matlab中,组合被称为
'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:
更新: 情绪化的卷心菜发布了以下参考图片:
我试图将原始图像放到引用中,但无法正确获取 我认为CFA的定位是:
J1
-红色通道。J2
和J3
-单色而非绿色通道。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);
结果:为了得到正确的结果,仍然缺少一些信息…虽然您已经接受了另一个答案,但我想在这里保存我的努力成果,以防其他人有类似的问题。根据原始问题,此代码在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);
}
RAW意味着没有格式,所以RAW。原始格式不是一种格式,但缺少一种,世界上的每个设备都可能有不同的原始写入方式。当你说RAW时,它的意思是“无论设备测量了什么,一点一点”。因此,只有您(或制造商)知道如何准确读取原始数据。只需按照说明进行操作制造商的说明是:“使用QGIS插件”,不幸的是,这在OSX上不起作用。那么,要么找出运行QGID插件(可能是虚拟机)的方法,要么让制造商告诉您文件是如何编写的。没有其他选项,无法猜测原始文件包含的内容您知道图像的尺寸吗?W x H像素?好的,那我就可以了-我想我的代码看起来有点乱,我有点忙,但我以后应该有一个解决方案给你。谢谢你的帮助!但遗憾的是,这似乎并不完全正确。图像应该看起来像。无论我尝试哪种组合,都不能得到相同的结果。显然,这些图像存储为16位字中12位的块。所以前12位是一个像素,剩下的4位和后面的8位是下一个像素。@u coball先生,这是不正确的。4032px x x 3024px生成15925248个像素,而您的文件正好是字节数的两倍,因此每个像素有2个字节,即1个字节表示红色,1个字节表示NIR,而不是12位红色和12位NIR。所有16位都由原始格式使用,但像素的分块方式使每个像素的一些数据重叠到下一个字中。因此,第一个字的前12位将是一个像素,然后该字的下4位将是下一个像素,然后下一个字的前8位将是第二个像素的其余部分,依此类推。这是支持人员告诉我们的。@这不正确。如果是这样,您需要3个字节(24位)来存储2个像素(每个像素12位),因此您的文件需要是4608*3456*3或47775744字节,但它只有3185046字节。@此外,您说“正确”的图像有三个通道,所有通道都是唯一的,而原始图像有两个通道,那么第三个通道来自哪里?它不是任何其他通道的副本,因为3个通道都有不同的平均值和标准偏差。
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