szukanie w obrazie obrazku

0

Witam,
Mam taki problem iż nie wiem jak można zrobić takie wyszukanie, to jest
mam jakiś obrazek i mam drugi mniejszy (nie zabrudzony, przejrzysty etc)
i teraz jak znaleźć drugi obrazek w pierwszym? (zależałoby mi aby pracować nad jpg).
próbowałem już kilku sposobów ale albo większość na bmp co niszczy pierwszy obrazek albo w ogóle nic nie wychodziło,

Chodzi mi o np że mam zdjęcie jakiegoś otoczenia i drugie zdjęcie z np budynkiem które znajduje się na zdjęciu numer 1 lub nie, i teraz chciałbym dowiedzieć się czy w pierwszym obrazku występuje obrazek 2, (na obrazku 1 może być tak że budynek może być brudny, lub np obrazek 2 będzie miał większy wymiar niż 1 (w sensie obiekt))

czy ktoś ma jakiś pomysł?

0

użyj Canvas i sprawdzaj linię po linii czy w linii dużego obrazka znajduje się linia wielkości małego obrazka - gdzie kolory pixeli będą takie same ,a jeżeli obrazki mogą być różnej wielkości to powtarzaj tę procedurę od początku pomniejszając go za każdym razem i w tym przypadku kolory pixeli przyjmuj z pewną tolerancją.

0

tak, i bedzie tak rok sprawdzac....

0

nie, obrazek nie jest wycięty z oryginału wręcz przeciwnie,
myślałem o usunięciu kolorów i porównaniu np tylko kształtów czy taki kształt istnieje ale problem będzie z wielkościami obrazków

0

Z opisu nic nie wynika ,że ma być szybko.A poza tym wszystko zależy jak duże będą oba obrazki.

0

Ten problem chyba wchodzi w zakres biblioteki do analizy obrazów (porównywanie ze wzorcem) opencv. Być może też da się to zrobić algorytmem genetycznym.

0

tylko czy opencv potrafi rozpoznac dwa obrazy, czy najpierw trzeba nauczyc go rozpoznawania na podstawie 5000 wzorców?

0

A czy można skądś pobrać te opencv dla Delphi?
bo szukałem lecz znaleźć nie mogę

0

Po pierwsze:

cimak 2010-03-16 23:14 napisał(a)

powiem tak: jesli nie znasz sie dobrze na programowaniu to za openCV sie nie bierz bo porywasz sie z motyka na slonce, takie jest moje zdanie.

Pod drugie:
http://www.megaupload.com/?d=LRFX9WPC

0

Jest jeden problem znalazłem to wcześniej i niestety wyskakuje mi bląd z cv100.dll pisze mi że nie może znaleźć jakieś funkcji w tym dll

0

Od biedy możesz użyć bardzo prostego algorytmu, ale tylko pod warunkiem że znajdowany fragment ma taką samą wielkość i nie ma wielu obszarów różniących się pikseli od wzorca. Bo jeśli na przykład na obrazie znajdowany fragment ma inną jasność i kontrast od wzorca to nie znajdziesz tą prostą metodą.

Metoda polega na tym, że po prostu przeszukujesz w podwójnej pętli wszystkie możliwe prostokąty na obrazie i porównujesz ze wzorcem. Porównanie to robisz metodą wagową dla każdego piksela prostokątu, przy czym współczynniki dla wag dopasowujesz doświadczalnie. Znajdujesz sposób żeby ocenić (jasność, nasycenie) czy dany piksel różni się od wzorca w danym miejscu i stopień różnicy zapisujesz dla każdego piksela. Im większa różnica tym bardziej to zaznaczasz tym współczynnikiem. Później bierzesz z tych wszystkich wartości średnią arytmetyczną która nie ma przekroczyć pewnej przyjętej wartości.

0

A jakbym mógł prosić o jedną rzecz to jest jak program ma wyciąć np wszystkie prostokąty z obrazku wtedy miałbym lepiej do porównywania, lecz niestety nie wiem jak zrobić aby program wyciął wszystkie trójkąty z obrazka(wiadomo potem koła prostokąty etc)

0

A po co ma wycinać koła i trójkąty? Przecież obrazy do porównywania zawsze zawarte są w prostokątnych bitmapach.

0

powiedzmy że mam taki obrazek
http://www.humorpage.pl/obrazki/p/456_polskie_drogi_kaluza_znak_ostrzegawczy.jpg</img>

i chciałbym aby program mi powiedział że na zdjęciu jest znak ostrzegawczy uwaga niebezpieczeństwo

0

Najpierw przestudiuj wszystko co znajdziesz tutaj: http://www.google.pl/search?hl=pl&q=algorytmy+rozpoznawanie+obrazu&aq=f&aqi=&aql=&oq=, albo daj sobie z tym zadaniem spokój.

0

nie moge to na zaliczenie jest:/

0

