I have the following binary image in bitmap extension:
Now I would like to:
I have tried the at
function, image.at<uchar>(i,j)
but did not succeed. Would really appreciate if anyone can help me. Thanks in advance!
Mat image = imread("Before.bmp");
int i=1;
imshow("Before", image);
vector<Point> locations; // output, locations of non-zero pixels
cv::findNonZero(image, locations);
Point pnt = locations[i]; /Assertion error
for (int i = 0; i < image.rows; i++) {
for (int j = 0; j < image.cols; j++) {
if (image.at<uchar>(i,j) == 255 ) {
cout << i << ", " << j << endl; //give wrong coordinate
}
}
}
//imshow("black", image);
//imwrite("blackie.bmp", image);
waitKey(0);
return(0);
You can use cv::findNonZero
to find the coordinates of any non-zero (i.e. not black) pixels. According to the documentation, this function requires the input to be a single channel image, so you need to first convert to grayscale.
In the following example, I work with an assumption that the white lines go all the way from the top to bottom row, and that on there are exactly two of those lines at the top and bottom edge of the image (like on your image). You might want to extend this to be more flexible.
#include <opencv2/opencv.hpp>
int main(int argc, char *argv[])
{
cv::Mat image(cv::imread("foo.png"));
cv::Mat gray;
cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);
std::vector<cv::Point> locations[2];
// Top points
cv::findNonZero(gray.row(0), locations[0]);
// Bottom points (need to offset Y since we take a single row ROI)
cv::findNonZero(gray.row(image.rows - 1), locations[1]);
for (auto& p : locations[1]) {
p.y += image.rows - 1;
}
// Validate our assumption of having exactly two points on both top as well as bottom row
if ((locations[0].size() != 2) && (locations[0].size() != 2)) {
std::cerr << "Unexpected input.\n";
return -1;
}
for (int i(0); i < 2; ++i) {
cv::line(image, locations[0][i], locations[1][i], cv::Scalar(0, 255, 255));
}
cv::imwrite("foo_out.png", image);
}