【问题标题】:How to find nonzero pixels in specific territory in Mat如何在 Mat 的特定区域中找到非零像素
【发布时间】:2016-08-09 17:57:21
【问题描述】:

我想在特定位置找到具有findNonZero 函数的非零像素,而不是整个 Mat。

在下面发布的图片中,我找到了具有findContours 功能的白斑区域。后来,我用bitwise_not 函数反转下面发布的图像,我需要为每个白色块分别找到那些黑色图案的像素位置。 我该怎么做?对于每个白色补丁,都应该有一个带有黑色像素坐标的 Mat 或 Array。

我目前的方法是找到白色斑块的轮廓并将它们全部绘制到单独的 Mats 中。然后,用findNonZero找到白块白色像素的坐标,将图像与黑色图案混合,用for循环检查像素,原来是白色的,现在是黑色的。把这些像素的坐标放到一个List中,以后再做其他的事情……但是这种方法既不聪明也不简单,效率也不高。

有没有可能更简单、更高效地完成它?喜欢在轮廓内找到nonZero 像素?

【问题讨论】:

  • 问题不够清楚,你能详细说明预期的输出吗?
  • @ZdaR 我认为 OP 想要使用 Mask 查找非零像素!目前OpenCV不支持此操作的任何Mask!

标签: opencv math image-processing matrix computer-vision


【解决方案1】:

您好,这是一个示例实现!请使用这个!

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);

    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);

    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);

    waitKey(0);
    return 0;
}

【讨论】:

  • 谢谢,但我没有得到这个:findNonZero(mSrc_Gray,mSrc_Mask,locations);,因为在任何文档和 Java 的 OpenCV(我确实用于此任务)中没有找到非零的函数树参数。你怎么能用这个?
  • 就像我之前说的! OpenCV 没有对 findNonZero 函数的 Mask 支持!但是很容易实现像上面的代码一样!
  • 对不起,我错误地没有看到上面的函数名。谢谢
猜你喜欢
  • 2018-07-04
  • 1970-01-01
  • 2021-12-09
  • 2018-11-30
  • 2020-10-30
  • 1970-01-01
  • 1970-01-01
  • 2019-12-07
  • 1970-01-01
相关资源
最近更新 更多