okazało się iż wystarczy że powiem że jest to znak ostrzegawczy nie muszę mówić dokładnie jaki.
czy znacie jakiś algorytm do delphi na wykrywanie krawędzi? chyba to będzie dobry pomysł?

0

Tym prostym algorytmem tego nie zrobisz. Musiałby szukany element mieć dokładnie taką samą wielkość jak element na obrazie. Wtedy wycinasz kształt ze wzorca umieszczając go na jednokolorowym tle i przy porównywaniu prostokątów porównujesz tylko te odpowiadające sobie piksele, które na wzorcu nie są koloru tła. W innych przypadkach trzeba stosować zaawansowane algorytmy. Są do tego gotowe biblioteki. Nawet widziałem interfejs do opencv żeby można było łatwo użyć tej biblioteki w Delphi z konwersjami typów z języka C na Delphi. Jest też książka do tego. Jednak przypuszczam że tam jest tyle różnych współczynników do ustawiania, zależnych od sytuacji, że do tego potrzebna jest spora wiedza, i szybko tego się nie da opanować.

0

a czy nie idzie zrobić tak że wycinam znaleziony trójkąt poprzez krawędzie (np filtr laplace'a) i sprawdzam kolor czy jest to żółty czy nie(oczywiście różne odcienie żółtego ?, jeśli tak jest to znak ostrzegawczy

0

Zapytaj w dziale "algorytmy i struktury danych". Tam są specjaliści od takich rzeczy.

0

napisałem już w dziale algorytmy ale tutaj także napiszę
jak w delphi sprawdzić czy są na takim obrazku jak poniżej trójkąty prostokąty etc?

http://ip12.pl/test.gif

z góry dziękuje za pomoc

0

Cienko to widzę, i od razu nikt ci nie poda gotowego rozwiązania, materiałów do delphi raczej nie znajdziesz. Oczywiście można sobie usiąść i np. zakładając, że operujemy na jakichś wyraźnych, stałych wzorcach napisać prymitywny algorytm (prymitywny nie znaczy prosty ani krótki). Podawałem ci link do wyników w google, abyś się zorientował, że nie jest to takie proste. Masz następny link (podobny do twojego zadania) - zobacz złożoność problemu.

System rozpoznawania znaków drogowych SSN (back propagation)

ogólnie: siadaj i płacz :(

0

a czy nie idzie tego zrobić jakąś prostą metoda/algorytmem który rozpozna kształty (trójkąt,koło etc?), bo to by było chyba najlepsze rozwiązanie w takim wypadku SSN odpada.
znalazłem taki pdf
http://home.agh.edu.pl/~horzyk/pracedyplom/2009mateuszmazurprmagist.pdf

jest to praca dyplomowa pokazująca jak rozpoznać znaki drogowe bez SSN ale nie potrafię za bardzo tego wlepić do delphi(wykonać tego).
chodzi teraz tylko o rozpoznanie kształtu chyba najlepszy sposób jak na laika

aktualnie znajdowanie znaku drogowego poprzez barwę robię tak:

var
  x,y: Integer;
col:Tcolor;
R,G,B,i : Integer;

begin
i:=0;
      for y:=0 to image2.Height-1 do
      for x:=0  to  image2.Width-1 do
begin
col:=image2.Canvas.Pixels[x,y];
R := Col and $ff ;
G := (Col and $ff00)  shr 8;
B := (Col and $ff0000)   shr 16;
//memo1.lines.add(inttostr(r)+' '+inttostr(g)+' '+inttostr(b));
//label1.Caption:=inttostr(y);
if (R>190) and (R<250) and (G>100) and (G<220) and (B>0) and (B<120) then
begin
inc(i);
end
else
 begin
 image2.Canvas.Pixels[x,y]:=rgb(0,0,0);
 end;
end;
if(i>600) then
 label2.Caption:='Na obrazku znajduje się znak ostrzegawczy!';

Czyli piksel po pikselu i jeśli nie jest w kolorze jaki chce to zmienia pixel na czarny, może za pomocą tego idzie wykryć czy jest to koło czy coś innego?

Zadanie to jest na zaliczenie, na zajęciach nie robiliśmy nic takiego:(

Proszę o pomoc

0

zwiększ bardzo mocno kontrast obrazka (jak bardzo - musisz to sprawdzić doświadczalnie) i/lub zmień kolory na monochromatyczne (tak samo musisz potraktować wszystkie obrazki wzorcowe). następnie usuń z obrazka wszystkie jasne obszary mniejsze od kilku procent powierzchni. na koniec policz korelację (algorytmów jest kilka, znajdź sobie najbardziej odpowiedni, np. http://local.wasp.uwa.edu.au/~pbourke/miscellaneous/correlate/) między obrazkami, wybierz ten o największym współczynniku, jeśli współczynnik dla niego jest odpowiednio wysoki (zgaduję, że więcej niż 0,7), to wygrałeś.
do ćwiczenia polecam matlaba, gdzie będziesz mógł wszystko sprawdzić nie bawiąc się w szczegóły implementacyjne.

w drugiej, prostszej ale też i prymitywnej opcji robisz tak: najpierw jak wyżej, zwiększ bardzo mocno kontrast obrazka (jak bardzo - musisz to sprawdzić doświadczalnie) i/lub zmień kolory na monochromatyczne (tak samo musisz potraktować wszystkie obrazki wzorcowe). potem

pętla po każdym z wzorcowych obrazków W
{
  pętla zmieniająca obrazek W od rozmiaru np. 10% mniejszego wymiaru obrazka D do 50% mniejszego wymiaru obrazka D (skok o kilka-kilkanaście procent)
  {
    pętla po szerokości dużego obrazka D (skok o kilka procent szerokości)
    {
      pętla po wysokości dużego obrazka D (skok o kilka procent wysokości)
      {
        p = ile procent obrazka W zgadza się z leżącym pod nim obrazkiem D;
        p > największe_p ? 
        {
          zapamiętaj p jako nowe największe_p; 
          zapamiętaj obrazek W; 
          zapamiętaj współrzędne; 
          nowe p większe od np. 90%? bardzo duża korelacja, pewnie znaleźliśmy właściwy obrazek, wyjdź ze wszystkich pętli;
        }
      }
    }
  }
}
ośmiokąt i okrąg to prawie to samo, do tego okrągłe są zarówno znaki zakazów, jak i nakazów, 
warto więc dla okręgu sprawdzić kolor znaku: korzystając z zapamiętanych współrzędnych i wiedzy 
o środku obrazka W przesuwamy się po oryginalnym (przed usunięciem kolorów) obrazku i liczymy 
średnią po kilkunastu/kilkudziesięciu pikselach, jeśli w średniej dominuje niebieski, to jest to 
znak nakazu, jeśli czerwony, to znak stop (zakaz wjazdu ma w środku białą krechę), biały/szary,
niebieski lub czerwony z dużym dodatkiem niebieskiego to nakaz.

problem można trochę uprościć pozbywając się skalowania wzorca i modląc się, żeby wzorzec i znak na zdjęciu odpowiadały sobie wielkością.
tak czy inaczej problem jest niebanalny i wydaje mi się, że jeśli będziesz próbował go rozwiązać pierwszą metodą i nie uda Ci się, ale będziesz umiał wytłumaczyć i uzasadnić algorytm wykładowcy/ćwiczeniowcowi, to i tak zaliczy.
poczytaj koniecznie o szukaniu wzorca w obrazku. algorytmów jest sporo, być może korelacja nie jest najprostszym (choć na pewno nie jest najtrudniejszym) i znajdziesz coś łatwiejszego.
matlab na pewno ułatwi Ci pracę na etapie szukania rozwiązania (ma zaimplementowane tysiące funkcji matematycznych i nie tylko, w tym te do liczenia korelacji).

0

mam jeszcze jedno pytanko jak w delphi sprawdzić czy jeden obrazek jest w drugim ale nie przez scanline etc? bo to sprawdza czy jest identyczny obrazek i jeśli jeden jest większy to już kapa, chodzi mi o sprawdzenie czy dana rzecz jest na obrazku lub ile jej powierzchni (najlepiej aby ignorować czarne piksele bo nie mogę zrobić bitmapy przeźroczystej. a aktualnie nie wiem jak to zrobić moja specjalizacja to nie delphi:(

0

nie, nie che gotowego kod!!,
Co do sposobów próbuję wyszukać kontury,znalazłem program w C# który wykrywa kwadraty trójkąty i koła lecz mam problem mały a mianowicie,
w delphi używam opencv i próbuje przepisać kod z c# na delphi, w delphi mam teraz taka linijkę:

cvFindContours(img0,storage,contours,sizeof(CvContour),CV_RETR_LIST, CV_CHAIN_APPROX_SIMPLE,CvPoint_(0,0));

Ale podczas próby uruchomienia tego ody wyskakuje mi błąd:
"Null pointer (NULL double CvSeq pointer) in function cvFindContours[..]"

i nie wiem jak naprawić to:/

0

ok to już wyżej nie ważne teraz pytanie jak z pcvseq/pointer odczytać te dane pomocne do zaznaczenia trójkąta na obrazku?

0

A po co przepisywać opencv z C do Delphi? To może być za dużo roboty. Skompiluj opencv do dll kompilatorem C i użyj tego dll w Delphi. Pozostaje kwestia konwersji typów wyprowadzonych na zewnątrz parametrów funkcji. Pamiętaj, żeby wszystkie wyprowadzane na zewnątrz funkcje w dll miały tą samą konwencję przekazywania parametrów co ich deklaracja importowa w Delphi. Zazwyczaj stosuje się tu stdcall (powinny być wpisane w obu wymienionych miejscach).

1 użytkowników online, w tym zalogowanych: 0, gości: 1