2016-08-09 78 views
1

我想在特定位置找到非零像素,findNonZero函數,而不是整個Mat。如何在特定區域找到非零像素Mat

在下面張貼的圖片中,我找到了具有findContours功能的白色補丁的細節。稍後,我將bitwise_not函數的圖像反轉爲以下圖像,我需要爲每個白色補丁單獨查找這些黑色圖案的像素位置。 我該怎麼做?對於每個白色補丁應該有一個Mat或陣列與黑色像素座標。

enter image description here

我目前的做法是發現白色斑塊的輪廓,它們每一個都吸引到單獨的墊子。然後,用findNonZero找到白色斑點白色像素的座標,將圖像與黑色圖案混合,然後用for循環檢查現在是白色的像素現在是否是黑色。將這些像素的座標放在列表中,稍後再做其他事情......但這種方法既不聰明又簡單,而且效率不高。

有沒有可能更簡單更有效地做到這一點?像能夠在輪廓內找到nonZero像素?

+0

問題不夠清楚,你能否解釋預期的輸出? – ZdaR

+0

@ZdaR我認爲OP想用Mask來找到非零像素!目前OpenCV不支持此操作的任何掩碼! –

回答

2

嗨,這是一個示例實現!請使用這個!

void findNonZero(InputArray _src, InputArray _Mask, OutputArray _idx) 
{ 
    Mat src = _src.getMat(); 
    Mat msk = _Mask.getMat(); 
    CV_Assert(src.type() == CV_8UC1); 
    CV_Assert(src.size() == msk.size()); 

    int n = countNonZero(src); 
    if(n == 0) 
    { 
     _idx.release(); 
     return; 
    } 
    if(_idx.kind() == _InputArray::MAT && !_idx.getMatRef().isContinuous()) 
     _idx.release(); 
    _idx.create(n, 1, CV_32SC2); 
    Mat idx = _idx.getMat(); 
    CV_Assert(idx.isContinuous()); 
    Point* idx_ptr = idx.ptr<Point>(); 

    for(int i = 0; i < src.rows; i++) 
    { 
     const uchar* bin_ptr = src.ptr(i); 
     const uchar* msk_ptr = msk .ptr(i); 
     for(int j = 0; j < src.cols; j++) 
      if(bin_ptr[j] && msk_ptr[j]) 
       *idx_ptr++ = Point(j, i); 
    } 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    string sFileNameEx="F:\\Balaji\\Image Samples\\Test.jpg"; 
    size_t lastindex = sFileNameEx.find_last_of("."); 
    String sFileName = sFileNameEx.substr(0, lastindex); 
    bool bSaveImages=true; 

    Mat mSrc_Gray,mSrc_Mask,mResult_Bgr; 

    mSrc_Gray= imread(sFileNameEx,0); 
    mSrc_Mask= Mat(mSrc_Gray.size(),CV_8UC1,Scalar(0)); 
    cvtColor(mSrc_Gray,mResult_Bgr,COLOR_GRAY2BGR); 


    if(mSrc_Gray.empty()) 
    { 
     cout<<"[Error]! Invalid Input Image"; 
     return 0; 
    } 

    threshold(mSrc_Gray,mSrc_Gray,10,255,THRESH_BINARY); 
    imshow("mSrc_Gray",mSrc_Gray); 

enter image description here

vector<vector<Point> > contours; 
    vector<Vec4i> hierarchy; 
    /// Find contours 
    findContours(mSrc_Gray.clone(), contours, hierarchy, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE, Point(0, 0)); 

    for(size_t i = 0; i < contours.size(); i++) 
    { 
     if(contourArea(contours[i])>500) 
     { 
      drawContours(mSrc_Mask,contours,i,Scalar(255),-1); 
     }  
    } 

    //May be further Filtering like erode needed? 
    imshow("mSrc_Mask",mSrc_Mask); 

enter image description here

vector<Point> locations; // output, locations of non-zero pixels 

    findNonZero(mSrc_Gray,mSrc_Mask,locations); 

    for(size_t i = 0; i < locations.size(); i++) 
    { 
     circle(mResult_Bgr,locations[i],1,Scalar(0,255,0),1); 
    } 
    imshow("mResult_Bgr",mResult_Bgr); 

enter image description here

waitKey(0); 
    return 0; 
} 
+0

謝謝,但我沒有得到這個:'findNonZero(mSrc_Gray,mSrc_Mask,locations);',因爲在任何文檔和OpenCV for Java中(我用於此任務)沒有找到非標準的函數與樹參數。你如何能夠使用它? –

+0

就像我之前說的! OpenCV沒有用於findNonZero函數的Mask支持!但是實現上面的代碼很容易! –

+0

對不起,我錯誤地沒有看到上面的函數名稱。謝謝 –