g_stabilize.m 4.93 KB
Newer Older
Pascal Bourgault's avatar
Pascal Bourgault committed
1
2
3
4
function g_stabilize(root_img_name,ext,id_img_ref,id_img_first,id_img_last,precision,varargin)
% Function that calls the stabilization algorithm. The stabilized files
% contain the datetime values stored in the 'DateTime' or the 'Comment'
% field of the unstabilized images.
Daniel Bourgault's avatar
Daniel Bourgault committed
5
6
7
% 
% Input: 
%   root_img_fname: The root name of the images before the id number.
Pascal Bourgault's avatar
Pascal Bourgault committed
8
9
%   ext:            The image extension (.jpg .png etc), is case
%                   insensitive
Daniel Bourgault's avatar
Daniel Bourgault committed
10
11
12
13
14
15
16
%   id_img_ref:     The id number of the reference image
%   id_img_first:   The id number of the first image of the sequence to 
%                   be stabilized
%   id_img_last:    The id number of the last image of the sequence to 
%                   be stabilized
%   precision:      The number of digit for the file name 
%                   (e.g.: IMG_0400.JPG would be 4).
Pascal Bourgault's avatar
Pascal Bourgault committed
17
18
19
20
21
22
23
%   Parameters, Name,       Value
%               roiFile,    [Defaults: roi.mat] Name of the file with roi
%                           information.
%               auto,       [Defaults: 0 (false)] If true, overrides any
%                           interaction with the user (for use in scripts)
%               suffix,     [Defaults: '_stable'] Suffix to add to the
%                           stabilized images.
Daniel Bourgault's avatar
Daniel Bourgault committed
24
25
%
% Output:
26
%   All stabilized images are rewritten as image files.
Daniel Bourgault's avatar
Daniel Bourgault committed
27
%
28
29
30
31
32
% Example:
%   g_stabilize('IMG_', '.JPG', 1, 2, 20, 4);
%
% Will run the stabilization reference to IMG_0001.JPG, on
% IMG_0002.JPG to IMG_0020.JPG
Daniel Bourgault's avatar
Daniel Bourgault committed
33
34

fname_suffix = '_stable';
Pascal Bourgault's avatar
Pascal Bourgault committed
35
36
37
38
39
40
41
42
43
44
45
46
47
auto = 0;
roifile = 'roi.mat';
if length(varargin) > 1
    for i=1:2:length(varargin)
        if strcmpi(varargin{i},'roiFile')
            roifile = varargin{i+1};
        elseif strcmpi(varargin{i},'auto')
            auto = varargin{i+1};
        elseif strcmpi(varargin{i},'suffix')
            fname_suffix = varargin{i+1};
        end
    end
end
Daniel Bourgault's avatar
Daniel Bourgault committed
48

Pascal Bourgault's avatar
Pascal Bourgault committed
49
hw = waitbar(0,'Preparing images');
Daniel Bourgault's avatar
Daniel Bourgault committed
50
% Region of interest
Pascal Bourgault's avatar
Pascal Bourgault committed
51
52
display(' Loading the roi.mat file containing the region of interest (roi)');
load(roifile);
Daniel Bourgault's avatar
Daniel Bourgault committed
53
54


Pascal Bourgault's avatar
Pascal Bourgault committed
55
ndigit = ['%',num2str(precision),'.',num2str(precision),'i']
Daniel Bourgault's avatar
Daniel Bourgault committed
56
57

% Read the reference image
Pascal Bourgault's avatar
Pascal Bourgault committed
58
59
60
61
62
63
64
65
66
67
68
try
    img_ref = [root_img_name,num2str(id_img_ref,ndigit),lower(ext)];
    im2     = double(imread(img_ref))/255;
catch
    img_ref = [root_img_name,num2str(id_img_ref,ndigit),upper(ext)];
    im2     = double(imread(img_ref))/255;
end

if size(im2,3) ~= 1
    im2     = uint8(g_rgb2gray(im2)*255);
end
Daniel Bourgault's avatar
Daniel Bourgault committed
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90


% Pyramid level for the stabilization.
% See documentation in the g_stabilize folder.
% L = 4 worked well on initial application but may require adjustments.
L = 4;

% Number of iterative improvement. Probably ok just 1 iteration.
niter = 1;

