Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

OpenCV: Find all non-zero coordinates of a binary Mat image

Tags:

I'm atttempting to find the non-zero (x,y) coordinates of a binary image.

I've found a few references to the function countNonZero() which only counts the non-zero coordinates and findNonZero() which I'm unsure how to access or use since it seems to have been removed from the documentation completely.

This is the closest reference I found, but still not helpful at all. I would appreciate any specific help.

Edit: - To specify, this is using C++

like image 983
DMor Avatar asked Oct 08 '13 08:10

DMor


2 Answers

Here is an explanation for how findNonZero() saves non-zero elements. The following codes should be useful to access non-zero coordinates of your binary image. Method 1 used findNonZero() in OpenCV, and Method 2 checked every pixels to find the non-zero (positive) ones.

Method 1:

#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; } 

Method 2:

#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; } 
like image 67
WangYudong Avatar answered Sep 22 '22 06:09

WangYudong


There is the following source code that was supplied for OpenCV 2.4.3, which may be helpful:

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

Note - it looks like the function signature was wrong so I've changed the output vector to pass-by-reference.

like image 20
Roger Rowland Avatar answered Sep 25 '22 06:09

Roger Rowland