-
Notifications
You must be signed in to change notification settings - Fork 9
/
Copy pathimseq.m
182 lines (179 loc) · 6.83 KB
/
imseq.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
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
%IMSEQ Open an image sequence as if it were a video stream.
%
% h = imseq(filename)
%
% This class creates an interface to a sequence of images similar to that
% of MATLAB's VideoReader class. However, the read method can only read an
% image at a time.
%
% There are two ways of defining the files to be used:
% Wildcard - e.g. filename = 'images/*.jpg' will use all files fitting
% that pattern (as found by DIR), and sort them alphabetically.
% Note that this doesn't work for image sequences containing
% (for example) 1.jpg and 10.jpg, as such files will not be
% sorted numerically.
% Numbered - e.g. filename = 'images/im.1.jpg' will use all files fitting
% that numbered pattern, in numerical order, starting at the
% number given. The format of the filename is assumed to
% contain an integer, and the sequence is assumed to increment
% that integer by one for each consecutive frame, e.g.:
% input.98.jpg, input.99.jpg, input.100.jpg, etc.
% The integer can also be zero padded, e.g.:
% 0000.png, 0001.png, 0002.png, etc.
%
% IN:
% filename - string containing the full or partial path to the first
% frame in an image sequence, or a filename pattern with
% wildcards.
%
% OUT:
% h - handle to the stream.
%
% See also VIDEOREADER, IMSTREAM.
% Copyright (C) Oliver Woodford 2011
classdef imseq < hgsetget
properties (Hidden = true, GetAccess = private, SetAccess = private)
% Internal properties
nameFunc;
end
properties (SetAccess = private)
% Visible properties
NumberOfFrames;
Duration;
FrameRate;
Height;
Width;
BitsPerPixel;
Name;
VideoFormat;
Type;
end
properties
% Writable properties
CurrentTime;
end
properties
% Editable properties
Tag;
UserData;
end
% Functions - copy of VideoReader functions
methods
% Contructor
function this = imseq(sname)
if iscell(sname)
this.NumberOfFrames = numel(sname);
this.nameFunc = @(n) sname{n};
elseif any(sname == '*')
% Directory listing
[fpath, fname, fext] = fileparts(sname);
if isempty(fpath)
fpath = cd();
else
fpath = cd(cd(fpath));
end
fpath = [fpath '/'];
list = dir([fpath fname fext]);
list = sort({list(:).name});
this.NumberOfFrames = numel(list);
this.nameFunc = @(n) [fpath list{n}];
else
% Format string
this.Name = sname;
[fpath, fname, fext] = fileparts(which(sname));
if isempty(fname)
[fpath, fname, fext] = fileparts(sname);
if isempty(fpath)
fpath = cd();
else
fpath = cd(cd(fpath));
end
end
% Find the last set of consecutive digits
[start, finish] = regexp(fname, '[0-9]+');
if isempty(start)
error('No image index found.');
end
start = start(end);
finish = finish(end);
format_string = sprintf('%s/%s%%.%dd%s%s', strrep(fpath, '\', '/'), fname(1:start-1), finish-start+1, fname(finish+1:end), fext);
zero_index = str2double(fname(start:finish)) - 1;
this.nameFunc = @(n) sprintf(format_string, n+zero_index);
% Compute sequence length
fnum = 0;
while 1
fnum = fnum + 1;
% Check we can open the file for reading
fh = fopen(this.nameFunc(fnum), 'r');
if fh == -1
break;
end
fclose(fh);
end
this.NumberOfFrames = fnum - 1;
end
% Set frame rate and duration
this.FrameRate = 30;
this.Duration = this.NumberOfFrames / this.FrameRate;
% Compute frame info
A = read(this, 1);
this.Width = size(A, 2);
this.Height = size(A, 1);
switch class(A)
case {'uint8', 'int8'}
this.BitsPerPixel = 8;
case {'uint16', 'int16'}
this.BitsPerPixel = 16;
case {'uint32', 'int32', 'single'}
this.BitsPerPixel = 32;
case {'uint64', 'int64', 'double'}
this.BitsPerPixel = 64;
end
this.BitsPerPixel = size(A, 3) * this.BitsPerPixel;
str = {'Gray%d', '%d', 'RGB%d', 'CMYK%d'};
this.VideoFormat = sprintf(str{size(A, 3)}, this.BitsPerPixel);
this.Type = 'imseq';
this.Tag = '';
this.CurrentTime = 0;
end
% Destructor
function this = delete(this)
end
% Read - same as VideoReader
function A = read(this, fnum)
if fnum == Inf
% Seek to the end
fnum = this.NumberOfFrames;
end
this.CurrentTime = fnum / this.FrameRate;
if fnum < 1 || fnum > this.NumberOfFrames
error('Frame %d is not in the range of allowed frames: [1 %d].', fnum, this.NumberOfFrames);
end
[A, map] = imread(this.nameFunc(fnum));
if ~isempty(map)
A = reshape(map(uint32(A)+1,:), [size(A) size(map, 2)]); % Assume indexed from 0
end
end
% hasFrame - same as VideoReader
function tf = hasFrame(this)
tf = this.CurrentTime < this.Duration;
end
% readFrame - same as VideoReader
function A = readFrame(this)
A = read(this, round(this.CurrentTime * this.FrameRate) + 1);
end
end
% Other VideoReader functions
methods(Static)
function b = isPlatformSupported()
b = true; % Always supported
end
function formats = getFileFormats()
extensions = {'bmp', 'tif', 'tiff', 'jpeg', 'jpg', 'png', 'ppm', 'pgm', 'pbm', 'gif'};
formats = audiovideo.FileFormatInfo.empty();
for a = 1:numel(extensions)
formats(a) = audiovideo.FileFormatInfo(extensions{a}, [upper(extensions{a}) ' file sequence'], true, false);
end
end
end
end