C++中的二进制图像处理
binary image manipulation in C++
我有一组来自相机的二进制图像,并由相机进行预阈值处理。然后我使用OpenCV来找到每个图像中的轮廓和轮廓中心的坐标。
但我的问题是,这种过程非常缓慢。该相机以每秒170帧的速度工作,分辨率为2048*1088。
我知道当我实时这样做时,数据量是巨大的。有没有什么好的库可以用来加快速度,因为我只需要坐标。我需要扔掉所有的灰度信息,只提取每个图像中轮廓中心的坐标。
如果有人能提供我和想法,我将不胜感激。
正如评论中所要求的,我的部分代码被添加到这里:
图像获取部分
#include <opencv2opencv.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帧/秒。然后我把所有其他处理作为:
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帧/秒,这是不可接受的。
在我的ROI中,所需轮廓的数量大约是10个。我的应用程序的最终目标是监视框架内大约50米距离的几个飞行物体。它们的坐标就是我认为的全部。
我在一台带有i7-500U 2.4GHz CPU的笔记本电脑上运行这个。
更新:这是一张二值化的图像,来自于在一次非常基本的试验中监测一只大黄蜂的相机。在正常的试验中,相机框架内可能有几十只飞虫。捕获的大黄蜂的一个二进制帧
在您的代码中有很多的东西(见下文)。但是:
只需调用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?面具是单通道的 - 您的函数所做的大部分工作都是为了调试。对于关键代码,应该避免使用这些东西
- CCD_ 6用于寻找轮廓将浪费大量空间
- 只需使用
connectedComponentWithStats
,它比findContours
快得多,并且已经为您提供了每个斑点的面积和质心
相关文章:
- Qt中的RGB图像处理
- 有关图像处理应用程序的硬件和软件安全性的建议
- C++灰度图像处理
- C++二进制文件 I/O 操作速度变慢.数据库如何处理二进制文件?
- CUDA 速度比预期慢 - 图像处理
- 如何将 MATLAB 图像处理库内置函数转换为 MATLAB 编码器代码生成不支持的 C++?
- 矢量化图像处理
- OpenGL (ES) 图像处理C++
- C++:灰度位图标题和实时绘画+opencv图像处理
- 在 Unity 中C++使用后台线程进行图像处理会导致崩溃
- 线程会影响树莓派的图像处理性能吗?
- 低性能 – 补丁匹配.GPU 上的图像处理 (CUDA)
- 如何使用OpENCV解决图像处理摄像头IO延迟
- 从单线程到多线程图像处理
- 如何使用win IoT在Raspberry Pi上的相机中显示视频流以及一些图像处理
- C 图像处理(来自单元格的裁剪图像)
- C++中的二进制图像处理
- 实时图像处理:HSV图像中的噪声(openCV)
- c_str() 或reinterpret_cast更适合处理二进制文件
- C 图像处理数据块进入数组 /指针