我尝试在edgeimages上使用MatchTemplate来查找图像中的高速缓存对象。作为图像源我使用kinect2。我首先教一个边缘图像,并在以后捕获的图像中搜索教学模板。使用canny计算边缘图像效果非常好。我将边缘保存为byte [] with
byte[] bytes = cannyFrame.GetData();
稍后我尝试使用给定的数据创建Image。不幸的是,有时候创建图像会在ArgumentOutOfRange-Exception中运行并声称数组很大。有时发生异常,有时不会发生。创建当前图像时以及我正在创建教学图像时会出现异常(请参阅我的代码中的注释)。任何人都能告诉我,为什么会发生这种异常?
Bitmap bmp;
//bmp is filled with the image from the kinect
int width;
int height;
byte[] currentEdges = EdgeDetector.CalculateEdges(bmp, referenceImage.BorderOne, referenceImage.BorderTwo, out width, out height);
try
{
Console.WriteLine("ref width: {0}, height: {1}, byte[]length: {2}", referenceImage.Width_px, referenceImage.Height_px, referenceImage.Edges.Length);
//Here happens the exception sometimes:
Image<Gray, byte> templateImage = new Image<Gray, byte>(referenceImage.Width_px, referenceImage.Height_px);
templateImage.Bytes = referenceImage.Edges;
Console.WriteLine("current image width: {0}, height: {1}, byte[]length: {2}", width, height, currentEdges.Length);
//Here happens the exception sometimes:
Image<Gray, byte> searchImage = new Image<Gray, byte>(width, height);
searchImage.Bytes = currentEdges;
Console.WriteLine("");
Image<Gray, float> imgMatch = searchImage.MatchTemplate(templateImage, TemplateMatchingType.CcoeffNormed);
}
catch (Exception)
{
Console.WriteLine(ex.ToString());
}
internal class EdgeDetector
{
internal static byte[] CalculateEdges(Bitmap bmp, int borderOne, int borderTwo, out int width, out int height)
{
try
{
Image<Bgr, byte> img = new Image<Bgr, byte>(bmp);
Mat smallGrayFrame = new Mat();
Mat smoothedGrayFrame = new Mat();
Mat cannyFrame = new Mat();
CvInvoke.PyrDown(img, smallGrayFrame);
CvInvoke.PyrUp(smallGrayFrame, smoothedGrayFrame);
CvInvoke.Canny(smoothedGrayFrame, cannyFrame, borderOne, borderTwo);
byte[] bytes = cannyFrame.GetData();
width = cannyFrame.Width;
height = cannyFrame.Height;
return bytes;
}
catch (Exception ex)
{
width = 0;
height = 0;
return null;
}
}
示例输出: ref width:46,height:44,byte [] length:2024 System.ArgumentOutOfRangeException:请求的范围超出了结尾 阵列。 在System.Runtime.InteropServices.Marshal.CopyToNative(Object source,Int32 s) tartIndex,IntPtr目的地,Int32长度) 在Emgu.CV.CvArray`1.set_Bytes(Byte []值) at AlgorithmsHelper.SearchEdgeImage(AssistentEdgeImageOpenCv referenceImage,Image currentImage)
感谢任何帮助。
答案 0 :(得分:0)
我仍然不知道为什么会发生异常,但我找到了一个解决方案作为walkaround。就像http://www.emgu.com/wiki/index.php/Working_with_Images建议我创建一个Mat,用字节填充它并从Mat巫婆中创建一个图像。
Mat currentMat;
using (MemoryStream memoryStream = new MemoryStream(currentEdges))
{
byte[] rawData = new byte[memoryStream.Length];
memoryStream.Read(rawData, 0, (int)memoryStream.Length);
GCHandle rawDataHandle = GCHandle.Alloc(rawData, GCHandleType.Pinned);
IntPtr address = rawDataHandle.AddrOfPinnedObject();
currentMat = new Mat(new System.Drawing.Size(width, height), DepthType.Cv8U, 1, address, width);
rawDataHandle.Free();
}
Image<Gray, byte> currentImage = currentMat.ToImage<Gray, byte>();
Mat templateMat;
using (MemoryStream memoryStream = new MemoryStream(referenceImage.Edges))
{
byte[] rawData = new byte[memoryStream.Length];
memoryStream.Read(rawData, 0, (int)memoryStream.Length);
GCHandle rawDataHandle = GCHandle.Alloc(rawData, GCHandleType.Pinned);
IntPtr address = rawDataHandle.AddrOfPinnedObject();
templateMat = new Mat(new System.Drawing.Size(referenceImage.Width_px, referenceImage.Height_px), DepthType.Cv8U, 1, address, referenceImage.Width_px);
rawDataHandle.Free();
}
Image<Gray, byte> templateImage = templateMat.ToImage<Gray, byte>();
Image<Gray, float> imgMatch = currentImage.MatchTemplate(templateImage, TemplateMatchingType.CcoeffNormed);