email: r.honeder[at]gmx.at

KONTAKT

informatik

12. April 2008

Apple Safari für Windows

Der Safari ist seit einiger Zeit (endlich) auch für Windows verfügbar. Ein sehr eleganter und vor allem schneller Browser.

Download

9. April 2008

Neue Seite online

Unter www.thomas-immervoll.net ist seit heute eine meiner jüngeren Arbeiten online.

thomas

Als Basis für die Entwicklung diente das Zend Framework, das mich mittlerweile sehr überzeugt. Verwendet habe ich die schon etwas ältere 1.04er Release, mittlerweile ist 1.5 erschienen.

Für die Pflege der Inhalte habe ich auf dieser Grundlage ein kleines (und für mich wiederverwendbares) CMS entwickelt. Sämtliche Inhalte der Seite können dadurch sehr einfach modifiziert werden. Das Menü stammt ebenfalls aus der Datenbank und kann bei Bedarf sehr leicht angepasst und geändert werden. (Der Punkt "Publications" ist noch deaktiviert, da keine Publications vorhanden sind.)
Weiters unterstützt die Seite Mehrsprachigkeit und ist um einige Stufen zoombar - ohne dass das Layout bricht. 100% valide.

Für Feedback bin ich immer dankbar. Internet Explorer 5.0 und 5.5 werden von mir - zumindest bei solch kleinen Seiten - nicht mehr unterstützt.

21. August 2007

Neuronale Netze

Neuronale Netze bilden die Struktur und Informationsarchitektur von Gehirn und Nervensystem von Tieren und Menschen: Neuronen und Glia [Gliazellen, "Stützgerüst" für Neuronen; Anm.] sind in der Art eines Netzes miteinander verknüpft. Zwischen ihnen findet auf chemischem und elektrischem Weg ein Informationsaustausch statt.



Input Units (rot): empfängt ein Signal (Reiz)
Hidden Units (gelb): "interne Repräsentation" der Außenwelt
Output Units (grün): sendet Signal an die Außenwelt

Ein künstliches neuronales Netz besteht i.d.R. aus 10 bis 1000 Einheiten (Units). (Im Vergleich: das menschliche Gehirn verfügt über/besteht aus etwa 10 000 000 000 Neuronen).
Die Einheiten sind über Kanten miteinander verbunden. Die Stärke der Verbindung (also der Kante) wird durch ein Gewicht ausgedrückt (positive Gewichte - erregender Einfluß, negative Gewichte - hemmender Einfluß, null - kein Einfluß).

Anwendung:
Seine besonderen Eigenschaften machen das KNN bei allen Anwendungen interessant, bei denen kein bzw. nur geringes explizites (systematisches) Wissen über das zu lösende Problem vorliegt. Dies sind z.B. die Texterkennung, Bilderkennung und Gesichtserkennung, bei denen einige Hunderttausend bis Millionen Bildpunkte in eine im Vergleich dazu geringe Anzahl von erlaubten Ergebnissen überführt werden müssen.

Lernverfahren:
Lernverfahren dienen dazu, ein neuronales Netz dazu zu bringen, für bestimmte Eingangsmuster zugehörige Ausgabemuster zu erzeugen. Dies geschieht grundsätzlich auf drei verschiedenen Wegen.
Es wird zwischen überwachtem, bestärkendem und unüberwachtem Lernen unterschieden."

Theoretisch kann ein Netz durch folgende Methoden lernen:
- Entwicklung neuer Verbindungen, bzw. Löschen bestehender Verbindungen
- Anpassen der Gewichte wij von Neuron i zu Neuron j
- Anpassen der Schwellwerte der Neuronen
- Hinzufügen oder Löschen von Neuronen

[Sources:
Künstliches Neuronales Netz - de.wikipedia.org
www.neuronalesnetz.de]

23. Juni 2007

Support Vector Machines

"Often we are interested in classifying data as a part of a machine-learning process. Each data point will be represented by a p-dimensional vector (a list of p numbers). Each of these data points belongs to only one of two classes. We are interested in whether we can separate them with an "p minus 1" dimensional hyperplane." (en.wikipedia.org)

