2014-06-17 3 views
1

나는 cv::Mat을 가지고 있으며 요소 별 작업을 일부 수행하려고합니다. 예를 들어 float 행렬이 cv::Mat m(100,100, CV_64F);입니다. 다음과 같은 또 다른 함수가 있습니다 :요소 당 Opencv 행렬

double fun(double elem); 

이 함수를 요소별로 수행 할 수있는 행렬에 적용하는 방법.

답변

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 라이브러리의 릴리스 버전을 사용하면 꽤 빠릅니다. 당신이이 기능을 형성 반환하는 대신 인수 자체를 변경 재미있는 기능의 소스를 변경할 수있는 경우 :

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)); 
5

당신은처럼 작업을 수행 할 수 있습니다

void fun(double &elem); 

그런 다음() 호출 하나를 생략 할 수 있습니다 이 :

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; 
} 
+0

매우 우아한 솔루션을 표준 라이브러리를 사용하여. 그러나 오래된 실험에서 MatIterator가 행 데이터에 직접 액세스하는 것보다 훨씬 느리기 때문에 – remi

+0

@remi하지만 MatIterator 성능은 사용중인 라이브러리 유형 (디버그/릴리스)에 따라 달라 지므로 성능면에서 정말 효율적인지 궁금합니다. Mat :: at() 메서드의 경우와 마찬가지로? 제 말은, realease 버전의 성능이 상당히 높음을 의미합니다. – marol

+0

@marol 필자는 동일한 환경 (opencv의 릴리스 버전), 원시 데이터 및 MatIterator를 사용하여 비교 공연을 이야기했습니다. raw data> Mat.at> MatIterator를 잘 기억하고 있지만, 최상의 btw mat.at 및 iterator가 무엇인지 확실하지 않습니다. mat.at는 항상 행렬의 시작 부분에서 시프트를 계산하고 mat.isContinuous()가 필요하지 않으며 MatIterator도 마찬가지이기 때문에 이는 매우 정상적인 것처럼 보입니다. 행렬이 연속적이며 최적의 처리 시간을 원한다면 원시 데이터 포인터를 사용하십시오 – remi

2

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) 
0

디자인 매트릭스에 대한 루프에 대한 일반적인

/** 
*@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; 
} 

당신은 벡터 형식도

for_each<cv::vec3d>(m, [](cv::vec3d& a) 
{ 
    a = ..... //do something 
}); 

을 지원하기 위해 API를 확장 할 수

cv::Mat m(100, 100, CV_64F); 
//......initialize m 
for_each_channels<double>(m, [](double &a) 
{ 
    a = std::sin(a) * 2.14168;; 
}); 

를 다음과 같이 사용 나야 디 일반 API를 사용하여 디자인, 나는 그들을 넣어 github