Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   C# schnelle Bildverarbeitung? (https://www.delphipraxis.net/154400-schnelle-bildverarbeitung.html)

jfheins 9. Sep 2010 14:54


schnelle Bildverarbeitung?
 
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)
            {
            }

implementation 9. Sep 2010 16:25

AW: schnelle Bildverarbeitung?
 
Naja, du benutzst die GDI+ und das ist nunmal sehr langsam.
Wenn du's schneller willst, bau dir einen Header für's GDI :wink:

Robotiker 9. Sep 2010 18:49

AW: schnelle Bildverarbeitung?
 
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.

jfheins 9. Sep 2010 20:19

AW: schnelle Bildverarbeitung?
 
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.


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:20 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