我有一组来自相机的二进制图像,并由相机预先设定阈值。然后我使用OpenCV查找每个图像中的轮廓和轮廓中心的坐标。
但我遇到的问题是,这种过程非常缓慢。相机的工作速度为170 fps,分辨率为2048 * 1088。
我知道实时执行此操作时数据量巨大。有什么好的库可以用来加速它,因为我需要的只是坐标。我需要丢弃所有灰度信息并仅提取每个图像中轮廓中心的坐标。
如果有人可以提供我的想法,我将不胜感激。
根据评论中的要求,我的部分代码将添加到此处:
图像采集部分
#include <opencv2\opencv.hpp>
#include <stdio.h>
#include "xiApiPlusOcv.hpp"
#include <ctime>
xiAPIplusCameraOcv cam;
Mat frame;
vector<Mat> frames;
...
cam.StartAcquisition();
startTime = clock();
for (int j = 0; j < 600; j++)
{
frame = cam.GetNextImageOcvMat();
frames.push_back(frame.clone());
frame.release();
}
cam.StopAcquisition();
cam.Close();
我正在使用XIMEA的CMOS单声道摄像头,在这里我通过相机的RAM缓冲对600帧进行采样。收购种子最高可达170 fps。然后我把所有其他处理都放在这之后:
vector<Mat> masks(frames.size());
for (int s = 0; s < frames.size(); s++)
{
cvtColor(frames[s], masks[s], CV_GRAY2BGR);
vector<Vec4i> hierarchy;
vector<vector<Point> > contours;
findContours(frames[s], contours, hierarchy, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
vector<Moments> M(contours.size());
vector<Point2f> MC(contours.size());
for (size_t i = 0; i < contours.size(); i++)
{
M[i] = moments(contours[i]);
}
for (size_t i = 0; i < contours.size(); i++)
{
MC[i] = Point2f(M[i].m10 / M[i].m00, M[i].m01 / M[i].m00);
}
for (size_t i = 0; i < contours.size(); ++i)
{
// Calculate the area of each contour
double area = contourArea(contours[i]);
// Ignore contours that are too small or too large
if (area < 1e2 || 1e5 < area) continue;
// Draw each contour only for visualisation purposes
drawContours(masks[s], contours, static_cast<int>(i), Scalar(0, 0, 255), 2, 8, hierarchy, 0);
circle(masks[s], MC[i], 4, Scalar(0, 0, 255), -1);
}
}
如果我发现离线轮廓,就像上面显示的那样,我对结果感到满意。但是只能记录几分钟的非常短的视频,这意味着无法进行更长时间的监控。
如果我将处理与采集一起移动到一个不确定的循环中,它只给我30-40 fps,这是不可接受的。
我的投资回报率中所需轮廓的数量约为10。 我的应用的最终目标是在距离约50米的地方监视框架内的几个飞行物体。我认为它们的坐标都很重要。
我在i7-5500U 2.4GHz CPU的笔记本电脑上运行。
更新: 这是一张来自相机的二进制图像,用于在非常基本的试验中监控一只大黄蜂。在正常的试验中,相机框架内可能会有数十只飞虫。 one binarized frame of the captured bumble bee
答案 0 :(得分:1)
你的代码中有很多的东西真的很奇怪(见下文)。 但是:
您只需调用connectedComponentsWithStats
来计算质心:
vector<Mat> frames;
...
cv::Mat1i labels;
cv::Mat1i stats;
cv::Mat1d centroids;
for(size_t i=0; i<frames.size(); ++i)
{
// centroids will contain in each row the coordinates x,y of the centroids.
int n_labels = cv::connectedComponentsWithStats(frame[i], labels, stats, centroids);
// Remember that label 0 is the background... not really useful.
for(int j=1; j<n_labels; ++j)
{
// Filter by area
int area = stats(j, cv::CC_STAT_AREA);
if (area < 1e2 || 1e5 < area) continue;
// Do something with the centroid
cv::Point2d centroid(centroids(j,0), centroids(j,1));
...
}
}
CV_8UC1
,因为您正在使用它们。否则请致电cv::Mat1b temp; cvtColor(frame[i], temp, cv::COLOR_BGR2GRAY);
,然后使用temp
。cvtColor(frames[s], masks[s], CV_GRAY2BGR);
中将灰色转换为rgb?面具是单通道! CV_CHAIN_APPROX_NONE
寻找轮廓会浪费很多空间。connectedComponentWithStats
快得多的findContours
,并且已经为您提供了每个blob的区域和质心。