当前位置:

图像相似度算法的C#实现及测评

2012-3-25 13:57  作者:炉石    阅读:2048

 

近日逛博客的时候偶然发现了一个有关图片相似度的Python算法实现。想着很有意思便搬到C#上来了,给大家看看。

闲言碎语

 

  才疏学浅,只把计算图像相似度的一个基本算法的基本实现方式给罗列了出来,以至于在最后自己测评的时候也大发感慨,这个算法有点不靠谱。不管怎么样,这个算法有时候还是有用的,所以还是列出来跟大家伙一起分享分享~~

  PS:图像处理这一块博大精深,个人偶尔发现了点东西拿来分享。说的不好的地方,写得太糟的地方,诸位准备扔砖头还望淡定,淡定~~

 

基本知识介绍

颜色直方图

颜色直方图是在许多图像检索系统中被广泛采用的颜色特征,它所描述的是不同色彩在整幅图像中所占的比例,而并不关心每种色彩所处的空间位置,即无法描述图像中的对象或物体。颜色直方图特别适用于描述那些难以进行自动分割的图像。

灰度直方图

  灰度直方图是灰度级的函数,它表示图像中具有每种灰度级的像素的个数,反映图像中每种灰度出现的频率。灰度直方图的横坐标是灰度级,纵坐标是该灰度级出现的频率,是图像的最基本的统计特征。

  本文中即是使用灰度直方图来计算图片相似度,关于算法那一块也不赘言了,毕竟图像学图形学,直方图我是门儿都不懂,我也不准备打肿脸充胖子,只想实现一个最基本的算法,然后从最直观的角度看看这个算法的有效性,仅此而已。

 

算法实现

诸位看官休怪笔者囫囵吞枣,浅尝辄止的学习态度。额毕竟是因兴趣而来,于此方面并无半点基础(当然,除了知道RGB是啥玩意儿——这还幸亏当年计算机图形学的老师是个Super美女,因此多上了几节课的缘故),更谈不上半点造诣,看官莫怪莫怪,且忍住怒气,是走是留,小生不敢有半点阻拦~~

大致步骤如下:

1,将图像转换成相同大小,以有利于计算出相像的直方图来

2,计算转化后的灰度直方图

3,利用XX公式,得到直方图相似度的定量度量

4,输出这些不知道有用没用的相似度结果数据

代码实现

步骤1,将图像转化成相同大小,我们暂且转化成256 X 256吧。

 

publicBitmap Resize(string imageFile, string newImageFile)

{

img = Image.FromFile(imageFile);

Bitmap imgOutput = new Bitmap(img, 256, 256);

imgOutput.Save(newImageFile, System.Drawing.Imaging.ImageFormat.Jpeg);

imgOutput.Dispose();

return (Bitmap)Image.FromFile(newImageFile);

}

 

  这部分代码很好懂,imageFile为原始图片的完整路径,newImageFile为强转大小后的256 X 256图片的路径,为了“赛”后可以看到我们转化出来的图片长啥样,所以我就把它保存到了本地了,以至于有了上面略显丑陋的代码。

步骤2,计算图像的直方图

publicint[] 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;

}

这段就是惊天地泣鬼神的灰度直方图计算方法,里面的弯弯绕还是留给诸位自己去掺和。

步骤3,计算直方图相似度度量

这一步骤的法宝在于这个:

Sim(G,S)=HowTo其中G,S为直方图,N 为颜色空间样点数

为了大家少敲两行字儿,也给出一堆乱七八糟的代码:

 

//计算相减后的绝对值

private float GetAbs(int firstNum, int secondNum)

{

float abs = Math.Abs((float)firstNum - (float)secondNum);

float result = Math.Max(firstNum, secondNum);

if (result == 0)

result = 1;

return abs / result;

}

 

//最终计算结果

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;

}

}