Ziel: Klassifizieren von Filmmaterial (+ Audiomaterial).
Zuerst wird ein Feature aus dem gegebenen Material extrahiert. Solche Features könnten z.B. Bewegungsintensität und die durschnittliche (Grauwert)Intensität sein.
Um das Material aufzubereiten, sollte der Film vor der Featureextraktion in entsprechende Sequenzen (automatische Schnitterkennung) geteilt werden. Dazu gibt es verschiedene Verfahren - im Allgemeinen ist es leichter, harte Schnitte zu erkennen.
-) Kantendifferenz: ein (harter) Schnitt liegt dann vor, wenn die Anzahl der Kanten eines Frames um einen bestimmten Betrag höher bzw. niedriger ist als im vorhergehenden. Es lässt sich dazu ein Threshold angeben.
Um die Kanten festzustellen, gibt es in Matlab die Funktion edge, die als Parameter (zumindest) ein Graustufenbild und eine Kantenerkennungsmethode (z.B. 'canny') erwartet.
f_prevEdge = edge(rgb2gray(f_prev),'canny');
f_prevEdge - das Resultat - ist eine Matrix, die gefundene Kanten als 1en darstellt:
0 0 0 0 1 0 0 1 1 1 0 1
1 1 1 0 0 0 0 1 0 0 1 0
0 0 1 0 1 0 1 0 0 1 0 1
Obige nxm Matrix (n=12, m=3) stellt ein 12x3 großes Bild - bzw seine Kanten - dar.
Somit lässt sich über den Befehl sum(f_prevEdge) einfach die enthaltene Anzahl an Kanten berechnen. (Hier 15).
Eine andere Methode zur Erkennung harter Schnitte ist die sog. "Chi Quadrat" Methode. Ihr Ansatz besteht darin, 2 aufeinanderfolgendene Frames in 16 Blöcke zu zerteilen und die durschn. RGB Intensität/Block zu berechnen. In Schritt 2 vergleicht man die "zusammengehörigen" Bildblöcke dieser beiden Frames. Diejenigen 8 Blöcke, deren Diff. einen angegebenen Threshold überschreitet, werden verworfen. Über die gemittelte Differenz der restlichen Blöcke lässt sich gegebenfalls ein Schnitt erkennen, so die Diff. erneut einen Threshold überschreitet.
Abszissenachse: Frames.
Ordinatenachse: ermittelte Kanten.
1.) Videofeature
Für die Videomerkmalsextrahierung habe ich beschlossen, die Bewegungsintensität (Anzahl bewegter Objekte + Bewegungsgeschwindigkeit) und die durschnittl. Grauwertintensität des Filmes zu berechnen.
Am Ende einer Analyse erhält man einen Vektor der Form [x y z]. Sollte zumindest, so kein fatal error auftritt...
x repräsentiert das Verhältnis aller Blöcke / bewegter Blöcke. Bewegter Block liegt dann vor, wenn der Betrag des Vektors ~= 0 ist.
y repräsentiert den durchschnittlichen Betrag aller Vektoren. (Generell: je länger ein Vektor, desto stärker bewegt sich ein Block). Dies wird umgerechnet auf eine Intensität zw. 0 - 100. 0 = kein Block hat sich bewegt, 100 drückt aus, dass sich alle Blöcke bewegt haben. Hier ließe sich z.B. zwischen Nachrichtensendungen (Moderation) und Sportsendungen etc. eine Merkmalsdifferenz ermitteln. Es sei denn, man hat es mit Golf zu tun...
z ist die durchschnittliche Grauwertintensität des gesamten Filmes. (Theoretisch Werte zw. 0 und 255 möglich).
Bsp.haftes Resultat: 84.186 27.0788 201.7178]
3 Kernfunktionen: videofeature -> opticalflow -> blockmatching.
a) Die Funktion "Videofeature" nimmt das Filmmaterial entgegen, und übermittelt zwei jeweils nachfolgende Frames an die Funktion opticalflow. Videofeature kennt zwei Parameter, zum einen den Dateinamen (avi), sowie die Block Matching Size (mbSize). Diese ist für den optical flow wichtig, da man auch hier die Frames(Bilder) in Blöcke teilt. Eine Standardgröße für einen Block wäre z.b. 8x8 Pixel.
for k = 2:avi_inf.NumFrames
f_prev = avi_in(k-1).cdata; %previous frame
f_now = avi_in(k).cdata;
vec_temp = opticalFlow(f_prev, f_now, mbSize);
vvec(k-1,:) = vec_temp;
end
In dieser for loop (wir beginnen bei Frame 2 und enden beim letzten Frame des Movies), belegten wir 2 temporäre images mit den jeweiligen Bilddaten, die an die Funktion opticalFlow übergeben werden.
b) opticalflow
for curblock_y = 1:blocks_y
for curblock_x = 1: blocks_x
k = k+1;
temp_img = cell2mat(seg(curblock_x,curblock_y));
%array with all the intensity per block
inttemp(k) = blockIntensity(temp_img);
%do a blockmatch
v_end(k,:) = blockMatch(frame_now, mbSize, inttemp(k),mbSize);
v_start(k,:) = [(curblock_x*mbSize)-mbSize+1 (curblock_y*mbSize)-mbSize+1]; %erster pixel
end
end
Blockweise wird der erste Frame durchgegangen, pro Block berechnet man die Intensität, und der Blockmatch (funktion blockMatch) berechnet. Als Rückgabe die Koordinate des passenden Blocks. (hier v_end -> Endpunkt des Vektors; v_end demgemäß der Startpunkt).
c) blockmatch, Parameter: gesuchte Intensität (sInt), Schrittweite, zu durchsuchendes Image.
Eine (sehr einfache) Implementation eines Blockmatching Algorithmus. Merkmale: full search (das gesamte Bild wird nach passenden Blöcken durchsucht - Nachteil: Performance), und angabe einer Schrittweite. Der Suchblock wird über das gesamte Bild verschoben, die Schrittweite gibt an, in welchen Schritten das erfolgt (1 = pixelweise). Ein guter Kompromiss ist es, die Schrittweite im Intervall [mbSize/2,mbSize] zu wählen.
for cur_y = 1:stepSize:max_y %jede reihe
for cur_x = 1:stepSize:max_x %jede spalte
k = k+1;
temp_img = imcrop(img, [cur_x cur_y mbSize-1 mbSize-1]);
temp_intensity = abs(sInt - blockIntensity(temp_img));
if (temp_intensity < intensity)
intensity = temp_intensity;
temp_vector = [cur_x cur_y];
end
end
cur_x = 1; %spalte auf 0 setzen
end
Zurückgegeben werden die Koordinaten des entsprechenden Blockes.
Daraus lassen sich in den obigen Funktionen die Vektoren zusammenbauen und analysieren.
2.) Audiofeatures
-) Zero Crossing Rate (ZC) -> Nullkreuzungsrate. => Anzahl der Vorzeichenwechsel in einem Frame.
-) Center Frequency
Das Signal wird in Frames gleicher Länge unterteilt. Ein Frame enthält z.B. 10000 Samples. Pro Frame werden die features berechnet und am Ende gemittelt. Bei Cepstrum (= "Spektrum eines Spektrums", Einheit Qufrequenz; inverse Fourier Transformation des logarithmierten Spektrums) Features sollte allerdings
nicht gemittelt werden.
%center freq
ft=fft(signal.*hamming(length(signal)));
ceps = fft(log(abs(ft)+eps));
cfreq(k)=max(abs(ceps(max_herz:min_herz)));
Berchne die Fast Fourier Transformation eines Signals (signal).
ad hamming: hamming(n) returns an n-point symmetrically sampled Hamming window in the column vector w. n should be a nonnegative integer.
%zero crossing
zc = (signal >= thresh) - (signal < thresh);
zcrossing(k) = sum((zc(1:length(signal)-1) - zc(2:length(signal))) ~= 0);
todo: mehr Cepstrum features berechnen.