gpt4 book ai didi

c# - 为什么 OpenCV 加载图像的时间比 .NET 长得多?

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:39:28 25 4
gpt4 key购买 nike

我正在研究在性能关键型应用程序中使用 OpenCV,因此我决定从基础开始并测试图像加载速度。令我惊讶的是,与 .NET 相比,使用 OpenCV 加载图像(我们经常做的事情)需要大约 1.5 倍的时间。

这是我的代码:

CvDll.cpp

#include "stdafx.h"
#include <opencv2\opencv.hpp>

#define CVDLL_API __declspec(dllexport)

extern "C"
{
CVDLL_API void CvLoadImage(const char* imagePath);
CVDLL_API void CvCreateMat(int width, int height, int stride, int channels, void* pBuffer);
}

CVDLL_API void CvLoadImage(const char* imagePath)
{
cv::Mat image = cv::imread(imagePath, CV_LOAD_IMAGE_UNCHANGED);
}

CVDLL_API void CvCreateMat(int width, int height, int stride, int channels, void* pBuffer)
{
int type = CV_MAKETYPE(CV_8U, channels);
cv::Mat image(cv::Size(width, height), type, pBuffer, stride);
}

程序.cs

   static class Cv
{
[DllImport("CvDll.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "CvLoadImage")]
public static extern void LoadImage(string imagePath);

[DllImport("CvDll.dll", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "CvCreateMat")]
public static extern void CreateMat(int width, int height, int stride, int channels, IntPtr pBuffer);
}

static void Main(string[] args)
{
if (args.Length < 1)
{
Console.WriteLine("Usage: {0} (path to image)", Path.GetFileName(System.Reflection.Assembly.GetCallingAssembly().Location));
Console.Write("Press any key to continue...");
Console.ReadKey();
return;
}

string imagePath = args[0];

try
{
if (!File.Exists(imagePath)) throw new ApplicationException("Image file does not exist.");

// Time .NET
Console.Write(".NET Loading {0} Bitmaps: ", ITERATIONS);
TimeSpan timeDotNet = TimeIt(
() =>
{
using (Bitmap img = new Bitmap(imagePath))
{
int width = img.Width;
int height = img.Height;
int channels = Image.GetPixelFormatSize(img.PixelFormat) / 8; // Assumes 1 byte per channel

BitmapData bd = img.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, img.PixelFormat);

// Create a Mat from the bitmap data to make the operation equivalent
Cv.CreateMat(width, height, Math.Abs(bd.Stride), channels, bd.Scan0);

img.UnlockBits(bd);
}
}
, ITERATIONS
);
Console.WriteLine("{0}", timeDotNet);

// Time OpenCV
Console.Write("OpenCV Loading {0} Mats: ", ITERATIONS);
TimeSpan timeCv = TimeIt(
() => Cv.LoadImage(imagePath)
, ITERATIONS
);
Console.WriteLine("{0}", timeCv);

// Show ratio
Console.WriteLine("CV / .NET: {0:0.000}", timeCv.TotalMilliseconds / timeDotNet.TotalMilliseconds);
}
catch (Exception ex)
{
Console.WriteLine("Exception caught: {0}{1}", ex.Message, Environment.NewLine);
}

// End
Console.Write("Press any key to continue...");
Console.ReadKey();
}

static TimeSpan TimeIt(Action action, int iterations)
{
Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < iterations; ++i)
{
action();
}
return sw.Elapsed;
}
}

Here是我一直用来测试的花卉图片的链接。

我的结果(CV 时间/.NET 时间):

  • 1 channel PNG:1.764
  • 3 channel PNG:1.290
  • 4 channel PNG:1.336

  • 1 channel BMP:1.384

  • 3 channel BMP:1.099
  • 4 channel BMP:1.809

  • 3 channel JPG:2.816(示例图片)

这些测试是在 Release模式下编译完成的,没有使用官方 OpenCV Windows 库附加调试器。

我最初的想法是内存分配的速度,但看不同 channel 图像之间的差异似乎暗示并非如此。

我尝试过的其他事情:

  • 将循环移动到 C++ 函数中:没有变化
  • 打开我能在 VS 中找到的所有优化选项:无变化
  • 第二台机器:在 AMD Phenom II 机器上试过,彩色图像开始显示 1.25 左右,灰度显示 1.5 左右。因此,尽管有所不同,但仍然受到 .NET 的青睐。

其他细节:

  • Windows 7 x64
  • Visual Studio 2013
  • OpenCV 2.4.9
  • .NET 4.5

结果似乎有点违反直觉,但在这种特定情况下,OpenCV 似乎确实更慢。

编辑:

感谢@πìντα ῥεῖ 指出操作不等同,编辑以在两种情况下创建一个 Mat 以隔离加载方法。我希望这能使它成为一个有效的测试。

编辑2:

修复了@B 指出的问题,修改了加载 CV_LOAD_IMAGE_UNCHANGED 时的数字。

最佳答案

除非您另有指定,否则 OpenCv 会返回彩色图像。因此,对于 OpenCV,您需要为 .NET 可能不会发生的颜色转换付费。对于一张彩色图像,您需要指定 CV_LOAD_IMAGE_GRAYSCALE,或将标志设置为 -1 以获取文件中的任何内容。

查看源代码,看起来 3 channel 图像以 RGB channel 顺序从实际解码器(至少 PNG 和 Jpeg)中出来,并且这些图像被交换为 OpenCV 在任何地方都期望的 BGR 顺序。如果您的 .NET 库以 RGB 顺序返回图像,那么如果您要将图像传递给其他 OpenCV 函数,则可能需要转换为 BGR。然后你可能会失去速度优势。

公平地说,您需要将 RGB2BGR 转换添加到您的 .NET 加载代码中 - 请参阅 Converting a BGR bitmap to RGB

此外,对于 4 channel PNG,OpenCV 将丢弃 alpha channel 并返回 3 channel 图像,除非您指定 flags = -1。

关于c# - 为什么 OpenCV 加载图像的时间比 .NET 长得多?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24419711/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com