使用MATLAB和OpenCV对图像求和的效率

时间:2016-06-10 07:36:52

标签: c++ matlab opencv

我对你的所有答案都感到惊讶。 非常感谢!

错误代码如下所示: percentage = (double)kk * 100.0 / (double)totalnum;

我将其修改为: percentage = (double)kk * 100.0 / totalnum;

问题已解决。这个简单的部门在150年代中耗费了大约90秒。也许 double int 之间的划分比 double 之间的划分更快。

再次感谢您的所有答案!

我试图从一组来自视频的图片中获取平均图像。这项工作只有两个步骤:

  1. 将所有图像汇总成矩阵。
  2. 将矩阵除以图像数量。
  3. 我在OpenCV中使用了以下代码:(C ++)

    Mat avIM = Mat::zeros(IMG_HEIGHT, IMG_WIDTH, CV_32FC3);
    
    for (ii = startnum; ii <= endnum; ii += interval) {
        string fullname = argv[1];
        sprintf(filename, "\\%d.png", ii);
        fullname.append(filename);
    
        Mat tempIM = imread(fullname.c_str());
        if (tempIM.empty()) { cout << "Can't open image!\n"; return -1; }
        tempIM.convertTo(tempIM, CV_32FC3);     
    
        avIM += tempIM;     //Sum up every image
        ++kk;
    
    }
    avIM = avIM * (double)(1.0 / kk);   //get average'
    

    关注MatLab中的代码:(2015a)

    avIM = zeros(size(imread([im.dir,'\',num2str(startnum),'.png'])));
    
    pointIdx = startnum:interval:endnum;
    for j=pointIdx,
        IM = imread([im.dir,'\',num2str(j),'.png']);
        avIM = avIM + double(IM); %Sum up every image
    end
    avIM = uint8(round(avIM./size(pointIdx,2))); %get average
    

    但是,当我在2,100张图片上运行这两个程序时,OpenCV采用 150.3s (发布),而MatLab采用 103.1s 。我真的很困惑,C ++程序比MatLab脚本运行得慢。

    那么我的OpenCV程序放慢了什么?如果它是由我的矩阵访问方法引起的,我该怎么做才能提高效率?

2 个答案:

答案 0 :(得分:0)

引起我注意的一点是“CV_32FC3”类型。你是否特别喜欢32位浮点矩阵,你确定Matlab也能以相同的方式获得像素值吗?

因为你有额外的步骤

tempIM.convertTo(tempIM, CV_32FC3);     

在您的Cpp代码中,Matlab在没有任何转换的情况下检索图像后立即直接运行,这可能会降低您的cpp代码速度。此外,如果Matlab没有以浮点值获取图像,那可能会导致速度差异,因为与整数相比,浮点算术是一个比较难处理的CPU处理任务。

答案 1 :(得分:0)

您的代码似乎已经足够好了,在我的测试中,我发现它的运行速度比Matlab代码快10倍。

但是,我展示了稍微优化的代码,其执行速度比您的快一些。

备注

请注意,我没有一个包含您的图像的文件夹,因此我在C ++版本中使用cv::glob,在Matlab版本中使用dir来获取图像的名称文件夹。

在我的文件夹中我有82张小图片,因此运行时间明显比你的小,但相对性能应该可靠。

执行时间

                    Sum only      Get filenames + Sum
Matlab:             0.173543 s    (0.185308 s)
OpenCV @Seven Wang: 0.0145206 s   (0.0155748 s)
OpenCV @Miki:       0.0128943 s   (0.013333 s)

<强>考虑

确保您在OpenCV和Matlab中一致地计算运行时间。

<强>代码

Matlab代码:

tic

folder = 'D:\\SO\\temp\\old_075_6\\';
filenames = dir([folder '*.bmp']);

% Get rows and cols from 1st image
img = imread([folder name]);



S = zeros(size(img));

for ii = 1 : length(filenames)
    name = filenames(ii).name;
    currentImage = imread([folder name]);    
    S = S + double(currentImage);
end

S = uint8(round(S / length(filenames)));

toc

C ++代码:

#include <opencv2\opencv.hpp>
#include <vector>
#include <iostream>

int main()
{
    double ticLoad = double(cv::getTickCount());

    std::string folder = "D:\\SO\\temp\\old_075_6\\*.bmp";
    std::vector<cv::String> filenames;
    cv::glob(folder, filenames);

    int rows, cols;
    {
        // Just load the first image to get rows and cols
        cv::Mat3b img = cv::imread(filenames[0]);
        rows = img.rows;
        cols = img.cols;
    }

    /*{
        double tic = double(cv::getTickCount());

        cv::Mat3d S(rows, cols, 0.0);

        for (const auto& name : filenames)
        {
            cv::Mat currentImage = cv::imread(name);
            currentImage.convertTo(currentImage, CV_64F);

            S += currentImage;

        }
        S = S * double(1.0 / filenames.size());

        cv::Mat3b avg;
        S.convertTo(avg, CV_8U);

        double toc = double(cv::getTickCount());

        double timeLoad = (toc - ticLoad) / cv::getTickFrequency();
        double time = (toc - tic) / cv::getTickFrequency();
        std::cout << "@Seven Wang: " << time << " s (" << timeLoad << " s)" << std::endl;
    }*/

    {
        double tic = double(cv::getTickCount());

        cv::Mat3d S(rows, cols, 0.0);
        cv::Mat3b currentImage;

        for (const auto& name : filenames)
        {
            currentImage = cv::imread(name);
            cv::add(S, currentImage, S, cv::noArray(), CV_64F);
        }
        S /= filenames.size();

        cv::Mat3b avg;
        S.convertTo(avg, CV_8U);

        double toc = double(cv::getTickCount());

        double timeLoad = (toc - ticLoad) / cv::getTickFrequency();
        double time = (toc - tic) / cv::getTickFrequency();
        std::cout << "@Miki: " << time << " s (" << timeLoad << " s)" << std::endl;
    }
    getchar();






    return 0;
}