OpenCV: Summe mehrerer Bilder
-
Hallo Zusammen,
ich hätte eine Frage zu OpenCV...
Ich habe ein Feld mit dem Typ Mat mit 256 Einträgen. Diese möchte ich in einer Schleife aufaddieren zu einem Summenbild.
Nachfolgender Code bringt nicht das erhoffte Resultat.
Auch die OpenCV Methode add() hat mir nicht weitegeholfen.Ich danke euch vorab herzlich für eure Tipps und Ratschläge!
Viele Grüßeint z = 0; while (z<=255) { if (z==0) { out = image_array[z]; } else { out += image_array[z]; } z += 1; };
-
Es wäre gut, wenn du auch schreiben würdest, welches Resultat du dir erhoffst und welches du stattdessen tatsächlich erhälst. Dazu wär vielleicht noch ein kompilierbares Minimalbeispiel toll, damit man deinen Fehler nachstellen könnte. (siehe hier: http://www.c-plusplus.net/forum/304133) So kann ich nur ins blaue raten. Aus deinem code geht hervor, dass du sowas versuchst (einfach alle Elemente zu einem Skalar aufaddieren):
#include <opencv2\opencv.hpp> #include <iostream> int main() { cv::Mat m(256, 1, CV_64FC1, cv::Scalar(2)); double sum(0.0); for (int i(0); i < m.rows; ++i ) { sum += m.at<double>(i); } std::cout << sum << "\n"; }
Ein Summenbild (meinst du Integralbild?) ist aber was anderes:
#include <opencv2\opencv.hpp> int main() { const int numRows(256); cv::Mat m(numRows, 1, CV_64FC1, cv::Scalar(2.0)); cv::Mat integralImage(numRows, 1, CV_64FC1, cv::Scalar(0.0)); double sum(0.0); for (int i(0); i < numRows; ++i) { sum += m.at<double>(i); integralImage.at<double>(i) = sum; } std::cout << sum << "\n"; }
-
Dobi, erstmal vielen Dank für Deine Rückmeldung!
Resultat soll ein "Maximumbild" sein. Hintergrund: ich habe 256 Binärbilder. Diese möchte ich zu einem Grauwertbild aufaddieren.Ergänzend zu dem von mir geposteten Code:
"out" ist vom Typ Mat, wie auch die einzelnen Bilder in image_array[].Leider komme ich erst wieder übernächste Woche dazu, mit Deinem Vorschlag rumzutesten. Ich melde mich dann mit dem Feedback.
Viele Grüße und Danke!
-
Hallo Zusammen,
ich bin trotz Dobi's Rückmeldung nicht wirklich weiter gekommen.
Auch der modifizierte Code (s.u.) liefert nicht das gewünschte Resultat.Noch einmal zum Verständnis:
Ich habe 256 Einzelbilder in einem Array vorliegen. Diese Einzelbilder möchte ich über Summenbildung zu einem Gesamtbild fusionieren (pixelweise Aufsummierung).// add images: Mat integralImage = Mat::zeros(rws,cls,CV_64F) ; Mat sum = Mat::zeros(rws,cls,CV_64F); int k = 0; while (k<256) { Mat m; image_array[k].convertTo(m,CV_64F); for (int i=0; i < rws; i++) { for(int j=0; j<cls; j++) { sum.at<double>(i,j) += m.at<double>(i,j); integralImage.at<double>(i,j) = sum.at<double>(i,j); } }; k = k+1; };
Ich danke vielmals vorab für Eure Vorschläge!
-
mark81 schrieb:
ich bin trotz Dobi's Rückmeldung nicht wirklich weiter gekommen.
Auch der modifizierte Code (s.u.) liefert nicht das gewünschte Resultat.Welches Resultat liefert er denn? Mit "funktioniert nicht" kann keiner was anfangen.
-
Ich rate einfach mal ins Blaue.
Willst du das?
#include <opencv2/opencv.hpp> #include <iostream> #include <vector> #include <algorithm> int main() { // Drei Bilder a 2*2 Pixel. Du kannst natuerlich auch 256 Bilder in den Vector pappen. ;) std::vector<cv::Mat> images; images.push_back(cv::Mat(2, 2, CV_64FC1, cv::Scalar(1))); images.push_back(cv::Mat(2, 2, CV_64FC1, cv::Scalar(2))); images.push_back(cv::Mat(2, 2, CV_64FC1, cv::Scalar(3))); // Ein paar Pixel anders setzen, damit das Ergebnis interessanter wird. images.at(0).at<double>(0, 0) = 4; images.at(0).at<double>(1, 1) = 5; images.at(1).at<double>(1, 1) = 6; // Summenbild mit Nullen vorinitialisieren. cv::Mat sum(2, 2, CV_64FC1, cv::Scalar(0)); // Alle Bilder pixelweise aufaddieren. std::for_each(std::begin(images), std::end(images), [&](const cv::Mat& image) { for (int i(0); i < image.rows; ++i ) for (int j(0); j < image.cols; ++j ) sum.at<double>(i, j) += image.at<double>(i, j); }); // Quellbilder ausgeben. std::for_each(std::begin(images), std::end(images), [&](const cv::Mat& image) { std::cout << image << "\n"; }); // Summenbild ausgeben. std::cout << "Summenbild: " << sum << "\n"; }
Ausgabe:
[4, 1; 1, 5] [2, 2; 2, 6] [3, 3; 3, 3] Summenbild: [9, 6; 6, 14]
-
Hallo Zusammen,
vielen Dank Dobi, das hat mir weitergeholfen.
Darüber hinaus habe ich noch herausgefunden, wie es kürzer geht (OpenCv Methode add):while (k<256) { image_array[k].convertTo(m,CV_64F); image_array[k+1].convertTo(m2,CV_64F); add(m,m2,sum_image); k = k+1; };
Nochmals vielen Dank und Grüße!
-
Jupp, und noch kürzer geht's mit dem überladenen operator+. In meinem Beispiel sieht's damit so aus:
std::for_each(std::begin(images), std::end(images), [&](const cv::Mat& image) { sum += image; });
Du wandelst übrigens jedes Bild zwei mal nach CV_64F um. Das stört die Funktionalität zwar nicht, verschwendet aber Rechenzeit und finde ich persönlich nicht besonders elegant.
-
Dobi schrieb:
Jupp, und noch kürzer geht's mit dem überladenen operator+. In meinem Beispiel sieht's damit so aus:
std::for_each(std::begin(images), std::end(images), [&](const cv::Mat& image) { sum += image; });
Das ist
std::accumulate()
aus<algorithm>
-
accumulate() schrieb:
Das ist
std::accumulate()
aus<algorithm>
Aus <numeric>, nicht aus <algorithm>.
Ansonsten hast du natürlich vollkommen recht.@mark81: So dann also mit maximaler Hübschizität:
#include <opencv2/opencv.hpp> #include <iostream> #include <vector> #include <algorithm> #include <numeric> int main() { // Drei Bilder a 2*2 Pixel. Du kannst natuerlich auch 256 Bilder in den Vector pappen. ;) std::vector<cv::Mat> images; images.push_back(cv::Mat(2, 2, CV_64FC1, cv::Scalar(1))); images.push_back(cv::Mat(2, 2, CV_64FC1, cv::Scalar(2))); images.push_back(cv::Mat(2, 2, CV_64FC1, cv::Scalar(3))); // Ein paar Pixel anders setzen, damit das Ergebnis interessanter wird. images.at(0).at<double>(0, 0) = 4; images.at(0).at<double>(1, 1) = 5; images.at(1).at<double>(1, 1) = 6; // Alle Bilder pixelweise aufaddieren. cv::Mat sum(std::accumulate(std::begin(images), std::end(images), cv::Mat(2, 2, CV_64FC1, cv::Scalar(0)))); // Quellbilder ausgeben. std::for_each(std::begin(images), std::end(images), [&](const cv::Mat& image) { std::cout << image << "\n"; }); // Summenbild ausgeben. std::cout << "Summenbild: " << sum << "\n"; }