使用matlab读取ENVI_standard格式数据的方法

目录

    • ENVI_standard文件的获取
    • 方法①:matlab内置函数
    • 方法②:freadenvi.M
    • 方法③:read_ENVIimagefile.M

寻找文中这三种方法花了我一下午的时间,把他们发出来希望能给同行们便利。

所有方法均非原创!只是想汇集起来方便大家ctrl+C

ENVI_standard文件的获取

方法①:matlab内置函数

在matlab中输入:help multibandread 看看介绍说明基本就懂了。
用写字板打开.hdr文件,可以找到参数。
在这里插入图片描述
(关于data type,在方法③的M文件里有说明)

例子如下:

1
 inputimg = multibandread('tifname',[M,N,D],'uint16',0,'bsq','ieee-le' );

方法②:freadenvi.M

M文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
function [image,p,t]=freadenvi(fname);

%%%%%%%%%%%%%

% Parameters initialization
elements={'samples ' 'lines   ' 'bands   ' 'data type '};
d={'bit8' 'int16' 'int32' 'float32' 'float64' 'uint16' 'uint32' 'int64' 'uint64'};
% Check user input
if ~ischar(fname)
    error('fname should be a char string');
end


% Open ENVI header file to retreive s, l, b & d variables
rfid = fopen(strcat(fname,'.hdr'),'r');

% Check if the header file is correctely open
if rfid == -1
    error('Input header file does not exist');
end;

% Read ENVI image header file and get p(1) : nb samples,
% p(2) : nb lines, p(3) : nb bands and t : data type
while 1
    tline = fgetl(rfid);
    if ~ischar(tline), break, end
    [first,second]=strtok(tline,'=');
   
    switch first
        case elements(1)
            [f,s]=strtok(second);
            p(1)=str2num(s);
        case elements(2)
            [f,s]=strtok(second);
            p(2)=str2num(s);
        case elements(3)
            [f,s]=strtok(second);
            p(3)=str2num(s);
        case elements(4)
            [f,s]=strtok(second);
            t=str2num(s);
            switch t
                case 1
                    t=d(1);
                case 2
                    t=d(2);
                case 3
                    t=d(3);
                case 4
                    t=d(4);
                case 5
                    t=d(5);
                case 12
                    t=d(6);
                case 13
                    t=d(7);
                case 14
                    t=d(8);
                case 15
                    t=d(9);
                otherwise
                    error('Unknown image data type');
            end
    end
end
fclose(rfid);

t=t{1,1};
disp([('Opening '),(num2str(p(1))),('cols x '),(num2str(p(2))),('lines x '),(num2str(p(3))),('bands')]);
disp([('of type '), (t), (' image...')]);
fid=fopen(fname);
image=fread(fid,t);
image=reshape(image,[p(1),p(2),p(3)]);
fclose(fid);

matlab里输入:[image,p,t]=freadenvi('filename'); 即可得到输出。
注意:输出是列×行×波段的格式! 我试了把它转置能M×N×D形式,和方法①的结果完全相同。

方法③:read_ENVIimagefile.M

M文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
function data=read_ENVIimagefile(imgfilename)
if length(imgfilename)>=4
    switch strcmp(imgfilename(length(imgfilename)-3:end), '.img')
     case 0
     hdrfilename=strcat(imgfilename, '.hdr');
    case 1
     hdrfilename=strcat(imgfilename(1: (length(imgfilename)-4)), '.hdr');
end
else
    hdrfilename=strcat(imgfilename, '.hdr');
end

fid = fopen(hdrfilename, 'r');

info = fread(fid,'char=>char');

info=info';%默认读入列向量,须要转置为行向量才适于显示

fclose(fid);

a=strfind(info,'samples = ');

b=length('samples = ');

c=strfind(info,'lines');

samples=[];

for i=a+b:c-1

    samples=[samples,info(i)];

end

samples=str2num(samples);

%查找行数

a=strfind(info,'lines   = ');

b=length('lines   = ');

c=strfind(info,'bands');

lines=[];

for i=a+b:c-1

    lines=[lines,info(i)];

end

lines=str2num(lines);

%查找波段数

a=strfind(info,'bands   = ');

b=length('bands   = ');

c=strfind(info,'header offset');

bands=[];

for i=a+b:c-1

    bands=[bands,info(i)];

end

bands=str2num(bands);

%查找数据类型

a=strfind(info,'data type = ');

b=length('data type = ');

c=strfind(info,'interleave');

datatype=[];

for i=a+b:c-1

    datatype=[datatype,info(i)];

end

datatype=str2num(datatype);

precision=[];

switch datatype

    case 1

        precision='uint8=>uint8';%头文件中datatype=1对应ENVI中数据类型为Byte,对应MATLAB中数据类型为uint8

    case 2

        precision='int16=>int16';%头文件中datatype=2对应ENVI中数据类型为Integer,对应MATLAB中数据类型为int16

    case 12

        precision='uint16=>uint16';%头文件中datatype=12对应ENVI中数据类型为Unsighed Int,对应MATLAB中数据类型为uint16

    case 3

        precision='int32=>int32';%头文件中datatype=3对应ENVI中数据类型为Long Integer,对应MATLAB中数据类型为int32

    case 13

        precision='uint32=>uint32';%头文件中datatype=13对应ENVI中数据类型为Unsighed Long,对应MATLAB中数据类型为uint32

    case 4

        precision='float32=>float32';%头文件中datatype=4对应ENVI中数据类型为Floating Point,对应MATLAB中数据类型为float32

    case 5

        precision='double=>double';%头文件中datatype=5对应ENVI中数据类型为Double Precision,对应MATLAB中数据类型为double

    otherwise

        error('invalid datatype');%除以上几种常见数据类型之外的数据类型视为无效的数据类型

end

%查找数据格式

a=strfind(info,'interleave = ');

b=length('interleave = ');

c=strfind(info,'sensor type');

interleave=[];

for i=a+b:c-1

    interleave=[interleave,info(i)];

end

    interleave=strtrim(interleave);%删除字符串中的空格

%读取图像文件

fid = fopen(imgfilename, 'r');

data = multibandread(imgfilename ,[lines, samples, bands],precision,0,interleave,'ieee-le');

data= double(data);

end

在matlab里输入:image=read_ENVIimagefile('filename'); 即可得到相同的输出。