In a larger program, I came across the following problem, which I do not understand.
Basically, I am processing an opencv matrix of type float (cv::Mat1f
) (docs here). OpenCV provides iterators to iterate over a matrix. When I iterate over the matrix using range-based iterators and a reference to the matrix members, the code works (test1
in the example below).
When I use std::transform
and apply it to the entire matrix, the code below (test3
) also works.
However, when I do the iteration row-wise, then the version with std::transform
fails (it never (?) terminates).
(The reason I work on rows is that in the real application rows are processed in different parallel threads, but that is of no concern here)
#include <iostream>
#include "opencv2/imgproc.hpp"
void test1(cv::Mat1f& img) {
for (int r = 0; r < img.rows; r )
for (auto& v : img.row(r))
v = v 1;
}
void test2(cv::Mat1f& img) {
for (int r = 0; r < img.rows; r )
std::transform(
img.row(r).begin(),
img.row(r).end(),
img.row(r).begin(),
[](float v)->float { return v 1; });
}
void test3(cv::Mat1f& img) {
std::transform(
img.begin(),
img.end(),
img.begin(),
[](float v)->float { return v 1; });
}
int main() {
auto img = cv::Mat1f(5, 5, 0.0);
int i = 0;
for (auto &v : img)
v = i ;
std::cerr << img << "\n";
test1(img);
std::cerr << img << "\n";
// test2(img); does not work
test3(img); // works !
std::cerr << img << "\n";
}
On my system (with opencv installed in /usr/local
) I run the example code above with
g -std=c 17 -I/usr/local/include/opencv4 mwe.cpp -L/usr/local/lib -lopencv_core && ./a.out
What is wrong with the code in test2
?
CodePudding user response:
Each call to row
creates a new object, and these objects have distinct iterators.
So, row(r).begin()
will never be equal to row(r).end()
.
Get the iterators from the same object instead:
void test2(cv::Mat1f& img) {
for (int r = 0; r < img.rows; r )
auto row = img.row(r);
std::transform(
row.begin(),
row.end(),
row.begin(),
[](float v)->float { return v 1; });
}