[ GyG@ @ 27.03.2005. 21:26 ] @
Kako da napravim da mi delphi prepozna da li su slika1.bmp i slika2.bmp iste? Ako moze i kod. Hvala unapred! |
[ GyG@ @ 27.03.2005. 21:26 ] @
[ sasas @ 27.03.2005. 22:31 ] @
Evo jedno rešenje koje radi solidno brzo (ako uopšte radi :)).
Code: function Diff2(fn1, fn2: string): boolean; var b1, b2: TBitmap; x, y: integer; pix1, pix2: PByteArray; begin try b1 := TBitmap.Create; b2 := TBitmap.Create; b1.LoadFromFile(fn1); b2.LoadFromFile(fn2); Result := false; if (b1.Width <> b2.Width) or (b1.Height <> b2.Height) then begin Result := true; exit; end; for y := 0 to b1.Height - 1 do begin pix1 := b1.ScanLine[y]; pix2 := b2.ScanLine[y]; for x := 0 to b1.Width * 4 do if pix1[x] <> pix2[x] then begin Result := true; exit; end; end; finally FreeAndNil(b1); FreeAndNil(b2); end; end; evo i jednostavnije, ali i značajno sporije rešenje (10ak puta, ovako odokativno) Code: function Diff2(fn1, fn2: string): boolean; var b1, b2: TBitmap; x, y: integer; begin try b1 := TBitmap.Create; b2 := TBitmap.Create; b1.LoadFromFile(fn1); b2.LoadFromFile(fn2); Result := false; if (b1.Width <> b2.Width) or (b1.Height <> b2.Height) then begin Result := true; exit; end; for y := 0 to b1.Height - 1 do for x := 0 to b1.Width - 1 do if b1.Canvas.Pixels[x, y] <> b2.Canvas.Pixels[x, y] then begin Result := true; exit; end; finally FreeAndNil(b1); FreeAndNil(b2); end; end; ss. [ Rapaic Rajko @ 28.03.2005. 09:39 ] @
Prvi primer je dobar, uz sledecu izmenu za unutrasnju petlju (poredjenje unutar scanline-a):
Code: result := not CompareMem(pix1, pix2, b1.Width * 4); // hm, a drugi pixelformati-? Rajko [ bancika @ 28.03.2005. 10:31 ] @
a zar se ne svodi onda to na uporedjivanje fajlova?
malo je zeznutije ako su slike "skoro" iste, recimo jedna je kompresovana jpg-om pa je malo zamrljana u odnosu na original, ili ako je jednoj promenjena velicina... [ Srki_82 @ 28.03.2005. 11:43 ] @
To bi bilo prilicno zanmiljivo uraditi... trebalo bi dodati neku delta vrednost prilikom uporedjivanja pixela npr:
Code: if Abs(Pixel1[X, Y] - Pixel2[X, Y]) < DeltaColor then BojeSuJednake := True else BojeSuJednake := False; Tako boje pixela ne moraju da budu jednake, dovoljno je da budu priblizno jednake. Sto je delta vece moguce su i vece greske prilikom uporedjivanja slika. Moglo bi se jos dodati i da je dok se bar 80% pixela jedne slike slazu sa drugom slikom to dovoljno da se kaze da su slike "iste". Za uporedjivanje slika razlicitih velicina mozlim da je bolje vecu sliku smanjiti na velicinu manje nego obrnuto jer ce mozda nekom pasti na pamet da npr. uporedjuje sliku 5000x5000 sa slikom 16x16 ![]() ![]() [ sasas @ 28.03.2005. 11:45 ] @
Citat: // hm, a drugi pixelformati-? He he, bravo. Prilikom copy-paste-a mi se izgubilo par linija kooda, pa evo popravljena verzija: Code: function Diff2(fn1, fn2: string): boolean; var b1, b2: TBitmap; y, bpp: integer; pix1, pix2: PByteArray; begin Result := false; try b1 := TBitmap.Create; b2 := TBitmap.Create; b1.LoadFromFile(fn1); b2.LoadFromFile(fn2); if (b1.Width <> b2.Width) or (b1.Height <> b2.Height) or (b1.PixelFormat <> b2.PixelFormat) then begin Result := true; exit; end; case b1.PixelFormat of pf8bit: bpp := 1; pf16bit: bpp := 2; pf24bit: bpp := 3; pf32bit: bpp := 4; else exit; end; for y := 0 to b1.Height - 1 do begin pix1 := b1.ScanLine[y]; pix2 := b2.ScanLine[y]; if not CompareMem(pix1, pix2, b1.Width * bpp) then begin Result := true; exit; end; end; finally FreeAndNil(b1); FreeAndNil(b2); end; end; Naravno, funkcija je i dalje bušna na sve strane (ne podržava sve pixelformate, vraća nekakav rezultat u svakom slučaju, iako poređenje nije uspešno...), ali mislim da se iz ovog može videti ideja. Citat: a zar se ne svodi onda to na uporedjivanje fajlova? Ovo u suštini i jeste poređenje fajlova, s obzirom da se radi o bitmapi (nekompresovanoj). S tim što je bolje porediti ovako (imho) jer se postižu velike uštede u vremenu u očiglednim slučajevima (da su slike različite veličine, recimo). ss. [ bancika @ 28.03.2005. 22:19 ] @
@srki:
ne mozes tek tako da oduzimas boje. posto su one poredjane u jednoj 32bit-noj reci onda ce recimo razlika za 1 u red komponenti nositi 2^16 puta manju razliku boja nego razlika za 1 u green komponenti jer je bajt koji predstavlja zelenu pomeren 16bita ulevo. mozda je ispravnije da se rastavi na rgb komponente pa da se uzme recimo srednja vrednost apsolutne vrednosti razlike svake komponente [ Srki_82 @ 28.03.2005. 23:17 ] @
To je bio samo pseudo kod. Da li bi tako nesto odradilo posao?
[ bancika @ 28.03.2005. 23:23 ] @
ne znam, mozda. opet ostaje ako su recimo dva pixela potpuno razlicita, a ostalo isto...moglo bi recimo da se napravi jedan niz gde je i-ti clan broj pixela koji se razlikuju za i (kad se uzmu u obzir rgb-ovi). onda na osnovu tog niza (sto je vise elemenata niza sa manjim indexima to bolje) odredi procentualno podudaranje slike. to je i dalje glupo resenje. treba prepoznati oblike i slicno, ali za prvu pomoc i nije lose :)
[ _v!rus_ @ 29.03.2005. 19:27 ] @
Au bre, preplashiste coveka sa rodjene mu teme... ;)
Ne, salim se, mislim da je procentualno uporedjivanje "istoce" odnosno slicnosti piksela najbolje sto se moze bez HC metoda. A HC metode bi bile neki neural networks algoritam koji bi radio prepoznavanje oblika (kao OCR - prepoznavanje teksta), jednom recju - more fun than it's worth... Npr. JPEG kompresija ne "zamucuje" piksele, nego pravi blokove piksela slicnih vrednosti (lakse se pakuje), time ce se dobiti GOMILA razlicitih piksela na orginalu i kompresovanoj kopiji, a samim tim i velika razlika na istim slikama. Jos plus sto ce procentualna metoda dati koliko-toliko korisne rezultate samo na slikama sa jasnim kontrastom (jasnim konturama - velika razlika izmedju susednih piksela), na slikama sa gradient filom razlike piksela su minimalne... Daleko je sve to od filmova i serija (citaj: Nikita i sl. sra*ja) u kojima racunari "vrte slike" osumnjicenih dok ne nadju podudarnost, trebalo bi njihove programere priupitati kako su to oni odradili! :))) Copyright (C) 2001-2025 by www.elitesecurity.org. All rights reserved.
|