Autor |
Beitrag |
C#
![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png)
Beiträge: 561
Erhaltene Danke: 65
Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
|
Verfasst: Do 17.01.13 16:56
Hallo,
hat jemand ein gutes Bespiel um einen Viertelkreis zuverlässig aus einem Color[,] herausfiltert.
Ich möchte damit erkennn wo sich entsprechender Viertelkreis befindet und ihn durch ein Eck ersetzen.
Praktisch soll später aus einem ( ein [ werden. Das ( als Halbkreis vorstellen.
//EDIT
Es handelt sich übrigens um eine Monochrome Bitmap, also habe ich nur schwarz und weiß, was die Farberkennung recht einfach gestaltet.
_________________ Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
|
|
Palladin007
![Palladin007 hat insgesamt 89.9% On-Topic und 10.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![Palladin007 hat insgesamt 89.9% On-Topic und 10.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![Palladin007 hat insgesamt 89.9% On-Topic und 10.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![Palladin007 hat insgesamt 89.9% On-Topic und 10.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![Palladin007 hat insgesamt 89.9% On-Topic und 10.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![Palladin007 hat insgesamt 89.9% On-Topic und 10.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![Palladin007 hat insgesamt 89.9% On-Topic und 10.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png)
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Fr 18.01.13 00:07
Wirklich eine Antwort habe ich nicht, aber ich habe eine Idee, wie es vielleicht funktionieren könnte.
Und zwar habe ich in einem anderen Forum ein ähnliches Thema angeschnitten. Dort ging es darum, Dublikate schnell und einfach zu entfernen und ich hab dazu eben ein kleines Mini-Konsolen-Tool geschrieben. Im Laufe der Diskussion sind wir dann dazu gelangt, ähnliche Bilder zu filtern und das ist meine Idee, die dir vielleicht helfen kann.
Denn vielleicht funktioniert es, wenn du einen Halbkreis als Bild vor gibst und dann mit Teilen des anderen Bildes vergleichst.
Die Methode, wie du ähnliche Bilder vergleichst, kann ich dir geben, allerdings Ungetestet, da es dort ein Problem gab, nämlich schlicht der Faulheit, einen notwendigen Wert, der nur experimentell bestimmt werden kann, heraus zu finden. ^^
Hier erst einmal die Methode:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40:
| static bool IstÄhnlich(Bitmap _img1, Bitmap _img2, int grenzwert) { int width = 25; int hight = 25;
Bitmap img1 = verkleinern(_img1, width, hight); Bitmap img2 = verkleinern(_img2, width, hight);
int sum = 0; for (int y = 0; y < hight; y++) for (int x = 0; x < width; x++) sum += (int)(Math.Pow(img1.GetPixel(x, y).R - img2.GetPixel(x, y).R, 2) + Math.Pow(img1.GetPixel(x, y).G - img2.GetPixel(x, y).G, 2) + Math.Pow(img1.GetPixel(x, y).B - img2.GetPixel(x, y).B, 2));
return sum < grenzwert || grenzwert == 0; }
static Bitmap verkleinern(Bitmap image, int width = 25, int hight = 25) { Bitmap bmpOutput = new Bitmap(width, hight, PixelFormat.Format24bppRgb); Graphics gOutput = Graphics.FromImage(bmpOutput); Rectangle rectOutput = new Rectangle(0, 0, bmpOutput.Width, bmpOutput.Height);
ImageAttributes ia = new ImageAttributes(); ia.SetWrapMode(WrapMode.TileFlipXY);
gOutput.InterpolationMode = InterpolationMode.HighQualityBilinear; gOutput.PixelOffsetMode = PixelOffsetMode.Half; gOutput.CompositingMode = CompositingMode.SourceCopy;
gOutput.DrawImage(image, rectOutput, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel, ia); bmpOutput.Save("output.bmp", ImageFormat.Bmp);
return bmpOutput; } |
Nun fehlt aber der Parameter C#-Quelltext .
Intern wird nämlich ein Wert errechnet, der dann mit grenzwert verglichen wird.
Wenn der intern errechnete Wert 0 ist, dann sind die Bilder gleich, wenn er über grenzwert liegt, wird false zurück gegeben.
Wo dieser Wert nun liegt, damit dein Halbkreis auch richtig bestimmt wird, musst du selber aus testen. Dafür hab ich die obere Methode so umgeschrieben:
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16:
| static int IstÄhnlich(Bitmap _img1, Bitmap _img2) { int width = 25; int hight = 25;
Bitmap img1 = verkleinern(_img1, width, hight); Bitmap img2 = verkleinern(_img2, width, hight);
int sum = 0; for (int y = 0; y < hight; y++) for (int x = 0; x < width; x++) sum += (int)(Math.Pow(img1.GetPixel(x, y).R - img2.GetPixel(x, y).R, 2) + Math.Pow(img1.GetPixel(x, y).G - img2.GetPixel(x, y).G, 2) + Math.Pow(img1.GetPixel(x, y).B - img2.GetPixel(x, y).B, 2)); return sum; } |
Die Methode gibt den errechneten Wert nun einfach zurück. Wenn du nun mehrere Tests durchführst, dann rechnest du aus den Werten den Mittelwert aus und probierst, ob dieses Ergebnis für grenzwert reicht.
Wenn du weißt, dass der Halbkreis ganz exakt genauso ist, wie in der Vorlage, dann kannst du ja gleich testen, ob der Wert 0 ist. Oder du errechnest von den Bildern dir den Hash-Wert und vergleichst den, was sehr viel schneller gehen würde und Performance ist bei dem, was du vor hast, Gold wert.
Das funktioniert aber nur, wenn die Bitmaps wirklich exakt, also Pixel für Pixel gleich sind und selbst dann bin ich mir nicht sicher. Beim Vergleich von Bildern aus Dateien funktioniert es ganz gut und schnell.
Wenn du nun so weit bist und ein Halbkreis erfolgreich erkannt wird, dann musst du den Halbkreis finden und da fällt mir, ohne tief greifende Kenntnisse, keine andere Möglichkeit ein, als jede Position abzusuchen. Du nimmst also deine Vorlage und vergleichst es mit jeder Position in dem großen Bild, angefangen von der linken oberen Ecke. Dann die Auswahl ein Pixel weiter verschieben und wieder vergleichen. Das Gleiche in der nächsten Zeile und das so lange, bis du eine Übereinstimmung findest.
Ich hatte noch etwas über eine Methode gelesen, bei der man ein Bild nach einem bestimmten Raster durchsucht, aber da weiß ich nicht, wie das geht und habe auch noch nichts, was dir da helfen kann. Allerdings denke ich, dass es sicher die eine oder andere Bibliothek gibt, die entsprechende Funktionen und Klassen zur Verfügung stellt.
Gruß
|
|
C# ![Threadstarter Threadstarter](./graphics/viewtopic/threadstarter.png)
![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png)
Beiträge: 561
Erhaltene Danke: 65
Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
|
Verfasst: Mi 23.01.13 14:59
Also ich habe jetzt mal einige Zeit rumprobiert. Ich werde jetzt keine Viertelkreise, sondern Vollkreise erkennen.
Die Kreise sind so aufgebaut dass sie immer 2 Pixel dick sind. Der äußere Kreis ist dabei weiß und der Innere schwarz.
Ich erstelle meine Kreise aus 2 Methoden:
1. Über Bitmap und die Graphics-Klasse, lasse ich dann ein Kreis reinzeichnen (der ist nicht symmetrisch)
2. Über eine Methode die den Bresenham-Algorithmus benutzt (der ist symmetrisch).
jetzt habe ich bei keiner der Methoden einen Durchschlagenden Erfolg. Ich brauche bei beiden Varianten eine Toleranz von 25% (-> 75% aller verglichenen Pixel müssen überein stimmen) um Kreise ab Durchmesser = 6 zu erkennen. Bei einem kleineren Kreis brauche ich eine größere Toleranz, was wiederum zu Fehlern führt und Kreise erkannt werden, wo gar keine sind.
Nun zu meiner Frage. Was für Algorithmen gibt es um einen Kreis zu zeichnen?
Dann könnte ich nämlich vor dem Scannen des Bildes einfach den entsprechenden Algo auswählen.
Hier noch der Code für Methode 1: Bitmap und Graphics (Ist noch in Testphase, daher sehr unsauber. Die Klasse RoBitmap hab ich iwo aus dem Netz, die arbeitet nicht mit GetPixel() und SetPixel())
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102: 103: 104: 105: 106: 107: 108: 109: 110: 111: 112: 113: 114: 115: 116: 117: 118: 119: 120: 121: 122: 123: 124: 125: 126: 127: 128: 129: 130: 131: 132: 133: 134: 135: 136: 137: 138: 139: 140: 141: 142: 143: 144: 145: 146: 147: 148: 149: 150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186:
| private void RemoveCurves(Bitmap bitmap, int minRadus, int maxRadius, float scale) { bool replaceFast = true; List<Point> drillPos = new List<Point>();
Stopwatch watch = new Stopwatch(); watch.Start();
RoBitmap pic = new RoBitmap(bitmap); pic.Image = new Bitmap(pic.GetFormat1BppIndexed(0.2f));
Graphics picGraphics = Graphics.FromImage(pic.Image);
boxImage.Image = pic.Image;
bool[,] mapPic = new bool[pic.Width,pic.Height]; for (int x = 0; x < pic.Width; x++) for (int y = 0; y < pic.Height; y++) mapPic[x, y] = pic.GetPixel(x, y).ToArgb() == ARGB_WHITE;
RoBitmap tmp = new RoBitmap(new Bitmap(pic.Width, pic.Height)); for (int x = 0; x < pic.Width; x++) for (int y = 0; y < pic.Height; y++) tmp.SetPixel(x, y, mapPic[x, y] ? Color.White : Color.Black);
dbView.boxBuf1.Image = tmp.Image;
barProgress.Maximum = (maxRadius - minRadus + 1) * pic.Height - (maxRadius - (maxRadius - minRadus + 1)); barProgress.Value = 0;
for (int r = maxRadius; r >= minRadus; r--) { labRadius.Text = string.Format("r = {0}px", r);
int d = 2 * r; int size = (int)Math.Round(d * scale); int offset = (int)Math.Round((size - d) / 2d); Bitmap buffer = new Bitmap(size, size);
Graphics g = Graphics.FromImage(buffer); g.Clear(Color.Green); g.FillRectangle(new SolidBrush(Color.White), offset - 1, offset - 1, (size - 2 * offset) + 2, (size - 2 * offset) + 2); g.FillEllipse(new SolidBrush(Color.Black), offset, offset, size - 2 * offset, size - 2 * offset); g.FillEllipse(new SolidBrush(Color.Red), offset + 2, offset + 2, (size - 2 * offset) - 4, (size - 2 * offset) - 4);
RoBitmap circle = new RoBitmap(buffer);
dbView.boxBuf5.Image = circle.Image;
Dictionary<Point, bool> comparor = new Dictionary<Point, bool>(); List<Point> replacer = new List<Point>(); Rectangle replacerFast = new Rectangle(0, 0, circle.Width, circle.Height);
for (int x1 = 0; x1 < circle.Width; x1++) { for (int y1 = 0; y1 < circle.Height; y1++) { int c = circle.GetPixel(x1, y1).ToArgb();
if (c == ARGB_WHITE || c == ARGB_GREEN) replacer.Add(new Point(x1 - offset, y1 - offset));
if ((c == ARGB_WHITE || c == ARGB_BLACK) && x1 - offset >= 0 && y1 - offset >= 0) comparor.Add(new Point(x1 - offset, y1 - offset), c == ARGB_WHITE); } }
tmp = new RoBitmap(new Bitmap(circle.Width, circle.Height)); foreach (var pair in comparor) tmp.SetPixel(pair.Key.X, pair.Key.Y, pair.Value ? Color.White : Color.Black); dbView.boxBuf4.Image = tmp.Image;
for (int y = 0; y < pic.Height - d; y++) { barProgress.Value++;
for (int x = 0; x < pic.Width - d; x++) { int compareMax = comparor.Count; int compareSum = 0; int tolerance = (int)(2.5 * r);
foreach (var pair in comparor) if (mapPic[pair.Key.X + x, pair.Key.Y + y] == pair.Value) compareSum++;
if (compareMax > compareSum + tolerance) continue;
labDetects.Text = (int.Parse(labDetects.Text) + 1).ToString();
if (!replaceFast) { foreach (Point p in replacer) { if (p.X + x >= pic.Width || p.Y + y >= pic.Height) continue; pic.SetPixel(p.X + x, p.Y + y, Color.White); } } else { picGraphics.FillRectangle(new SolidBrush(Color.White), x - offset, y - offset, replacerFast.Width, replacerFast.Height); drillPos.Add(new Point(x + replacerFast.Width, y + replacerFast.Height)); }
boxImage.Image = pic.Image; } }
}
RoBitmap drillPic = new RoBitmap(new Bitmap(pic.Width, pic.Height)); drillPic.Image.SetResolution(pic.Image.VerticalResolution, pic.Image.HorizontalResolution); drillPic.Image = drillPic.GetFormat1BppIndexed();
foreach (Point p in drillPos) drillPic.SetPixel(p.X, p.Y, Color.White);
dbView.boxBuf1.Image = drillPic.Image;
watch.Stop(); labTime.Text = watch.ElapsedMilliseconds.ToString(); boxImage.Image = pic.Image; butStart.Enabled = true; } |
und hier für Methode 2: Bresenham
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64: 65: 66: 67: 68: 69: 70: 71: 72: 73: 74: 75: 76: 77: 78: 79: 80: 81: 82: 83: 84: 85: 86: 87: 88: 89: 90: 91: 92: 93: 94: 95: 96: 97: 98: 99: 100: 101: 102:
| private void RemoveCurves_Method3(Bitmap bitmap, int minRadus, int maxRadius, float scale, float tolerance) { bool replaceFast = true; List<Point> drillPos = new List<Point>();
Stopwatch watch = new Stopwatch(); watch.Start();
RoBitmap pic = new RoBitmap(bitmap); pic.Image = new Bitmap(pic.GetFormat1BppIndexed(0.2f));
Graphics picGraphics = Graphics.FromImage(pic.Image);
boxImage.Image = pic.Image;
bool[,] mapPic = new bool[pic.Width,pic.Height]; for (int x = 0; x < pic.Width; x++) for (int y = 0; y < pic.Height; y++) mapPic[x, y] = pic.GetPixel(x, y).ToArgb() == ARGB_WHITE;
RoBitmap tmp = new RoBitmap(new Bitmap(pic.Width, pic.Height)); for (int x = 0; x < pic.Width; x++) for (int y = 0; y < pic.Height; y++) tmp.SetPixel(x, y, mapPic[x, y] ? Color.White : Color.Black);
dbView.boxBuf1.Image = tmp.Image;
barProgress.Maximum = (maxRadius - minRadus + 1) * pic.Height - (maxRadius - (maxRadius - minRadus + 1)); barProgress.Value = 0;
for (int r = maxRadius; r >= minRadus; r--) { labRadius.Text = string.Format("r = {0}px", r);
int d = 2 * r; int size = (int)Math.Round(d * scale); IEnumerable<Point> comparorWhite = GetCircle(new Point(0, 0), r + 1); IEnumerable<Point> comparorBlack = GetCircle(new Point(0, 0), r); IEnumerable<Point> replacer = GetRectangleWithCircle(size, size, new Point(size / 2), comparorBlack);
RoBitmap bmp = new RoBitmap(new Bitmap(d + 4, d + 4)); foreach (Point p in comparorWhite) bmp.SetPixel(p.X + r + 1, p.Y + r + 1, Color.White); foreach (Point p in comparorBlack) bmp.SetPixel(p.X + r + 1, p.Y + r + 1, Color.Black);
dbView.boxBuf1.Image = bmp.Image;
bmp = new RoBitmap(new Bitmap(size, size)); foreach (Point p in replacer) bmp.SetPixel(p.X, p.Y, Color.Black);
dbView.boxBuf5.Image = bmp.Image;
int maxFails = (int)(tolerance * (comparorWhite.Count() + comparorBlack.Count())); for (int y = r + 1; y < pic.Height - r - 1; y++) { barProgress.Value++;
for (int x = r + 1; x < pic.Width - r - 1; x++) { int fails = 0; foreach (Point p in comparorBlack) { if (mapPic[x + p.X, y + p.Y]) fails++; if (fails > maxFails) break; }
foreach (Point p in comparorWhite) { if (fails > maxFails) break; if (!mapPic[x + p.X, y + p.Y]) fails++; }
if (fails > maxFails) continue; labDetects.Text = (int.Parse(labDetects.Text) + 1).ToString();
if (!replaceFast) { foreach (Point p in replacer) pic.SetPixel(p.X + x - size / 2, p.Y + y - size / 2, Color.White); } else { picGraphics.FillRectangle(new SolidBrush(Color.White), x - size/2, y - size/2, size, size); drillPos.Add(new Point(x + size, y + size)); }
} } }
watch.Stop(); labTime.Text = watch.ElapsedMilliseconds.ToString(); boxImage.Image = pic.Image; butStart.Enabled = true;
} |
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57:
| public static IEnumerable<Point> GetCircle(Point midpoint, int radius) { Point returnPoint = new Point(); int f = 1 - radius; int ddF_x = 1; int ddF_y = -2 * radius; int x = 0; int y = radius;
returnPoint.X = midpoint.X; returnPoint.Y = midpoint.Y + radius; yield return returnPoint; returnPoint.Y = midpoint.Y - radius; yield return returnPoint; returnPoint.X = midpoint.X + radius; returnPoint.Y = midpoint.Y; yield return returnPoint; returnPoint.X = midpoint.X - radius; yield return returnPoint;
while (x < y) { if (f >= 0) { y--; ddF_y += 2; f += ddF_y; } x++; ddF_x += 2; f += ddF_x; returnPoint.X = midpoint.X + x; returnPoint.Y = midpoint.Y + y; yield return returnPoint; returnPoint.X = midpoint.X - x; returnPoint.Y = midpoint.Y + y; yield return returnPoint; returnPoint.X = midpoint.X + x; returnPoint.Y = midpoint.Y - y; yield return returnPoint; returnPoint.X = midpoint.X - x; returnPoint.Y = midpoint.Y - y; yield return returnPoint; returnPoint.X = midpoint.X + y; returnPoint.Y = midpoint.Y + x; yield return returnPoint; returnPoint.X = midpoint.X - y; returnPoint.Y = midpoint.Y + x; yield return returnPoint; returnPoint.X = midpoint.X + y; returnPoint.Y = midpoint.Y - x; yield return returnPoint; returnPoint.X = midpoint.X - y; returnPoint.Y = midpoint.Y - x; yield return returnPoint; } } |
_________________ Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
|
|
Palladin007
![Palladin007 hat insgesamt 89.9% On-Topic und 10.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![Palladin007 hat insgesamt 89.9% On-Topic und 10.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![Palladin007 hat insgesamt 89.9% On-Topic und 10.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![Palladin007 hat insgesamt 89.9% On-Topic und 10.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![Palladin007 hat insgesamt 89.9% On-Topic und 10.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![Palladin007 hat insgesamt 89.9% On-Topic und 10.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![Palladin007 hat insgesamt 89.9% On-Topic und 10.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png)
Beiträge: 1282
Erhaltene Danke: 182
Windows 11 x64 Pro
C# (Visual Studio Preview)
|
Verfasst: Mi 23.01.13 19:00
Als letztes wüsste ich nur noch das gute alte Pixel suchen. Also du durchläufst alle Pixel und prüfst dann, ob dieser Pixel Teil des Kreises sein kann, also ob entsprechende Pixel an entsprechenden Personen darum herum liegen.
Aber mehr weiß ich jetzt auch nicht :/
Ich persönlich hab das auch noch nie gebraucht, beruht also alles auf der reinen Theorie und was ich mal so irgendwann gelesen habe.
|
|
Kha
![Kha hat insgesamt 95.6% On-Topic und 4.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![Kha hat insgesamt 95.6% On-Topic und 4.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![Kha hat insgesamt 95.6% On-Topic und 4.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![Kha hat insgesamt 95.6% On-Topic und 4.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![Kha hat insgesamt 95.6% On-Topic und 4.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![Kha hat insgesamt 95.6% On-Topic und 4.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![Kha hat insgesamt 95.6% On-Topic und 4.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png)
Beiträge: 3803
Erhaltene Danke: 176
Arch Linux
Python, C, C++ (vim)
|
Verfasst: Mi 23.01.13 21:05
Ich weiß nicht, ob es bessere Ergebnisse liefert als dein eigener Algorithmus, aber ein allgemeines Verfahren zum Erkennen von Kreisen ist die Hough-Transformation.
_________________ >λ=
|
|
C# ![Threadstarter Threadstarter](./graphics/viewtopic/threadstarter.png)
![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png)
Beiträge: 561
Erhaltene Danke: 65
Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
|
Verfasst: Do 24.01.13 11:40
Hmmm. Also bei der Hough Transformation ist dass komisch :/. Ich habe mir Testweise mal das AForge.NET Framework runtergeladen und ein Sample mit der Hough Transformation gestartet. Als ich mein Bild ausgewählt hatte, hatte ich nach Beendigung - etwa 10min - 281422 gefundene Kreise. Bei meiner Methode - die auch schneller ist - sind es ca. 100 (je nach Toleranz).
Im Anhang findet sich das Bild, dass ich scanne.
Einloggen, um Attachments anzusehen!
_________________ Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
|
|
jfheins
![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. offtopic star](./graphics/ranks/star_offtopic_full.png)
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Do 24.01.13 13:56
Dann machst du irgendwas falsch
Ic habe das gerade mal in Matlab gebaut, hier mein Skript:
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
| bild = imread('board.bmp'); bild = imresize(bild, 2); % Bikubisch vergrößern kantenbild = edge(bild, 'canny'); % Kantenfilter [centers_1,radii_1] = imfindcircles(kantenbild,[10 25]); [centers_2,radii_2] = imfindcircles(kantenbild,[25 60]);
centers = [centers_1; centers_2]; % Arrays zusammenfügen radii = [radii_1; radii_2]; % Arrays zusammenfügen
count = size(radii, 1);
imshow(bild); viscircles(centers, radii,'EdgeColor','b'); |
Das Ergebnis anbei. Du brauchst auf jeden Fall einen Kantendetektor und wenn du ein höher aufgelöstes Bild hast, wäre das auch ganz gut. Was die Funktionen machen kannst du in der matlab Hilfe nachschlagen: www.mathworks.de/de/help/matlab/index.html
Ich habe auch bei den viertelkreisen schon an Hough gedacht, aber da hat das nicht funktioniert. Für gnaze Kreise ist der Ansatz aber schon sehr gut.
Das Skript findet genau 116 Kreise und liefert direkt alle Radien und Mittelpunkte.
Einloggen, um Attachments anzusehen!
|
|
C# ![Threadstarter Threadstarter](./graphics/viewtopic/threadstarter.png)
![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png)
Beiträge: 561
Erhaltene Danke: 65
Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
|
Verfasst: Do 24.01.13 16:21
Hmm. Also ich kapier das nicht so ganz mit dem Hough Algorithmus. Kann mir dass jemand erklären? Am Besten noch mit einem Beispiel.
_________________ Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
|
|
jfheins
![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. offtopic star](./graphics/ranks/star_offtopic_full.png)
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Do 24.01.13 17:19
C# hat folgendes geschrieben : | Hmm. Also ich kapier das nicht so ganz mit dem Hough Algorithmus. Kann mir dass jemand erklären? Am Besten noch mit einem Beispiel. |
Hmmm ... ich nehme mal an dass die die Wikipedia nicht so weitergeholfen hat, daher versuche ich das jetzt einfach zu erklären
1. Für eine Hough-Transformation musst du wissen was du suchst und wieviele Parameter das hat. Ein Kreis hat bspw. 3 Parameter: Mittelpunktskoordinaten und den Radius.
2. Für jeden Pixel im Bild der zu einem Objekt gehören könnte, malst du jetzt in einem "Zielbild" (das Teil hat so viele Dimansionen wie das Objekt Parameter) alle Stellen etwas heller, deren Parameter den aktuellen Pixel erklären würden.
3. In dem resultierenden Bild bestimme man die Maxima.
Nehmen wir an, wie suchen einen Kreis mit Radius 50 und vertikal in Bildmitte. (Damit ist es besonders einfach, wir haben nur noch einen Parameter!)
Jetzt gehen wir jeden Pixel durch und entdecken an einer Stelle einen schwarzen Pixel: Zum Beispiel den in dem roten Kreis.
An dieser Stelle könnten es aber zwei Kreise sein die hier einen schwarzen Pixel bewirken:
Wenn wir jetzt noch eine Achse und eine Skala hinzufügen können wir die beiden möglichen Mittelpunkte quantifizieren und eine Art Strichliste führen:
Die 45 wird auf dieser Strichliste ganz weit vorne liegen während alle anderen Zahlen verschwindend wenige Striche bekommen. Dann können wir sagen: Der Kreis war wohl bei der Koordinate 45.
Für dein Beispiel bedeutet das: Es wird quasi ein 3D-Quader im Parameterraum aufgespannt und bei jedem Pixel wird eine Kegelmantelfläche an Werten inkrementiert.
Also wenn an Position (100, 250) ein Pixel gefunden wurde, dann könnte das ein Kreis mit Durchmesser 10 sein, dessen Mittelpunkt irgendwo auf einem Kreis mit Radius 5 liegt. Oder ein Kreis mit Durchmesser 12 dessen Mittelpunkt 6 Pixel entfernt liegt. Oder Durchmesser 14, dann aber 7 Pixel entfernt.
Ist das einigermaßen klar geworden?
Einloggen, um Attachments anzusehen!
|
|
C# ![Threadstarter Threadstarter](./graphics/viewtopic/threadstarter.png)
![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png)
Beiträge: 561
Erhaltene Danke: 65
Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
|
Verfasst: Fr 25.01.13 08:46
Danke für die Erklärung. Ich glaube ich bin etwas schwer von Begriff
Könntest du das mit der Strichliste etwas genauer erklären? Also wenn sich jetzt wie in Bild 2 die Kreise schneiden, woher weis ich, dass das andere Objekt auch ein Kreis ist und nicht nur eine Linie? Und was hat es mit der Kegelmantelfläche auf sich?
Also ich habe meinen Quader, der - so wie ich es verstanden habe - x, y und r representiert. Und da drin befindet sich jetzt ein Kegel der meine neuen Parameter gibt.
Ist das soweit richtig?
/// EDIT
Habe noch einen Crosspost in Tutorials.de eröffnet.
_________________ Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
|
|
jfheins
![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. offtopic star](./graphics/ranks/star_offtopic_full.png)
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Fr 25.01.13 15:58
C# hat folgendes geschrieben : | Danke für die Erklärung. Ich glaube ich bin etwas schwer von Begriff
Könntest du das mit der Strichliste etwas genauer erklären? Also wenn sich jetzt wie in Bild 2 die Kreise schneiden, woher weis ich, dass das andere Objekt auch ein Kreis ist und nicht nur eine Linie? |
Das weißt du nicht. Aber durch die Aufaddierung bekommt der Kreismittelpunkt dennoch einen viel höheren Wert.
Für jeden schwarzen Pixel wird immer die Annahme getroffen dass dieser durch einen Kreis entstanden ist. Falls da Linien in dem Bild sein sollten, dann erzeugen diese nur ein geringes Grundrauschen.
Nehmen wir einmal den obersten Pixel des Kreises: Der kann wirklich nur durch den Kreis an Position 45 erklärt werden. Macht einen Strich bei 45. der oben erklärte Pixel könnte durch zwei Kreise entstanden sein. Macht einen Strich für 45 und einen für 10 und einen für 45. In der gleichen Bildzeile weiter rechts ist noch ein schwarzer Pixel. Macht einen Strich für 25 und einen für 70.
Eine Zeile drunter sind wieder zwei schwarze Pixel: Der eine kann durch 45 und 9 erklärt werden. Also Striche für 9 und 45. Der nächste Pixel erzeugt Striche bei 45 und 71. Eine Zeile drunter dann das gleiche Spiel: Striche für 8, 45 (links) und 45, 72 (rechts).
dann wieder: jetzt vielleicht 6, 45, 45, 74.
Du siehst, die 45 taucht ständig auf.
Ich habe das mal in Matlab programmiert:
Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27:
| %% Kreis bild = imread('kreis_2.png'); bild = im2bw(bild, 0.15);
strichliste = zeros(500,1); radius = 84;
for x = 1:500 for y = 1:381 if bild(y, x) == 0 dist = 381/2 - y; offset_sqr = radius^2 - dist^2; if offset_sqr > 0 % Zwei Lösungen k1 = x + round(sqrt(offset_sqr)); strichliste(k1) = strichliste(k1) + 1; k2 = x + round(-sqrt(offset_sqr)); if k2 >0 strichliste(k2) = strichliste(k2) + 1; end end end end end
bar(strichliste); max(strichliste) |
Hier mal die Testbilder mit der Strichlist. (Die Strichliste ist als Balkendiagramm dargestellt. Wie du siehst ist das Maximum konsistent an der richtigen Stelle. Die Linien erzeugen ein bisschen Dreck, aber das Maximum bleibt.)
Hier mal die Strichliste von dem Originalbild oben:
Und hier ein etwas schwierigeres Testbild mit der Strichliste:
![test2 test2](attachedImage.php?readableid=test2&context_type=post&context_id=672701) ![bar2 bar2](attachedImage.php?readableid=bar2&context_type=post&context_id=672701)
Einloggen, um Attachments anzusehen!
|
|
C# ![Threadstarter Threadstarter](./graphics/viewtopic/threadstarter.png)
![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png)
Beiträge: 561
Erhaltene Danke: 65
Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
|
Verfasst: Fr 01.02.13 18:24
Update: Dieses Thema wird mal etwas zurückgestuft. Da ich bei der Arbeit vorübergehend eine andere Arbeit erhalten habe, wird dieses Projekt für ein paar Wochen zurückgestellt.
Ich schreibe wieder wenn ich wieder Fortschritte mache.
Danke an alle die bisher geholfen haben.
_________________ Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
|
|
C# ![Threadstarter Threadstarter](./graphics/viewtopic/threadstarter.png)
![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png)
Beiträge: 561
Erhaltene Danke: 65
Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
|
Verfasst: Mo 11.02.13 19:19
Hallo.
Habe jetzt mal weiter gemacht und mir dein Beispiel nochmal genauer angesehen, habs - denke ich ![:D](images/smiles/icon_biggrin.gif) - verstanden.
Aber mein Code funktioniert immer noch nicht so ganz und ich weis nicht woran es liegen könnte.
Hier der Code der Suche
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50:
| RoBitmap img = new RoBitmap(bitmap); RoBitmap newImg = new RoBitmap(new Bitmap(img.Width, img.Height)); Graphics g = Graphics.FromImage(newImg.Image); img.Image = img.GetFormat1BppIndexed(0.2f); bool[,] pic = new bool[img.Width,img.Height]; ushort[,] map = new ushort[img.Width,img.Height]; for (int w = 0; w < img.Width; w++) for (int h = 0; h < img.Height; h++) pic[w, h] = img.GetPixel(w, h).ToArgb() == ARGB_BLACK;
for (int r = minRadus; r < maxRadius; r++) { for (int x = 0; x < img.Width; x++) { for (int y = 0; y < img.Height; y++) { if (!pic[x, y]) continue; int dist = img.Height / 2 - y; int offset = r ^ 2 - dist ^ 2;
if (offset <= 0) continue;
int offX1 = x + (int)Math.Round(Math.Sqrt(offset)); int offX2 = x - (int)Math.Round(Math.Sqrt(offset));
Debug.WriteLine("Detected on {0}, {1}:\toffset={2}\toffX1={3}\toffX2={4}", x, y, offset, offX1, offX2);
if (offX1 >= 0 && offX1 < img.Width) map[offX1, y]++; if (offX2 >= 0 && offX2 < img.Width) map[x, offX2]++; } }
for (int x = 0; x < img.Width; x++) { for (int y = 0; y < img.Height; y++) { if (map[x, y] < minValue) continue; newImg.SetPixel(x, y, Color.Green); g.DrawEllipse(new Pen(Color.Red), x - r, y - r, x + r, y + r); } } }
boxImage.Image = newImg.Image; |
_________________ Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
|
|
jfheins
![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. offtopic star](./graphics/ranks/star_offtopic_full.png)
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Mo 11.02.13 21:59
Also erstmal ist "funktioniert nicht" keine akzeptable Fehlermeldung
Desweiteren hast du mein eindimennsionales beispiel kopiert, was erstmal nicht falsch ist, aber du hast ein paar klitzekleine Fehlerchen gemacht
ushort[,] map Da mein Beispiel eindimensional ist, brauchst du hier nur eine Dimension. also ushort[]
C#-Quelltext 1: 2:
| map[offX1, y]++; map[x, offX2]++; | x und y erübrigen sich dann hier auch. In offX1 und offX2 ist die interessante info.
C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9:
| using (var g = Graphics.FromImage(newImg.Image)) for (int i = 0; x < map.length; x++) { if (map[i] < minValue) continue; Point c = new Point(i, img.Height / 2); newImg.SetPixel(c, Color.Green); g.DrawEllipse(new Pen(Color.Red), c.x - r, c.y - r, c.x + r, c.y + r); } |
So in etwa. ich habe das ganze jetzt nicht getestet. Die graphhics-Klasse impelmentiert IDisposable und muss daher freigegeben werden; ein using-Block bietet sich an dieser Stelle an.
|
|
C# ![Threadstarter Threadstarter](./graphics/viewtopic/threadstarter.png)
![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png)
Beiträge: 561
Erhaltene Danke: 65
Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
|
Verfasst: Mo 11.02.13 22:08
Ah Eindimensional ![:autsch:](images/smiles/icon_autsch.gif) Dann macht das ganze etwas mehr Sinn mit k1 und k2 ![:D](images/smiles/icon_biggrin.gif) . Ich war nur verwirrt wegen der Initialisierung mit zeros(500, 1) verwirrt, was mir aber gerade klar wird weil dein zweiter parameter 1 ist omg.
Und zum Thema Fehlerangabe dachte ich gerade dass Gleiche, wollte grad den Post bearbeiten und dann Stand plötzlich die Antwort drunter xD.
Werde es gleich mal probieren. Danke für die viele Hilfe.
//P.S. Das mit Graphics ist ja theoretisch egal oder? Wenn ichs nicht frei gieb macht doch der GC nach Abschluss der Methode oder?
///EDIT
Was mir aber gerade auffällt - abgesehen davon dass es immer noch net funzt xD - ist, dass bei deinem Beispiel ja nur eine Unbekannte existier und dass ist x.
Den Radius bekomme ich ja auch weg durch meine for Schleife, aber da bei mir später x und y unbekannt sind, bin ich doch auf ein 2D Array angewiesen.
_________________ Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
|
|
C# ![Threadstarter Threadstarter](./graphics/viewtopic/threadstarter.png)
![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png)
Beiträge: 561
Erhaltene Danke: 65
Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
|
Verfasst: Mo 11.02.13 22:54
Also ich habs jetzt so probiert:
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40:
| for (int r = minRadus; r < maxRadius; r++) { for (int y = 0; y < img.Height; y++) { for (int x = 0; x < img.Width; x++) { for (int y1 = 0; y1 < img.Height; y1++) { if (!pic[x, y1]) continue;
int dist = y - y1; int offset = r ^ 2 - dist ^ 2;
if (offset <= 0) continue;
int offX1 = x + (int)Math.Round(Math.Sqrt(offset)); int offX2 = x - (int)Math.Round(Math.Sqrt(offset));
map[offX1, y1]++; if (offX2 > 0) map[offX2, y1]++; } } } for (int y = 0; y < img.Height; y++) { for (int x = 0; x < img.Width; x++) { if (map[x, y] < minValue) { newImg.SetPixel(x, y, Color.White); continue; }
Debug.WriteLine("Drawing Circle at {0}, {1} with radius={2}", x, y, r); newImg.SetPixel(x, y, Color.Green); } } |
Aber da erhalte ich ein seltsames Wackelbild bestehend aus den Mittelpunkten angeblcher Kreise :/
_________________ Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
|
|
jfheins
![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![jfheins hat insgesamt 76.6% On-Topic und 23.4% Off-Topic Beiträge geschrieben. offtopic star](./graphics/ranks/star_offtopic_full.png)
Beiträge: 918
Erhaltene Danke: 158
Win 10
VS 2013, VS2015
|
Verfasst: Di 12.02.13 11:53
Schon wieder
Wenn du schon Bilder als Ergebnis bekommst, meinst du nicht es wäre praktisch diese anzuhängen??
Ich habe dir weiter oben versucht, ein Beispiel vorzurechnen und dafür die Freiheitsgrade (Fg) reduziert so dass nur noch einer übrig bleibt. Du bastelst da dann immer direkt 'rum und versucht ihn auf 3 Fg zu erweitern. Ich würde dir erstmal empfehlen das ganze mit einem Fg zum laufen zu bekommen - und dann wenn es funktioniert auf 3 Fg erweitern.
Aber vielleicht hast du das auch schon gemacht und das nur nicht geschrieben. (Du musst echt noch klarer bei deinen Antworten werden, Probleme raten macht nicht so viel Spaß...)
Bei deinem letzten Code: Das ist irgendwie mehr "1D auf 3d hingefrickelt" statt "Algorithmus verstanden und erweitert"
Also gehen wir nochmal an den Anfang, also vor die Schleife. Deine Kreise haben 3 Fg, daher brauchst du ein 3D Array:
C#-Quelltext 1: 2: 3: 4: 5:
| var minRadius = 10; var maxRadius = 20; var radius_range = maxRadius - minradius + 1:
ushort[,,] map = new ushort[radius_range, img.Width, img.Height]; |
Die Schleifen brauchst du dann auch nur 3 mal: C#-Quelltext 1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20:
| for (int radius = minRadius; r < maxRadius; r++) { for (int y = 0; y < img.Height; y++) { for (int x = 0; x < img.Width; x++) { if (!pic[x, y]) continue;
for (int i = x-radius; i <= x+radius; i++) for (int j = y-radius; i <= y+radius; j++) { int error = (x-i)*(x-i) + (y-j)*(y-j) - radius*radius if (error <= 1) map[radius - minRadius, i, j]++; } } } } |
Da sind bestimmt noch Fehler drin, aber ich hoffe das Prinzip wird klar.
Bitte versuche jetzt mal, den Code zu verstehen und falls das nicht klappt, den einfacheren, eindimensionalen Code zum laufen zu bekommen und zu verstehen.
|
|
C# ![Threadstarter Threadstarter](./graphics/viewtopic/threadstarter.png)
![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png) ![C# hat insgesamt 86.9% On-Topic und 13.1% Off-Topic Beiträge geschrieben. ontopic star](./graphics/ranks/star_ontopic_full.png)
Beiträge: 561
Erhaltene Danke: 65
Windows 10, Kubuntu, Android
Visual Studio 2017, C#, C++/CLI, C++/CX, C++, F#, R, Python
|
Verfasst: Di 12.02.13 22:32
Entschuldigung für diese Beiträge... Ich habe mehr vor mir her geschrieben als einen sinnvollen Beitrag zu machen.
Also die 1 Fg Methode funktioniert bei mir. Ich weis jetzt auch wo der Fehler lag, dass es nicht geklappt hat: Ich durfte nicht
C#-Quelltext 1:
| int offset = r ^ 2 - dist ^ 2; |
schreiben, da das keine Potenzrechnung sondern die Bitweise XOR Verknüpfung ist. Also hab ich
C#-Quelltext 1:
| int offset = (int)(Math.Pow(r, 2) - Math.Pow(dist, 2)); |
eingesetzt und siehe da es klappt.
Ich wollte ein 2D Array nehmen, weil bei 3D extrem viel Speicher benötigt wird, vor allem bei Bilder die mal in über 1000x1000 gehn und bei der mit 5 versch. Radien gesucht wird -> 5.000.000 Elemente im Array. Deshalb werde ich das Array schon innerhalb der Radius-Schleife filtern, und alle Koordinaten, die über den minValue kommen, in eine Liste packen.
Das grundlegende Prinzip der Funktion habe ich schon verstanden. Jetzt Versuche ich noch die 3Fg Technik zum laufen zu bekommen.
_________________ Der längste Typ-Name im .NET-Framework ist: ListViewVirtualItemsSelectionRangeChangedEventHandler
|
|
|