比较图像并标记差异c#
我目前正在从事一个项目,在这个项目中,我需要编写一个软件来比较由相同区域组成的两幅图像,并在差异周围画一个方框。我在几个小时内用c#net编写了这个程序,但很快就意识到它运行起来非常昂贵。以下是我在中实现它的步骤比较图像并标记差异c#,c#,.net,image,comparison,pixel,C#,.net,Image,Comparison,Pixel,我目前正在从事一个项目,在这个项目中,我需要编写一个软件来比较由相同区域组成的两幅图像,并在差异周围画一个方框。我在几个小时内用c#net编写了这个程序,但很快就意识到它运行起来非常昂贵。以下是我在中实现它的步骤 创建了存储每个像素的x、y坐标的像素类和存储像素列表以及宽度、高度、x和y属性的像素矩形类 循环通过每个图像的每个像素,比较每个对应像素的颜色。如果颜色不同,我就用像素的x,y坐标创建一个新的像素对象,并将其添加到像素差异列表中 接下来,我编写了一个方法,递归检查pixelDiffer
- 戴夫
作为跟踪已检查像素的替代方法,您可以在检查后从PixelDifference中删除项目。当然,这可能需要改变实现算法的方式,因为在检查列表时从列表中删除元素可能会带来一系列全新的问题 看起来您想要实现blob检测。我的建议是不要重新发明轮子,而只是使用openCVSharp或emgu来实现。谷歌“斑点检测”和opencv 如果你想在这里亲自动手,我的2美分价值: 首先,让我们澄清一下你想做什么。实际上有两件事是不同的:
//
///计算两个图像之间的差异并存储第三个图像
///输入图像必须具有相同的尺寸和颜色深度
///
///第一图像
///第二图像
///如果相同,则输出0;如果不同,则输出255
///图像宽度
///图像高度
///输入图像的颜色通道数
不安全的void计算差异(字节[]imageA、字节[]imageB、字节[]imageDiff、int-width、int-height、int-channels、int-threshold)
{
int ch=通道;
固定(字节*piA=imageB,piB=imageB,piD=imageDiff)
{
if(ch>1)//这是彩色图像(假设RGB ch==3和RGBA==4)
{
对于(int r=0;r阈值)
{
pD[c]=255;
}
其他的
{
pD[c]=0;
}
}
}
}
else//单灰度通道
{
对于(int r=0;r阈值)
{
pD[c]=255;
}
其他的
{
pD[c]=0;
/// <summary>
/// computes difference between two images and stores result in a third image
/// input images must be of same dimension and colour depth
/// </summary>
/// <param name="imageA">first image</param>
/// <param name="imageB">second image</param>
/// <param name="imageDiff">output 0 if same, 255 if different</param>
/// <param name="width">width of images</param>
/// <param name="height">height of images</param>
/// <param name="channels">number of colour channels for the input images</param>
unsafe void ComputeDiffernece(byte[] imageA, byte[] imageB, byte[] imageDiff, int width, int height, int channels, int threshold)
{
int ch = channels;
fixed (byte* piA = imageB, piB = imageB, piD = imageDiff)
{
if (ch > 1) // this a colour image (assuming for RGB ch == 3 and RGBA == 4)
{
for (int r = 0; r < height; r++)
{
byte* pA = piA + r * width * ch;
byte* pB = piB + r * width * ch;
byte* pD = piD + r * width; //this has only one channels!
for (int c = 0; c < width; c++)
{
//assuming three colour channels. if channels is larger ignore extra (as it's likely alpha)
int LA = pA[c * ch] + pA[c * ch + 1] + pA[c * ch + 2];
int LB = pB[c * ch] + pB[c * ch + 1] + pB[c * ch + 2];
if (Math.Abs(LA - LB) > threshold)
{
pD[c] = 255;
}
else
{
pD[c] = 0;
}
}
}
}
else //single grey scale channels
{
for (int r = 0; r < height; r++)
{
byte* pA = piA + r * width;
byte* pB = piB + r * width;
byte* pD = piD + r * width; //this has only one channels!
for (int c = 0; c < width; c++)
{
if (Math.Abs(pA[c] - pB[c]) > threshold)
{
pD[c] = 255;
}
else
{
pD[c] = 0;
}
}
}
}
}
}
Image<Gray, Byte> A;
Image<Gray, Byte> B;
A - B
B - A
(A - B) + (B - A)
CvInvoke.cvDFT(A.Convert<Gray, Single>().Ptr, DFTA.Ptr, Emgu.CV.CvEnum.CV_DXT.CV_DXT_FORWARD, -1);
CvInvoke.cvDFT(B.Convert<Gray, Single>().Ptr, DFTB.Ptr, Emgu.CV.CvEnum.CV_DXT.CV_DXT_FORWARD, -1);
CvInvoke.cvDFT((DFTB - DFTA).Convert<Gray, Single>().Ptr, AB.Ptr, Emgu.CV.CvEnum.CV_DXT.CV_DXT_INVERSE, -1);
CvInvoke.cvDFT((DFTA - DFTB).Ptr, BA.Ptr, Emgu.CV.CvEnum.CV_DXT.CV_DXT_INVERSE, -1);