Ich bin im Moment dabei einen Algorithmus zur Skelettierung in C# zu implementieren.
Dabei soll der Zhang-Suen Thinning Algorithmus ganz gut sein.
Hier habe ich eine Java-Implementierung gefunden und sie versucht zu übersetzen. nayefreza.wordpress.com/2013/0…ithm-java-implementation/
Der unten stehende Code ist dabei rausgekommen.
Klappt auch sehr gut, aber ist extrem langsam. (ca. 15sek. bei 1000x300 Pixeln)
Ich habe schon versucht den Algorithmus abschnittweise arbeiten zu lassen. (Nicht über das ganze Bild, sondern nur über relevante Abschnitte)
Da kam aber ein sehr komisches Ergebnis raus.
Meine Frage ist ob jemand eine Idee hat wie man das ganze beschleunigen kann?
(Paralell.For habe ich schon probiert)
Könnte man vielleicht Zeiger einsetzten?
Oder kennt jemand eine andere Methode die vielleicht schneller ist?
Grüße![:)](https://www.vb-paradise.de/wcf/images/smilies/smile.png)
Implementierung
Spoiler anzeigen
Angaben zum Code:
Gearbeitet wird mit einem
Dieses wird per
Anhang: Wie es später mal aussehen soll. (Nur damit man sich etwas drunter vorstellen kann)
Dabei soll der Zhang-Suen Thinning Algorithmus ganz gut sein.
Hier habe ich eine Java-Implementierung gefunden und sie versucht zu übersetzen. nayefreza.wordpress.com/2013/0…ithm-java-implementation/
Der unten stehende Code ist dabei rausgekommen.
Klappt auch sehr gut, aber ist extrem langsam. (ca. 15sek. bei 1000x300 Pixeln)
Ich habe schon versucht den Algorithmus abschnittweise arbeiten zu lassen. (Nicht über das ganze Bild, sondern nur über relevante Abschnitte)
Da kam aber ein sehr komisches Ergebnis raus.
Meine Frage ist ob jemand eine Idee hat wie man das ganze beschleunigen kann?
(Paralell.For habe ich schon probiert)
Könnte man vielleicht Zeiger einsetzten?
Oder kennt jemand eine andere Methode die vielleicht schneller ist?
Grüße
![:)](https://www.vb-paradise.de/wcf/images/smilies/smile.png)
Implementierung
C#-Quellcode
- private float maxBrightness = 0.9f;
- private const uint WHITE = 4294967295;
- public uint[] Thinning(uint[] buffer, int originX, int originY, int xWidth, int xHeight, int width, int height)
- {
- int a, b;
- List<Point> lpointsToChange = new List<Point>();
- bool hasChange;
- do
- {
- hasChange = false;
- for (int y = originY; y < originY + xWidth; y ++)
- {
- for (int x = originX; x + 1 < originX + xWidth; x++)
- {
- a = getA(buffer, y, x, width, height);
- b = getB(buffer, y, x, width, height);
- if (y > 0 && y + 1 < height && x > 0 && x + 1 < width)
- {
- int p1 = GetValueOfColor(buffer[y * width + x]);
- int p2 = GetValueOfColor(buffer[(y - 1) * width + x]);
- int p3 = GetValueOfColor(buffer[(y - 1) * width + x + 1]);
- int p4 = GetValueOfColor(buffer[(y) * width + x + 1]);
- int p5 = GetValueOfColor(buffer[(y + 1) * width + x + 1]);
- int p6 = GetValueOfColor(buffer[(y + 1) * width + x]);
- int p7 = GetValueOfColor(buffer[(y + 1) * width + x - 1]);
- int p8 = GetValueOfColor(buffer[(y) * width + x - 1]);
- int p9 = GetValueOfColor(buffer[(y - 1) * width + x - 1]);
- if (p1 == 1 && 2 <= b && b <= 6 && a == 1
- && (p2 * p4 * p6 == 0)
- && (p4 * p6 * p8 == 0))
- {
- lpointsToChange.Add(new Point(x, y));
- hasChange = true;
- }
- }
- }
- }
- foreach (Point p in lpointsToChange)
- buffer[p.Y * width + p.X] = WHITE;
- lpointsToChange.Clear();
- for (int y = originY; y < originY + xWidth; y++)
- {
- for (int x = originY; x + 1 < originX + xWidth; x++)
- {
- a = getA(buffer, y, x, width, height);
- b = getB(buffer, y, x, width, height);
- if (y > 0 && y + 1 < height && x > 0 && x + 1 < width)
- {
- int p1 = GetValueOfColor(buffer[y * width + x]);
- int p2 = GetValueOfColor(buffer[(y - 1) * width + x]);
- int p3 = GetValueOfColor(buffer[(y - 1) * width + x + 1]);
- int p4 = GetValueOfColor(buffer[(y) * width + x + 1]);
- int p5 = GetValueOfColor(buffer[(y + 1) * width + x + 1]);
- int p6 = GetValueOfColor(buffer[(y + 1) * width + x]);
- int p7 = GetValueOfColor(buffer[(y + 1) * width + x - 1]);
- int p8 = GetValueOfColor(buffer[(y) * width + x - 1]);
- int p9 = GetValueOfColor(buffer[(y - 1) * width + x - 1]);
- if (p1 == 1 && 2 <= b && b <= 6 && a == 1
- && (p2 * p4 * p8 == 0)
- && (p2 * p6 * p8 == 0))
- {
- lpointsToChange.Add(new Point(x, y));
- hasChange = true;
- }
- }
- }
- }
- foreach (Point p in lpointsToChange)
- buffer[p.Y * width + p.X] = WHITE;
- lpointsToChange.Clear();
- } while (hasChange);
- return buffer;
- }
- private int GetValueOfColor(uint value)
- {
- return (value.GetBrightness() <= maxBrightness) ? 1 : 0;
- }
- private int getA(uint[] buffer, int y, int x, int width, int height)
- {
- // 1 = black 0 = white
- // helligkeitswerte 1-weiß 0-schwarz
- if (y > 0 && y + 1 < height && x > 0 && x + 1 < width)
- {
- int p2 = GetValueOfColor(buffer[(y - 1) * width + x]);
- int p3 = GetValueOfColor(buffer[(y - 1) * width + x + 1]);
- int p4 = GetValueOfColor(buffer[(y) * width + x + 1]);
- int p5 = GetValueOfColor(buffer[(y + 1) * width + x + 1]);
- int p6 = GetValueOfColor(buffer[(y + 1) * width + x]);
- int p7 = GetValueOfColor(buffer[(y + 1) * width + x - 1]);
- int p8 = GetValueOfColor(buffer[(y) * width + x - 1]);
- int p9 = GetValueOfColor(buffer[(y - 1) * width + x - 1]);
- int count = 0;
- //p2 p3
- if (p2 == 0 && p3 == 1) count++;
- //p3 p4
- if (p3 == 0 && p4 == 1) count++;
- //p4 p5
- if (p4 == 0 && p5 == 1) count++;
- //p5 p6
- if (p5 == 0 && p6 == 1) count++;
- //p6 p7
- if (p6 == 0 && p7 == 1) count++;
- //p7 p8
- if (p7 == 0 && p8 == 1) count++;
- //p8 p9
- if (p8 == 0 && p9 == 1) count++;
- //p9 p2
- if (p9 == 0 && p2 == 1) count++;
- return count;
- }
- else
- return 0;
- }
- private int getB(uint[] buffer, int y, int x, int width, int height)
- {
- if (y > 0 && y + 1 < height && x > 0 && x + 1 < width)
- {
- int p2 = GetValueOfColor(buffer[(y - 1) * width + x]);
- int p3 = GetValueOfColor(buffer[(y - 1) * width + x + 1]);
- int p4 = GetValueOfColor(buffer[(y) * width + x + 1]);
- int p5 = GetValueOfColor(buffer[(y + 1) * width + x + 1]);
- int p6 = GetValueOfColor(buffer[(y + 1) * width + x]);
- int p7 = GetValueOfColor(buffer[(y + 1) * width + x - 1]);
- int p8 = GetValueOfColor(buffer[(y) * width + x - 1]);
- int p9 = GetValueOfColor(buffer[(y - 1) * width + x - 1]);
- return p2 + p3 + p4 + p5 + p6 + p7 + p8 + p9;
- }
- else
- return 0;
- }
Angaben zum Code:
Gearbeitet wird mit einem
uint
-Array, welches die Farbwerte jeden Pixel beinhaltet.Dieses wird per
LockBits
erzeugt. (Die Zeit bis die Bitmap "gelockt" ist sind in den 15. Sekunden nicht enthalten)Anhang: Wie es später mal aussehen soll. (Nur damit man sich etwas drunter vorstellen kann)