前言的前言:
最近小弟閑來無聊,就想到了在PPC上面來做個(gè)圖像對比的小東東,查找各方資料,終于在今天初步完成了這個(gè)程序,現(xiàn)在整理之后和各位共勉。程序中還存在很多不足之處,大家盡管提出自己的意見和建議,本人非常歡迎哦!
前言:
在閱讀本文后,你將知道:
-
如何在.net Compact Framework 2.0框架下使用C#語言進(jìn)行圖片的縮放操作、保存
-
如何在c#中計(jì)算圖片的直方圖量度
-
如何使用SelectPictureDialog對話框
你需要以下開發(fā)環(huán)境:
-
Visual Studio 2008
-
Windows Mobile 6 Professional SDK(WM6
可以直接運(yùn)行我提供的例子,WM5也可以開發(fā)
)
正文:
第一步:我們先來創(chuàng)建一個(gè)C#
智能設(shè)備項(xiàng)目,
我選用的是
.net Compact Framework 2.0
的框架庫,然后選擇?
Windows Mobile 6 Professional SDK
平臺。
在默認(rèn)的Form1窗體中,我們?nèi)缦聢D一樣進(jìn)行設(shè)計(jì):
一個(gè)Label2用于顯示對比結(jié)果、一個(gè)TabControl,tabPage1中有一個(gè)PictureBox1,tabPage2中同樣放入一個(gè)PictureBox2,兩個(gè)PictureBox的SizeMode屬性設(shè)置為
StretchImage。
設(shè)計(jì)好界面后,我們就添加代碼,在這里只列出關(guān)鍵代碼,詳細(xì)代碼請到下載的項(xiàng)目中查找吧。
在程序頭部引用
using Microsoft.WindowsMobile.Forms;
using System.Drawing;
然后,添加全局變量:
PicCompare.GetHisogram.GetHis getHis = new PicCompare.GetHisogram.GetHis();//直方圖度量計(jì)算類其中包括了圖像縮放方法
string pic1 = @"Storage Card/test.bmp";//指定縮放后的圖片存放位置和格式
string pic2 = @"Storage Card/test2.bmp";//指定縮放后的圖片存放位置和格式
int[] pic1t;//圖片一的直方圖量度容器
int[] pic2t;//圖片二的直方圖量度容器
定義好變量后,我們雙擊“圖片一”,給他添加如下代碼:
?
Code
SelectPictureDialog?spd?
=
?
new
?SelectPictureDialog();
spd.ShowDialog();
pic1t?
=
?getHis.GetHisogram(getHis.Resized(spd.FileName,?pic1));
//
計(jì)算出圖片一的直方圖量度存放到一個(gè)pic1t的數(shù)組變量中
Bitmap?bmp
=
new
?Bitmap(spd.FileName);
????????????
pictureBox1.Image?
=
?bmp;
//
把處理后的圖片放入pictureBox1進(jìn)行預(yù)覽
?
圖片二按鈕同上,只需修改相關(guān)參數(shù)即可。
然后我們看一下直方圖量度計(jì)算類的部分代碼實(shí)現(xiàn)吧:
計(jì)算圖像的直方圖的這個(gè)代碼從網(wǎng)絡(luò)上copy過來的,這個(gè)到處都有,我也不是太在行,所以暫不做解釋了,汗~
計(jì)算圖像的直方圖
?
///
?
<summary>
????????
///
?計(jì)算圖像的直方圖
????????
///
?
</summary>
????????
///
?
<param?name="img">
圖片
</param>
????????
///
?
<returns>
返回直方圖量度
</returns>
????????
public
?
int
[]?GetHisogram(Bitmap?img)
????????{
????????????
????????????BitmapData?data?
=
?img.LockBits(
new
?System.Drawing.Rectangle(
0
,?
0
,?img.Width,?img.Height),?ImageLockMode.ReadWrite,?PixelFormat.Format24bppRgb);
????????????
int
[]?histogram?
=
?
new
?
int
[
256
];
????????????
unsafe
????????????{
????????????????
byte
*
?ptr?
=
?(
byte
*
)data.Scan0;
????????????????
int
?remain?
=
?data.Stride?
-
?data.Width?
*
?
3
;
????????????????
for
?(
int
?i?
=
?
0
;?i?
<
?histogram.Length;?i
++
)
????????????????????histogram[i]?
=
?
0
;
????????????????
for
?(
int
?i?
=
?
0
;?i?
<
?data.Height;?i
++
)
????????????????{
????????????????????
for
?(
int
?j?
=
?
0
;?j?
<
?data.Width;?j
++
)
????????????????????{
????????????????????????
int
?mean?
=
?ptr[
0
]?
+
?ptr[
1
]?
+
?ptr[
2
];
????????????????????????mean?
/=
?
3
;
????????????????????????histogram[mean]
++
;
????????????????????????ptr?
+=
?
3
;
????????????????????}
????????????????????ptr?
+=
?remain;
????????????????}
????????????}
????????????img.UnlockBits(data);
????????????
return
?histogram;
????????}
?
下面的這個(gè)代碼就是在分別計(jì)算完兩張圖片的量度后,把兩個(gè)量度再放到這里面來計(jì)算結(jié)果,所得結(jié)果即為圖片相似度的一個(gè)參考值,代碼如下:
?
最終計(jì)算結(jié)果
????????
///
?
<summary>
????????
///
最終計(jì)算結(jié)果
????????
///
?
</summary>
????????
///
?
<param?name="firstNum">
圖片一的直方圖量度
</param>
????????
///
?
<param?name="scondNum">
圖片二的直方圖量度
</param>
????????
///
?
<returns>
計(jì)算結(jié)果
</returns>
????????
public
?
float
?GetResult(
int
[]?firstNum,?
int
[]?scondNum)
????????{
????????????
if
?(firstNum.Length?
!=
?scondNum.Length)
????????????{
????????????????
return
?
0
;
????????????}
????????????
else
????????????{
????????????????
float
?result?
=
?
0
;
????????????????
int
?j?
=
?firstNum.Length;
????????????????
for
?(
int
?i?
=
?
0
;?i?
<
?j;?i
++
)
????????????????{
????????????????????result?
+=
?
1
?
-
?GetAbs(firstNum[i],?scondNum[i]);
????????????????????Console.WriteLine(i?
+
?
"
----
"
?
+
?result);
????????????????}
????????????????
return
?result?
/
?j;
????????????}
????????}
?
其中,還有一個(gè)類是用來處理圖片大小的,在這里也貼出來,大家應(yīng)該用得到的哦!
?
Code
?
///
?
<summary>
????????
///
?圖片大小縮放(正方形)
????????
///
?作者:Jack?Fan
????????
///
?
</summary>
????????
///
?
<param?name="sideSize">
指定大小
</param>
????????
///
?
<param?name="srcBMP">
原始圖片
</param>
????????
///
?
<returns>
返回縮放后的Bitmap圖片
</returns>
????????
public
?Bitmap?ResizeBMP(
int
?sideSize,?Bitmap?srcBMP)
????????{
????????????Bitmap?bmp?
=
?
new
?Bitmap(sideSize,?sideSize);
????????????Rectangle?srcRec?
=
?
new
?Rectangle(
0
,?
0
,?srcBMP.Width,?srcBMP.Height);
????????????Rectangle?destRec?
=
?
new
?Rectangle(
0
,?
0
,?sideSize,?sideSize);
????????????Graphics?g?
=
?Graphics.FromImage(bmp);
????????????g.DrawImage(srcBMP,?destRec,?srcRec,?GraphicsUnit.Pixel);
????????????g.Dispose();
????????????
return
?bmp;
????????}
?
?
對比按鈕的代碼:
?
對比按鈕
?pictureBox1.Refresh();
pictureBox2.Refresh();
label2.Text?
=
?(getHis.GetResult(pic1t,?pic2t)?
*
?
100
).ToString()?
+
?
"
%
"
;
//
計(jì)算最終結(jié)果
?
好了,代碼就是這些了,下面來看看實(shí)際效果如何把:
1、程序運(yùn)行后,添加了兩張比較相似的圖片(不同點(diǎn)請看第三張圖片的紅圈):
然后,點(diǎn)擊“對比”按鈕后,即可見到相似度了:
?
結(jié)尾:
在這里,我想申明一點(diǎn),這個(gè)直方圖量度來計(jì)算圖片相似度的想法是我從園子里一個(gè)朋友
Aaron Wu
的blog上看來的,本想在前面附上他的署名,無奈今天無論如何都找不到他的原文,所以請見諒,您看到了就跟我說一聲,畢竟我還有很多問題想請教一二?。?原文名稱《圖像相似度算法的C#實(shí)現(xiàn)及測評》,在cnblogs里面好像搜不到了哦,大家股溝一下吧!)文中還有部分細(xì)節(jié)描述不清楚的地方,歡迎各位提問,在下文筆不好,只能是有問必答,呵呵。相信大家在看了源代碼以及了解了相關(guān)直方圖量度的知識后,會(huì)有另一番感覺。
另:在測試中,發(fā)現(xiàn)如果使用圖片分割,再逐個(gè)部分進(jìn)行對比,然后在匯總的方法,得出的結(jié)果就比較高了!但是無奈PPC設(shè)備硬件條件有限,暫時(shí)還不考慮。如果轉(zhuǎn)載請注明原文歸屬哦,謝謝。
?源代碼:
點(diǎn)擊下載
『原創(chuàng)』+『參考』基于PPC的圖像對比程序——使用直方圖度量