Получение координат верхнего и нижнего белых пикселей для рисования линии

У меня есть следующее двоичное изображение в растровом расширении:

введите описание изображения здесь

Теперь я хотел бы:

  1. Получить координаты верхнего и нижнего белого пикселя (синяя метка)
  2. Нарисуйте линию (желтую линию), пересекающую эти две координаты (что-то вроде следующего изображения)

введите описание изображения здесь

Я попробовал at функция, image.at<uchar>(i,j) но не удалось. Буду очень признателен, если кто-нибудь может мне помочь. Заранее спасибо!

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

2

Решение

Ты можешь использовать cv::findNonZero найти координаты любых ненулевых (т.е. не черных) пикселей. Согласно документации, эта функция требует, чтобы входное изображение было одноканальным, поэтому сначала необходимо преобразовать его в оттенки серого.

В следующем примере я работаю с предположением, что белые линии проходят от верхнего до нижнего ряда, и что на верхнем и нижнем краях изображения ровно две из этих линий (как на вашем изображении) , Возможно, вы захотите расширить это, чтобы быть более гибким.

Пример кода

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

Пример вывода

введите описание изображения здесь

0

Другие решения

Других решений пока нет …