【问题标题】:openCV: How can I increase performance on image processing?openCV:如何提高图像处理的性能?
【发布时间】:2018-07-11 11:18:33
【问题描述】:

我正在使用 FLIR 的 USB 摄像头,并对每个捕获的帧进行一些处理。

不幸的是,我每秒只能处理 10 帧(在“调试”配置下运行时甚至可以处理 5 帧)。

如何提高性能?

PC:英特尔酷睿 i5-5200u (Broadwell) 2.7GHz 8 GB RAM

操作系统:Windows 10

语言:c++

图像处理库:openCV ver 3.4.0

对比:2015 (vc14)

FLIR API:三角帆

这是我的代码:

#include <iostream>
#include "Spinnaker.h"
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;
using namespace Spinnaker;

#define GAUSSIAN_SIZE               11

Mat ConvertToCVmat(ImagePtr pImage)
{
    int result = 0;
    ImagePtr convertedImage = pImage->Convert(PixelFormat_BGR8, NEAREST_NEIGHBOR);

    unsigned int XPadding = static_cast<unsigned int>(convertedImage->GetXPadding());
    unsigned int YPadding = static_cast<unsigned int>(convertedImage->GetYPadding());
    unsigned int rowsize = static_cast<unsigned int>(convertedImage->GetWidth());
    unsigned int colsize = static_cast<unsigned int>(convertedImage->GetHeight());

    //image data contains padding. When allocating Mat container size, you need to account for the X,Y image data padding. 
    Mat cvimg = cv::Mat(colsize + YPadding, rowsize + XPadding, CV_8UC3, convertedImage->GetData(), convertedImage->GetStride());
    return cvimg.clone();
}

void measureTime(void)
{
    static int frameNumber = 0;
    frameNumber++;
    if (frameNumber == 24)
    {
        static int64 e2 = 1;
        static int64 e1 = 0;
        e2 = getTickCount();
        double time = (e2 - e1) / getTickFrequency();
        e1 = getTickCount();
        printf("Proccessed %d frames in %f seconds\n", frameNumber, time);
        frameNumber = 0;
    }
}

void run(CameraPtr pCam)
{
    // Initialize camera
    pCam->Init();

    // Set trigger off, software, and then on again: 
    pCam->TriggerMode.SetValue(TriggerModeEnums::TriggerMode_Off);
    pCam->TriggerSource.SetValue(TriggerSourceEnums::TriggerSource_Software);
    pCam->TriggerMode.SetValue(TriggerModeEnums::TriggerMode_On);

    // Set aqcuisition mode to continuous and start: 
    pCam->AcquisitionMode.SetValue(AcquisitionModeEnums::AcquisitionMode_Continuous);
    pCam->BeginAcquisition();

    // Retrieve the next image:
    namedWindow("image", CV_WINDOW_NORMAL);
    while (1)
    {
        pCam->TriggerSoftware.Execute();
        ImagePtr pResultImage = pCam->GetNextImage();

        // convert to openCV format
        Mat frame = ConvertToCVmat(pResultImage);
        pResultImage->Release();

        // convert to one channel
        cvtColor(frame, frame, COLOR_RGB2GRAY);

        // Gaussian blur:
        Mat imageProc1 = frame;
        GaussianBlur(frame, imageProc1, Size(GAUSSIAN_SIZE, GAUSSIAN_SIZE), 0, 0);

        // find max value:
        double minValue, maxValue;
        Point minIndex, maxIndex;
        minMaxLoc(imageProc1, &minValue, &maxValue, &minIndex, &maxIndex);

        // Draw circles: 
        circle(imageProc1, maxIndex, 29, Scalar(0, 0, 255), 3);

        // Measure time:
        measureTime();

        imshow("image", imageProc1);

        if (waitKey(1) >= 0)
        {
            break;
        }
    }

    // Deinitialize camera
    pCam->EndAcquisition();
    pCam->DeInit();
}

int main()
{
    // Retrieve singleton reference to system object
    SystemPtr system = System::GetInstance();

    // Retrieve list of cameras from the system
    CameraList camList = system->GetCameras();

    // Retrieve pointer for the camera: 
    run(camList.GetByIndex(0));

    // Clear camera list before releasing system
    camList.Clear();
    // Release system
    system->ReleaseInstance();
}

【问题讨论】:

  • 考虑将所有内容从 ConvertToCVmat() 移动到 circle() 到不同的线程。测量在没有任何处理的情况下采集需要多长时间,并测量在没有任何采集的情况下处理需要多长时间。然后想想如何使用一个或多个线程“隐藏”采集背后的处理过程。
  • 您不仅在处理图像,而且还在捕获和显示。最好的办法是异步运行。使用单独的线程来捕获图像并存储在队列中,并使用另一个线程进行处理,并且可能使用另一个线程来显示(某些相机可以将图像显示为采集步骤的一部分)。您可能需要实现多线程生产者-消费者算法(en.wikipedia.org/wiki/Producer–consumer_problem 或 goo.gl/h53TCt)。然后,您的 FPS 将受到最慢的图像捕获、处理和显示的限制。

标签: c++ opencv flir


【解决方案1】:

图像处理(尤其是批处理)是multi threading 的典型用例。

多线程提供了巨大的速度提升,因为可以一次处理多个图像(最多为您机器的核心数)。当然,您使用的库必须是明确的线程安全的(我不知道 OpenCV 是否是这种情况,请参阅手册 - 但我认为是的,因为库现在没有多大意义线程安全。不过,其中一些需要特殊定义来编译线程安全),而且您自己的代码也必须是线程安全的。thread-safe。这不是很容易学习,但绝对值得努力。

实现高速的另一种方法是将 GPU 用于此类任务。 GPU 是高度并行的,甚至比 CPU 上的多线程还要快。您使用的库必须支持 GPU 处理(同样,请参阅手册),或者您必须自己编写 GPU 代码(例如使用OpenCL)。而且您将需要功能强大的显卡和良好的 GPU。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-14
    • 1970-01-01
    • 2012-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-22
    • 1970-01-01
    相关资源
    最近更新 更多