|
» myCSharp.de Diskussionsforum |
|
|
|
Autor
 |
|
dr4g0n76
myCSharp.de-Poweruser/ Experte
Dabei seit: 07.07.2005
Beiträge: 2.890
Entwicklungsumgebung: SharpDevelop/VS.NET Herkunft: Deutschland
|
|
EDIT: 28.01.2014:
Ich bin jetzt den Schritt gegangen und habe das Projekt auf
https://imagerecognition2.codeplex.com/
gehostet.
EDIT 26.04.2012:
Lange nicht alle Menüpunkte funktionieren und das Rechteck das man mit der Maus aufziehen kann hat momentan auch keine Funktion... aber alles im entwickeln
Die wichtigsten Funktionen und Kürzel:
[U]Fenster
CTLR-N -> neues Fenster aufmachen
STRG-ALT-C -> Fenster kaskadieren
STRG-ALT-H -> Horizontal anordnen
STRG-ALT-V -> Vertikal anordnen
New Window (open copy) -> vom aktuellen Fenster aus eine Kopie in einem neuen Fenster erstellen
New Window (last loaded) -> neues Fenster mit dem zuletzt geladenen Bild
Filter
CTRL-F -> Filter ausführen
Windows->Script:
Filter ausführen (oberer Execute-button)
hier auch Kanal auswählen, A,R,G,B, Mask (unterer Execute-button)
Oder direkt im Menü entsprechenden Filter auswählen
Lambdaausdrücke:
Oben im Filter eingeben oder aus Combobox auswählen
Menüpunkt Windows->Script: Script ausführen....
Bilder verknüpfen/Contextmenü oder Toolleiste:
Bilder im Fenster aus Childwindowliste auswählen...
EDIT: 17.01.2012
Hier gibt's ab jetzt kleine Tutorials usw. über diese Library:
http://lowlevelgraphicslibrary.blogspot.com/
[B]EDIT: 22.04.2010
Als Dateianhang am Ende dieses Beitrags verfügbar.
Es wird immer mal wieder von mir ein Testprojekt hochgeladen, aber das wird nicht explizit hier jedesmal vermerkt.
EDIT: Prerelease Versionen gibt es immer - wenn vorhanden - hier:
Anmerkung: Ich behalte mir vor, die Datei umzubenennen oder herauszunehmen.
Der Code kann jetzt hier
heruntergeladen werden (s. Ende dieses Posts).
Achtung: Das Projekt ist noch nicht gegen Fehler getestet.
Zudem hat die Basis Klasse das Interface IFilter bekommen.
Dieses wird beinhalten:
- Steps (Quasi Pixel in X-Richtung und Y-Richtung überspringen)
- Rectangle (Ausschnitt auswählen, auf den der Filter angewendet werden kann)
- einige grundlegende Funktionen wie in der System.Drawing.Bitmaps-Klasse z.B. Height / Width, GetPixel / SetPixel
Was schon drin ist:
Einige Experimentelle Filter:
- Neue Filter, z.B. Background-Estimation
- Farben runden
- Segmentierungen
- Colorspaces, Umrechnungen von RGB in verschiedene Farbräume und zurück u.a.
YUV, YCbCr, HCL, HSV, XYZ, CIELUV, CIELAB usw.
- verschiedene Kantenfilter und ein neuer Konturfilter
- verschiedene rudimentäre Segmentierungsfilter.
- Viele statische RGB-Funktionen unter ColorFunctions wie z.B. Summe der Channels,
MaxChannel, MinChannel, Channels vertauschen per String z.B. mach BGG oder RBG oder BGR aus Original RGB, Channel-Ratio,
usw. alle diese Funktionen sind in ColorFunctions ausprogrammiert.
- BitmapFunctions-Klasse um ein Bild auf verschiedene Arten z.B. in einen Stream oder Byte-Array und wieder zurück umzuwandeln, zu resizen und zu rotieren.
Einen Filter benutzen:
C#-Code: |
Bitmap bitmap = (Bitmap)Image.FromFile("blub.jpg");
IFilter filter = new GrayScale();
filter.Execute(bitmap);
|
Die erste Zeile lädt das Bild,
die 2. Zeile instantiiert den Filter.
Dann wird der Filter angewendet
Zur Ausführung gibt es 3 Möglichkeiten:
1.) void Execute(bitmapSource);
Führt den Filter aus und bitmapSource enthält die neuen - veränderten - Informationen
2.) Bitmap ExecuteCloned(bitmapSource);
Führt den Filter geclont aus, d.h. bitmapSource wird nicht verändert, und die veränderte Bitmap wird zurückgegeben.
3.) void ExecuteMasked(bitmapSource, bitmapMask);
Führt den Filter aus und er wird nur an den Stellen angewendet in dem im Maskenbild weiße Pixel sind.
EDIT:
Als nächstes gibt es dann noch die Möglichkeiten:
4.) ExecuteChannelled
Für jeden Kanal kann angegegeben werden, ob das Ergebnis übernommen wird.
5.) ExecuteMaskedChannelled
Für jeden Kanal kann in Bezug auf die Maske angegeben werden, ob das Ergebnis übernommen wird.
EDIT: 4. und 5 sind jetzt implementiert.
Abkürzung des obigen Codes:
C#-Code: |
new GrayScale().Execute(bitmapSource);
|
Es gibt bisher ( mind.) folgende
Filterkategorien:
- Farb-filter
- Konvolutions-Filter
- Morphologie-Filter
- Histogramm-Filter
- Kanten-Filter
- Ecken-Filter
- Frequenz-Filter
- Binarisierungs-Filter (Thresholding)
- Kontur-Filter
- Korrektur-Filter
- Korrelations-Filter
- Deplatzierungs-Filter
- Segmentierungs-Filter
- Makro-Filter
- Textur-Filter
- Mathematische Filter (algebraisch, logisch)
Über ein UnsafeBitmap Objekt kann auf einfache und schnelle Weise auf ein Bitmap zugegriffen und es verändert werden:
C#-Code: |
UnsafeBitmap bitmap = new UnsafeBitmap(_bitmapSource);
bitmap.Dispose();
|
UnsafeBitmap bekommt als Eingang die originale Bitmap übergeben.
Dann wird intern alles durchgeführt um Unsafe auf die Bitmap zugreifen zu können.
Von außen sieht es aber aus, als würden wir ganz normal zugreifen.
C#-Code: |
List<Color> m_aColor = new List<Color>();
m_aColor.Add(Color.FromArgb(255,255,255));
UnsafeBitmap bitmap = new UnsafeBitmap(_bitmap);
for (int y = 0; y < bitmap.Height; y++)
{
for (int x = 0; x < bitmap.Width; x++)
{
Color color = bitmap.GetPixel(x, y);
if (!m_aColor.Contains(color))
{
bitmap.SetPixel(x, y, m_ColorToReplaceWith);
}
}
}
bitmap.Dispose();
|
ImageRecognition2.rar (3 MB, 42 mal heruntergeladen)
Hinweise:
Was tut sich aktuell?
EDIT: 15.03.2012
Aktuell geht es um alles fürs Vermessen und die Erkennung von Bildern, was eingebaut wird.
- Neuronale Netzwerke
- Snakes / Active Contours
3D:
- Parität / Depthmap
- Stereo: Anaglyph / Interlaced / 3d-Modellschätzung
Dieser Beitrag wurde 28 mal editiert, zum letzten Mal von dr4g0n76 am 28.01.2014 11:20.
|
|
07.07.2005 14:24
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
maxE
myCSharp.de-Mitglied
Dabei seit: 27.04.2004
Beiträge: 456
Entwicklungsumgebung: SharpDevelop Herkunft: Sachsen
|
|
Ganz nett, aber man könnte die Lib noch etwas mehr in Richtung OO bringen. Alle Filter sind einfache statische Funktionen. Kann es sein, dass du die aus einer ehemaligen C Library konvertiert hast?
Die Filter könnte man übrigens prima als Plugin in Paint.NET integrieren
http://www.eecs.wsu.edu/paint.net/
|
|
07.07.2005 20:16
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
shady
myCSharp.de-Mitglied
Dabei seit: 31.01.2005
Beiträge: 42
Entwicklungsumgebung: VS.NET 2003
|
|
irgendwie mekkert #Develop rum, wenn ich versuche den kram zu Kompilieren:
Zitat: |
PFAD\cImageFilters.cs(35,4): error CS0227: Nicht gesicherter Code wird nur angezeigt, wenn mit '/unsafe' kompiliert wird |
Das kommt überall da vor wo mit unsafe {} gearbeitet wurde.
Beim Kompilieren wird nur die .manifest Datei erstellt.
Wie kann ich das Lösen?
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von shady am 13.07.2005 13:12.
|
|
13.07.2005 13:10
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
Zwischen diesen beiden Beiträgen liegt mehr als ein Jahr. |
|
Hallo!
Die Komponente gefällt mir sehr gut, Kompliment!
Kurze Frage von einem Nicht-Experten in Sachen Bildbearbeitung:
Gibt es bzgl. der abgefragten Werte z.B. für Helligkeit, Kontrast, Gamma, ... bestimmte Grenzwerte?
EDIT: OK, lässt sich im Quellcode ablesen (0..255).
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von tom-essen am 18.12.2006 13:48.
|
|
18.12.2006 12:23
|
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
Zwischen diesen beiden Beiträgen liegen mehr als 2 Jahre. |
ErfinderDesRades
myCSharp.de-Poweruser/ Experte
Dabei seit: 31.01.2008
Beiträge: 5.298
|
|
Ist das Beispielprojekt [im neuen Download] iwie flötengegangen?
Bei mir findet sich nur ein Project, und zwar ganz ohne Property-Ordner - wo issn nun niedergelegt, dasses eine Dll ist, weil kommt beim Start schon die Fehlermeldung "Klassenbibliotheks-Projekt kann nicht StartProjekt sein"
Nee, flötengegangen auch nicht, verschiedene Forms sind ja noch vorhanden.
Also iwie ein unvollständiger Upload?
|
|
10.08.2009 19:44
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
|
@ErfinderDesRades:
EDIT 18.12.2009: Das komplette Projekt kann im 1. Thread heruntergeladen werden.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von dr4g0n76 am 18.12.2009 07:41.
|
|
10.08.2009 19:55
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
ErfinderDesRades
myCSharp.de-Poweruser/ Experte
Dabei seit: 31.01.2008
Beiträge: 5.298
|
|
Ohne Beispielprojekt findich schade, weil willichmal einen Blick reinwerfen, mussich erstmal iwas programmieren, dassich ühaupt was zu sehen kriege.
Habich jetzt ja gemacht, und noch folgendes gefunden:
CGraphics scheint versehentlich dringeblieben, weil die Arbeit scheint ja CImageFilters zu machen.
Von den Forms ist nur FormMain im Designer darstellbar, allen anderen melden: "Method 'System.Windows.Forms.Form.CenterToParent' not found."
Bei vielen Filtern kommt ein Eingabefenster "Value eingeben", da kann man dann einen Value eingeben - nirgends ein Hinweis, was der Value bewirkt. |
Und dass das Projekt keine Properties hat, scheint mir, wie gesagt, an einem fehlerhaften Upload zu liegen, odr?
|
|
10.08.2009 20:05
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
|
EDIT 18.12.2009:
Das Projekt wird immer hier im 1. Post dieses Threads hochgeladen.
Es ist aber immer noch kein endgültiges Release angesagt.
Ich stelle einfach hier die Prerelease-Versionen zur Verfügung.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von dr4g0n76 am 18.12.2009 07:42.
|
|
18.08.2009 10:28
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
|
Preview:
Wie im angehängten Bild zu sehen, können beim nächsten Upload auch farbige Blobs anhand der Rechtecke ermittelt werden.
Bildanalyse:
Mit einem "JOIN" können Rechtecke ähnlicher Farben zu größeren Rechtecken verschmolzen werden.
dr4g0n76 hat dieses Bild (verkleinerte Version) angehängt:
 Volle Bildgröße
