Laden...

Ausschnitt in Bild finden

Erstellt von paul_94 vor 10 Jahren Letzter Beitrag vor 10 Jahren 6.056 Views
P
paul_94 Themenstarter:in
1 Beiträge seit 2013
vor 10 Jahren
Ausschnitt in Bild finden

Beschreibung:
Hi,

ich habe eine Klasse erstellt welche in einem großen Bild ein kleineres Bild sucht.
Gibt es warscheinlich schon mehrere aber ich dachte ich beglücke euch einfach mal mit meinem Code.

Von meinen C# Künsten her würde ich mich etwas höher als Anfänger einordnen.

Das Bild wird vorher in eine List<List<Color>> umgewandeln um auf zu viele getPixel aufrufe zu verzichten, da diese wohl recht langsam zu sein scheinen.

Vllt sollte ich aber von den Listen weg gehen und zu Arrays wechseln, das diese glaube noch schneller sind.

Über verbesserungsvorschläge würde ich mich freuen 😄

Die methode "findPictureCoords" gibt die linke obere Ecke des teilbilds als Point auf dem Bild in dem gesucht wurde zurück.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;

namespace findMeinBild
{
    class findPicture
    {
        private Image searchIn;
        private List<List<Color>> list_searchIn;
        private List<List<Color>> list_searchedFor;
        private List <Point> maybe_points=new List<Point>();
        private List<int> hits_list = new List<int>();

        public findPicture(Image searchIn)
        {
            this.searchIn = searchIn;
            list_searchIn = imageToList(searchIn);
        }

        public Point findPictureCoords(Image searchedFor)
        {
            list_searchedFor = imageToList(searchedFor);
            int allPixels = searchedFor.Width * searchedFor.Height;
            
            if (searchIn.Size.Width > searchedFor.Width && searchIn.Height > searchedFor.Size.Height)
            {
                for (int line = 0; line < searchIn.Height - searchedFor.Height; line++)
                {
                    for (int col = 0; col < searchIn.Width - searchedFor.Width; col++)
                    {
                        if (list_searchIn[col][line] == list_searchedFor[0][0] && list_searchIn[col+searchedFor.Width-1][line] == list_searchedFor[searchedFor.Width-1][0])
                        {
                            maybe_points.Add(new Point(col,line));
                            int hits = 0;
                            for (int y = 0; y < searchedFor.Height; y++)
                            {
                                for (int x = 0; x < searchedFor.Width; x++)
                                {
                                    if (list_searchIn[x + col][y + line] == list_searchedFor[x][y])
                                    {
                                        hits++;
                                    }
                                }
                            }
                            hits_list.Add(hits);
                        }
                    }
                }
            }

            int highest=0;
            int i=0;
            while (i < hits_list.Count - 1)
            {
                if (hits_list[i] > highest)
                {
                    highest = i;
                }
                i++;
            }

            if (maybe_points[0] != null)
            {
                return maybe_points[highest];
            }
            else
            {
                return new Point(-1, -1);
            }
        }

        public List<List<Color>> imageToList(Image img)
        {
            List<List<Color>> pixelList = new List<List<Color>>();
            Bitmap bmp_pixels=new Bitmap(img);
            for (int col = 0; col < img.Width; col++)
            {
                List<Color> lines = new List<Color>();
                for (int line = 0; line < img.Height; line++)
                {
                    lines.Add(bmp_pixels.GetPixel(col,line));
                }
                pixelList.Add(lines);
            }
            return pixelList;
        }
    }
}

Verwenden tut man die Klasse folgendermaßen:


picfind = new findPicture(BILDINDEMGESUCHTWIRD);
point p = picfind.findPictureCoords(BILDAUSSCHNITT)


ps.: Wenn jemand diesen Code in seinem Projekt verwenden möchte und kein Geld damit verdient, kann er das gerne machen.
Ich möchte aber bitte informiert werden und ein Credit eintrag tut mir auch nicht weh :D

Schlagwörter: findPicture, bild finden, button finden,

if (brain != null)
{
BoardSearch.use(question);
}

49.485 Beiträge seit 2005
vor 10 Jahren

Hallo paul_94,

üblicherweise würde man zum schnellen Zugriff auf die Bitmap-Daten direkt oder indirekt Bitmap.LockBits und BitmapData.Stride verwenden. Siehe auch GetPixel und SetPixel um Längen geschlagen. 800 mal schneller.

herbivore

691 Beiträge seit 2007
vor 10 Jahren

@paul_94: Je nachdem was du vor hast, könntest du dir auch mal SIFT-Features angucken. Die sind nämlich rotations- und skalierunsinvariant.

mit freundlichen Grüßen,
Tomot

Projekte: www.gesellschaftsspieler-gesucht.de