我有一個cv::Mat
,我想做一些元素操作。例如,我有一個浮點矩陣,如cv::Mat m(100,100, CV_64F);
。我有另一個功能如下:每元素操作的Opencv矩陣
double fun(double elem);
如何應用此功能的矩陣,它可以做每元素操作。
我有一個cv::Mat
,我想做一些元素操作。例如,我有一個浮點矩陣,如cv::Mat m(100,100, CV_64F);
。我有另一個功能如下:每元素操作的Opencv矩陣
double 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++)
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));
你可以不喜歡它這樣的:
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)檢查您的墊子是連續
if(mat.isContinuous())
2)訪問的行數據指針,並投它加倍
double* buffer = (double*)mat.data;
// or
double* buffer = mat.ptr<double>(0);
double *bufferEnd = (double*)mat.end;
3)打電話給你的功能上的緩衝液,例如每個ELEM
for (; buffer != bufferEnd; ++buffer)
*buffer = fun(*buffer)
設計一個通用的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
});
我阿里亞dy設計了一些通用api來使用,我把它們放在了github
非常優雅的使用標準庫的解決方案。但是,我想知道它是否真的有效,因爲從舊的實驗來看,MatIterator比直接訪問行數據要慢得多 – remi
@remi但是也許MatIterator的性能取決於你正在使用的庫的類型(調試/發佈) ,就像Mat :: at()方法的情況一樣?我的意思是,在釋放版本中性能相當高。 – marol
@marol我說的是比較性能,使用相同的環境(發佈版本的opencv),btw原始數據和MatIterator。原始數據> Mat.at> MatIterator如果我記得不錯,但不知道什麼是最好的btw mat.at和迭代器。這看起來很正常,因爲mat.at總是計算從矩陣開始的位移,並且注意到mat.isContinuous()不是必需的,MatIterator也是如此。如果你知道你的矩陣是連續的,並且想要最好的處理時間,只需使用原始數據指針 – remi