『原创』+『参考』基于PPC的图像对比程序——使
	
		
		系统
		
		2197 0
	
	  
  
    
      前言的前言:
    
  
  
    最近小弟闲来无聊,就想到了在PPC上面来做个图像对比的小东东,查找各方资料,终于在今天初步完成了这个程序,现在整理之后和各位共勉。程序中还存在很多不足之处,大家尽管提出自己的意见和建议,本人非常欢迎哦!
  
  
    
      前言:
    
  
  
    在阅读本文后,你将知道:
  
  
    - 
      如何在.net Compact Framework 2.0框架下使用C#语言进行图片的缩放操作、保存
    
- 
      如何在c#中计算图片的直方图量度
    
- 
      如何使用SelectPictureDialog对话框
    
    你需要以下开发环境:
  
  
    - 
      Visual Studio 2008
    
- 
      Windows Mobile 6 Professional SDK(WM6
      
        可以直接运行我提供的例子,WM5也可以开发
      
      )
    
    
      正文:
    
  
  
    第一步:我们先来创建一个C# 
    
      智能设备项目,
    
    我选用的是
    
      .net Compact Framework 2.0
    
    的框架库,然后选择 
    
      Windows Mobile 6 Professional SDK
    
     平台。
  
  
    在默认的Form1窗体中,我们如下图一样进行设计:
  
  
     
     
  
  
    一个Label2用于显示对比结果、一个TabControl,tabPage1中有一个PictureBox1,tabPage2中同样放入一个PictureBox2,两个PictureBox的SizeMode属性设置为
    
      StretchImage。
    
  
  
    设计好界面后,我们就添加代码,在这里只列出关键代码,详细代码请到下载的项目中查找吧。
  
  
    在程序头部引用
  
  
    using Microsoft.WindowsMobile.Forms;
  
  
    using System.Drawing;
  
  
    然后,添加全局变量:
  
  
    PicCompare.GetHisogram.GetHis getHis = new PicCompare.GetHisogram.GetHis();//直方图度量计算类其中包括了图像缩放方法
    
    string pic1 = @"Storage Card/test.bmp";//指定缩放后的图片存放位置和格式
    
    string pic2 = @"Storage Card/test2.bmp";//指定缩放后的图片存放位置和格式
    
    int[] pic1t;//图片一的直方图量度容器
    
    int[] pic2t;//图片二的直方图量度容器
  
  
    定义好变量后,我们双击“图片一”,给他添加如下代码:
  
  
     
  
  
     
     Code
    
      Code
    
    
      
            
        SelectPictureDialog spd 
      
      
        =
      
      
         
      
      
        new
      
      
         SelectPictureDialog();
        
        spd.ShowDialog();
        
        pic1t 
      
      
        =
      
      
         getHis.GetHisogram(getHis.Resized(spd.FileName, pic1));
      
      
        //
      
      
        计算出图片一的直方图量度存放到一个pic1t的数组变量中
      
      
        
      
      
        Bitmap bmp
      
      
        =
      
      
        new
      
      
         Bitmap(spd.FileName);
        
                    
        
        pictureBox1.Image 
      
      
        =
      
      
         bmp;
      
      
        //
      
      
        把处理后的图片放入pictureBox1进行预览
      
    
   
  
     
  
  
    图片二按钮同上,只需修改相关参数即可。
  
  
    然后我们看一下直方图量度计算类的部分代码实现吧:
  
  
    计算图像的直方图的这个代码从网络上copy过来的,这个到处都有,我也不是太在行,所以暂不做解释了,汗~
  
  
     
     计算图像的直方图
    
      计算图像的直方图
    
    
      
            
         
      
      
        ///
      
      
         
      
      
        <summary>
      
      
        
                
      
      
        ///
      
      
         计算图像的直方图
        
                
      
      
        ///
      
      
         
      
      
        </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;
        
                }
      
    
   
  
     
  
  
    下面的这个代码就是在分别计算完两张图片的量度后,把两个量度再放到这里面来计算结果,所得结果即为图片相似度的一个参考值,代码如下:
  
  
     
  
  
     
     最终计算结果
    
      最终计算结果
    
    
      
            
                
      
      
        ///
      
      
         
      
      
        <summary>
      
      
        
                
      
      
        ///
      
      
        最终计算结果
        
                
      
      
        ///
      
      
         
      
      
        </summary>
      
      
        
                
      
      
        ///
      
      
         
      
      
        <param name="firstNum">
      
      
        图片一的直方图量度
      
      
        </param>
      
      
        
                
      
      
        ///
      
      
         
      
      
        <param name="scondNum">
      
      
        图片二的直方图量度
      
      
        </param>
      
      
        
                
      
      
        ///
      
      
         
      
      
        <returns>
      
      
        计算结果
      
      
        </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;
        
                    }
        
                }
      
    
   
  
     
  
  
    其中,还有一个类是用来处理图片大小的,在这里也贴出来,大家应该用得到的哦!
  
  
     
  
  
     
     Code
    
      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() 
      
      
        +
      
      
         
      
      
        "
      
      
        %
      
      
        "
      
      
        ;
      
      
        //
      
      
        计算最终结果
      
    
   
  
     
  
  
    好了,代码就是这些了,下面来看看实际效果如何把:
  
  
    1、程序运行后,添加了两张比较相似的图片(不同点请看第三张图片的红圈):
  
  
     
     
     
  
  
    然后,点击“对比”按钮后,即可见到相似度了:
  
  
     
  
  
     
  
  
    
      结尾:
    
  
  
    在这里,我想申明一点,这个直方图量度来计算图片相似度的想法是我从园子里一个朋友
    
      Aaron Wu
    
    的blog上看来的,本想在前面附上他的署名,无奈今天无论如何都找不到他的原文,所以请见谅,您看到了就跟我说一声,毕竟我还有很多问题想请教一二啊!(原文名称《图像相似度算法的C#实现及测评》,在cnblogs里面好像搜不到了哦,大家股沟一下吧!)文中还有部分细节描述不清楚的地方,欢迎各位提问,在下文笔不好,只能是有问必答,呵呵。相信大家在看了源代码以及了解了相关直方图量度的知识后,会有另一番感觉。
  
  
    另:在测试中,发现如果使用图片分割,再逐个部分进行对比,然后在汇总的方法,得出的结果就比较高了!但是无奈PPC设备硬件条件有限,暂时还不考虑。如果转载请注明原文归属哦,谢谢。
  
  
     源代码:
  
  
    
      点击下载
    
  
  
    
      『原创』+『参考』基于PPC的图像对比程序——使用直方图度量
    
  
 
 
 	
	
	
	
	
			
	
		
			
				
					更多文章、技术交流、商务合作、联系博主
					
						微信扫码或搜索:z360901061
					
					
					
						微信扫一扫加我为好友
						
							QQ号联系:  360901061
						
					 
				 
			 
		 
	 
	
		
			
				
					您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。
					
						【本文对您有帮助就好】元