怎样快速比对两幅图像是否完全一致 |
答題得分者是:wameng
|
whoawho
一般會員 發表:13 回覆:18 積分:6 註冊:2004-03-16 發送簡訊給我 |
既定条件:
一、内存(记忆体)中已有500多个TBitmap的样版组A;
二、TBitmap每个样版的大小为30*50(X*Y);
问:当有测试的TBitmap(30*50)B送到,怎样快速的比对出B与A中哪一个模版完全一致? 目前能想到的办法:
1、看到有资料介绍用scanline之后,逐Byte比对,但这样的方法在模版数量以及测试样品数量较多的时候,极为缓慢,无法适应及时响应的需求;
2、后来想到用GetDIBits将模版和样品都转为内存数据,然后用CompareMem来做比对,不知道这样的想法是否可行?如果可行,请各位大大给出一段示范代码。
3、另外,如果上面的样板组A的图像格式为8位、16位、24位(全样板组同一格式),按照2的处理方法会有不同吗?
4、或者有更好更快的比对图像的办法? 望不吝赐教。 發表人 - whoawho 於 2004/10/04 03:47:57 發表人 - whoawho 於 2004/10/04 03:52:17
|
wameng
版主 發表:31 回覆:1336 積分:1188 註冊:2004-09-16 發送簡訊給我 |
您的想法有點意思! 1. 目前來看用 ScanLine 是作法是比較簡單、明瞭。
還是有可以再提升比對速度的方式。要視您的做法而定。
{ 或用 Direct Draw 在效率比較好!} 2.建議用Scanline。
GetBitmapBits是位了兼容16位元的程序保留的,32位程序應該用GetDiBits。
其實與ScanLine的速度差不多,而Scanline更容易使用。 另外 CompareMem 可以用 TmemoryStream 代入,會比較快。
如
function StreamsEqual(S1, S2: TMemoryStream): Boolean;
begin
Result := (S1.Size = S2.Size) and CompareMem(S1.Memory, S2.Memory, S1.Size);
end;
{用 BMP.SavetoStream } 不過使用這種方式,如果圖形內容格式不同、圖形略不同、檔頭不同
可能都會影響判斷! 3.图像格式为8位、16位、24位,並需先轉換與樣版相同的Format
由於在轉換當中可能會失真 or ....
誤判的機率很大的! 4.由於不曉得,您主要比對的因素是什麼!
影像識別、或者......
依據此找出判斷的要點,因而找到合適的方法。
如果單單只是比對檔案的內容,不就得了!
|
andychang1690
資深會員 發表:20 回覆:694 積分:442 註冊:2003-03-14 發送簡訊給我 |
whoawho:以前有一位Tsay Yih-yuan 寫的一個
Duplicate Image Hunter 1.0 Beta 9
Freeware 禁止作任何商業用途
內容是:
搜尋電腦中重複的圖形檔案以及其他類型的檔案,更可以影像內容作比對搜
尋,同樣的圖形,就算是以不同的壓縮比來儲存,或者是不同的影像檔案格
式,都可以幫你找出來。
圖形檔並提供預覽的功能;其它類型的檔案可用系統預定的應用程式開啟。
他並沒有提供原始程式但介紹中提到他的作法提供給你參考!
尤其下文紅字段是一個方向。
※重複檔案比對項目分為檔名,檔案大小,檔案內容,影像內容,影像長
寬五種,可任意組合。若是全部都不選,則表示列出所有的檔案。 ※比對檔案內容時,可以自行設定內容比對的百分比。設為100%時,表
示當檔案在比對內容時,會比對全部的檔案內容,但是此時會花費較多
的時間。建議設為5%即可,以圖形檔為例,當兩個不同內容的圖形檔
,雖然檔案的大小相同,但是其檔案內容的前面5%都完全相同的可能
性是非常低的,因此,設為5%或許結果可能會有些許的誤差,但機率
不大。而且可以節省很多的時間。 若是選擇比對影像內容時,影像比對誤差度選擇5%即可。以兩張同樣
影像內容,但壓縮比不同的JPEG檔案為例,其影像比對誤差度大多介
於1%~4%之間。 因為我是採用抽樣比對的方式,所以有些同樣背景的圖形,或者是色調
接近的圖形,會判斷是相同的圖形。不過若是增加比對的樣本數量,雖
然結果的誤差會比較少,但花費的時間反而更多,權衡之下,還是以節
省時間為主要的考量因素。 ※顯示執行進度。在執行時,會在下方的狀態列顯示目前的執行進度。但
是因為ProgressBar牽涉到螢幕繪圖的關係,會用掉比較多的時間,
所以會稍微的拖慢搜尋的時間。時間就是金錢的人,可以把這個功能關
閉。若是選擇關閉,因為不曉得執行狀態,在執行時,若是硬碟是在讀
取的狀態,則表示程式正常的執行中,請稍後片刻。 重複檔案的搜尋,主要分為三個步驟:
(1)搜集檔案的資訊
由指定的檔案資料夾之中,蒐集檔案類型符合的所有檔案資訊。因為只
有讀取檔案的資訊,所以速度算是很快。若是要比對影像內容或是影像
長寬時,因為還要讀取影像的長寬,所以還要花費多一些的時間。 (2)排序
根據指定的比對項目,依據檔案的檔名、大小或是影像長寬來做排序。
這部分我是用宇宙銀河超級無敵霹靂最快最Turbo的QuickSort來作,
就算是五萬筆的資料,在一兩秒之內,輕輕鬆鬆就搞定了。所以排序所
花費的時間,基本上可以忽略。 (3)內容比對
若是有選擇要找出相同檔案內容或是圖形內容時,則進行這個步驟。
檔案內容比對只比對檔案大小相同的檔案。
影像內容比對只比對影像長寬相同的圖形。(目前只支援JPEG,GIF,
Bitmap三種圖形格式的檔案) 這部分最花時間,依每個人硬碟讀取的速度而有不同。當然,搜尋愈多
的檔案,要花的時間愈多。尤其是影像內容比對部分,因為必須讀入全
部的檔案,再針對其圖形作比對,更是需要花費較多的時間。
以我的電腦為例(K6-2-350MhzOverClock420Mhz UltraDMA66硬
碟 128MBSDRAM),針對約五萬八千個圖形檔作影像內容的比對搜尋
,總共大約花了125分鐘。 使用的元件:
JemNaadiAhmed的FileSearch元件
jemna@yahoo.com BradStowers的TdfsBrowseDirectoryDlg元件
http://www.delphifreestuff.com AndersMelander的TGIFImage元件
anders@melander.dk AlvaroL.S.Almeida的DrLABEL元件
http://www.di.com.br
請參考! Andy Chang
------
Andy Chang |
whoawho
一般會員 發表:13 回覆:18 積分:6 註冊:2004-03-16 發送簡訊給我 |
感谢andychang的指教,使我能了解更为深远的图像处理方法,谢谢!!!
由于我遇到的问题是要求比对“完全一致”的图像,意即“每一个像素都必须一致”,所以,这次的结案就感谢wameng了。
多谢wameng提及的BMP.SavetoStream方法,我随即去试试看。
至于wameng所担心的图像格式的问题,在我的问题中并不存在,因为所有的样板都保持一致,即:所有的样板都为8位,或者所有的样板都为16位,不会出现两种以上格式同时存在的可能。 發表人 - whoawho 於 2004/10/04 13:13:33
|
japhenchen
高階會員 發表:51 回覆:444 積分:184 註冊:2003-07-23 發送簡訊給我 |
我的做法是将TBitmap.Savetostream进TMemoryStream里头,直接对Stream作CRC32编码之后,只记录那个编码后的DWORD值(int64),就算是比对100万张图片,也只需要一百万个INT64元素的数组就能全部記錄起來,只要比對這個CRC32編碼後的值就行,這樣可以提升比對速度哦!
CRC32的編碼方式(取錄自TORRY DELPHI TIPS網站)
// The constants here are for the CRC-32 generator // polynomial, as defined in the Microsoft // Systems Journal, March 1995, pp. 107-108 const Table: array[0..255] of DWORD = ($00000000, $77073096, $EE0E612C, $990951BA, $076DC419, $706AF48F, $E963A535, $9E6495A3, $0EDB8832, $79DCB8A4, $E0D5E91E, $97D2D988, $09B64C2B, $7EB17CBD, $E7B82D07, $90BF1D91, $1DB71064, $6AB020F2, $F3B97148, $84BE41DE, $1ADAD47D, $6DDDE4EB, $F4D4B551, $83D385C7, $136C9856, $646BA8C0, $FD62F97A, $8A65C9EC, $14015C4F, $63066CD9, $FA0F3D63, $8D080DF5, $3B6E20C8, $4C69105E, $D56041E4, $A2677172, $3C03E4D1, $4B04D447, $D20D85FD, $A50AB56B, $35B5A8FA, $42B2986C, $DBBBC9D6, $ACBCF940, $32D86CE3, $45DF5C75, $DCD60DCF, $ABD13D59, $26D930AC, $51DE003A, $C8D75180, $BFD06116, $21B4F4B5, $56B3C423, $CFBA9599, $B8BDA50F, $2802B89E, $5F058808, $C60CD9B2, $B10BE924, $2F6F7C87, $58684C11, $C1611DAB, $B6662D3D, $76DC4190, $01DB7106, $98D220BC, $EFD5102A, $71B18589, $06B6B51F, $9FBFE4A5, $E8B8D433, $7807C9A2, $0F00F934, $9609A88E, $E10E9818, $7F6A0DBB, $086D3D2D, $91646C97, $E6635C01, $6B6B51F4, $1C6C6162, $856530D8, $F262004E, $6C0695ED, $1B01A57B, $8208F4C1, $F50FC457, $65B0D9C6, $12B7E950, $8BBEB8EA, $FCB9887C, $62DD1DDF, $15DA2D49, $8CD37CF3, $FBD44C65, $4DB26158, $3AB551CE, $A3BC0074, $D4BB30E2, $4ADFA541, $3DD895D7, $A4D1C46D, $D3D6F4FB, $4369E96A, $346ED9FC, $AD678846, $DA60B8D0, $44042D73, $33031DE5, $AA0A4C5F, $DD0D7CC9, $5005713C, $270241AA, $BE0B1010, $C90C2086, $5768B525, $206F85B3, $B966D409, $CE61E49F, $5EDEF90E, $29D9C998, $B0D09822, $C7D7A8B4, $59B33D17, $2EB40D81, $B7BD5C3B, $C0BA6CAD, $EDB88320, $9ABFB3B6, $03B6E20C, $74B1D29A, $EAD54739, $9DD277AF, $04DB2615, $73DC1683, $E3630B12, $94643B84, $0D6D6A3E, $7A6A5AA8, $E40ECF0B, $9309FF9D, $0A00AE27, $7D079EB1, $F00F9344, $8708A3D2, $1E01F268, $6906C2FE, $F762575D, $806567CB, $196C3671, $6E6B06E7, $FED41B76, $89D32BE0, $10DA7A5A, $67DD4ACC, $F9B9DF6F, $8EBEEFF9, $17B7BE43, $60B08ED5, $D6D6A3E8, $A1D1937E, $38D8C2C4, $4FDFF252, $D1BB67F1, $A6BC5767, $3FB506DD, $48B2364B, $D80D2BDA, $AF0A1B4C, $36034AF6, $41047A60, $DF60EFC3, $A867DF55, $316E8EEF, $4669BE79, $CB61B38C, $BC66831A, $256FD2A0, $5268E236, $CC0C7795, $BB0B4703, $220216B9, $5505262F, $C5BA3BBE, $B2BD0B28, $2BB45A92, $5CB36A04, $C2D7FFA7, $B5D0CF31, $2CD99E8B, $5BDEAE1D, $9B64C2B0, $EC63F226, $756AA39C, $026D930A, $9C0906A9, $EB0E363F, $72076785, $05005713, $95BF4A82, $E2B87A14, $7BB12BAE, $0CB61B38, $92D28E9B, $E5D5BE0D, $7CDCEFB7, $0BDBDF21, $86D3D2D4, $F1D4E242, $68DDB3F8, $1FDA836E, $81BE16CD, $F6B9265B, $6FB077E1, $18B74777, $88085AE6, $FF0F6A70, $66063BCA, $11010B5C, $8F659EFF, $F862AE69, $616BFFD3, $166CCF45, $A00AE278, $D70DD2EE, $4E048354, $3903B3C2, $A7672661, $D06016F7, $4969474D, $3E6E77DB, $AED16A4A, $D9D65ADC, $40DF0B66, $37D83BF0, $A9BCAE53, $DEBB9EC5, $47B2CF7F, $30B5FFE9, $BDBDF21C, $CABAC28A, $53B39330, $24B4A3A6, $BAD03605, $CDD70693, $54DE5729, $23D967BF, $B3667A2E, $C4614AB8, $5D681B02, $2A6F2B94, $B40BBE37, $C30C8EA1, $5A05DF1B, $2D02EF8D); type //----------------------------------crc32---------------------------------- {$IFDEF VER130} // This is a bit awkward // 8-byte integer TInteger8 = Int64; // Delphi 5 {$ELSE} {$IFDEF VER120} TInteger8 = Int64; // Delphi 4 {$ELSE} TInteger8 = COMP; // Delphi 2 or 3 {$ENDIF} {$ENDIF} //----------------------------------crc32---------------------------------- // Use CalcCRC32 as a procedure so CRCValue can be passed in but // also returned. This allows multiple calls to CalcCRC32 for // the "same" CRC-32 calculation. procedure CalcCRC32(p: Pointer; ByteCount: DWORD; var CRCValue: DWORD); // The following is a little cryptic (but executes very quickly). // The algorithm is as follows: // 1. exclusive-or the input byte with the low-order byte of // the CRC register to get an INDEX // 2. shift the CRC register eight bits to the right // 3. exclusive-or the CRC register with the contents of Table[INDEX] // 4. repeat steps 1 through 3 for all bytes var i: DWORD; q: ^BYTE; begin q := p; for i := 0 to ByteCount - 1 do begin CRCvalue := (CRCvalue shr 8) xor Table[q^ xor (CRCvalue and $000000FF)]; Inc(q) end end {CalcCRC32}; function CalcStringCRC32(s: string; out CRC32: DWORD): Boolean; var CRC32Table: DWORD; begin // Verify the table used to compute the CRCs has not been modified. // Thanks to Gary Williams for this suggestion, Jan. 2003. CRC32Table := $FFFFFFFF; CalcCRC32(Addr(Table[0]), SizeOf(Table), CRC32Table); CRC32Table := not CRC32Table; if CRC32Table <> $6FCF9E13 then ShowMessage('CRC32 Table CRC32 is ' IntToHex(Crc32Table, 8) ', expecting $6FCF9E13') else begin CRC32 := $FFFFFFFF; // To match PKZIP if Length(s) > 0 // Avoid access violation in D4 then CalcCRC32(Addr(s[1]), Length(s), CRC32); CRC32 := not CRC32; // To match PKZIP end; end; procedure CalcFileCRC32(FromName: string; var CRCvalue: DWORD; var TotalBytes: TInteger8; var error: Word); var Stream: TMemoryStream; begin error := 0; CRCValue := $FFFFFFFF; Stream := TMemoryStream.Create; try try Stream.LoadFromFile(FromName); if Stream.Size > 0 then CalcCRC32(Stream.Memory, Stream.Size, CRCvalue) except on E: EReadError do error := 1 end; CRCvalue := not CRCvalue finally Stream.Free end; end; procedure TForm1.Button1Click(Sender: TObject); var s: string; CRC32: DWORD; begin s := 'Test String'; if CalcStringCRC32(s, CRC32) then ShowMessage(IntToStr(crc32)); end;藏私の禁止 |
japhenchen
高階會員 發表:51 回覆:444 積分:184 註冊:2003-07-23 發送簡訊給我 |
就以你的例子为例,如果以内存比对的方式来处理,500张图就要比对125001次,那每一张图都要比对一次内存内容,一张图就有30*50=1500个像素,8位的图就要比对1500个位的值,两张图各读一次也要花上3000次的单位内存读取的时间,125001次比对所有的图片,一共要花上375003000个的单位内存读取时间 用我刚刚的方法,每张图只要读取一次,500张图一共需要花费1500*500=750000次的内存读取时间,INT64占8位长度,两张图共16位,比对500张图需16*125001=2000016次单位内存读取时间,加上开始读图的时间,大概耗时2750016个单位时间 第一种方法需时375003000单位时间
第二种方法需时2750016 单位时间
差别有多大?136倍,如果第二种方法需时1分钟,那第一种方法就要136分钟,两个多小时... 藏私の禁止
|
japhenchen
高階會員 發表:51 回覆:444 積分:184 註冊:2003-07-23 發送簡訊給我 |
|
japhenchen
高階會員 發表:51 回覆:444 積分:184 註冊:2003-07-23 發送簡訊給我 |
说到HASH碰撞,这个是最近的一件软件加密的重大事件,中国山东大学的王小云教授破解了MD5的加密方法,关键就是碰撞。。。。 说破了很简单,MD5这种东西,就是将一连串的内存内容依照查表的方式,一个字元转成一个长整数,旋转后取末尾几位的值,在和下一个字元查表值作反或运算,一直这样做下去..得出来的结果就是我们要的Hash值,原则上是没有任何不同的文件(或字符串)产生相同的Hash值,这个原则已经被深信不疑很久一段时间了,一直到了上个月....这个王教授,女性一语道破了这个编码.... 【碰撞=漏洞=别人可以伪造和冒用数字签名】 何谓“碰撞”?就是用一个无止尽长度的文件(内存流),试图去产生一组hash编码,一直到这组新编码和之前文件产生出来的HASH值相同为止。 这种方法是否可行?大家有空可以试验看看。。。。 藏私の禁止
|
conundrum
尊榮會員 發表:893 回覆:1272 積分:643 註冊:2004-01-06 發送簡訊給我 |
|
japhenchen
高階會員 發表:51 回覆:444 積分:184 註冊:2003-07-23 發送簡訊給我 |
|
whoawho
一般會員 發表:13 回覆:18 積分:6 註冊:2004-03-16 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |