【问题标题】:binary image manipulation in C++ [closed]C ++中的二进制图像处理
【发布时间】:2017-11-06 13:09:24
【问题描述】:

我有一组来自相机的二进制图像,并由相机预先设定阈值。然后我使用 OpenCV 在每个图像中查找轮廓以及轮廓中心的坐标。

但我的问题是,这种过程非常缓慢。相机以 170 fps 的速度工作,分辨率为 2048*1088。

我知道当我实时执行此操作时数据量很大。有什么好的库可以用来加速它,因为我需要的只是坐标。我需要丢弃所有灰度信息,只提取每个图像中轮廓中心的坐标。

如果有人能提供我和想法,我将不胜感激。

根据cmets的要求,我的部分代码在这里添加:

图像采集部分

#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,这是不可接受的。

我的 ROI 中所需的轮廓数约为 10。 我的应用程序的最终目标是在大约 50m 的距离处监视框架内的几个飞行物体。我认为它们的坐标才是最重要的。

我在配备 i7-5500U 2.4GHz CPU 的笔记本电脑上运行它。

更新: 这是在非常基本的试验期间监控大黄蜂的相机的二值化图像。在正常试验中,相机框架内可能有数十只飞虫。 one binarized frame of the captured bumble bee

【问题讨论】:

  • 请提供您的环境的示例图像和详细信息。每张图片中是否有多个对象?
  • "170 fps,分辨率为 2048*1088。"我不确定它是否可以变得更快。也许如果它是多线程的或者在 GPU 上移动就更好了。
  • 显示您的代码也会有所帮助
  • 它使用什么接口以 3Gb/s 运行?什么 CPU 正在处理你的帧?
  • 您的应用程序真的在 2K 分辨率下需要 170fps 吗?我建议您在进行任何处理之前降低 fps 或分辨率。如果需要,在处理后重新缩放和插入轮廓中心坐标。 OpenCV 可能已经是你最好的选择了。

标签: c++ image opencv


【解决方案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 快得多,并且已经为您提供了每个斑点的面积和质心。

【讨论】:

  • 您好,感谢您的回复。在传输到我的计算机之前,相机的 FPGA 完成了二值化,我将帧转换为掩码作为 BGR 的原因是我想要用红色圆圈而不是黑色或白色 xD 标记的轮廓。或者如果你有什么好的想法请告诉我。对于您提供的其他建议,我将对此进行深入研究。另外,您提到我的大部分功能都是为调试而做的,我不明白,您能否更具体一点。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-01
  • 2016-02-21
  • 2023-03-09
  • 2012-06-02
  • 2015-08-16
相关资源
最近更新 更多