【发布时间】: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 将受到最慢的图像捕获、处理和显示的限制。