2017-09-21 28 views
1

我的標題可能不夠清晰,但請仔細看下面的描述。提前感謝。Opencv obatin基於mask的某個像素RGB值

我有一個RGB圖像和二值遮掩圖像:

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

給予一定的人的面具,承擔者的數量是N.現在非零座標是已知的,基於這些座標,我們可以確保獲得原產image.I的對應像素的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++; 
     } 
    } 
} 

而且COORDS將如下: enter image description here

但是,這兩層for循環花費了太多時間。我想知道是否有更快的方法來抑制顏色,希望你們能理解我想表達的內容。

PS:如果我可以使用Python,這隻能在一個句子來完成:

colors = img[mask == 1] 
+0

爲什麼當你沒有存儲座標時,目標'Mat'稱爲'coords',而是來自輸入圖像的像素值? |此外,該Python代碼不正確,numpy數組不可調用。你的意思是'img [mask == 1]'?此外,它也不會生成一個座標列表。 –

+0

謝謝你的友善提醒:) – Terry

回答

1

如果您是使用使用C++的任何其他開放源碼庫靈活,嘗試Armadillo。您可以使用它進行所有線性代數運算,並且還可以將上面的代碼減少到一行(類似於您的Python代碼段)。

或者

嘗試findNonZero()功能,發現在含非零值圖像所有的座標。請檢查:https://stackoverflow.com/a/19244484/7514664

+0

findNonZero(mask,nonzeroCoordinates); int counter = 0; 對(INT I = 0; I (計數器,0)= img.at (nonzeroCoordinates.at (ⅰ).X,nonzeroCoordinates.at (i).y)[0]; \t coords.at (counter,1)= img。(i).y)[1]; (nonzeroCoordinates.at (i).x,nonzeroCoordinates.at (i).y)[1]; (2)= img.at (nonzeroCoordinates.at (i).x,nonzeroCoordinates.at (i).y)[2]; \t counter ++; } – Terry

+0

我不知道上面的方法可以加快我的程序... – Terry

+0

嘗試使用Armadillo庫然後。我使用過犰狳來進行這樣的操作,與OpenCV相比,它的速度相對較快。 – Jazz

1

.at()方法是訪問C++中的Mat值最慢的方法。最快的是使用指針,但最佳做法是迭代器。參見OpenCV tutorial on scanning images

請注意,雖然Python的語法對於類似的東西來說很好,但它仍然需要在一天結束時循環所有元素---並且由於在此之前它有一些開銷,事實上比帶指針的C++循環慢。你必須循環遍歷所有的元素,而不管你的圖書館是什麼,你正在與每個元素的面具進行比較。

+0

我想我沒有弄清楚......如果掩模矩陣很稀疏會怎麼樣?你將花費很多時間遍歷矩陣。一些退出的函數可能有修改後的算法來處理這種情況,這正是我試圖找到的。 – Terry

+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 –