我正在研究扭曲图像的工具,失真的目的是将图像投影到球形屏幕。所需的输出如下图所示。
我使用的代码如下 - 对于目标区域中的每个Point(x,y),我计算要检索的原始图像中的相应像素(sourceX,sourceY)。
但是这种方法很慢,在我的测试中,处理sunset.jpg(800 * 600)需要超过1500ms,如果我删除了数学/三角计算,单独调用cvGet2D和cvSet2D需要超过1200ms。
有更好的方法吗?我正在使用Emgu CV(OpenCV的.NET包装器库),但其他语言的示例也没问题。
private static void DistortSingleImage()
{
System.Diagnostics.Stopwatch stopWatch = System.Diagnostics.Stopwatch.StartNew();
using (Image<Bgr, Byte> origImage = new Image<Bgr, Byte>("sunset.jpg"))
{
int frameH = origImage.Height;
using (Image<Bgr, Byte> distortImage = new Image<Bgr, Byte>(2 * frameH, 2 * frameH))
{
MCvScalar pixel;
for (int x = 0; x < 2 * frameH; x++)
{
for (int y = 0; y < 2 * frameH; y++)
{
if (x == frameH && y == frameH) continue;
int x1 = x - frameH;
int y1 = y - frameH;
if (x1 * x1 + y1 * y1 < frameH * frameH)
{
double radius = Math.Sqrt(x1 * x1 + y1 * y1);
double theta = Math.Acos(x1 / radius);
int sourceX = (int)(theta * (origImage.Width - 1) / Math.PI);
int sourceY = (int)radius;
pixel = CvInvoke.cvGet2D(origImage.Ptr, sourceY, sourceX);
CvInvoke.cvSet2D(distortImage, y, x, pixel);
}
}
}
distortImage.Save("Distort.jpg");
}
Console.WriteLine(stopWatch.ElapsedMilliseconds);
}
}
答案 0 :(得分:2)
从我个人的经验来看,我正在做一些立体视觉的东西,与openCV交谈的最好方法是通过自己的包装器,你可以把你的方法放在c ++中并用c#调用它,这会给你1个本机调用,更快的代码,并且因为在Emgu保留OpenCV数据的情况下,也可以使用emgu创建图像,本地处理它并再次在c#中享受处理过的图像。
get / set方法看起来像Gdi的GetPixel / SetPixel方法,根据文档,它们是“缓慢但安全的方式”。
仅保留Emgu,文档告诉您如果要迭代像素,则应该访问.Data
属性:
安全(缓慢)
假设您正在处理图像。您可以通过调用获取第y行和第x列的像素 Bgr color = img [y,x]; 设置第y行和第x列的像素也很简单 img [y,x] = color;
快捷方式
图像像素值存储在Data属性(3D数组)中。如果需要迭代图像的像素值,请使用此属性。