Archiv verlassen und diese Seite im Standarddesign anzeigen : Sobel operator und weiteres vorgehen
GrinderFX
02.09.2006, 20:25
Hi!
Über sobel zur kantenerkennung findet man im netz ja relativ viel.
Seltsamerweise kommen fast alle zu unterschiedlichen ergebnissen
Die beiden matrizen sehen fast überall gleich aus. Bis auf manchmal die 1/9 als faktor davor.
1 , 0 , -1
2 , 0 , -2
1 , 0 , -1
und
1 , 2 , 1
0 , 0 , 0
-1,-2 -1,
Wobei da manche auch die minus tauschen(oben oder unten)
Die große frage ist aber, da kommen negative und positive werte über den grenzen von 255 und 0 raus. Kann man ja per hand nachrechnen.
Einige sagen wenn kleiner 0 dann =0 oder größer 255 dann =255.
Andere berechnen den maximalen und minimalen wert und berechnen so die werte.
Guckt man sich nun die beispielbilder von den seiten an und nutzt selber deren anfangsbild, kommt man nicht wirklich auf das selbe ergebnis, da diese seiten,quellen nie die letzte berechnung preisgeben.
Was ist nun wirklich richtig?
Meine bilder gehen immer mehr ins grau.
Wie hier zu sehen ist:
http://de.wikipedia.org/wiki/Sobel-Operator
Mein horizontal und vertikal gefalteter Sobel sehen da noch identisch mit dem beispiel aus. Kombiniere ich aber beide wie dort genannt, sieht mein bild nicht wirklich wie das letzte aus.
Mache ich was falsch oder verheimlichen die nur wieder was?
Poste mal deinen Code, ich machs genau wie bei Wiki und es klappt!
GrinderFX
03.09.2006, 10:01
Die seite weicht am stärksten von allen ab und laut vielen anderen seiten ist das mit dem hsv auch nicht so toll.
Hier mein vertikaler sobel:
void sobel_filtering2( )
/* Spatial filtering of image data */
/* Sobel filter (horizontal differentiation */
/* Input: image1[y][x] ---- Outout: image2[y][x] */
{
/* Definition of Sobel filter in horizontal direction */
int weight[3][3] = { { -1, 0, 1 },
{ -2, 0, 2 },
{ -1, 0, 1 }};
int x_size2,y_size2;
double pixel_value;
double min, max;
int x, y, i, j; /* Loop variable */
/* Maximum values calculation after filtering*/
printf("Now, filtering of input image is performed\n\n");
min = DBL_MAX;
max = -DBL_MAX;
for (y = 1; y < Y - 1; y++) {
for (x = 1; x < X - 1; x++) {
pixel_value = 0.0;
for (j = -1; j <= 1; j++) {
for (i = -1; i <= 1; i++) {
pixel_value += weight[j + 1][i + 1] * picdatagrey[(x+i)+X*(y+j)];//image1[y + j][x + i];
}
}
if (pixel_value < min) min = pixel_value;
if (pixel_value > max) max = pixel_value;
}
}
if ((int)(max - min) == 0) {
printf("Nothing exists!!!\n\n");
return ;
}
printf("max:%f\nmin:%f\n",max,min);
/* Initialization of image2[y][x] */
x_size2 = X;
y_size2 = Y;
for (y = 0; y < y_size2; y++) {
for (x = 0; x < x_size2; x++) {
//image2[y][x] = 0;
picdatafiltert[x+X*y];
}
}
/* Generation of image2 after linear transformtion */
for (y = 1; y < Y - 1; y++) {
for (x = 1; x < X - 1; x++) {
pixel_value = 0.0;
for (j = -1; j <= 1; j++) {
for (i = -1; i <= 1; i++) {
pixel_value += weight[j + 1][i + 1] * picdatagrey[(x+i)+X*(y+j)];//image1[y + j][x + i];
}
}
//printf("sobel:%f\n",pixel_value);
pixel_value = MAX_BRIGHTNESS * (pixel_value - min) / (max - min);
picdatafiltert[x+X*y] = (unsigned char)pixel_value;
}
}
}
Ich berechne vorher noch den maximalen und minimalen wert zur begrenzung.
Mein horizontaler sieht gleich aus, nur andere matrix
und das verbinden:
void verbinden()
{
for(int i=0;i<X*Y;i++)
{
picdatafiltert3[i]=sqrt(picdatafiltert2[i]*picdatafiltert2[i]+picdatafiltert[i]*picdatafiltert[i]);
//picdatafiltert3[i]=(picdatafiltert2[i]+picdatafiltert[i])/2;
}
}
Was mich wundert, wieso die anderen das letzte kombinierte bild so toll schwarz kriegen mit nur den kanten. Bei mir sehen die so aus:
http://mitglied.lycos.de/b534463/vertikal.jpg
http://mitglied.lycos.de/b534463/horizontal.jpg
http://mitglied.lycos.de/b534463/beide.jpg
Von hier hab ich das beispiel:
http://de.wikipedia.org/wiki/Sobel
RedBaron
03.09.2006, 11:01
Hi,
ich bin nicht so fit in C, deshalb kann ich zu deinem Code nichts sagen.
Dein Bild ist im wesentlichen identisch mit dem im Wiki, d.h. die eigentliche Transformation hast du hingekriegt.
Bei der Kombination der Ergebnisse G=sqrt(Gx*Gx + Gy*Gy) müssen wegen des Quadierens immer größere positive Ergebnisse entstehen, d.h. die ganze Sache wird grauer.
Versuche folgendes:
Nur Werte, die einen bstimmten Schwellwert übersteigen, werden hell dargestellt. Den Rest auf den Bereich 0..255 (oder 0..1 je nach Definition) strecken oder stauchen.
Also:
Min: 0
Max: 477
Schwellwert (Sw): 70
Faktor (F) = 255 / (Max - Sw) = 255 / (477-70)
x'= (x-Sw)*Faktor
x''= if (x' >= 0) then x' else 0
(ist jetzt nicht C, sollte aber trotzdem klar sein :-) )
Sw kann man jetzt variieren.
Schau vielleicht einmal hier nach:
http://homepages.inf.ed.ac.uk/rbf/HIPR2/filtops.htm
http://www.codeproject.com/cs/media/Image_Processing_Lab.asp
http://www.medialab.ch/archiv/pdf_studien_diplomarbeiten/1sa01/?C=D;O=A
http://wwwcg.in.tum.de/Teaching/SS2004/ProSem/Workouts/panev/Folien.pdf
Gruß Red Baron
GrinderFX
04.09.2006, 19:20
Danke erstmal für deine antwort.
Also deine untere rechnung verstehe ich vom sinn nicht so ganz.
Sw ist 70 , dachte ich zumindest. Schwellwert (Sw): 70 und dann setzt du 255 ein.
Aber ich hab verstanden was du meinst und kam auf ein passables ergebnis.
Nun kommt die alles entscheidene frage. Wie geht man weiter vor?
Ich meine, ich könnte nun selber was ausdenken und versuchen das objekt meiner wahl zu erkennen, aber das wäre äußerst ineffektiv.
Dazu habe ich bis heute noch nichts sinnvolles gefunden.
RedBaron
05.09.2006, 21:14
Hallo GrinderFX,
du hast recht, ich habe mich verschrieben, hätte 70 sein sollen. Hab's korrigiert.
Was genau möchtest du denn erkennen? Und vielleicht auch wozu? Je nach dem was man erreichen möchte, gibt es unterschiedliche Ansätze. Bisher hast du nur eine Bitmap mit ein paar mehr oder weniger schwarzen Punkten, die mehr oder weniger zusammenhängen...
Ich habe 'mal ein Programm geschrieben, mit dem habe ich meinen ASURO mit Hilfe einer WebCam verfolgt. Dazu habe ich noch nicht einmal eine Kantenerkennung benötigt.
Ohne deine Fragestellung zu kennen, kann man wenig sagen.
Gruß Red Baron
GrinderFX
05.09.2006, 21:39
Mein erstes ziel ist erstmal das erkennen eines hefters den ich in der hand halte. Ein normaler Din A4 hefter.
Später soll ein rundes objekt erkannt werden bzw. sogar eine bewegungs/geschwindigkeitsmessung.
Aber erstmal den hefter in halbwegs echtzeit erkennen.
Zuerst würde aber das erkennen des hefters in einem normalen bild reichen.
Wie in dem hier:
http://mitglied.lycos.de/b534463/hefter.jpg
Die meisten tutorials und bücher hören nach der kantenerkennung leider auf.
RedBaron
05.09.2006, 22:25
Hallo GrinderFX,
möchtest du diesen speziellen Hefter immer wieder erkennen und ihn von anderen Heftern oder Objekten unterscheiden können? Sprich Musterekennung machen? Was soll das Ergebnis einer solchen Erkennung sein? Etwa so: Nenn mir die 4 Eckpunkte eines jeden dunklen ungefähren Vierecks auf einem leidlich grauen Hintergrund? Mit diesen Punkten könnte man eine Menge machen, z.B. sie verbinden, dann hätte man die Umrisse. Wenn du das möchstest, musst du eine Möglichkeit finden, wie man die schwarzen Punkte der Bitmap zu einer Linie verkettet (Lückenschluss, etc). Dann die Linien in eine mathematische Form bringen (z.B. Angabe der beiden Endpunkte) und dann schauen, welche Linien gehören zu welchem Objekt bzw. machen die Umrandung des Objekts aus. Für das letztere benötigst du dann ein gutes Modell der Welt (und der möglichen Objekte).
Oder geht es eher darum ein Objekt im Fokus zu behalten? Für dieses Problem habe ich, wie oben schon erwähnt, mal ein Programm geschrieben. Das ging etwa so:
Ich habe das Objekt, das ich verfolgen wollte farblich markiert (Dein Ordner hat ja auch eine einheitliche Farbe). Ich habe auf meinen ASURO ein rotes Stück Papier geklebt, etwa 5x5cm² groß.
Ich habe das Bild der Kamera auf dem PC angezeigt und mit der Maus das Objekt angeklickt. Damit habe ich das Problem gelöst, welcher der vielen möglichen Farbkleckse bzw. Ordner der richtige ist. Um diesen Klick herum habe ich alle Punkte mit ähnlicher Farbe genommen (das löst das Problem der fest vorgegebenen Farbe) und die Lücken geschlossen. Vom Rest habe ich dann den Schwerpunkt berechnet. Das war dann der Mittelpunkt des Objekts. Unter der Annahme, dass mein Objekt sich nicht all zu schnell bewegt, habe ich vom alten Mittelpunkt ausgehend, den ganzen Vorgang erneut ablaufen lassen. Somit hatte ich als Ergebnis eine Folge von Koordinaten, auf denen sich mein Objekt bewegt hat. Ein Durchlauf dauerte knapp 100 mSec. Ich kam auf 12-13 Durchläufe pro Sekunde. Das sollte Echtzeit genug sein. Falls dich weitere Details interessieren, lass es mich wissen.
Gruss Red Baron
Kantenerkennung und Hough-Transformation. Damit erkennst du dann die Linien und kannst schaun wo sie sich schneiden um die Eckpunkte zu bekommen. Allerdings darfste das Ding halt nich wirklich drehen, jenachdem wie du die Erkennung progst...
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.