EKsumic's Blog

let today = new Beginning();

Click the left button to use the catalog.

RE

C#图像相似度的计算方法

前言:

这个方法对单一色图片的识别效果其实并不好,准确地说,就是黑白不分。

这是一个相对简单的识别,准确率不高,但可以满足部分需求,然后就是一部分代码是有问题的。

 

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 2020-08-28 09:07:07

* *