Datenvisualisierung mit Matlab

by Paul Balzer on 28. September 2011

1 Comment

Ich hatte vor ein paar Tagen die Möglichkeit auf einem heißen Sitz platz zu nehmen. Genauer gesagt auf dem Beifahrersitz eines BMW M3 3.2 E36, welcher von einem geschätzten Kollegen über den Eurospeedway Lausitzring bewegt wurde. Dazu habe ich mir eine Kamera und eine V-Box Mini geschnappt (danke an alle Beteiligten!) und ein paar Fahrdynamikdaten aufgezeichnet.

Screenshot

Wenn man genug Kleingeld hat, kann man ein fix und fertiges System kaufen, mit welchem Daten+Video synchron aufgezeichnet werden. Racelogic hat das z.B. im Angebot. Ich möchte im Folgenden zeigen, wie man aus Video und Daten trotzdem eine annehmbare Datenvisualisierung produzieren kann.

Datenaufzeichnung

Die Racelogic V-Box Mini zeichnet mit 10Hz die aktuelle Position (GPS), Längs- und Querbeschleunigung, Geschwindigkeit und auch Fahrtrichtung auf. Diese stehen dann über die Racelogic Software zur Verfügung. Der Export der Daten kann in .vbo (und dann mit einem VBO/Matlab Converter), „CommaSeparatedValues“ .csv Textdatei oder auch nach Excel .xls erfolgen. Ich habe die Daten in eine Excel Datei exportiert:

Download Fahrdynamikdaten BMW M3 Eurospeedway Lausitzring

Das Video kam von einer GoPro HD, welche an der Frontscheibe fixiert war. Die Umwandlung von .mp4 in .avi geschah mit dem Pazera Free MP4 to AVI Converter.

Matlab Script zur Darstellung von Daten in einem Video

Einen Großteil der Zeit habe ich mit hin & her probieren von Codecs und Versionen verbracht. Das ist ärgerlich. Letztendlich habe ich folgende Variante gewählt: Ich habe zum Einlesen des (komprimierten) AVI Files einen DirectShow (DirectX) based AVI File reader aus dem Matlab Central geladen und diesen über addpath zu den Matlab-Functions hinzugefügt. Damit war es dann auch möglich Videodateien größer 2GB einzulesen und auch die standard Windows Codecs werden erkannt. Ich benutze die Matlab Version 2006b, diese ist sowas von überholt wenn es um Videobearbeitung geht, dass man leider ein paar Umwege gehen muss.

1. Überprüfen ob DirectShow based AVI File reader installiert wurde

clear all, close all, clc
%% Checken ob Videofunction installiert wurde von
% http://www.mathworks.com/matlabcentral/fileexchange/9901
check = exist('dxAviOpen');
if check == 0
    disp('Bitte DirectShow (DirectX) based AVI file reader laden:')
    disp('http://www.mathworks.com/matlabcentral/fileexchange/9901')
    disp('und diesen über addpath() oder pathtool einbinden')
    warndlg({'Bitte DirectShow (DirectX) based AVI file reader laden:';...
        'http://www.mathworks.com/matlabcentral/fileexchange/9901'})
    return
end

2.  Excel Datei öffnen und in Workspace laden

%% open data file
[filename,path] = uigetfile('*.xls', 'Load XLS File');
if (isequal(filename, 0))
	return;% cancel
end
data = xlsread(fullfile(path,filename));

%% Variablen Fahrdynamik
t   = data(:,1); %Zeit in s
v   = data(:,2); %Geschwindigkeit in km/h
ay  = data(:,3); %Querbeschleunigung in g
ax  = data(:,4); %Längsbeschleunigung in g
yaw = data(:,5); %Fahrtrichtung in Grad
vv  = data(:,6); %Vertical Speed in km/h
nu  = data(:,7); %Anzahl Satelliten
B   = data(:,8); %Breitengrad in min
L   = data(:,9); %Längengrad in min
s   = data(:,10);%Weg in m
R   = data(:,12);%Kurvenradius in m

%% Querbeschleunigung filtern
ayf = filter(ones(1,5)/5,1,ay);

3. Videodatei mit Matlab einlesen

%% open video file
[filename,path] = uigetfile('*.avi', 'Select AVI File');

if (isequal(filename, 0))
	return; % cancel
end

file_avi = fullfile(path,filename);

% dxAviOpen ist eine Function von Matlabcentral
% http://www.mathworks.com/matlabcentral/fileexchange/9901
[avi_hdl, avi_inf] = dxAviOpen(file_avi);

fps = round(avi_inf.fps);
frames = avi_inf.NumFrames;

offset = -2.5; % Offset Video/Daten

4. Figure erzeugen worin Bilder + Daten angezeigt werden

%% Figure erzeugen
fig = figure(1);
set(fig,'Position',[100 100 avi_inf.Width avi_inf.Height],'MenuBar','none');
clf;
ax0 = axes('Position',[0 0 1 1]);

