我有一个cv::Mat
,我想做一些每元素操作。例如,我有一个像cv::Mat m(100,100, CV_64F);
这样的浮点矩阵。我有另一个功能如下:
double fun(double elem);
如何将此函数应用于矩阵,该矩阵可以执行每个元素的操作。
答案 0 :(得分:5)
你可以这样做:
double func(double x)
{
return(sin(x));
}
int main(void)
{
Mat M=Mat::eye(3,3,CV_64FC1);
std::transform(M.begin<double>(),M.end<double>(),M.begin<double>(),func);
cout << M;
getchar();
return 0;
}
答案 1 :(得分:2)
1)检查你的垫子是否连续
if(mat.isContinuous())
2)访问行数据指针并将其转换为double
double* buffer = (double*)mat.data;
// or
double* buffer = mat.ptr<double>(0);
double *bufferEnd = (double*)mat.end;
3)在缓冲区的每个元素上调用你的函数,例如
for (; buffer != bufferEnd; ++buffer)
*buffer = fun(*buffer)
答案 2 :(得分:1)
简单循环怎么样?
cv::Mat m(100, 100, CV_64F);
for(int x=0;x<m.cols;x++)
for(int y=0;y<m.rows;y++)
m.at<double>(y,x) = fun(m.at<double>(y,x));
如果您使用opencv库的发行版,这个速度非常快。如果您可以更改有趣的函数源,它会更改参数本身而不是从函数返回它:
void fun(double &elem);
然后您可以在()调用中省略一个:
cv::Mat m(100, 100, CV_64F);
for(int x=0;x<m.cols;x++)
for(int y=0;y<m.rows;y++)
fun(m.at<double>(y,x));
答案 3 :(得分:0)
为矩阵设计通用的for循环
/**
*@brief apply stl like for_each algorithm on every channels
*
* @param T : the type of the channel(ex, uchar, float, double and so on)
* @param func : Unary function that accepts an element in the range as argument
*
*@return :
* return func
*/
template<typename T, typename UnaryFunc, typename Mat>
UnaryFunc for_each_channels(Mat &&input, UnaryFunc func)
{
int rows = input.rows;
int cols = input.cols;
if(input.isContinuous()){
cols = input.total() * input.channels();
rows = 1;
}
for(int row = 0; row != rows; ++row){
auto begin = input.template ptr<T>(row);
auto end = begin + cols;
while(begin != end){
func(*begin);
++begin;
}
}
return func;
}
按以下方式使用
cv::Mat m(100, 100, CV_64F);
//......initialize m
for_each_channels<double>(m, [](double &a)
{
a = std::sin(a) * 2.14168;;
});
您也可以将api扩展为支持向量类型
for_each<cv::vec3d>(m, [](cv::vec3d& a)
{
a = ..... //do something
});
我已经设计了一些通用api,我将它们放在github