2016-06-10 12 views
1

Ich bin total überrascht von all Ihren Antworten. Vielen Dank!Effizienz der Summierung von Bildern mit MATLAB und OpenCV

Der Fehler-Code wird wie folgt gezeigt: percentage = (double)kk * 100.0/(double)totalnum;

Nachdem ich es geändert zu: percentage = (double)kk * 100.0/totalnum;

das Problem gelöst ist. Und diese einfache Teilung verbrauchte etwa 90 von 150. Vielleicht Division zwischen Doppel und Int ist schneller als es zwischen verdoppelt.

Nochmals vielen Dank für Ihre Antworten!


Ich versuche, das durchschnittliche Bild von einer Reihe von Bildern zu bekommen, die von einem Video kommen. Es gibt nur 2 Schritte für diesen Job:

  1. Summieren Sie alle Bilder in eine Matrix.
  2. Teilen Sie die Matrix nach der Anzahl der Bilder.

habe ich folgenden Code in 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' 

Und folgenden Code in 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 

Aber wenn ich die beiden Programme auf 2.100 Bilder laufen, OpenCV nahm 150,3s (Release) und MatLab nahm 103.1s. Es hat mich wirklich verwirrt, dass ein C++ Programm langsamer als ein MatLab Skript läuft.

Also was verlangsamt mein OpenCV-Programm? Wenn es durch meine Methode des Matrixzugriffs verursacht wird, was sollte ich tun, um die Effizienz zu verbessern?

+0

1. ist es möglich, dass Sie in den Debug-Modus statt Freigabemodus laufen in Visual Studio? ändere es in den Freigabemodus und starte das Programm mit Strg + F5 2. Ist die Konvertierung in float notwendig? kannst du ursprünglich bei float lesen? – drorco

+0

1. Ja, es ist ein Freigabemodus. 2. In der Tat, ich verwandle nur jemandes Code in C++ und ich sah, dass es eine (doppelte) vor IM gibt. Also ich denke, ich brauche eine float-artige Matrix zum Summieren dieser Bilder. –

+0

Ein anderes mögliches Problem: Wo sind Ihre Bilder? ist es möglich, dass sie sich auf einer externen Festplatte befinden? – drorco

Antwort

0

Ihr Code scheint gut genug zu sein, und in meinen Tests habe ich festgestellt, dass er 10 mal schneller läuft als Matlab-Code.

Allerdings zeige ich einen leicht optimierten Code, der ein wenig schneller ist als deins.

Hinweise

Bitte beachten Sie, dass ich nicht habe einen Ordner mit Bildern, wie Sie genannt, so habe ich cv::glob in C++ Version und dir in Matlab-Version, die Namen der Bilder im Ordner zu erhalten .

In meinem Ordner habe ich 82 kleine Bilder, so ist die Laufzeit offensichtlich kleiner als bei Ihnen, aber die relative Leistung sollte zuverlässig sein.

Ausführungszeit

    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) 

Überlegungen

Seien Sie sicher, dass Sie die Laufzeit konsequent in OpenCV und Matlab sind zu berechnen.


-Code

Matlab-Code:

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++ Code:

#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; 
} 
+0

OMG, danke für deine Analyse! Aber leider ist es total meine Schuld, die ich bei meiner Frage nicht gepostet habe: prozentual = (double) kk * 100,0/(double) totalnum; 'Dies ist der Fehlercode, der meine Zeit verbraucht hat. Nach dem Ändern in% (= doppelt) kk * 100,0/totalnum; 'ist das Problem vollständig gelöst. Wie auch immer, ich werde deinen Code studieren. Nochmals vielen Dank! –

0

Ein Punkt, der meine Aufmerksamkeit auf sich zog, ist der Typ "CV_32FC3". Ziehen Sie die 32-Bit-Float-Matrix besonders vor und sind Sie sicher, dass Matlab auch die Pixelwerte auf die gleiche Weise erhält?

Weil Sie, dass zusätzlicher Schritt

tempIM.convertTo(tempIM, CV_32FC3);  

in Ihrem Cpp-Code, wo Matlab arbeitet direkt, sobald er das Bild abruft ohne Konvertierung, die Ihren CPP Code könnte verlangsamen. Wenn Matlab das Bild nicht in Gleitkommawerten erhält, trägt dies möglicherweise zur Geschwindigkeitsdifferenz bei, da Gleitpunktarithmetik im Vergleich zu Ganzzahlen eine schwierigere Aufgabe für die CPU ist.

+0

Das ist ein Punkt. Aber im MatLab-Code gibt es auch einen zusätzlichen Schritt: 'avIM = avIM + double (IM);' –

+0

Welchen Schritt meinen Sie? –

+0

Entschuldigung, ich bin ein neuer Benutzer hier, ich bin verwirrt mit Mini-Markdown-Formatierung. Was ich meine, ist das ** double() ** in Zeile 5, das auch eine Umwandlung vornimmt. –

Verwandte Themen