In einem älteren Eintrag habe ich beispielhafte (und sehr rudimentäre) Methoden vorgestellt, Audio- bzw. Videomaterial anhand bestimmter, aus gegebenem Material errechneter Merkmale nach Ähnlichkeit zu einem Ausgangsmedienobjekt hin zu sortieren. Die vorgestellten Features (Zero Crossing für Audio, Bildbewegungsintensität über optical flow sowie Intensitäten für Video) funktionierten für die gegebenen Files einigermaßen gut. (ZC - Häufigkeit des Vorzeichenwechsel in einem Audiosignal - ist übrigens gut für die Unterscheidung von Tierstimmen - etwa Katzen, Vögel, etc. - geeignet). Aus der richtigen Kombination verschiedener Features mögen sich bessere Klassfizierungen bzw. Reihungen ergeben.
Natürlich bleibt zumeist eine Unschärfe, d.h., der User - er fordert die n ähnlichsten Objekte zu einem Ausgansobjekt an - erhält in den meisten Fällen auch einige irrelevante Treffer; je nach Qualität des Information Retrieval Systems und dem gelieferten Input variieren diese freilich in ihrer Anzahl.
An diesem Punkt kommen SVMs zum Tragen. Für Matlab habe ich osu svm verwendet.

Unser Ausganspunkt:
Wir wählen ein Medienobjekt als Input, das System errechnet uns die besten neun Treffer anhand unserer Features und dem gewählten Distanzmaß, und präsentiert diese dem Anwender:
screenshot

(Diese Matlab GUI ist, wie man sogleich bemerkt, eine verderbte Schönheit!).

Der Anwender kann die zurückgegeben Treffer nun überprüfen, und falls ein "Treffer" aus dem Rahmen fällt, diesen als irrelevant markieren. (Man sollte, dies habe ich nicht berücksichtigt, auch die Möglichkeit schaffen, Treffer als neutral zu kennzeichnen).
Unsere Daten, d.h. alle berechneten Vektoren aller analysierten Medienfiles, liegen übrigens in einer nxm Matrix vor (Zeile die Vektoren pro File), die wir, um sie für SVMTrain in die korrekte Form zu bringen, transponieren müssen.

Hat der User seine Entscheidung getroffen, d.h. die Samples markiert, ergibt sich uns demnach eine Menge von neun gekennzeichneten Objekten. Diese benötigen wir für das Training der SVM.
osu svm stellt dazu die Funktion SVMTrain zur Verfügung, die als Input die Vektoren der Samples und deren Label (relevant, is not relevant) erwartet. Zwei weitere - optionale - Parameter, nämlich Parameters und Weight stehen zur Verfügung. Unter Parameters lässt sich zum Beispiel der zu verwendende Kernel Typ (Linear = default, Polynoimal, RBF - Radial Basis Function, sowie sigmoid) oder der SVM Type (C SVC - default, nu SVC etc) definieren.
[AlphaY, SVs, Bias, Parameters, nSV, nLabel] = SVMTrain(Samples, Labels, Parameters, Weight).

