AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

schnelle Bildverarbeitung?

Ein Thema von jfheins · begonnen am 9. Sep 2010 · letzter Beitrag vom 9. Sep 2010
Antwort Antwort
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#1

schnelle Bildverarbeitung?

  Alt 9. Sep 2010, 14:54
Hallo,
ich habe mal meine C# Kenntnisse ausgepackt und ein kleine Programm geschrieben. Das Teil soll mir Bilder auswerten, die ich für eine Studienarbeit mache.
Anforderung ist einfach: Anzahl schwarze Pixel zählen und zurückgeben. Mit GetPixel() ist das natürlich total lahm, deshalb war ich auf der Suche nach Alternativen und bin auf LockBits() gestoßen.

Aber genug der schönen Worte, hier mein Code:
Code:
private uint CountPixels(Image img)
        {
            var s = DateTime.Now;
            uint result = 0;
            int col = colorDialog1.Color.ToArgb();
            Bitmap bmp = new Bitmap(img);

            Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
            System.Drawing.Imaging.BitmapData bmpData =
                bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadWrite,
                bmp.PixelFormat);

            bmpData.PixelFormat = System.Drawing.Imaging.PixelFormat.Format32bppArgb;


            // Get the address of the first line.
            IntPtr ptr = bmpData.Scan0;

            // Declare an array to hold the bytes of the bitmap.
            int pixelcount = bmp.Width * bmp.Height;
            int[] rgbValues = new int[pixelcount];

            // Copy the RGB values into the array.
            System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, pixelcount);

            for (int i = 0; i < rgbValues.Length; i++)
            {
                if (rgbValues[i] == col)
                    result++;
            }
            // Unlock the bits.
            bmp.UnlockBits(bmpData);
            bmpData = null;
            bmp.Dispose();
            rgbValues = null;

            var e = DateTime.Now;
            System.Console.WriteLine((e - s).TotalMilliseconds);

            return result;
        }
Braucht bei mir für ein 10 MP Bild ungefähr 500ms. Geht das noch schneller?
Danke schonmal im Voraus

P.S.: Wenn möglich bitte ohne unsafe Code.


P.P.S.: Hier der Aufruf der Funktion:
Code:
// For Schleife
            try
            {
                Image img = Image.FromFile(Files[i].FullName);
                try
                {
                    var x = CountPixels(img);
                    // Anzeige von x                  
                }
                finally
                {
                    img.Dispose();
                }
            }
            catch (OutOfMemoryException)
            {
            }

Geändert von jfheins ( 9. Sep 2010 um 15:26 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von implementation
implementation

Registriert seit: 5. Mai 2008
940 Beiträge
 
FreePascal / Lazarus
 
#2

AW: schnelle Bildverarbeitung?

  Alt 9. Sep 2010, 16:25
Naja, du benutzst die GDI+ und das ist nunmal sehr langsam.
Wenn du's schneller willst, bau dir einen Header für's GDI
  Mit Zitat antworten Zitat
Robotiker
(Gast)

n/a Beiträge
 
#3

AW: schnelle Bildverarbeitung?

  Alt 9. Sep 2010, 18:49
Hallo !

Wenn man die Bitmap verändern will, ist die Verwendung eines Pointers am schnellsten. Erfordert aber unsafe code:

http://www.codeproject.com/KB/GDI-pl...filters11.aspx

In WPF gibt es die Klassen WriteableBitmap und InteropBitmap, die sind bei solchen Operationen wohl geeigneter.
  Mit Zitat antworten Zitat
Benutzerbild von jfheins
jfheins

Registriert seit: 10. Jun 2004
Ort: Garching (TUM)
4.579 Beiträge
 
#4

AW: schnelle Bildverarbeitung?

  Alt 9. Sep 2010, 20:19
Hallo,
danke erstmal für die Antworten. Allerdings muss ich euch widersprechen: Der unsafe Code ist sogar einen Hauch langsamer als der bisherige ...

Wenn ich den Profiler richtig bedient (und verstanden) habe, sind die Engpässe vor allem die Zeilen:
Code:
            Image img = Image.FromFile(Files[index].FullName); // 49% der Zeit
            Bitmap bmp = new Bitmap(img); // 24% der Zeit
            if (rgbValues[i] == col) // Das was er eigentlich machen soll: 13% der Zeit
Aber ich sehe da (leider) nicht viel Einsparpotenzial ...


-------------------------------------------------------------------------

Okay, hat sich erledigt. Ich habe die ersten beiden Engpässe zusammengelegt (Bitmap Konstruktor mit Dateiname akzeptiert auch jpeg und png) sowie die Verarbeitung an die Fartiefe angepasst. (24bit oder 32bit) (vorher immer nach 32 bit konvertiert)
Damit (und dank des Threadpools+Quadcore) läuft das Programm auf meiner Testmenge (100 jpegs, 300 MB) in unter 10 Sekunden durch.

Geändert von jfheins ( 9. Sep 2010 um 22:06 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:51 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz