当前位置:文档之家› c#灰度直方图算法及调用

c#灰度直方图算法及调用

颜色直方图
颜色直方图是在许多图像检索系统中被广泛采用的颜色特征,它所描述的是不同色彩在整福图像中所占的比例,而并不关心每种色彩所处的空间位置,即无法描述图像中的对象或物体。

颜色直方图特别适用于描述那些难以进行自动分割的图像
灰度直方图
灰度直方图是灰度级的函数,它表示图像中具有每种灰度级的像素的个数,反映图像中每种灰度出现的频率。

灰度直方图的横坐标是灰度级,纵坐标是该灰度级出现的频率,是图像的最基本的统计特征。

灰度直方图的算法实现
大致步骤如下:
1.将图像转换成相同大小,以有利于计算出想象的直方图来
2.计算转化后的会度直方图
3.利用xx公式,得到直方图相似度的定量度量
4.输出这些不知道有用没用的相似度结果数据
代码实现
步骤1.将图像转化成相同大小,我们暂且转化成256×256吧
public static Bitmap Resize(string imageFile, string newImageFile)
{
Image 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×256图片的路径,为了“赛”后可以看到我们转化出来的图片长啥样,所以我就把它保存到了本地了,以至于有了上面的代码
步骤2.计算图像的直方图
/// <summary>
/// 灰度直方图计算方法
/// </summary>
/// <param name="img"></param>
/// <returns></returns>
public static int[] GetHisogram(Bitmap img)
{
System.Drawing.Imaging.BitmapData data = img.LockBits(new System.Drawing.Rectangle(0, 0, img.Width, img.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite,
System.Drawing.Imaging.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)= (好像是欧氏距离公式,不清楚)其中G,S为直方图,N为颜色空间样点数为了大家少敲两行字儿,也给出一堆代码
///<summary>
///计?算?相à减?后ó绝?对?值μ
///</summary>
///<param name="firstNum"></param>
///<param name="secondNum"></param>
///<returns></returns>
private static 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;
}
///<summary>
///结á算?最?终?结á果?
///</summary>
///<param name="firstNum"></param>
///<param name="secondNum"></param>
///<returns></returns>
public static float GetResult(int[] firstNum, int[] secondNum)
{
if (firstNum.Length != secondNum.Length)
{
return 0;
}
else
{
float result = 0;
int j = firstNum.Length;
for (int i = 0; i < j; i++)
{
result += 1 - GetAbs(firstNum[i], secondNum[i]);
}
return result / j;
}
}
步骤4 输出
调用的时候是这样的调用的
public MainWindow()
{
InitializeComponent();
//448前° 448后ó 0.6946089
//418后ó 448后ó 0.81816417
//418前° 448前° 0.766890645
//468 468红ì 0.192232266
//468黄? 468红ì 0.286766857
//448前° 448前° 1.0
int[] firstNum = GetHisogram(Resize("C:\\Img\\448.jpg", "C:\\Img\\NewImg\\448.jpg"));
int[] secondNum = GetHisogram(Resize("C:\\Img\\418.jpg", "C:\\Img\\NewImg\\418.jpg"));
float result = GetResult(firstNum, secondNum);
}。

相关主题