基于范围的 for 循环和 std::transform with input/output 迭代器在应用于 opencv Mat(rix) 行时不等效
range-based for loop and std::transform with input/output iterators not equivalent when applied to rows of opencv Mat(rix)
在一个较大的程序中,我遇到了以下问题,我不明白。
基本上,我正在处理一个 float (cv::Mat1f
) 类型的 opencv 矩阵(文档 here)。 OpenCV 提供迭代器来迭代矩阵。当我使用基于范围的迭代器和对矩阵成员的引用遍历矩阵时,代码有效(下面示例中的test1
)。
当我使用 std::transform
并将其应用于 整个 矩阵时,下面的代码 (test3
) 也有效。
但是,当我按行进行迭代时,带有 std::transform
的版本失败(它永远不会(?)终止)。
(我处理行的原因是在实际应用程序中,行是在不同的并行线程中处理的,但这在这里无关紧要)
#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";
}
在我的系统上(在 /usr/local
中安装了 opencv)我 运行 上面的示例代码
g++ -std=c++17 -I/usr/local/include/opencv4 mwe.cpp -L/usr/local/lib -lopencv_core && ./a.out
test2
中的代码有什么问题?
每次调用 row
都会创建一个新对象,并且这些对象具有不同的迭代器。
所以,row(r).begin()
永远不会等于 row(r).end()
.
改为从同一对象获取迭代器:
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; });
}
在一个较大的程序中,我遇到了以下问题,我不明白。
基本上,我正在处理一个 float (cv::Mat1f
) 类型的 opencv 矩阵(文档 here)。 OpenCV 提供迭代器来迭代矩阵。当我使用基于范围的迭代器和对矩阵成员的引用遍历矩阵时,代码有效(下面示例中的test1
)。
当我使用 std::transform
并将其应用于 整个 矩阵时,下面的代码 (test3
) 也有效。
但是,当我按行进行迭代时,带有 std::transform
的版本失败(它永远不会(?)终止)。
(我处理行的原因是在实际应用程序中,行是在不同的并行线程中处理的,但这在这里无关紧要)
#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";
}
在我的系统上(在 /usr/local
中安装了 opencv)我 运行 上面的示例代码
g++ -std=c++17 -I/usr/local/include/opencv4 mwe.cpp -L/usr/local/lib -lopencv_core && ./a.out
test2
中的代码有什么问题?
每次调用 row
都会创建一个新对象,并且这些对象具有不同的迭代器。
所以,row(r).begin()
永远不会等于 row(r).end()
.
改为从同一对象获取迭代器:
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; });
}