【发布时间】:2014-06-27 16:58:14
【问题描述】:
如果满足某些条件,是否有一种简单的方法可以将 cv::Mat 中的所有值设置为给定值。例如,我有 CV_32FC1,我想将所有值设置为 0 到 20。在 MATLAB 中我会简单地这样做:
M(M == 0) = 20;
【问题讨论】:
如果满足某些条件,是否有一种简单的方法可以将 cv::Mat 中的所有值设置为给定值。例如,我有 CV_32FC1,我想将所有值设置为 0 到 20。在 MATLAB 中我会简单地这样做:
M(M == 0) = 20;
【问题讨论】:
你可以使用
cv::Mat mask = M == 0;
M.setTo(0.5, mask);
但是,它包括使用额外的内存来创建掩码,但它是使用 opencv API 的解决方案,因此可以应用于所有矩阵类型。如果您考虑性能问题,您始终可以直接参考 Mat::data 以针对具体矩阵类型优化此解决方案。
【讨论】:
cv::Mat newMask = mask <= 2; 但这不适用于cv::Mat newMask = mask > 2 && mask < 5;
(mask > 2) & (mask < 5)
这是look-up table 的经典案例。它快速、简单,并且可以同时重新映射多个值。
【讨论】:
感谢@marol 的 cmets,我选择了下面的实现。我正在使用 C++11 lambda 函数来确定需要更改哪些值。为了展示它的强大,我的条件是当值超出范围[MIN_VAL,MAX_VAL]时设置为DEFAULT_VAL:
#include <functional>
#define MatType float
#define MatCmpFunc std::function<bool(const MatType&)>
.
.
.
// function which accepts lambda function to condition values which need to
// be changed
void MatSetIf(cv::Mat& inputmat, const MatType& newval, MatCmpFunc func) {
float* pmat = (float*)inputmat.data;
// iterate and set only values which fulfill the criteria
for (int idx = 0; idx < inputmat.total(); ++idx) {
if (func(pmat[idx])) {
pmat[idx] = newval;
}
}
}
.
.
.
void main() {
cv::Mat mymat(100,100,CV_32FC1);
const float MIN_VAL = 10;
const float MAX_VAL = 1000;
const float DEFAULT_VAL = -1;
.
.
.
// declare lambda function which returns true when mat value out of range
MatCmpFunc func = [&](const DepthMatType& val) -> bool {
return (val < MIN_VAL || val > MAX_VAL) ? true : false;
};
// use lambda func above to set all out of range values to 50
Mat32FSetIf(mymat, DEFAULT_VAL, func);
.
.
.
}
【讨论】: