C#图像相似度的计算方法
            Copyright Notice: This article is an original work licensed under the CC 4.0 BY-NC-ND license.
            If you wish to repost this article, please include the original source link and this copyright notice.
            
            Source link: https://v2know.com/article/441
前言:
这个方法对单一色图片的识别效果其实并不好,准确地说,就是黑白不分。
这是一个相对简单的识别,准确率不高,但可以满足部分需求,然后就是一部分代码是有问题的。
ImageSimilarity.cs:
public class ImageSimilarity
{
    public 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);
    }
    //灰度直方图计算方法
    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;
    }
    //计算相减后的绝对值
    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;
        }
    }
}
调用例:
ImageSimilarity sim = new ImageSimilarity();         
int[] firstimg=sim.GetHisogram(sim.Resize("[email protected]", "resize_test1.jpeg"));
int[] secondimg = sim.GetHisogram(sim.Resize("dd4.png", "resize_test2.jpeg"));
MessageBox.Show(sim.GetResult(firstimg, secondimg).ToString());
看了下
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;
}
这段代码有误,原文应该是计算在RGB空间中的间距,在RGB中的R上相邻的两点直接相减差值可能非常巨大,直接用减法做分子是不对的。
参考来源:
https://www.cnblogs.com/wuchaodong/archive/2009/04/28/1444792.html
This article was last edited at