我正在开发一个项目,我尝试在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