2017-09-21 1 views
1

제목이 명확하지 않을 수 있지만 다음 설명을주의 깊게 살펴보십시오. 미리 감사드립니다.Opencv obatin 특정 픽셀 마스크를 기반으로 한 RGB 값

은 내가 RGB 이미지와 바이너리 마스크 이미지가 있습니다

Mat img = imread("test.jpg") 
Mat mask = Mat::zeros(img.rows, img.cols, CV_8U); 

은, 마스크에 어떤 사람을 지정 사람의 수는이 좌표를 기반으로, N. 이제 제로가 아닌 좌표를 알고 가정을, 우리 확실히 원래 어 이미지의 대응하는 픽셀의 RGB 값을 얻을 수있는이 다음과 같은 코드에 의해 수행 될 수 알고

Mat colors = Mat::zeros(N, 3, CV_8U); 
int counter = 0; 
for (int i = 0; i < mask.rows; i++) 
{ 
    for (int j = 0; j < mask.cols; j++) 
    { 
     if (mask.at<uchar>(i, j) == 1) 
     { 
      colors.at<uchar>(counter, 0) = img.at<Vec3b>(i, j)[0]; 
      colors.at<uchar>(counter, 1) = img.at<Vec3b>(i, j)[1]; 
      colors.at<uchar>(counter, 2) = img.at<Vec3b>(i, j)[2]; 
      counter++; 
     } 
    } 
} 

다음과 같은 좌표가 될 것이다 enter image description here

,617,

그러나 for 루프의이 두 계층에는 너무 많은 시간이 걸립니다. 색상을 알아내는 더 빠른 방법이 있는지 궁금 해서요. 사람들이 제가 전달하려고 한 것을 이해할 수 있기를 바랍니다.

PS : 나는 파이썬을 사용할 수 있다면, 이것은 단지 한 문장으로 수행 할 수 있습니다 : 당신이 C++를 사용하는 다른 오픈 소스 라이브러리를 사용하여 유연 경우, Armadillo을 시도

colors = img[mask == 1] 
+0

대상 '매트'는 좌표를 저장하지 않고 '입력'이미지의 픽셀 값을 '좌표'라고 부르는 이유는 무엇입니까? | 또한, 그 파이썬 코드가 정확하지, numpy 배열 호출 할 수 없습니다. 'img [mask == 1]'을 의미 했습니까? 또한 좌표 목록도 생성하지 않습니다. –

+0

친절하게 상기시켜 주셔서 감사합니다 :) – Terry

답변

1

. 모든 선형 대수 연산을 수행 할 수 있으며 위 코드를 한 줄로 줄일 수도 있습니다 (파이썬 코드 조각과 유사 함).

또는

findNonZero() 기능을 사용해보십시오 0이 아닌 값을 포함하는 이미지의 모든 좌표를 찾을 수 있습니다. 이것을 확인하십시오 : https://stackoverflow.com/a/19244484/7514664

+0

findNonZero (mask, nonzeroCoordinates); int counter = 0; { \t coords.at (계수, 0) = img.at (nonzeroCoordinates.at (I) .x를, nonzeroCoordinates.at위한 는 (; 나는 nonzeroCoordinates.total()은 (i) .y) [0]; \t coords.at (counter, 1) = img. (nonzeroCoordinates.at (i) .x, 0zeroCoordinates.at (i) .y) [1]; \t coords.at (카운터, 2) = img.at (nonzeroCoordinates.at (i) .x, nonzeroCoordinates.at (i) .y) [2]; \t 카운터 ++; } – Terry

+0

위의 방법으로 내 프로그램의 속도를 높일 수 있는지 모르겠습니다 ... – Terry

+0

그러면 Armadillo 라이브러리를 사용해보십시오. 나는 이러한 작업을 위해 Armadillo를 사용했으며 OpenCV에 비해 비교적 빠릅니다. – Jazz

1

.at() 방법은 C++에서 Mat 값에 액세스하는 가장 느린 방법입니다. 포인터를 사용하는 것이 가장 빠르지 만 모범 사례는 반복자입니다. OpenCV tutorial on scanning images을 참조하십시오.

파이썬 구문이 이런 식으로 멋지더라도, 하루가 끝날 때 모든 요소를 ​​반복해야합니다. 그리고이 전에 약간의 오버 헤드가 있기 때문에, 포인터로 C++ 루프보다 사실상 느립니다. 라이브러리에 관계없이 모든 요소를 ​​반복해야 할 필요가 있습니다. 모든 요소에 대한 마스크와 비교할 수 있습니다.

+0

나는 그것을 분명하게 만들지 않았다고 생각합니다 ... 마스크 매트릭스가 희박한 경우에는 어떨까요? 행렬 탐색에 많은 시간을 할애 할 것입니다. 일부 기존 함수는이 상황을 처리하기 위해 수정 된 알고리즘을 가질 수 있습니다. 이는 내가 찾고자하는 것입니다. – Terry

+0

스파 스 매트릭스는 다르게 저장되며, 0이 아닌 요소는 인덱스와 함께 저장되므로 인덱스로 만 인덱스 할 수 있습니다. 색인 생성을 위해 드문 드문 한 행렬을 원한다면 색인 행렬을 만들어 색인 생성에 사용하십시오. 일반적인 마스크는 스파 스 매트릭스로 저장되지 않습니다. 마스크에서 희소 행렬을 만들려는 경우에는 마스크를 반복 작성해야합니다. –

+0

마스크를 만드는 방법에 대해 걱정하지 마십시오. 이미 존재한다고 가정하십시오. – Terry

0

컴파일 최적화가 활성화와 함께,이 버전을 프로파일 링하려고하고 빠른 경우 우리에게 : 당신이 색상의 크기를 알고있는 경우

vector<Vec3b> colors; 
if (img.isContinuous() && mask.isContinuous()) { 
    auto pimg = img.ptr<Vec3b>(); 
    for (auto pmask = mask.datastart; pmask < mask.dataend; ++pmask, ++pimg) { 
     if (*pmask) 
      colors.emplace_back(*pimg); 
    } 
} 
else { 
    for (int r = 0; r < img.rows; ++r) { 
     auto prowimg = img.ptr<Vec3b>(r); 
     auto prowmask = img.ptr(r); 
     for (int c = 0; c < img.cols; ++c) { 
      if (prowmask[c]) 
       colors.emplace_back(prowimg[c]); 
     } 
    } 
} 

는, 미리위한 공간을 보유하고 있습니다.

+0

당신의 버전을 시험해 보았습니다 만 for 루프를 사용하여 (int i = 0; i Terry

+0

어떻게 확인 했습니까? 시도해 본 결과 코드와 동일한 결과를 얻었습니다. 여기에서 일련의 테스트를 찾을 수 있습니다. https://ideone.com/1nJuBV –

관련 문제