% Parameters for equalization. See help clahs for details.
nry = 4;
nrx = 4;
im2 = clahs(im2,nry,nrx);
im2 = double(im2);

% Remove mean and divide by the standard deviation.
inorm = find(roi > 0);
im2_norm = (im2 - nanmean(im2(inorm)))./nanstd(im2(inorm));

% Take the norm of the gradient of the image. This helps the
% stabilization algorithm
Pascal Bourgault's avatar
Pascal Bourgault committed
91
[im2x, im2y] = gradient(im2_norm);
Daniel Bourgault's avatar
Daniel Bourgault committed
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
grad_im2    = sqrt(im2x.^2 + im2y.^2);

% This is the referecne frame for the stabilization algorithm.
frames(2).im = grad_im2;


figure(1);
imagesc(im2);
colormap(gray);
title('Reference image normalized intensity');

figure(2);
imagesc(grad_im2);
colormap(gray);
title('Gradient of the referemce image');


figure(3);
imagesc(roi);
title('roi');

Pascal Bourgault's avatar
Pascal Bourgault committed
113
114
115
116
117
if ~auto
    answer = input('Happy with roi (y/n)? ','s');
    if answer == 'n'
        return
    end
Daniel Bourgault's avatar
Daniel Bourgault committed
118
end
Pascal Bourgault's avatar
Pascal Bourgault committed
119
120
num_img = id_img_last-id_img_first;
time_per_img = 0;
Daniel Bourgault's avatar
Daniel Bourgault committed
121
for i = id_img_first:id_img_last
Pascal Bourgault's avatar
Pascal Bourgault committed
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
    time_rem = (id_img_last-i+1)*time_per_img;
    waitbar((i-id_img_first)/num_img,hw,sprintf('Stabilizing image #%d. %.0fh%02.2fmn remaining',i,fix(time_rem/3600),rem(time_rem,3600)/60));
    total = tic;
    %Reading current image;
    try
        img_to_stabilize = [root_img_name,num2str(i,ndigit),lower(ext)];
        im1     = imread(img_to_stabilize);

    catch
        img_to_stabilize = [root_img_name,num2str(i,ndigit),upper(ext)];
        im1     = imread(img_to_stabilize);
    end
    im_info = imfinfo(img_to_stabilize);
    if size(im1,3) ~= 1
        im1     = uint8(g_rgb2gray(double(im1)/255)*255);
    end
Daniel Bourgault's avatar
Daniel Bourgault committed
138
139
140
    
    im1 = clahs(im1,nry,nrx);
    im1 = double(im1);
Pascal Bourgault's avatar
Pascal Bourgault committed
141
    
Daniel Bourgault's avatar
Daniel Bourgault committed
142
    im1_norm = (im1 - nanmean(im1(inorm)))./nanstd(im1(inorm));
Pascal Bourgault's avatar
Pascal Bourgault committed
143
    [im1x, im1y] = gradient(im1_norm);
Daniel Bourgault's avatar
Daniel Bourgault committed
144
145
146
147
148
149
150
151
152
    grad_im1 = sqrt(im1x.^2 + im1y.^2);
    
    frames(1).im = grad_im1;
    for iter = 1:niter
        [motion,stable] = g_videostabilize(frames,roi,L);
        frames(1).im = stable(1).im;
        %motion.A
        %motion.T
    end
Pascal Bourgault's avatar
Pascal Bourgault committed
153
    
Daniel Bourgault's avatar
Daniel Bourgault committed
154
155
156
    im_stable = g_warp(im1,motion.A,motion.T);
    im_stable = uint8(im_stable);
    %frames(2).im = stable(1).im;
Pascal Bourgault's avatar
Pascal Bourgault committed
157
158
159
160
161
162
163
164
165
166
167

    if isfield(im_info,'DateTime')
        datetime = im_info.DateTime;
    elseif isfield(im_info,'Comment')
        datetime = im_info.Comment;
    else
        datetime = '';
    end
    imwrite(im_stable,[img_to_stabilize(1:end-4) fname_suffix '.jpg'],'Quality',100,'Comment',datetime);

    time_per_img = toc(total);
Daniel Bourgault's avatar
Daniel Bourgault committed
168
end
Pascal Bourgault's avatar
Pascal Bourgault committed
169
close(hw)