Saturday, 27 July 2013

Taking the Grunt out of Geotags


Here's a matlab script to automatically compile all geo-tagged images from a directory and all its subdirectories into a Google Earth kml file showing positions and thumbnails

close all;clear all;clc
addpath('/path/where/googleearth/toolbox/is')
% get main directory (Projects directory)
pathFolder=uigetdir();
% get list of subfolders
d = dir(pathFolder);
isub = [d(:).isdir];
nameFolds = {d(isub).name}';
nameFolds(ismember(nameFolds,{'.','..'})) = [];
% prompt user to select which subfolders to process
[s,v] = listdlg('PromptString','Select folders:',...
'SelectionMode','multiple',...
'ListString',nameFolds);
% use only those directories
directories=char(nameFolds(s));
for md=1:size(directories,1)
% get list of subfolders
d = dir(strtrim([pathFolder,filesep,directories(md,:)]));
isub = [d(:).isdir];
nameFolds = {d(isub).name}';
nameFolds(ismember(nameFolds,{'.','..'})) = [];
subdirectories{md}=char(nameFolds);
end
mattime=[]; timestring=[]; lat=[]; lon=[]; filenames={};
direc=[];
counter=0;
for dd=1:size(directories,1)
for sd=1:size(subdirectories{dd},1)
if isempty(strmatch(strtrim(subdirectories{dd}(sd,:)),'dng')) &&...
isempty(strmatch(strtrim(subdirectories{dd}(sd,:)),'crw'))
files1=ReadImDir(strtrim([pathFolder,filesep,strtrim(directories(dd,:)),...
filesep,strtrim(subdirectories{dd}(sd,:))]),'JPG');
files2=ReadImDir(strtrim([pathFolder,filesep,strtrim(directories(dd,:)),...
filesep,strtrim(subdirectories{dd}(sd,:))]),'jpg');
files=char(files1,files2); %,files3
for k=1:size(files,1)
in=strtrim([pathFolder,filesep,strtrim(directories(dd,:)),filesep,strtrim(subdirectories{dd}(sd,:)),...
filesep,strtrim(files(k,:))]);
if isempty(regexp(in,'ppm.jpg', 'once'))
counter=counter+1;
filenames{counter}=in;
[stat,res]=system(['exiftool -h "',in,'"']);
latstr=res(regexp(res,'>GPS Latitude<')+22:regexp(res,'>GPS Latitude<')+41);
if ~isempty(latstr)
deg=str2double(strtrim(latstr(1:2)));
mins=str2double(strtrim(latstr(8:9)));
secs=str2double(strtrim(latstr(16:end)));
lat=[lat; deg+ mins/60 + secs/3600];
lonstr=res(regexp(res,'>GPS Longitude<')+22:regexp(res,'>GPS Longitude<')+42);
deg=str2double(strtrim(lonstr(2:4)));
mins=str2double(strtrim(lonstr(10:11)));
secs=str2double(strtrim(lonstr(17:end)));
lon=[lon; deg+ mins/60 + secs/3600];
timestr=res(regexp(res,'>GPS Date/Time<')+23:regexp(res,'>GPS Date/Time<')+41);
y=str2double(timestr(1:4)); m=str2double(timestr(6:7)); d=str2double(timestr(9:10));
H=str2double(timestr(12:13)); M=str2double(timestr(15:16)); S=str2double(timestr(18:19));
if S==0
S=S+1;
end
mattime=[mattime;datenum([y,m,d,H,M,S])];
timestring=[timestring;datestr(datenum([y,m,d,H,M,S]))];
direc=[direc;dd];
else
lat=[lat;NaN]; lon=[lon;NaN];
timestr=res(regexp(res,'>Create Date<')+21:regexp(res,'>Create Date<')+39);
y=str2double(timestr(1:4)); m=str2double(timestr(6:7)); d=str2double(timestr(9:10));
H=str2double(timestr(12:13)); M=str2double(timestr(15:16)); S=str2double(timestr(18:19));
if y==2012
y=y+1;
end
if S==0
S=S+1;
end
mattime=[mattime;datenum([y,m,d,H,M,S])];
timestring=[timestring;datestr(datenum([y,m,d,H,M,S]))];
direc=[direc;dd];
end
end % if not ppm.jpg
end %k
end % if not dng or crw
end %sd
end %dd
thumbfiles=cell(size(filenames));
for i=1:length(lat)
thumbfiles{i}=[filenames{i},'_thumb.jpg'];
end
kmlStr=cell(1,length(lat));
for i=1:length(lat)
system(['exiftool -b -ThumbnailImage ',filenames{i},' > ',thumbfiles{i}])
kmlStr{i} = ge_point_new(-lon(i),lat(i),0,...
'description',['<a href="',filenames{i},'">link to file</a>'] ,...
'iconURL',thumbfiles{i},...
'name',filenames{i}(regexp(filenames{i},'IMG'):end));
end
tmp=[];
for i=1:length(lat)
tmp=[tmp,eval(['kmlStr{',num2str(i),'}'])];
end
ge_output('points.kml',...
ge_folder('points',tmp));
system(['google-earth "',pwd,filesep,'points.kml" &'])
save('photo_res','mattime','lat','lon','direc','timestring','filenames','directories')
view raw geophotos2kml.m hosted with ❤ by GitHub


Like most of my matlab scripts, it's essentially just a wrapper for a system command. It requires exiftool for the thumbnail creation (available on both *nix and for Windows). It also needs the (free) Google Earth toolbox for Matlab.

Right now it's just set up for JPG/jpg files, but could easily be modified or extended. As well as the kml file (Google Earth will launch as soon as the script is finished) it will save a matlab format file contining the lats, longs, times and filenames.

Outputs look a little like this (a selection of over 30,000 photos taken in Grand Canyon)




No comments: