【问题标题】:OpenCV: Find all non-zero coordinates of a binary Mat imageOpenCV:查找二进制 Mat 图像的所有非零坐标
【发布时间】:2013-10-15 01:53:04
【问题描述】:

我正在尝试查找二进制图像的非零 (x,y) 坐标。

我发现了一些对函数 countNonZero() 的引用,它只计算非零坐标和 findNonZero(),我不确定如何访问或使用它,因为它似乎已从文档中完全删除。

This 是我找到的最接近的参考,但仍然没有任何帮助。如果有任何具体帮助,我将不胜感激。

编辑: - 指定,这是使用C++

【问题讨论】:

标签: c++ opencv image-processing computer-vision computer-science


【解决方案1】:

Here 解释了findNonZero() 如何保存非零元素。以下代码对于访问 二进制 图像的非零坐标应该很有用。方法 1 在 OpenCV 中使用findNonZero(),方法 2 检查每个像素以找到非零(正)像素。

方法一:

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;

int main(int argc, char** argv) {
    Mat img = imread("binary image");
    Mat nonZeroCoordinates;
    findNonZero(img, nonZeroCoordinates);
    for (int i = 0; i < nonZeroCoordinates.total(); i++ ) {
        cout << "Zero#" << i << ": " << nonZeroCoordinates.at<Point>(i).x << ", " << nonZeroCoordinates.at<Point>(i).y << endl;
    }
    return 0;
}

方法二:

#include <iostream>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
using namespace std;
using namespace cv;

int main(int argc, char** argv) {
    Mat img = imread("binary image");
    for (int i = 0; i < img.cols; i++ ) {
        for (int j = 0; j < img.rows; j++) {
            if (img.at<uchar>(j, i) > 0) {  
                cout << i << ", " << j << endl;     // Do your operations
            }
        }
    }
    return 0;
}

【讨论】:

  • 我收到一条错误消息:“findNonZero()”未在此范围内声明。我需要导入什么才能使用此功能?
  • 是的,我已经成功编译并运行了从加载图像、显示窗口到使用 Canny 边缘检测和阈值处理的所有内容。
  • 希望方法2有所帮助!
  • 你的问题的答案很简单,至少需要 OpenCV 2.4.4。
  • 循环顺序应该颠倒:遍历行,然后是列。 OpenCV 的 Mat 容器以行优先顺序存储,因此对列进行迭代对缓存不友好。
【解决方案2】:

有下面的源代码是supplied for OpenCV 2.4.3,可能有帮助:

#include <opencv2/core/core.hpp>
#include <vector>

/*! @brief find non-zero elements in a Matrix
 *
 * Given a binary matrix (likely returned from a comparison
 * operation such as compare(), >, ==, etc, return all of
 * the non-zero indices as a std::vector<cv::Point> (x,y)
 *
 * This function aims to replicate the functionality of
 * Matlab's command of the same name
 *
 * Example:
 * \code
 *  // find the edges in an image
 *  Mat edges, thresh;
 *  sobel(image, edges);
 *  // theshold the edges
 *  thresh = edges > 0.1;
 *  // find the non-zero components so we can do something useful with them later
 *  vector<Point> idx;
 *  find(thresh, idx);
 * \endcode
 *
 * @param binary the input image (type CV_8UC1)
 * @param idx the output vector of Points corresponding to non-zero indices in the input
 */
void find(const cv::Mat& binary, std::vector<cv::Point> &idx) {

    assert(binary.cols > 0 && binary.rows > 0 && binary.channels() == 1 && binary.depth() == CV_8U);
    const int M = binary.rows;
    const int N = binary.cols;
    for (int m = 0; m < M; ++m) {
        const char* bin_ptr = binary.ptr<char>(m);
        for (int n = 0; n < N; ++n) {
            if (bin_ptr[n] > 0) idx.push_back(cv::Point(n,m));
        }
    }
}

注意 - 函数签名似乎有误,因此我将输出 vector 更改为 pass-by-reference。

【讨论】:

  • 这个函数好像没什么用,我的向量pastebin.com/Rznhb4wv
  • 见上面的编辑 - 看起来向量是按值传递的,所以我修改了代码并添加了注释。
  • 它仍然显示为空。我通过使用 coordinates.size() 进行检查,它等于 0。(变量在上面的 pastebin 链接中解释)。
  • @Dmor574 那么也许你没有通过单通道灰度图像?上面的代码假定 CV_8UC1 并且需要更改任何其他内容。如果不是这样,那么您的图像是否真的没有零像素?代码很简单。
  • 我相信它的格式可能不同,但是@WangYudong,他的第二种方法有效(我不确定它是否相关)。
【解决方案3】:

你可以不使用 findNonZero() 这个 opencv 方法找到它。相反,您可以通过简单地使用 2 个 for 循环来获得它。这是sn-p。希望对你有帮助。

**

for(int i = 0 ;i <image.rows() ; i++){// image : the binary image
            for(int j = 0; j< image.cols() ; j++){
                double[] returned = image.get(i,j); 
                int value = (int) returned[0]; 
                if(value==255){
                System.out.println("x: " +i + "\ty: "+j);// returned the (x,y) //co ordinates of all white pixels.
                }
            }

        }

**

【讨论】:

    猜你喜欢
    • 2013-02-20
    • 2020-10-30
    • 2021-09-03
    • 2013-08-07
    • 2014-08-07
    • 2012-01-15
    • 1970-01-01
    • 2012-02-21
    • 1970-01-01
    相关资源
    最近更新 更多