|
|
20.08.2009 17:03
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
|
Hier gibt's jetzt die Preview Applikation.
Der Code ist noch nicht gecleant und viele Filter sind noch mit Bitmap.SetPixel GetPixel implementiert und deswegen langsam.
Es ist eben noch ein Entwicklungsprojekt. Aber solange kann jeder ja mal damit rumspielen.
Fehler zu monieren hat momentan keinen Sinn. Die werden erst wichtig, wenn die neue Version komplett veröffentlicht wird.
Z.B. wird die Klasse ImageFilters noch in LowLevelGraphicsLibrary wandern, ebenso wie die Blobs usw.
EDIT: Graue Funktionen sind momentan nicht aktiviert/implementiert...
EDIT: Download s. oberster Post.
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von dr4g0n76 am 11.09.2009 14:07.
|
|
23.08.2009 18:43
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
|
[EDIT] 18.12.2009:
- Viele neue Filter, z.B. Segmentierung
- Color-Blob-Extraktor mit neuem Verfahren
- ColorSpaces, Umrechnung von RGB in andere Farbräume...
- RGB-Funktionen (z.B. Abfrage auf RGB-Range, Maxchannel, Minchannel usw.)
Einfach dazu das Projekt im ersten Post dieses Threads herunterladen.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von dr4g0n76 am 18.12.2009 07:43.
|
|
10.09.2009 18:11
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
|
Habe heute ein erstes Prerelease veröffentlicht. Damit man sich den Code schon mal anschauen kann. Und nein, der Code bleibt nicht so. An vielen Stellen wird es noch Änderungen und Optimierungen geben.
Die Syntax der Filter bleibt so.
Es wird noch ein ExecuteCloned hinzukommen, bei dem man das bearbeitete Bitmap als Ergebnis erhalten wird und das Original-Bild bleibt dabei wie es ist.
|
|
30.09.2009 20:25
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
|
Ihr dürft aber gerne schon Rückmeldungen geben, vielleicht fehlt euch noch ein Filter oder ihr habt grundsätzliche Fehler entdeckt, ich werde die Vorschläge aufnehmen, prüfen und falls sinnvoll ggf. berücksichtigen.
|
|
02.10.2009 14:46
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
|
Die Beschreibung der Filter werde ich heute noch hier online stellen:
[EDIT] die erste Anleitung ließ sich nicht online laden, deshalb bis ich wieder dazu komme wird es noch wohl eine Weile dauern.
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von dr4g0n76 am 19.10.2009 09:15.
|
|
12.10.2009 14:30
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
|
Neues Prerelease erstellt.
Unter anderem funktionieren jetzt:
- Houghtransform
- Moravec
- ZeroCrossing
- AdaptiveThresholding
Funtionen in ColorFunctions:
u.a.
- Mul(Color, Color)
- Sub (Color, Color)
- Div(Color, Color)
EDIT: noch nicht hochgeladen
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von dr4g0n76 am 11.11.2009 16:52.
|
|
11.11.2009 16:49
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
HeRaider
myCSharp.de-Mitglied
Dabei seit: 26.06.2008
Beiträge: 81
|
|
Hm sieht ganz interessant aus. Muss ich mir mal anschauen.
PS: Ich suche noch nach einer Funktion die weiße Ränder an Grafiken entfernen kann falls dir da was einfallen sollte
|
|
12.11.2009 16:05
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
|
Die Bibliothek ist eigentlich ausgelegt für Stills (Einzelbilder), nicht für Videobearbeitung
- Viele kleine Korrekturen (Fehlende Konstruktoren, Falsche Berechnungen, fehlende Benutzung von UnsafeBitmap und dazugehöriges UnsafeBitmap.Dispose() an manchen Stellen )
- Autocrop ist jetzt rudimentär implementiert, kann benutzt werden.
Funktioniert fürs erste IMHO relativ gut.
- Korrektur von Umrechnungen für Farbmodelle und redundante Farbmodelle entfernt
- Alle vorgesehenen Filter zum Funktionieren gebracht
- Objektextraktor begonnen
Es gibt jetzt im wesentlichen 4 Komponentenarten:
- Extractors (Klassen um bestimmte Features/Objekt usw. zu extrahieren)
- Colorspaces (Farbräume)
- Filter (z.B. Farbfilter-, Morphologie-, Kanten-, Eck-Filter usw.)
- Histogramm und Statistikfunktionen
(- sowie Hilfsfunktionen (BitmapFunctions, ColorFunctions))
|
|
07.12.2009 15:18
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
ErfinderDesRades
myCSharp.de-Poweruser/ Experte
Dabei seit: 31.01.2008
Beiträge: 5.298
|
|
Hi!
als ich vor längerer Zeit mal reingeguckt hab, fandich das mit den Filtern suboptimal - für jeden Filter eine eigene klasse.
Dabei sind die meisten Filter ja ConvolutionFilter, nur je mit verschiedenen Parametern.
Das kann man wesentlich vereinfachen, indem man einen ConvolutionFilter schreibt, und den mit verschiedenen Parametern aufruft.
Ich hab sowas mal gemacht, da habich die verschiedenen Parameter in einer DataTable zusammengefasst., und User kann wählen.
Das hat den lustigen NebenEffekt, der User kann seine eigenen Filter erfinden, indem er der DataTable weitere Datensätze zufügt.
gugge Convolution-Filter
|
|
07.12.2009 15:45
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
|
@ErfinderDesRades:
Das ist nicht mehr so, dass die meisten Filter Convolution-Filter sind.
Außerdem werde ich einige Filter sowieso zusammenfassen (Es macht z.B. keinen Sinn einen Filter Contours und einen Contours-Filter zu haben.)
Außerdem sind die Filter von BaseImageFilter abgeleitet und haben die eigene Schnittstelle IFilter. So kann also jeder seinen eigenen Filter kreieren und hinzufügen.
Außerdem veröffentliche ich hier einfach die Fortschritte damit jeder damit arbeiten kann.
z.B. gibt es auch noch keine sinnvolle Namespace-Aufteilung, die IMHO aber inzwischen nötig ist. z.B. in Convolution, Morphology, Color usw.
Bis dahin. ;-) Viel Spass damit.
Probiers doch einfach mal aus.
|
|
07.12.2009 16:31
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
|
Nach Weihnachten, werde ich diese Version veröffentlichen:
Dann können einige dieser Extraktoren benutzt werden.
- Impainter: kann benutzt werden, um ein Bild zu restaurieren
- Freistellungstool: kann benutzt werden, um Bereiche eines Bildes über eine Maske freizustellen
- AutoCrop: Wird benutzt, um ein Bild vollautomisch auszuschneiden (unwichtige Bereiche werden abgeschnitten)
Bei Vorschau wird ein rotes Rechteck in das Bild eingeblendet.
- Color-Blob-Extraktor: Schon bekannt von dem Knopf links unten. ;-)
- Objekt-Extraktor: Das Herzstück des Projekts (deswegen hab ich eigentlich mal das ganze angefangen in dieser Dimension auszuarbeiten)
Wenn der Objekt-Extraktor RICHTIG(!) funktioniert können in einem beliebigen Bild,
mittels des angewendeten von mir entwickelten One-Pass-Verfahrens, Objekte vollautomatisch extrahiert werden.
dr4g0n76 hat dieses Bild (verkleinerte Version) angehängt:
 Volle Bildgröße
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von dr4g0n76 am 18.12.2009 13:11.
|
|
18.12.2009 13:06
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
digi333
myCSharp.de-Mitglied
Dabei seit: 17.06.2006
Beiträge: 290
|
|
Tolle Funktionen... einige sind ja so auch in der AForge drinne von CodeProject.
Du solltest vielleicht auch ein SVN anlegen für neue Versionen. Wenn zum Beispiel die Funktionen geupdated werden mit und die SetPixel und GetPixel weg sind.
Gruß,
Digi333
|
|
22.12.2009 17:51
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
ErfinderDesRades
myCSharp.de-Poweruser/ Experte
Dabei seit: 31.01.2008
Beiträge: 5.298
|
|
ich krittel mal ein bischen herum.
zunächst die Test-Anwendung: ich finde, man bräuchte was, wo man vorher und nachher nebeneinander vergleichen kann, vlt sogar Tabpages, wo man verschiedene Filter-Ausgaben durchblättern kann.
Und das bei der Ausgabe angegeben ist, was man eingegeben hat, am liebsten was mit Abspeichern.
also ich jedenfalls hab nach 3 Sekunden vergessen, welches MenuItem ich geklickst hatte, und was in die EingabeMaske eingegeben.
Ich hab grad angemacht, ein Bild geladen, und dann mal bei den Filtern Binarisierung-BarCode geklickst, was immer das sein mag, darüber hoffte ich ja was zu erfahren.
Da geht ein Dialog auf, da soll ich einen Grenzwert eingeben, und checken (oder nicht), ob "nur diesen grenzwert".
Damit kann ich überhaupt nichts anfangen, was denn für ein Grenzwert?
habich 142 eingegeben.
Dann steht die Anwendung, und nach ca. 10s kommt ein schwarzweiß-Bild, bei dem scheinbar die Graustufen entfernt sind.
Vermutlich ist das die Binarisierung, dasses nurnoch schwarz-weiß gibt, aber warum Barcode? - na, so heißt es eben.
Nächster Test: Binarisierung-treshold MinMax - da muß man keinen Grenzwert angeben, aber die Anwendung steht für 20s.
Dafür gibts dann aber eine Ausgabe, bei der das Bild viel besser wieder zu erkennen ist - ein wirklich interessanter Filter. Blos wie gesagt - ich kann die Ausgabe nicht mit der Eingabe vergleichen, das ist schade.
Guck ich mal in den Code, da sehe ich gleich, warum das immer so lange steht: ist voll mit GetPixel und SetPixel. Wo ich denken täte, in etwas, was sich "LowLevel..." nennt, haben die nix verloren.
Man kann doch sicherlich alle Bildformate nach 24RGB umwandeln (bei Transparenz-Unterstützung 32ARGB), die Bitmap locken, und auf einem Array mit den Farbwerten arbeiten. Für 24RGB habich das mal selbst gemacht, und habe den Scan-Pointer in ein 2-dim ArbeitsArray kopiert, da kann man dann direkt mit x und y auf jeden Farbwert jedes Pixels zugreifen. Ich müsste mal probieren, ob mans nicht sogar in ein 3-dim Array bekommt, dann könnte man RGB quasi als Z-Achse auffassen.
Etwas, was danach aussieht, ist ja enthalten "UnsafeBitmap", nur wird es scheinbar nicht verwendet.
Als nächstes hab ich in die Convolutions geguckt, und scheint doch immer noch so, dass für jeden Filter eine eigene Klasse gebaut ist, dabei ist es immer derselbe Filter, nur mit verschieden beschickter 3*3-Matrix.
Sowas kann man doch variabel programmieren, dass im Button-Handler dann die Matrix beschickt wird, nicht für jeden filter eine extra-Klasse.
Einige Convolutions gehen dann auch wieder andere Wege, "SimpleConvolution" zB. wendet Bitmap-Locking an, und greift auf die Farbwerte direkt zu, aber eben ohne die "UnsafeBitmap" zu verwenden, wozu ist die denn nun eiglich da?
Oder im Ordner "Edges" guck ich den ersten an, da ist der Code komplett auskommentiert.
Und im 2. Edges-Filter, namens "Compass" findet sich wieder etwas, was sehr nach Convolution-Filter aussieht, allerdings sind es 688 Zeilen, die sich endlos wiederholen, und Get/SetPixel ist wieder dabei.
Zu Get/SetPixel habich mich schon geäußert, nun, solche "Compass"-Code-Wiederholungs-Wüsten sollte man aber auch unbedingt parametrisieren, also dass am Ende ein Algo mit geeigneten Parametern beschickt wird, anstatt für jede Variante den gleichen Algo re-implementieren.
In Corners.Moravec fund ich diese Minimum-Funktion:
C#-Code: |
private int Min(int x, int y, int[,,] aSum)
{
int[] aInt = new int[8];
for (int i = 0; i < 8;i++ )
{
aInt[i] = aSum[x,y,i];
}
Array.Sort(aInt);
return aInt[0];
}
|
Verstehe ich das richtig, dass alle 8 Werte in ein int-Array geschrieben werden, dieses sortiert, und dann das oberste Element zurückgegeben? - isnichdeinErnst, odr?
Das mit den BarCodes habichjetzt auch nochmal nachgeguckt
C#-Code: |
public override void Execute(Bitmap _bitmap) {
Bitmap bitmap = _bitmap;
List<Color> aColor = new List<Color>();
int y = 0;
int x = 0;
int nCount = 0;
aColor.Add(bitmap.GetPixel(x, y));
aColor.Add(bitmap.GetPixel(x, y));
nCount++;
Color colorToSet = Color.Transparent;
for(y = 0; y < bitmap.Height; y++) {
for(x = 0; x < bitmap.Width; x++) {
List<Color> aColorLine = new List<Color>();
Color color = bitmap.GetPixel(x, y);
aColor.Add(color);
aColorLine.Add(color);
Color colorPrev = aColor[nCount - 1];
Color colorCurrent = aColor[nCount];
Color colorAvg = ColorFunctions.AverageColor(aColorLine);
int nRGBSum = ColorFunctions.RGBChannelSum(colorAvg);
if(bOnlyThreshold) {
if(nRGBSum == nThreshold) {
colorToSet = Color.White;
aColorLine.Clear();
} else {
colorToSet = Color.Black;
}
} else {
if(nRGBSum > nThreshold) {
colorToSet = Color.White;
aColorLine.Clear();
} else {
colorToSet = Color.Black;
}
}
bitmap.SetPixel(x, y, colorToSet);
nCount++;
}
}
}
|
Interessant.
Da wird von den bisher durchlaufenen Pixeln ein Durchschnittspixel gebildet, und wenn die Summe der Farbwerte des Durchschnittspixels den Schwellwert (Threshold) überschreitet, wird weiß gesetzt, und die Liste der durchlaufenen Pixel gelöscht. (Ich hoffe, richtig verstanden zu haben, bischen Kommentation wäre nicht schlecht).
Welche Funktion hat aber die zweite Liste, "aColor"?
Forms.FormConvolution kann unnötigerweise im Designer nicht geöffnet werden. Das liegt am Aufruf von
C#-Code: |
this.CenterToParent();
|
innerhalb von InitializeComponent(), wohl weil der Designer .CenterToParent() nicht ausführen kann.
Jedenfalls eine Verlegung des Aufrufes in den Konstruktor, nach InitializeComponent() schafft Abhilfe.
Was hat es mit diesem Interface auf sich?
C#-Code: |
public interface ICommand
{
string Description { get; set; }
object Owner { get; set; }
void Run(object sender, EventArgs e);
}
|
Description: wird im ganzen Code nirgends gesetzt
Owner: desgleichen
Run: Was sollen die Argumente sender und e? Die werden zwar übergeben, aber nirgends dann auch verwendet - ich wüsste auch nicht, was ein filter mit einem toolstripMenuItem anfangen sollte, und e ist immer empty.
Auch die vielen Actions verstehe ich nicht. ist auch immer wieder ganz ähnlicher Code
C#-Code: |
namespace ImageRecognition2.Action
{
class ActionEdge : AbstractCommand
{
protected PictureBox m_PictureBox = null;
private short m_shType = -1;
public ActionEdge(PictureBox _pictureBox, short _shType)
{
m_PictureBox = _pictureBox;
m_shType = _shType;
}
public override void Run(object sender, EventArgs e)
{
FormParameter parameter = new FormParameter();
if (parameter.ShowDialog() == DialogResult.OK)
{
Bitmap bitmap = (Bitmap)m_PictureBox.BackgroundImage;
new EdgeDetectConvolution(m_shType, (byte)parameter.nValue).Execute(bitmap);
}
}
}
}
|
C#-Code: |
namespace ImageRecognition2.Action
{
public class ActionDither : AbstractCommand
{
private PictureBox m_PictureBox = null;
public ActionDither(PictureBox _pictureBox)
{
m_PictureBox = _pictureBox;
}
public override void Run(object sender, EventArgs e)
{
Bitmap bitmap = (Bitmap)m_PictureBox.BackgroundImage;
BaseImageFilter filter = new Dither();
filter.Execute(bitmap);
Bitmap bitmapDithered = filter.Bitmap;
m_PictureBox.BackgroundImage = bitmapDithered;
}
}
}
|
Ist zwar ähnlich, aber nicht gleich - warum nicht? beide Filter erben von einer gemeinsamen BasisFilterKlasse - trotzdem wird der EdgeFilter nur executet, beim Dither aber noch zusätzlich filter.Bitmap abgerufen.?.
Die Run-Methode hat dieselbe Signatur wie ein üblicher Eventhandler, und ich fänds glaub einfacher, den Code auch tatsächlich in einen echten Eventhandler reinzuschreiben, statt des in Form1 gegangenen Umwegs über eine Methode SetEventHandler
C#-Code: |
public void SetEventHandler(ToolStripMenuItem _item, ICommand _icommand)
{
_item.Tag = _icommand;
_item.Enabled = true;
_item.Click += delegate(object sender, EventArgs e)
{
ExecuteAction(_item.Tag,EventArgs.Empty);
this.pictureBox1.Invalidate();
Debug.WriteLine(_icommand.Description);
};
}
|
Also, ich mach Schluß für heut, hofflich habich dich nicht zu sehr geärgert.
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von ErfinderDesRades am 02.01.2010 01:48.
|
|
02.01.2010 01:09
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
ErfinderDesRades
myCSharp.de-Poweruser/ Experte
Dabei seit: 31.01.2008
Beiträge: 5.298
|
|
ja, geht tatsächlich, die BitmapScan als 3-dim - Pointer aufzufassen. Wenn man dann die Matrix als 2-dim Array auffasst, ergibt sich z.B. ein sehr übersichtlicher Convolution-Filter, ich habs leider nur in VB
Code: |
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:
|
Private Sub ApplyCurrentFilter()
'Über jedes Pixel wird eine 3*3-Gewichtungs-Matrix gelegt, die darunter liegenden Werte
'! gewichtet aufsummiert. Die Gesamtsumme wird durch den Divisor geteilt, um den
'! Durchschnitts-Wert wieder herzustellen.
'Heben sich positive und negative Gewichtungen auf (Summe der Matrix = 0) so wird die
'! Durchschnitts-Helligkeit des Bildes gewährleistet durch Addition eines Offsets von 127.
If FilterBindingSource.Position < 0 Then Return
Dim Filter As FilterRow = GetRow(Of FilterRow)(Me.FilterBindingSource.Current)
Dim Img As Image = DirectCast(cmbSourcePic.SelectedValue, Image)
Dim Helper As New PixelHelper(Img, PixelFormat.Format24bppRgb, ckGray.Checked)
'Filter-Daten
Dim Matrix As SByte(,) = Me.UclMatrixGrid1.GetMatrix
Dim Offset As Short = Filter.Offset
Dim Divisor As Single = Filter.Divisor
'3-dim Pixel-Arrays
Dim ReadPixels As Byte(,,) = Helper.ReadPixels
Dim WritePixels As Byte(,,) = Helper.CreateWritePixels(PixelFormat.Format24bppRgb)
Dim YUbound As Integer = Img.Height - 1
Dim XUbound As Integer = Img.Width - 1
'die Hauptschleife läßt die Ränder aus, da die Anwendung der Matrix auf Randpixel
'! zu Array-Überschreitungen führt (s. Start- und End-Werte von Y, X).
For Y As Integer = 1 To YUbound - 1
For X As Integer = 1 To XUbound - 1
For Z As Integer = 0 To 2 'auf der "Z-Achse" liegen die 3 Farbwerte
Dim WeightedSum As Double = 0
For mtrY As Integer = 0 To 2
For mtrX As Integer = 0 To 2
Dim rpY As Integer = Y + mtrY - 1
Dim rpX As Integer = X + mtrX - 1
' rpY, rpX, die Indizees der ReadPixel, beinhalten den Offset des Matrix-Punktes,
'°der grad abgefragt wird
WeightedSum += ReadPixels(rpY, rpX, Z) * Matrix(mtrY, mtrX)
Next
Next
WeightedSum = ClipBetween(0.0, WeightedSum / Divisor + Offset, 255.0)
WritePixels(Y, X, Z) = CByte(WeightedSum)
Next
Next
Next
'BackgroundImage austauschen - der PixelHelper erstellt aus den WritePixels die Bitmap
ExchangeDisposable(Me.SplitContainer1.Panel2.BackgroundImage, Helper.GetResultBitmap)
End Sub |
|
- aus LowLevelGraphics.Filter.Convolution3x3
C#-Code: |
public override void Execute(Bitmap _bitmap) {
Bitmap b = _bitmap;
if(0 == m_ConvolutionMatrix.Factor) return;
Bitmap bSrc = (Bitmap)b.Clone();
BitmapData bmData = b.LockBits(new Rectangle(0, 0, b.Width, b.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
BitmapData bmSrc = bSrc.LockBits(new Rectangle(0, 0, bSrc.Width, bSrc.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
int stride = bmData.Stride;
int stride2 = stride * 2;
IntPtr Scan0 = bmData.Scan0;
IntPtr SrcScan0 = bmSrc.Scan0;
unsafe {
byte* p = (byte*)(void*)Scan0;
byte* pSrc = (byte*)(void*)SrcScan0;
int nOffset = stride - b.Width * 3;
int nWidth = b.Width - 2;
int nHeight = b.Height - 2;
int nPixel;
for(int y = 0; y < nHeight; ++y) {
for(int x = 0; x < nWidth; ++x) {
nPixel = ((((pSrc[2] * m_ConvolutionMatrix.TopLeft) + (pSrc[5] * m_ConvolutionMatrix.TopMid) + (pSrc[8] * m_ConvolutionMatrix.TopRight) +
(pSrc[2 + stride] * m_ConvolutionMatrix.MidLeft) + (pSrc[5 + stride] * m_ConvolutionMatrix.Pixel) + (pSrc[8 + stride] * m_ConvolutionMatrix.MidRight) +
(pSrc[2 + stride2] * m_ConvolutionMatrix.BottomLeft) + (pSrc[5 + stride2] * m_ConvolutionMatrix.BottomMid) + (pSrc[8 + stride2] * m_ConvolutionMatrix.BottomRight)) / m_ConvolutionMatrix.Factor) + m_ConvolutionMatrix.Offset);
if(nPixel < 0) nPixel = 0;
if(nPixel > 255) nPixel = 255;
p[5 + stride] = (byte)nPixel;
nPixel = ((((pSrc[1] * m_ConvolutionMatrix.TopLeft) + (pSrc[4] * m_ConvolutionMatrix.TopMid) + (pSrc[7] * m_ConvolutionMatrix.TopRight) +
(pSrc[1 + stride] * m_ConvolutionMatrix.MidLeft) + (pSrc[4 + stride] * m_ConvolutionMatrix.Pixel) + (pSrc[7 + stride] * m_ConvolutionMatrix.MidRight) +
(pSrc[1 + stride2] * m_ConvolutionMatrix.BottomLeft) + (pSrc[4 + stride2] * m_ConvolutionMatrix.BottomMid) + (pSrc[7 + stride2] * m_ConvolutionMatrix.BottomRight)) / m_ConvolutionMatrix.Factor) + m_ConvolutionMatrix.Offset);
if(nPixel < 0) nPixel = 0;
if(nPixel > 255) nPixel = 255;
p[4 + stride] = (byte)nPixel;
nPixel = ((((pSrc[0] * m_ConvolutionMatrix.TopLeft) + (pSrc[3] * m_ConvolutionMatrix.TopMid) + (pSrc[6] * m_ConvolutionMatrix.TopRight) +
(pSrc[0 + stride] * m_ConvolutionMatrix.MidLeft) + (pSrc[3 + stride] * m_ConvolutionMatrix.Pixel) + (pSrc[6 + stride] * m_ConvolutionMatrix.MidRight) +
(pSrc[0 + stride2] * m_ConvolutionMatrix.BottomLeft) + (pSrc[3 + stride2] * m_ConvolutionMatrix.BottomMid) + (pSrc[6 + stride2] * m_ConvolutionMatrix.BottomRight)) / m_ConvolutionMatrix.Factor) + m_ConvolutionMatrix.Offset);
if(nPixel < 0) nPixel = 0;
if(nPixel > 255) nPixel = 255;
p[3 + stride] = (byte)nPixel;
p += 3;
pSrc += 3;
}
p += nOffset;
pSrc += nOffset;
}
}
b.UnlockBits(bmData);
bSrc.UnlockBits(bmSrc);
}
|
dabei sollte es in c# noch viel cooler sein, weil da muß man nicht in ein Array umkopieren, sondern kann Scan0 gleich als (byte ***) auffassen.
Dreimal dieselbe sehr lange Zeile zur Berechnung jedes der 3 Farbwerte ist jedenfalls nicht nötig, und wiederspricht dem DRY-Grundsatz (don't repeat yourself) von Clean Code Developer (CCD)
Und ich denke eben, so ein 3-D-Pointer ließe sich für fast alle Filter einheitlich verwenden - Get/Set-Pixel muß weg.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von ErfinderDesRades am 02.01.2010 09:02.
|
|
02.01.2010 09:00
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
ErfinderDesRades
myCSharp.de-Poweruser/ Experte
Dabei seit: 31.01.2008
Beiträge: 5.298
|
|
Habe jetzt fleißig dran rumgeforscht, und (als erstes) gemerkt, dass das mit mehrdim Pointern nicht geht.
Und die superlangen Additionen eignen sich hervorragend als Optimierung. Elegant wäre gewesen, die Matrix in einer geschachtelten Schleife zu durchlaufen (wie im VBCode gezeigt), aber das ist 5 mal langsamer, als alle 9 Durchgänge in einer einzigen Addition aneinander zu hängen.
Ich find, Optimierungen sollte man kommentieren, weil der Code sieht üblicherweise grauenhaft und umständlich aus, und wenn man nicht weiß, dasses eine Optimierung ist, will man das natürlich gleich vereinfachen.
Ist auch ein Bug drin, nämlich vor und nach der X-Schleife musstenoch die Pointer um 3 hochsetzen, da du die Randpunkte ja nicht bearbeitest.
Der Bug führt zu falsch addressierten Pixeln, die sich im Filter-Ergebnis als Diagonale Linie zeigen, von obere rechte Ecke an.
Sieht man zB. beim Laplace-Filter.
|
|
08.01.2010 14:08
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
|
@ErfinderDesRades:
ich krittel mal ein bischen herum.
Zitat: |
zunächst die Test-Anwendung: ich finde, man bräuchte was, wo man vorher und nachher nebeneinander vergleichen kann, vlt sogar Tabpages, wo man verschiedene Filter-Ausgaben durchblättern kann.
Und das bei der Ausgabe angegeben ist, was man eingegeben hat, am liebsten was mit Abspeichern.
also ich jedenfalls hab nach 3 Sekunden vergessen, welches MenuItem ich geklickst hatte, und was in die EingabeMaske eingegeben. |
Mdi Anwendung mit mehreren Fenstern ist jedenfalls wirklich eine gute Idee.
Intern wird durch die Actions sowieso gemerkt, welche Aktion zuletzt ausgeführt werde, muss ich noch überlegen ob und wenn ja, wie ich das mache.
Zitat: |
Ich hab grad angemacht, ein Bild geladen, und dann mal bei den Filtern Binarisierung-BarCode geklickst, was immer das sein mag, darüber hoffte ich ja was zu erfahren.
Da geht ein Dialog auf, da soll ich einen Grenzwert eingeben, und checken (oder nicht), ob "nur diesen grenzwert".
Damit kann ich überhaupt nichts anfangen, was denn für ein Grenzwert?
habich 142 eingegeben.
Dann steht die Anwendung, und nach ca. 10s kommt ein schwarzweiß-Bild, bei dem scheinbar die Graustufen entfernt sind.
Vermutlich ist das die Binarisierung, dasses nurnoch schwarz-weiß gibt, aber warum Barcode? - na, so heißt es eben. |
Vielleicht weil es helfen könnte einen Barcode zu erkennen!? Also willkürlich sind die Namen für die Filter jedenfalls nicht gewählt.
Zitat: |
Nächster Test: Binarisierung-treshold MinMax - da muß man keinen Grenzwert angeben, aber die Anwendung steht für 20s. |
Erstens: Die Filter sind noch nicht alle optimiert,
deswegen, lies bitte auch alles was hier steht:
Zitat: |
EDIT: Vorabversion mit neuen Filtern hochgeladen. Bisher ungetestet.
Code an vielen Stellen jetzt gecleant(er).
Als Dateianhang am Ende dieses Beitrags verfügbar:
Habe heute ein erstes Prerelease veröffentlicht. Damit man sich den Code schon mal anschauen kann. Und nein, der Code bleibt nicht so. An vielen Stellen wird es noch Änderungen und Optimierungen geben.
Die Syntax der Filter bleibt so.
Es wird noch ein ExecuteCloned hinzukommen, bei dem man das bearbeitete Bitmap als Ergebnis erhalten wird und das Original-Bild bleibt dabei wie es ist.
|
Zitat: |
Dafür gibts dann aber eine Ausgabe, bei der das Bild viel besser wieder zu erkennen ist - ein wirklich interessanter Filter. Blos wie gesagt - ich kann die Ausgabe nicht mit der Eingabe vergleichen, das ist schade. |
Das wird sich ändern.
Zitat: |
Guck ich mal in den Code, da sehe ich gleich, warum das immer so lange steht: ist voll mit GetPixel und SetPixel. Wo ich denken täte, in etwas, was sich "LowLevel..." nennt, haben die nix verloren.
Man kann doch sicherlich alle Bildformate nach 24RGB umwandeln (bei Transparenz-Unterstützung 32ARGB), die Bitmap locken, und auf einem Array mit den Farbwerten arbeiten. Für 24RGB habich das mal selbst gemacht, und habe den Scan-Pointer in ein 2-dim ArbeitsArray kopiert, da kann man dann direkt mit x und y auf jeden Farbwert jedes Pixels zugreifen. Ich müsste mal probieren, ob mans nicht sogar in ein 3-dim Array bekommt, dann könnte man RGB quasi als Z-Achse auffassen.
Etwas, was danach aussieht, ist ja enthalten "UnsafeBitmap", nur wird es scheinbar nicht verwendet. |
Bitte? Natürlich wird das verwendet aber noch nicht überall...
Zitat: |
Als nächstes hab ich in die Convolutions geguckt, und scheint doch immer noch so, dass für jeden Filter eine eigene Klasse gebaut ist, dabei ist es immer derselbe Filter, nur mit verschieden beschickter 3*3-Matrix.
Sowas kann man doch variabel programmieren, dass im Button-Handler dann die Matrix beschickt wird, nicht für jeden filter eine extra-Klasse. |
Die 3x3 Convolution ist ein Relikt von der ursprünglichen LowLevelGraphicsLibrary die am 07.07.2005 verwendet wurde, den Filter möchte ich denen die vielleicht schon Code mit der Lib aufgebaut haben nicht unbedingt wegnehmen, möglich ist aber das
er intern die anderen Convolutions benutzt, da hier ja mehrere Klassen inzwischen existieren.
Zitat: |
Einige Convolutions gehen dann auch wieder andere Wege, "SimpleConvolution" zB. wendet Bitmap-Locking an, und greift auf die Farbwerte direkt zu, aber eben ohne die "UnsafeBitmap" zu verwenden, wozu ist die denn nun eiglich da? |
Erstens: Sowohl UnsafeBitmap als auch SimpleConvolution wenden BitmapLocking an, nur dass bei SimpleConvolution die Pixel der Reihe nach iteriert werden (hintereinander), wobei es mit UnsafeBitmap möglich ist eine 2dimensionale Schleife
á la
C#-Code: |
UnsafeBitmap bitmap = new UnsafeBitmap(_bitmap);
for y...
{
for x...
{
Color color = bitmap.GetPixel(x,y);
}
}
|
Zitat: |
Oder im Ordner "Edges" guck ich den ersten an, da ist der Code komplett auskommentiert.
Und im 2. Edges-Filter, namens "Compass" findet sich wieder etwas, was sehr nach Convolution-Filter aussieht, allerdings sind es 688 Zeilen, die sich endlos wiederholen, und Get/SetPixel ist wieder dabei. |
Dann sieh Dir bitte mal an, warum Crimmins Speckle Removal so funktioniert und warum es so heißt. Außerdem: Lies Dir bitte die Kommentare im Code durch:
C#-Code: |
|
Zitat: |
Zu Get/SetPixel habich mich schon geäußert, nun, solche "Compass"-Code-Wiederholungs-Wüsten sollte man aber auch unbedingt parametrisieren, also dass am Ende ein Algo mit geeigneten Parametern beschickt wird, anstatt für jede Variante den gleichen Algo re-implementieren. |
Und nochmals: es ist IMMER NOCH eine Vorabversion.
Zitat: |
Habe jetzt fleißig dran rumgeforscht, und (als erstes) gemerkt, dass das mit mehrdim Pointern nicht geht.
Und die superlangen Additionen eignen sich hervorragend als Optimierung. Elegant wäre gewesen, die Matrix in einer geschachtelten Schleife zu durchlaufen (wie im VBCode gezeigt), aber das ist 5 mal langsamer, als alle 9 Durchgänge in einer einzigen Addition aneinander zu hängen.
Ich find, Optimierungen sollte man kommentieren, weil der Code sieht üblicherweise grauenhaft und umständlich aus, und wenn man nicht weiß, dasses eine Optimierung ist, will man das natürlich gleich vereinfachen. |
Na fein, schön dass DU es selbst herausgefunden hast.
Die Fehler sind mir übrigens bekannt. Aber danke für den Hinweis. Es sind auch noch viel mehr Fehler in der Library. Deshalb wird es auch von nun ab ne Weile dauern bis wieder eine neue Version rauskommt.
Zitat: |
Ist auch ein Bug drin, nämlich vor und nach der X-Schleife musstenoch die Pointer um 3 hochsetzen, da du die Randpunkte ja nicht bearbeitest.
Der Bug führt zu falsch addressierten Pixeln, die sich im Filter-Ergebnis als Diagonale Linie zeigen, von obere rechte Ecke an.
Sieht man zB. beim Laplace-Filter. |
Dass es ab und zu zu der berühmt-berüchtigten Diagonale kommt, ist mir schon längst bekannt, es ist nicht nur beim Laplace Filter ab und zu der Fall.
Wenn Du jetzt noch weiter rausfindest, siehst Du dass GetPixel und SetPixel an fast allen Stellen von einer Klasse namens UnsafeBitmap benutzt wird.
Und auch dass es einige Klassen ibt, die gar nicht benutzt werden usw.
Aber um jetzt mal langer Rede langen Sinn einfach sich selbst zu überlassen:
Was möchtest Du denn programmieren oder ausprobieren? Bin einfach neugierig für was Du die Lib momentan verwendest.
Gruß, dr4g0n76
|
|
08.01.2010 14:44
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
|
Diese Features werden mit dem nächsten Upload veröffentlicht:
- Kuwahara Filter hinzugefügt (Rauschverringerungsfilter der Kanten erhält)
- Photoshopmodus-Filter (Farbig abwedeln, Multiplizieren, Weiches Licht, Hartes Licht, Umgekehrt Multiplizieren usw...)
- Bernsen Operator
- Lipschitz Filter
- Windowed Sinc Filter
- Non Maximum Suppression
- ChannelDifference Filter hinzugefügt (Unterschiede in Kanälen
- EntropyThreshold
- EnergyMap
- EntropyMap
- Lambda-Erweiterung LambdaPixel (Bitmap, x,y, Color, Rectangle Area)
Damit können auch auf ganz einfache Weise Flips u.ä. realisiert werden
- Bitmap 2 LINQ (Bitmap kann aufgrund Neighbouringsfunktionen als LINQ Objekt zurückgegeben werden)
Die neue Version gibt's diesmal erst, wenn alles andere auch durchgetestet sind.
Außerdem werden einige Filter wesentlich verschnellert werden.
- Einführung von Neighbouring zur eigenen Benutzung.
Durch ein GetNeighbour kann ein Window mit Größe s direkt erhalten werden:
Bsp. für die Neighbour von P für Window mit s = 3:
***
*P*
***
Bsp. für die Neighbours von P für Window mit s = 5:
*****
*****
**P**
*****
*****
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von dr4g0n76 am 25.01.2010 17:08.
|
|
13.01.2010 17:40
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
|
Zitat: |
Hast du schon (neben Grayscale) einen Brightness- und Contrastfilter implementiert?
Das ist nämlich gerade genau das was ich suche. Wenn ja, arbeitet der schon mit Scan0 ? Das ganze muss so schnell wie möglich laufen damit es für mich ineteressant ist. |
Die Filter befinden sich in dem Namespace LowLevelGraphics.Filter und heißen:
und heißen:
GrayScale,
Brightness,
Contrast
Alle benutzen Scan0.
Anwendungsbeispiele:
C#-Code: |
new GrayScale().Execute(bitmap);
new Brightness(10).Execute(bitmap);
new Contrast(10).Execute(bitmap);
|
usw.
|
|
14.01.2010 12:40
|
E-Mail |
Beiträge des Benutzers |
zu Buddylist hinzufügen
|
|
|
|