OpenCV、EmguCV和OpenCvSharp指针访问图像像素值耗时测评(附源码)

2022-09-26 10:15:30 浏览数 (1)

背景介绍

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,以上结果仅供参考。

—THE END—

0 人点赞