Avatar billede mysitesolution Nybegynder
17. september 2005 - 14:54 Der er 10 kommentarer og
2 løsninger

Algoritme: finde farve

Hej...

Jeg søger en algoritme der kan finde farver der fx er over 250rød,over 250 blå og over 250 gul fra fx et Image, eller bitmap...

Jeg har selv lavet en, som simpelhen søger hvert enkelt pixel, men det tager ALLLLLLT for lang tid... det skulle gerne gå forholdsvis hurtigt
Avatar billede arne_v Ekspert
17. september 2005 - 15:18 #1
hvis du skal checke alle pixels så skal du vel checke alle pixels ??
Avatar billede driis Nybegynder
17. september 2005 - 15:24 #2
Bruger du GetPixel / SetPixel ? Det er kendt, at disse metoder er ret langsomme.

Du er nødt til at søge hver pixel igennem for at opnå det du søger. Men det går sikkert hurtigere hvis du laver en buffer med de rå data og selv løber det igennem.
Avatar billede mysitesolution Nybegynder
17. september 2005 - 15:25 #3
ja kan du have ret i...

Men måden jeg gjorde det var noget lignede det her:

for (int i = 0; i < ANTALPIXELS)
{
  if (billede.getpixel.color.red > 250) //tror det bar nogenlunde det den hed
  {
      blah
  }
}

jeg ved der er en hurtigere løsning, da jeg har set andre programmer gøre noget ligende...

ville det være bedre at tage bitmap billedet binært, og så kører alle bytes igennem?
Avatar billede mysitesolution Nybegynder
17. september 2005 - 15:26 #4
driis-> noget ikke at se dit svar inden jeg postede, men ja getpixel...
Avatar billede arne_v Ekspert
17. september 2005 - 15:29 #5
at læse billedet ind som byte array og løbe bytes igennem vil uden tvivl være
hurtigere men forudsætter dog at man kender formatet
Avatar billede mysitesolution Nybegynder
17. september 2005 - 15:46 #6
har en bog hvor formatet er vist hhm... tror bare ikke jeg er alt for cool til c# til at kunne lave det... men man kan jo lærer af det så :)
Avatar billede driis Nybegynder
17. september 2005 - 15:49 #7
Følgende er en mulighed:
unsafe static void Main(string[] args)
        {           
            Bitmap bm = new Bitmap("mc.jpg");
            BitmapData data = bm.LockBits(new Rectangle(new Point(0), bm.Size),
                ImageLockMode.ReadOnly,PixelFormat.Format24bppRgb);
            IntPtr ptr = data.Scan0;
            int rCount = 0, gCount = 0, bCount = 0;
            int threshold = 200;
            byte * ptrByte = (byte *)ptr.ToPointer();
       
            for ( int pos = 0 ; pos < 3 * data.Width * data.Height ; pos += 3 )
            {
                if ( *(ptrByte + pos) > threshold )
                    rCount++;
                if ( *(ptrByte + pos + 1) > threshold )
                    gCount++;
                if ( *(ptrByte + pos + 2) > threshold )
                    bCount++;
            }
       
            Console.WriteLine("{0}, {1}, {2}",rCount,gCount,bCount);
        }

Jeg tror ikke det kan laves meget hurtigere. Du skal i øvrigt kompilere med /unsafe eller finde en måde at undgå pointeren.
Avatar billede driis Nybegynder
17. september 2005 - 15:50 #8
Og kald i øvrigt bm.UnlockBits(data) til sidst, det glemte jeg.
Avatar billede driis Nybegynder
17. september 2005 - 16:07 #9
Her er en lidt optimeret version, der sparer nogle additioner:
        unsafe static void Main(string[] args)
        {           
            Bitmap bm = new Bitmap("mc.jpg");
            DateTime dtBegin = DateTime.Now;
            BitmapData data = bm.LockBits(new Rectangle(new Point(0), bm.Size),
                ImageLockMode.ReadOnly,PixelFormat.Format24bppRgb);
            IntPtr ptr = data.Scan0;
            int rCount = 0, gCount = 0, bCount = 0;
            int threshold = 200;
            byte * ptrByte = (byte *)ptr.ToPointer();           
            byte * endloc = ptrByte + data.Width * data.Height * 3;
            while(ptrByte < endloc)
            {
                if ( *(ptrByte++) > threshold )
                    rCount++;
                if ( *(ptrByte++) > threshold )
                    gCount++;
                if ( *(ptrByte++) > threshold )
                    bCount++;
            }
            bm.UnlockBits(data);
            Console.WriteLine("{0}, {1}, {2}",rCount,gCount,bCount);
            TimeSpan ts = DateTime.Now - dtBegin;
            Console.WriteLine("Execution time: {0}.{1} seconds",ts.Seconds,ts.Milliseconds);
        }
Avatar billede driis Nybegynder
17. september 2005 - 16:09 #10
Sidste version kan eksekveres på 31 millisekunder ved 4 mio. pixels (på min maskine). Det er eksklusive indlæsning af billedet på disk.
Avatar billede mysitesolution Nybegynder
17. september 2005 - 16:10 #11
DAMN det går hurtigt :) lige hvad jeg havde brug for... TAK TAK og atter tak :)

det går i hvert fald 9 gange så hurtigt som min :)
Avatar billede mysitesolution Nybegynder
17. september 2005 - 16:10 #12
nej, 90 gange hurtigere mente jeg..
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester