使用地球的移动距离与Emgu CV

时间:2018-02-02 12:53:35

标签: c# opencv image-processing emgucv

我正在开发一个项目,我尝试在C#中比较两个图像。我正在使用EmguCV(OpenCV的C#包装器)。我已经测试了一些有效的功能(例如compareHist)。 我现在正在尝试使用Earth's Mover Distance的实现。当我使用彩色图像时,我根据HSV图像构建了一个二维直方图。然后我构建相应的签名(如文档中所述,并解释here)。 问题是我总是获得NaN作为我的代码的输出。由于我是C#和EmguCV的新手,我试图做同样的步骤,但这次是在Python中,并且它有效,EMD返回一个没有任何错误的数字。 我花了很多时间在这个问题上试图改变直方图的类型(在OpenCV Mat和EmguCV图像之间),查看直方图值以验证它们是否正确,......但是我找不到我做错了什么。

关于代码: 我有一个“Comparator”类,它只包含2个图像:

class Comparator
{
    public Image<Bgr, Byte> RefImage;
    public Image<Bgr, Byte> TestImage;

    public Comparator(string TestPath, string RefPath)
    {
        Image<Bgr, Byte> TestImagetemp = new Image<Bgr, Byte>(TestPath);
        Image<Bgr, Byte> RefImagetemp = new Image<Bgr, Byte>(RefPath);
        int newCols = Math.Min(TestImagetemp.Cols, RefImagetemp.Cols);
        int newRows = Math.Min(RefImagetemp.Rows, TestImagetemp.Rows);
        Rectangle roi = new Rectangle(0, 0, newCols, newRows);
        this.RefImage = crop(RefImagetemp, roi);
        this.TestImage = crop(TestImagetemp, roi);
        string DiffPath = "C:\\Users\\EPIERSO\\Docs\\testdiff";
        this.TestImage.Save(DiffPath + "testavant.png");
    }

以下是用于计算直方图的方法:

public static Mat CalcHistHSV(Image<Bgr,Byte> image)
    {
        int[] histbins = new int[] { 30, 32 };
        float[] ranges = new float[] { 0.0f, 180.0f, 0.0f, 256.0f };
        Mat hist = new Mat();
        VectorOfMat vm = new VectorOfMat();
        Image<Hsv,float> imghsv = image.Convert<Hsv, float>();
        vm.Push(imghsv);
        CvInvoke.CalcHist(vm, new int[] { 0, 1 }, null, hist, histbins, ranges, false);
        return hist;
    }

这是用于与EMD比较的方法:

public bool EMDCompare()
    {
        int hbins = 30;
        int sbins = 32;
        Mat histref = CalcHistHSV(RefImage);
        Mat histtest = CalcHistHSV(TestImage);
        //Computing the signatures
        Mat sigref = new Mat(hbins*sbins,3,Emgu.CV.CvEnum.DepthType.Cv32F,1);
        Mat sigtest = new Mat(hbins*sbins,3, Emgu.CV.CvEnum.DepthType.Cv32F, 1);
        for (int h = 0; h<hbins; h++)
        {
            for (int s = 0; s < sbins; s++)
            {
                var bin = MatExtension.GetValue(histref,h,s);          
                MatExtension.SetValue(sigref, h * sbins + s, 0, bin);
                MatExtension.SetValue(sigref, h * sbins + s, 1, h);
                MatExtension.SetValue(sigref, h * sbins + s, 2, s);

                var bin2 = MatExtension.GetValue(histtest, h, s);
                MatExtension.SetValue(sigtest, h * sbins + s, 0, bin2);
                MatExtension.SetValue(sigtest, h * sbins + s, 1, h);
                MatExtension.SetValue(sigtest, h * sbins + s, 2, s);

            }
        }
        float emd = CvInvoke.EMD(sigref, sigtest, DistType.L2);
        return ((1 - emd) > 0.7);
    }

为了修改Mat值,我使用名为MatExtension的扩展名,在此处找到:How can I get and set pixel values of an EmguCV Mat image?

这是等效的Python代码:https://pastebin.com/drhvNMNs

0 个答案:

没有答案