2014-05-09 6 views
6

cv :: Mat의 모든 값이 어떤 조건을 만족하면 주어진 값으로 설정하는 간단한 방법이 있습니까? 예를 들어, 내가 CV_32FC1를 가지고 있고, 나는 단순히이 작업을 수행 한 것 MATLAB에서 20 0 모든 값을 설정하려면 :OpenCV cv :: Mat set if

M(M == 0) = 20; 

답변

11

당신은 그러나

cv::Mat mask = M == 0; 
M.setTo(0.5, mask); 

사용할 수 있습니다, 그것은 사용 포함 마스크 생성을위한 추가 메모리가 있지만 opencv API를 사용하는 솔루션이므로 모든 매트릭스 유형에 적용 할 수 있습니다. 성능 문제를 고려한 경우 Mat :: data를 직접 참조하여이 솔루션을 콘크리트 매트릭스 유형에 맞게 최적화 할 수 있습니다.

+0

이것은 매우 강력합니다! 식의 두 번째 부분을 더 복잡하게 만듦으로써 thresholding 등에 사용할 수 있습니다. 문서 또는 튜토리얼에서이를 찾을 수없는 것 같습니다. 우리는 사람들이 그것을 사용하는 것을 알 수 있도록이 게시물을 홍보해야합니다! 불행하게도 복합 표현식에서는 작동하지 않는다. 즉,'cv :: Mat newMask = mask <= 2; '하지만 이것은'cv :: Mat newMask = mask> 2 && mask <5;' –

+0

이 아니다. @DavidDoria 내 마음에 지금 오는 것은 오직 두 개의 추가 임시 마스크, 즉 cv :: Mat maskGreaterThan2 = M> 2를 사용하는 것입니다. cv :: Mat maskLessThan5 = M <5; cv :: Mat mask = massGreaterThan2 & maskLessThan5. 불행히도 이것은 실제로 우리가 여기서 얻는 생산성 향상과 비교할 때 메모리와 시간이 많이 소요됩니다. – marol

2

@marol의 의견에 감사 드리며, 아래 구현을 위해 합의했습니다. C++ 11 람다 함수를 사용하여 어떤 값을 변경해야 하는지를 결정합니다. 그 힘을 설명하기 위해, 내 조건 [MAX_VAL, MIN_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); 
    . 
    . 
    . 
} 
+2

이것은 부분적으로 직접 매트 :: 데이터 액세스라고합니다. 디버그 모드에서 at()을 사용하는 것은 setTo()보다 확실히 느립니다. 따라서 그런 종류의 솔루션을 사용하기로 결정하고 특정 행렬 유형을 사용하는 경우에는 직접 작동하는 구체적인 함수가 아닌 일반적인 템플릿 함수를 사용하지 않는 것이 좋습니다. Mat :: data (opencv 문서에서 "최적화의 조건에 이르면 아무것도 C 배열 연산자 []"를 이길 수 없음) – marol

+0

@marol에게 감사드립니다 ... 두 주석 모두 정말 유용했습니다 :) – ahmadh

3
look-up table

이 클래식 경우이다. 빠르고 간단하며 여러 값을 동시에 재 매핑 할 수 있습니다.

관련 문제