% dxAviReadMex ist eine Function von Matlabcentral
% http://www.mathworks.com/matlabcentral/fileexchange/9901
pixmap = dxAviReadMex(avi_hdl, 1);
pic = reshape(pixmap,[avi_inf.Height,avi_inf.Width,3])/256;
bild = image(pic);
axis off
daspect([1 1 1]);

5. Dummys der Datenvisualisierungen erstellen

% Geschwindigkeitsdummy vorbereiten
vh = text('Position',[0.5 0.1],'Units','normalized','String','0',...
    'Color','g','FontSize',32,'FontName',...
    'Tahoma','HorizontalAlignment','center');
text('Position',[0.5 0.04],'Units','normalized','String','km/h',...
    'Color','g','FontSize',10,'FontName',...
    'Tahoma','HorizontalAlignment','center');

% Querbeschleunigungsbar Dummy erzeugen (rechts)
axr = axes('Position',[0.6 0.05 0.38 0.05]);
aybarr = barh(0,0);
set(axr,'Color','none','YColor','k','XColor','w',...
    'XTick',[0.2 0.4 0.6 0.8 1.0 1.2 1.4],...
    'YTick',[-1 1.4],'XGrid','on','FontName','Tahoma');
xlim([0.1 1.4])

% Querbeschleunigungsbar Dummy erzeugen (links)
axl = axes('Position',[0.02 0.05 0.38 0.05]);
aybarl = barh(0,0);
set(axl,'Color','none','YColor','k','XColor','w',...
    'XTick',[-1.4 -1.2 -1.0 -0.8 -0.6 -0.4 -0.2],...
    'YTick',[-1 1.4],'XGrid','on','FontName','Tahoma');
xlim([-1.4 -0.1])

% Map hinterlegen vorbereiten
    % Index für eine Runde
    start = 4262;
    stop = 5594;
    axmap = axes('Position',[0.8 0.7 0.18 0.28]);
    line(B(start:stop),L(start:stop),'LineWidth',3,'color','black')
    axis([3091.68 3092.16 -836.2 -835.3])
    axis off

% Position Dummy erzeugen
    axpos = axes('Position',[0.8 0.7 0.18 0.28]);
    pos = line('XData',B(1),'YData',L(1),'LineWidth',1,'Marker',...
        'o','MarkerSize',10,'MarkerFaceColor','g');
    axis([3091.68 3092.16 -836.2 -835.3])
    axis off

6. Videoframes einlesen, Daten darüber legen und abspeichern

%% Neues Video vorbereiten
k=0; % k ist der Zähler für die Outputvideodateien, wenn >2GB

new_mov = avifile(['GoProData' num2str(k) '.avi'],...
    'compression','none','quality',100,'fps',fps);

for i=1:frames %Frame für Frame abarbeiten
    clc
    disp([num2str(round(i*100/frames)) '% completed']) %Fortschritt

    zeit = i/fps + offset; % Zeitbezug herstellen

    % dxAviReadMex ist eine Function von Matlabcentral
    % http://www.mathworks.com/matlabcentral/fileexchange/9901
    pixmap = dxAviReadMex(avi_hdl, i);
    pic =  reshape(pixmap,[avi_inf.Height,avi_inf.Width,3])/256;
    set(bild,'CData',pic); % Bild aktualisieren

    index = find(t(:,1)<zeit,1,'last'); % Wert zum aktuellen Frame finden

    % Querbeschleunigung in Balken anzeigen
    if ayf(index)>0 %Linkskurve
        set(aybarr,'YData',ayf(index))
        set(aybarl,'Ydata',0)
    else
        set(aybarl,'YData',ayf(index))
        set(aybarr,'YData',0)
    end

    % Geschwindigkeit setzen
    set(vh,'String',num2str(round(v(index))));

    % Position setzen
    set(pos,'YData',L(index),'XData',B(index));

    drawnow

    new_mov = addframe(new_mov,getframe(fig));

    % 2 GB Dateigrößengrenze beachten
    s = dir(['GoProData' num2str(k) '.avi']);
    if s.bytes >= 2e9 % wenn > 2GB eine neue anlegen
        new_mov = close(new_mov);
        k=k+1;
        new_mov = avifile(['GoProData' num2str(k) '.avi'],...
            'compression','none','quality',100,'fps',fps);
    end
end

7. Videodatei schließen

new_mov = close(new_mov); % File schließen
close all; % Figure schließen

Nachbearbeitung der Videofiles

Wie im Matlab Code zu sehen ist, erzeugt das Script unkomprimierte AVI Files ohne Ton. Diese sind auf ~2GB gesplittet abgespeichert. Nachträglich muss dann noch die Tonspur des Originalvideos mit den Videoteilen zusammengesetzt werden. Das kann man z.B. mit Microsofts Live Movie Maker erledigen. In diesem Fall mit 14min Video in 848x480px Auflösung ergibt sich eine Datenmenge von 25GB, diese sollte man auf der Festplatte zur Verfügung haben.

Ergebnis der Datenvisualisierung mit Matlab

Leave a Reply

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.