Der Output der Funktion ist u.a. (aus der Dokumentation @ http://svm.sourceforge.net/docs/3.00/api/SVMTrain.html):
AlphaY: Alpha * Y where the Alpha vector contains the non-zero Lagrange Coefficients and Y are the corresponding labels.
SVs: The Support Vectors (M x sum(nSV) matrix) for this classifier/regressor-- the samples corresponding to the non-zero Lagrange multipliers AlphaY. A M x sum(nSV) matrix of sum(nSV) support vectors in M dimensions.
Bias:
- Binary Classification/Outlier Detection/Regression: A scalar value representing the bias or threshold of the SVM classifier.
- Multi-class Classification: A (1x(L*(L-1)/2)) row vector of biases for all the two-class classifiers.

Nachdem das (erste) Training der SVM vollzogen ist - wir ließen Paramter in diesem Test außer Acht -, können wir SVMClass verwenden. Wir übergeben dazu die aus SVMTrain gewonnen Informationen sowie alle Vektoren der analysieren Medienfiles an die Funktion SVMClass. Das System versucht anhand der zuvor erhaltenen Informationen (AlphaY, Bias etc.) zu erkennen, welche Medienfiles relevant sind und welche nicht. Nicht relevante Mediendateien können sodann von vornherein ausgeschlossen werden. Dem User ist allerdings freigestellt, weiterhin als nicht relevant erkannte Objekte zu markieren und eine erneute Query durchzuführen (=Refinement).

Graphisch lässt sich das so darstellen:

(http://en.wikipedia.org/wiki/Support_vector_machine#Motivation)

Die Hyperebene(n) trennt relevante von nicht relevanten Daten, allerdings erreicht nur genau eine Hyperebene die maximale Trennung zwischen den beiden Klassen. Die Stichproben entlang der Hyperebenen werden Support Vectors (SVs) genannt (siehe oben). Zumeist sind die Trainingsdaten nicht streng linear teilbar (Überlappungen, Messungenauigkeiten, etc).


Resources: http://www.dtreg.com/svm.htm

Die Qualität eines solchen Information Retrieval Systems lässt sich übrigens via Recall(Vollständigkeit) und Precision (Genauigkeit) beurteilen:


(de.wikipedia.org/wiki/Recall_und_Precision)

Musik & Algorithmen

Ein kleiner Einblick in die "algorithmische Komposition" mit chuck; samt Hörbeispiel... :)

Wir verwenden dazu
- einen Voss Generator für die Steuerung der Lautstärke
- ein L System für Tonhöhe und Tondauer.

Für das L System definieren wir zuerst vier Regeln:
A -> ABC
B -> BAD
C -> DDA
D -> CBC

nach n Rekursionen erhalten wir nach dieser Regel:
für n gleich 1: ABC
für n gleich 2: ABCBADDDA
für n gleich 3: ABCBADDDABADABCCBCCBCCBCABC
für n gleich 5: ABCBADDDABADABCCBCCBCCBCABCBADABCCBCABCBADDDADDABA
DDDADDABADDDADDABADDDAABCBADDDABADABCCBCABCBADDDADDABADDDAAB
CBADDDABADABCCBCCBCCBCABCCBCCBCABCBADABCCBCCBCCBCABCCBCCBCAB
CBADABCCBCCBCCBCABCCBCCBCABCBADABCCBCCBCCBCABCABCBADDDABADAB
CCBCCBCCBCABC

usw.

Natürlich ließen sich auch Symbole verwenden, die nicht auflösbar sind.

Zuerst übersetzen wir das L System in eine Funktion (anstelle von strings werden wir mit integer arbeiten).

Die Variable symbol (ein eindimensionales Array) von der Länge hundert hält am Ende alle Symbole, und zwar genau ein Symbol pro Zeile.
[1]... zeile 1
[3]... zeile 2
[2]... zeile 3
usf.

Als Parameter benötigt die Methode das Startsymbol sowie die verwendeten Regeln. Die Funktion ist unelegant (und sehr einschränkend) programmiert, allerdings stabil.

Eine weitere Methode weist einem Symbol die Symbole der verknüpften Regel zu - auf ein Symbol kommen lt. Regelwerk stets genau drei Symbole.

Das funktioniert natürlich nur dann, wenn die Regeln dem aus der for Schleife implizierten "Muster" entsprechen: würde eine Regel A->BC lauten, fände man zusätzliche Nullen im Array vor, etc. Leider ist chuck z.T. sehr unflexibel - stringfunktionen sind z.B. sehr schlecht (und deshalb auch der Rückgriff auf Arrays), die Größe von Arrays muss vor der Initialisierung bekannt sein, und - zu guter letzt - die tatsächliche Länge eines Arrays lässt sich (soviel ich weiß) nicht feststellen (natürlich kann man diese Dinge selbst implementieren, doch uns soll vorerst dieser einfache Ansatz ausreichend sein).

Das Resultat (der Rückgabewert der Funktion) ist das Array symbol, das - Stelle für Stelle - die durch das L System bedingten Symbole hält.

Nachdem die Symbole berechnet sind - und dies war auch schon die schwierigste Arbeit - muss man die einzelnen Symbole mit bestimmten Tonfolgen (es könnten auch einzelne Töne sein) verknüpfen, die in weiterer Folge entsprechend aufgerufen werden. Dies geschieht in der main loop. Unsere Bedingung ist, dass diese main loop "unendlich lange" laufen soll.

Die Funktion melody hält nichts anderes als verschiedene 2dimensionale Arrays, die einem Symbol zugewiesen sind. Wird in der main loop als Parameter z.B. "1" übergeben, erhält man die damit verknüpfte "Melodie" (Tonhöhe + Tondauer aller zu spielenden Töne) zurück.

Die main loop durchläuft das Symbol Array (und erzeugt bei Bedarf ein neues) und sorgt für die Klangausgabe, wobei verschiedene zufällige Parameter für etwas mehr Varianz sorgen; dazu haben ich insgesamt vier Tonleitern definiert, pro Durchlauf wird eine Tonleiter gewählt.

3. Mai 2007

Video Features etc.

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.
cuterkennung

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.

20. April 2007

ChucK

Ein Klangbeispiel für einen in ChucK realisierten "Sequencer" - er entstand im Rahmen der VU Audio bei Jörg Piringer im SS07. Der Sequ. spielt einige kurze Töne, dann die ersten Akkorde von Händels Sarabande, allerdings sind diese Akkorde ein bisserl "vertauscht"... ;) Am Ende macht sich der Sequencer gar selbstständig. Mehr über ChucK. Also: Sequencer + Subtraktive Synthese. Wir haben drei Oszillatoren (Sinus, Pulse, Sägezahn), die durch einige Effekte laufen (Resonanz, Chorus, Reverb, Low Pass, Hüllkurve), und schließlich ausgegeben werden (dac). //Three Main Osciallators SinOsc snOsc => ResonZ resonance => Chorus chorus => PRCRev reverb => LPF filter => ADSR envelope =>Gain g => dac; SawOsc sawOsc => resonance => chorus => reverb => filter => envelope => g ; PulseOsc plsOsc => resonance => chorus => reverb => filter => envelope => g ; etc. etc. Der Sequencer hält alle Toninformationen. Eine Zeile setzt sich aus folgenden Params zusammen: /* SEQUENCER / [length][pitch][lfo_freq][lfo_gain][ressonance, use .0 - .9][cutoff_freq][REVERB, use .1 - 1] / [chor_freq][chor_depth][chor_mix][GAIN][freq_diff for pulseOsc][freq_diff for sawOsc] / [adsr_att_time][adsr_del_time][adsr_sustain][adsr_release] */ Es folgt der große Spaß - die "Programmierung" des Sequencers. Wir sagen ihm, welche Töne er wie lange und mit welchen Effekten zu spielen hat. Dies geschieht über ein zweidimensionales float Array: [ [300.0, 261.6, 2.0, 1.0, .2, 3000, .1, .0, .0, .0, .1, -10, 40, 200,20, 1,20], [300.0, 523.3, 4.0, 2.0, .2, 2900, .2, .1, .1, .1, .2, 10, 30, 0, 20, 1, 20], [300.0, 261.6, 8.0, 3.0, .3, 2800, .1, .2, .2, .2, .2, -10, 40, 240,20, 1, 20], [300.0, 523.3, 16.0,3.0, .4, 2700, .2, .5, .4, .5, .3, 10, -34, 0,6, 5, 20] ] @=> float sequencer[][]; Jede Zeile steht demnach für einen "Ton", die einzelnen Spalteneinträge definieren bestimmte Parameter (Tondauer in ms, Frequenz, relative Frequenz der beiden anderen Osc., Effekteinstellungen...). Gain g kontrolliert die Ausgangsvolume. ChucK übersteuert leicht, demnach ist Vorsicht geboten, insbesondere wenn man mit Kopfhörern vorm PC sitzt und mit Effekten hantiert... In einer main loop werden die Parameter aus den einzelenen Zeilen gelesen, gesetzt und der Ton wird gespielt. Das klingt dann über das loop so wie das Klangbeispiel.

ausstellung
informatik
literatur
musik
nachrichtensprecher
Profil
Abmelden
Weblog abonnieren