2016-08-09 80 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

对不起,我错误地没有看到上面的函数名称。谢谢 –