结合这两个答案并根据您得到的垫子类型(此处为 CV_64F):
bool findValue(const cv::Mat &mat, double value) {
for(int i = 0;i < mat.rows;i++) {
const double* row = mat.ptr<double>(i);
if(std::find(row, row + mat.cols, value) != row + mat.cols)
return true;
}
return false;
}
(请参阅find docs 了解更多信息)。当然,首先将 mat 行转换为向量,然后在该向量上使用 std::find 比直接在指向行数组的指针上使用 find 慢。
编辑:经过更多研究,开发通用版本并不难:
template <class T>
bool findValue(const cv::Mat &mat, T value) {
for(int i = 0;i < mat.rows;i++) {
const T* row = mat.ptr<T>(i);
if(std::find(row, row + mat.cols, value) != row + mat.cols)
return true;
}
return false;
}
我在更复杂的数据类型上对其进行了测试:
cv::Mat matDouble = cv::Mat::zeros(10, 10, CV_64F);
cv::Mat matRGB = cv::Mat(10, 10, CV_8UC3, cv::Scalar(255, 255, 255));
std::cout << findValue(matDouble, 0.0) << std::endl;
std::cout << findValue(matDouble,1.0) << std::endl;
std::cout << findValue(matRGB, cv::Scalar(255, 255, 255)) << std::endl;
std::cout << findValue(matRGB, cv::Scalar(255, 255, 254)) << std::endl;
令我惊讶的输出是:
1
0
0 // should be 1, right?
0
问题在于 cv::Scalar 大小结构。无论我们使用的是什么版本的构造函数(即一个、两个、三个或四个参数),大小都是……常量。这并不奇怪,因为这仍然是相同的结构,在我的机器上大小是 32 字节(默认情况下 cv::Scalar 是双精度类型,所以在我的机器上双精度是 8 字节和 4 * 8 = 32)。所以查找出错了,因为它假定数组中元素的大小为 32 个字节,它应该是 3 个字节。
所以不要将 std::find 与 cv::Scalar 一起使用! 但是它可以很好地和高效地处理原始数据类型。
EDIT2(在 berak 的评论之后):
是的,您可以将 cv::Vec3b 与 find 一起使用,它似乎运行良好,尽管它没有做更多的测试,只是简单地正确测试:
cv::Mat matRGB = cv::Mat(10, 10, CV_8UC3, cv::Scalar(255, 255, 255));
std::cout << findValue(matRGB, cv::Vec3b(255, 255, 255)) << std::endl;
std::cout << findValue(matRGB, cv::Vec3b(255, 255, 254)) << std::endl;
(您仍然必须在 Mat 构造函数中使用 Scalar,但这并不重要,并且 Mat 已正确初始化)。现在输出如预期:
1
0