使用emgu cv迭代图像的像素

Ben*_*nks 16 c# loops image

我想迭代图像的所有像素并与搜索模式进行比较.具有最佳性能并且在C#中.我找到了emgu cv,它是Intels opencv的包装器.但我不知道如何正确使用emgu.有人知道我怎么做吗?图像的数据属性是什么?这是imagedata吗?如果是,哪个值是什么?谢谢

更新:

我用C#编写了我的函数,它运行良好,但速度太慢了!我已经在c中使用了algorhytm,我将其翻译成C#.C#比c慢3到4倍!(我的函数迭代几乎图像的每个像素以寻找图像中的形状. - > Hugh Transformation)

好吧,我听说不安全的代码可能更快,因为它不检查数组边界和东西.真的吗?直接在物理机上运行不安全的代码?

无论如何,我试图将不安全的代码放入我的函数中.但我无法获得指向我的3D数组的指针或使用指针访问3D数组.如何用不安全的代码重写上面的代码?这会带来额外的性能提升,甚至可以像c代码一样快速运行吗?

Luc*_*ngo 50

正如emgu网站所述,主要有两种策略:

安全(缓慢)的方式

假设你正在做一个Image<Bgr, Byte>.您可以通过调用获取第y行和第x列的像素

Bgr color = img[y, x];
Run Code Online (Sandbox Code Playgroud)

设置第y行和第x列的像素也很简单

img[y,x] = color;
Run Code Online (Sandbox Code Playgroud)

快捷的方式

图像像素值存储在Data属性(3D数组)中.好的,这是真的,但没有说明如何在真实场景中做到这一点.那么让我们看看一些工作代码,然后讨论性能和优化:

Image<Bgr, Byte> original = newImage<Bgr, byte>(1024, 768);
Stopwatch evaluator = newStopwatch(); 

int repetitions = 20;
Bgr color = newBgr(100, 40, 243);

evaluator.Start();

for (int run = 0; run < repetitions; run++)
{
    for (int j = 0; j < original.Cols; j++)
    {
        for (int i = 0; i < original.Rows; i++)
        {
            original[i, j] = color;
        }
    }
}

evaluator.Stop();
Console.WriteLine("Average execution time for {0} iteration \n using column per row access: {1}ms\n", repetitions, evaluator.ElapsedMilliseconds / repetitions);
Run Code Online (Sandbox Code Playgroud)

所以这是20次运行后使用安全慢速设置图像像素的平均运行时间在我的机器上需要1021ms ......

因此,循环的平均时间为1021毫秒,并将像素数设置为1024*768.我们可以通过逐行循环来做得更好一些

所以让我们重构一下我们的代码,让我们使用更快的方式直接使用Image.Data属性:

evaluator.Reset();
evaluator.Start();

for (int run = 0; run < repetitions; run++)
{
    for (int i = 0; i < original.Rows; i++)
    {
        for (int j = 0; j < original.Cols; j++)
        {
            original.Data[i, j, 0] = 100;
            original.Data[i, j, 1] = 40;
            original.Data[i, j, 2] = 243;
        }
    }
}

evaluator.Stop();
Console.WriteLine("Average execution time for {0} iterations \n using Data property: {1}ms\n", repetitions, evaluator.ElapsedMilliseconds / repetitions);
Run Code Online (Sandbox Code Playgroud)

在我的机器上需要519ms.所以我们的性能提升了50%.执行时间减少了两倍.

所以仔细查看代码,记住我们正在使用C#,我们可以做一个小的改动,这将大大提高我们的图像像素设置性能... 我们不应该在循环内使用c#属性!

evaluator.Reset();
evaluator.Start();

byte[,,] data = original.Data;

for (int run = repetitions - 1; run >= 0; run--)
{
    for (int i = original.Rows - 1; i >= 0; i--)
    {
        for (int j = original.Cols - 1; j >= 0; j--)
        {
            data[i, j, 0] = 100;
            data[i, j, 1] = 40;
            data[i, j, 2] = 243;
        }
    }
}

evaluator.Stop();
Run Code Online (Sandbox Code Playgroud)

使用这一最新的代码,由于正确使用C#语言,您将获得巨大的性能提升(73ms).

  • 使用数据属性没什么不安全的.开发人员需要更多关注指定正确的索引来获取或设置正确的值,因为Data属性是一个三维数组 (2认同)
  • 你为什么要翻转范围?例如,在第一个代码段中,您从[0到行]进行了迭代,然后从[row到0]进行了迭代。 (2认同)