背景介绍
EmguCV和OpenCvSharp都是OpenCV在.Net下的封装,常常会听到有人说EmguCV或OpenCvSharp同样的函数比OpenCV函数运行速度慢,到底是不是真的?博主暂时也没有去一一验证,本文主要对比下三者用指针方法读取像素的速度、耗时情况。
对比实验说明
提供2张图片做测试,分辨率分别是3000 x 3835 和 600 x 676:
分别使用OpenCV、EmguCV和OpenCvSharp指针方法来读取修改像素值,并计算所用时间。
测试图与结果图:
【1】OpenCV测试
代码如下:
代码语言:javascript复制// Read_Modify_Piexl_Value.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include "pch.h"
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
Mat readPixelNormal(Mat img, Mat thres)
{
for (int i = 0; i < thres.rows; i )
{
for (int j = 0; j < thres.cols; j )
{
if (thres.at<uchar>(i, j) == 255)
img.at<Vec3b>(i, j) = Vec3b(197, 247, 254); //BGR彩色图像素值改变
}
}
return img;
}
Mat readPixelFast(Mat img, Mat thres)
{
for (int i = 0; i < thres.rows; i )
{
uchar *ptr = thres.ptr<uchar>(i);
uchar *ptrColor = img.ptr<uchar>(i);
for (int j = 0; j < thres.cols; j )
{
if (ptr[j] == 255)
{
ptrColor[j * 3] = 197;
ptrColor[j * 3 1] = 247;
ptrColor[j * 3 2] = 254;
}
}
}
return img;
}
int main()
{
Mat img = imread("S.png");
Mat gray, thres;
cvtColor(img, gray, COLOR_BGR2GRAY);
threshold(gray, thres, 0, 255, THRESH_BINARY | THRESH_OTSU);
double start = static_cast<double>(getTickCount());
//Mat result = readPixelNormal(img, thres);
Mat result = readPixelFast(img, thres);
double end = static_cast<double>(getTickCount());
double useTime = ((double)end - start) / getTickFrequency() * 1000;
cout << "use-time = " << useTime << "ms" << endl;
imwrite("res.png", result);
return 0;
}
测试结果:
3000 x 3835 图像耗时 12ms左右
600 x 676 图像耗时 0.7ms左右
【2】EmguCV测试
代码如下:
代码语言:javascript复制using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Emgu.CV;
using Emgu.Util;
using Emgu.CV.Structure;
using Emgu.CV.CvEnum;
namespace Read_Modify_Pixel
{
class Program
{
static void Main(string[] args)
{
Mat img = CvInvoke.Imread("S.png");
Mat gray = new Mat();
Mat thres = new Mat();
CvInvoke.CvtColor(img, gray, ColorConversion.Bgr2Gray);
CvInvoke.Threshold(gray, thres, 0, 255, ThresholdType.Binary | ThresholdType.Otsu);
DateTime startTime = DateTime.Now;
unsafe
{
for (int i = 0; i < img.Rows; i )
{
IntPtr ptr = thres.DataPointer;
IntPtr ptrColor = img.DataPointer;
byte* data = (byte*)ptr.ToPointer();
byte* dataColor = (byte*)ptrColor.ToPointer();
for (int j = 0; j < img.Cols; j )
{
if (data[i * img.Cols j] == 255)
{
int index = (img.Step * i) (j * 3);
dataColor[index] = 197;
dataColor[index 1] = 247;
dataColor[index 2] = 254;
}
}
}
}
DateTime stopTime = DateTime.Now;
TimeSpan useTime = stopTime - startTime;
Console.WriteLine("useTime: {0}ms", useTime.TotalMilliseconds);
CvInvoke.Imwrite("res.png", img);
}
}
}
测试结果:
3000 x 3835 图像耗时 950ms左右
600 x 676 图像耗时 44ms左右
【3】OpenCvSharp测试
代码如下:
代码语言:javascript复制using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;
namespace Read_Pixel_Value
{
class Program
{
//指针方法修改像素值
static void Main(string[] args)
{
Mat img = Cv2.ImRead("S.png");
Mat gray = new Mat();
Mat thres = new Mat();
Cv2.CvtColor(img, gray, ColorConversionCodes.BGR2GRAY);
Cv2.Threshold(gray, thres, 0, 255, ThresholdTypes.Binary | ThresholdTypes.Otsu);
DateTime startTime = DateTime.Now;
//指针方法修改像素值
unsafe
{
for (int i = 0; i < thres.Rows; i )
{
IntPtr ptr = thres.Ptr(i);
IntPtr ptrColor = img.Ptr(i);
for (int j = 0; j < thres.Cols; j )
{
byte* data = (byte*)ptr.ToPointer();
byte* dataColor = (byte*)ptrColor.ToPointer();
if (data[j] == 255)
{
dataColor[j * 3] = 197;
dataColor[j * 3 1] = 247;
dataColor[j * 3 2] = 254;
}
}
}
}
DateTime stopTime = DateTime.Now;
TimeSpan useTime = stopTime - startTime;
Console.WriteLine("useTime: {0}ms", useTime.TotalMilliseconds);
Cv2.ImWrite("res.png", img);
Console.WriteLine("Done!");
}
}
}
测试结果:
3000 x 3835 图像耗时 340ms左右
600 x 676 图像耗时 18ms左右
测试结果
由上面测试结果汇总成下表,明显看出C OpenCV指针方法访问像素值最快,其次是OpenCvSharp,最慢的则是EmguCV,以上结果仅供参考。