前幾篇利用類似隔行掃描的方式實(shí)現(xiàn)了對屏幕圖像差異的獲取,并基于該算法實(shí)現(xiàn)了一個屏幕傳輸程序,,通過使用該屏幕傳輸程序,,明顯感受到該算法的性能存在一定的不足,因此需要改進(jìn),。最近參考了DG大哥DGScreenSpy_0.4e版的算法實(shí)現(xiàn)了分塊的方式,。由于還沒有實(shí)現(xiàn)基于此算法的屏幕傳輸程序,所以目前還無法斷然認(rèn)為該算法一定優(yōu)于隔行的方式,。不過,,從當(dāng)前對該算法的測試數(shù)據(jù)上來看,估計可以達(dá)到20幀每秒(不考慮網(wǎng)絡(luò)傳輸?shù)鹊挠绊懀?/p> 按照慣例應(yīng)該先帖幾張效果圖,,但是發(fā)現(xiàn)和之前發(fā)布的圖像差異獲取v1.0中的圖片相差無幾,,所以就不帖了。直接來看下文,。 我們對兩幅圖像的比較,,可以逐個像素比較,也可以先把圖像分塊,,然后比較對應(yīng)塊中的數(shù)據(jù),。那么,到底分塊是什么個概念,,又該如何分塊,,分塊后的數(shù)據(jù)如何比較呢?下面我將逐一進(jìn)行介紹,。 分塊也就是說把圖片分成“幾乘幾”的小塊,,如圖1所示一幅200*80的圖像。按橫向劃分4塊,,縱向劃分2塊的方式,,可以畫出一個二行四列的網(wǎng)格,其中每一格就是分塊數(shù)據(jù),。 看起來似乎很簡單,,其實(shí)實(shí)現(xiàn)上也很簡單,^_^,。在Dot Net中,,Bitmap類有一個很好用的方法就是Clone,該方法的其中一個重載方法為:public Bitmap Clone(Rectangle rect, PixelFormat format); 怎么樣,?知道怎么做了吧,。你只需要建立一個圖像數(shù)組用于存儲所有塊數(shù)據(jù),然后其中的每一個塊數(shù)據(jù)均通過Clone方法從母圖像中獲取,。 分塊后的數(shù)據(jù)其實(shí)仍然是一個圖像,,怎么比較這個圖像呢?我第一次接觸到分塊算法的時候,,就愣住了,,難道對于分塊數(shù)據(jù)仍然采用像素掃描的方式?研究了DG的算法后才發(fā)現(xiàn)自己太天真了,。對于分塊數(shù)據(jù),,可以直接在內(nèi)存中進(jìn)行比較,這種比較方式速度最快,。說到這里,,不知道是否有朋友會有疑問:“既然內(nèi)存中比較速度最快,那為什么還要搞隔行,、分塊呢,?”,答案很簡單,,因?yàn)槲覀儾恢故且容^出不同,,更重要的是要把不同的部分加以利用。不管是隔行還是分塊,,目的都是為了能最小化變化的區(qū)域,,只有這樣才能有效降低網(wǎng)絡(luò)負(fù)載。 如果對上述內(nèi)容理解清楚了,,那接下來就來看下分塊的思路,。這個思路主要還要感謝DG的算法。 首先對原圖進(jìn)行分塊的初始化,,經(jīng)過這步之后會得到一個最原始的分塊數(shù)組,。然后拿該分塊數(shù)組與第二張圖片進(jìn)行內(nèi)存比較。比較的時候,,并非逐個分塊進(jìn)行比較,,而是有選擇的進(jìn)行比較,,這種選擇建立在三種假設(shè)的基礎(chǔ)上: 1. 鼠標(biāo)所在的塊會發(fā)生變化; 2. 當(dāng)一個塊變化的時候,,該塊周圍的塊也會發(fā)生變化,; 3. 圖片第一行和最后一行會發(fā)生變化; 當(dāng)比較出不同的時候,,即可以采取我們想要的一些行為,。另外,要注意的就是選擇一個合適分塊粒度(即你要把圖像分成“幾乘幾”),。如果分塊多,,則每一個分塊的數(shù)據(jù)量就小,但是比較的次數(shù)就會變多,。如果分塊少,,則每一個分塊的數(shù)據(jù)量較多,但是比較次數(shù)就會變少,。因此選擇一個合適的粒度會影響程序的性能,,據(jù)文獻(xiàn)資料的記載和他人的嘗試,一般認(rèn)為把屏幕分成16*8塊最為合適,。 說了這么多,,下面來看下關(guān)鍵代碼吧: 初始化所有分塊的數(shù)據(jù) 查找差異的塊 注:該實(shí)現(xiàn)由于并不是特地為了實(shí)現(xiàn)屏幕傳輸,所以在比較的時候,,我利用了Clone方式獲取第二張圖片的對應(yīng)塊,。該方式需要耗時0.015s左右,因此比較100塊圖像就會額外使用1.5s左右的時間,。 |
|