Jak wykrywać krawędzie i prostokąty

14

Staram się wykrywać prostokąty na obrazach. Tło obrazów ma jeden kolor (przez większość czasu). Próbowałem dwóch metod, aby uzyskać obraz binarny (1 = tło, 0 = krawędzie), aby później wykonać transformację Hougha ...

  1. Filtr Sobel lub Canny

  2. Gładki obraz A, Utwórz obraz różnicowy A - gauss, Utwórz obraz binarny z progiem (Utwórz histogram, najwyższy przedział powinien być tłem ...)

Rezultatem jest obraz binarny z krawędziami. Naprawdę nie wiem, która metoda działa lepiej dla różnych obrazów. Jakieś pomysły?

Martin Thompson
źródło
1
Co rozumiesz przez „działa lepiej”? Canny jest bardzo popularny w tego typu rzeczach, ale zależy to od tego, co próbujesz zrobić, gdy masz już krawędzie. Co dokładnie próbujesz osiągnąć?
Paul R
4
Nie głosuj w dół na nowych użytkowników za pierwsze pytanie w społeczności!
1
Ten wątek może być przydatny
Jim Clay
Wyjaśnienie detektorów krawędzi: dsp.stackexchange.com/q/74/1273
penelopa,
„Wynikiem jest obraz binarny z krawędziami. Naprawdę nie wiem, która metoda działa lepiej dla różnych obrazów. Jakieś pomysły?” Może potrzebujesz biblioteki testowej obrazu, aby znaleźć odpowiedź lub zrobić zdjęcia w środowiskach, które możesz policzyć. Jeśli istnieją najlepsze algorytmy w tej dziedzinie, dlaczego mielibyśmy uczyć się tylu innych? Wierzę, że każdy algorytm ma czasem swoją przewagę, w sensie prawdopodobieństwa.

Odpowiedzi:

10

Kiedyś napisałem aplikację do wykrywania prostokątów. Wykorzystano wykrywanie krawędzi Sobela i transformację liniową Hougha.

Zamiast szukać pojedynczych pików na obrazie Hougha (linie), program szukał 4 pików w odległości 90 stopni między nimi.

Dla każdej kolumny na obrazie Hougha (odpowiadającej pewnym kątom), trzy inne kolumny były wyszukiwane pod kątem lokalnych maksimów. Po znalezieniu satifactory peak w każdej z czterech kolumn wykryto prostokąt.

Program skonstruował prostokąt i wykonał dodatkowe kontrole spójności kolorów wewnątrz i na zewnątrz prostokąta w celu rozróżnienia fałszywych trafień. Program służył do wykrywania umieszczania papieru w zeskanowanych arkuszach papieru.

Libor
źródło
5

Może się okazać, że lepszym wyborem jest wykrywacz krawędzi Laplaciana Gaussa. Powinien dawać ci zamknięte kontury częściej niż wykrywacz krawędzi Canny. Wierzę, że tego właśnie chcesz, ponieważ następnym krokiem jest zastosowanie transformacji Hougha.

wióry
źródło
2

Może ci się przydać, ale jest za późno, kiedy odwiedzam tę stronę dzisiaj

        Bitmap bmp=new Bitmap(pictureBox1.Image);
        int x1=0, x2=0, y1=0, y2=0;            
        for (int i = 1; i < bmp.Height;i++ )
        {                
            for (int j = 1; j < bmp.Width;j++ )
            {
                if( bmp.GetPixel(j,i).R<7  &&  bmp.GetPixel(j-1,i).R>240  && bmp.GetPixel(j,i-1).R>240 ){

                    for (int k = j; k < bmp.Width - 1;k++ )
                    {

                        if ((bmp.GetPixel(k, i).R < 7) && (bmp.GetPixel(k+1, i).R > 240) && (k-j>30)) {
                            int count1 = 0;

                            for (int g = j; g < k;g++ ){
                                if(bmp.GetPixel(g,i).R<7){
                                    count1++;                                    
                                }
                            }//get total width

                         if(count1==k-j){                                 
                             x1 = j;
                             y1 = i;
                             x2 = k;
                         }
                        }
                    }
                         for (int a = i; a < bmp.Height - 1;a++ )
                         {
                             if ((bmp.GetPixel(j, a).R < 7) && (bmp.GetPixel(j, a+1).R > 240) && (a- i > 30)) {

                                 int count2 = 0;

                                 for (int x = i; x < a;x++ )
                                 {
                                     if(bmp.GetPixel(j,x).R<7){                                            
                                         count2++;
                                     }
                                 }


                                 if (count2 == (a - i))
                                 {

                                     y2 = a;
                                 }
                                 else {
                                     Console.WriteLine("check");
                                 }
                             }

                         }

                         if ((bmp.GetPixel(x2, y2).R < 7) && (bmp.GetPixel(x2 + 1, y2).R > 240) && (bmp.GetPixel(x2, y2+1).R > 240))
                         {

                             bool r1 = false;
                             bool r2 = false;
                             int count3 = 0;
                             for (int y = y1; y < y2;y++ )
                             {
                                 if(bmp.GetPixel(x2,y).R<7){
                                     count3++;                                     
                                 }
                             }

                             if (count3== y2 - y1) {
                                 r1 = true;
                             }                                
                             if(r1==true){
                                 int count4=0;
                                 for (int x = x1; x < x2;x++ )
                                 {
                                     if(bmp.GetPixel(x,y1).R<7){
                                         count4++;
                                     }
                                 }

                                 if(count4==x2-x1){
                                     r2 = true;
                                     Console.WriteLine("values :  X1 " + x1 + "   y1 :" + y1 + "   width : " + (x2 - x1) + "  height :  " + (y2 - y1));
                                     Pen pen = new Pen(Color.Red, 2);
                                     pictureBox1.CreateGraphics().DrawRectangle(pen, x1, y1, x2 - x1, y2 - y1);
                                 }                     
                             }
                            }

                }

                    }// initial point loop




                }// first if
Zunera Altaf
źródło
2
Witamy w dsp.stackexchange :) Każda odpowiedź, nawet późna, jest bardzo mile widziana, ale byłoby miło, gdybyś podał kontekst z odpowiedzią. Preferowane są odpowiedzi, które zawierają wyjaśnienia i źródła - czy możesz edytować swoją odpowiedź, napisać kilka zdań na temat tego, co robi kod i jak pomogłoby to w zadawanym problemie, a może zacytować źródło, jeśli to nie ty? Gdyby twoja odpowiedź była znacznie lepsza. Zmodyfikuj też swoją tożsamość - próbowałem, ale zgubiłem się po przejściu jednej trzeciej twojego kodu.
penelopa,
0

Jeśli twój obraz jest względnie czysty, masz wyraźne prostokąty bez wielu przerw. Alternatywą dla transformacji Hougha jest tworzenie konturów i zmniejszanie ich, aż utworzą 4-stronny kontur = prostokąt.

Są do tego próbki OpenCV

Martin Beckett
źródło