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



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

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

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

问题解决了。这个简单的划分消耗了150年代中的90年代。也许doubleint之间的除法比duples更快。

再次感谢您的回答!


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

  1. 将所有图像求和为矩阵
  2. 将矩阵除以图像数

我在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

但当我在2100张图片上运行这两个程序时,OpenCV花了150.3s(发布),MatLab花了103.1s。C++程序比MatLab脚本运行得慢,这让我很困惑。

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

您的代码似乎已经足够好了,在我的测试中,我发现它的运行速度是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 <opencv2opencv.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;
}

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

因为你有额外的步骤

tempIM.convertTo(tempIM, CV_32FC3);     

在您的Cpp代码中,Matlab在检索图像时直接操作,而无需任何转换,这可能会减慢您的Cpp代码。此外,如果Matlab没有以浮点值获取图像,这可能会导致速度差,因为与整数相比,浮点算法对CPU来说是一项更难处理的任务。

最新更新