【问题标题】:Obtaining coordinate of the top and bottom white pixels in order to draw a line获取顶部和底部白色像素的坐标以绘制一条线
【发布时间】:2017-02-08 08:29:30
【问题描述】:

我在位图扩展中有以下二进制图像:

现在我想:

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

【问题讨论】:

  • 尝试切换ij,比如image.at&lt;uchar&gt;(j,i)
  • 嗨@JeruLuke,感谢您的快速回复。不幸的是,这也没有奏效。我当前的代码使用 image.at(i,j) 或 (j,i) 没有输出正确的白色像素坐标。你知道是什么原因造成的吗?
  • cv::findNonZero 怎么样?您可能只在第一行和最后一行运行它。
  • 欢迎来到 Stack Overflow!请edit您的问题显示what you have tried so far。您应该包含您遇到问题的代码的minimal reproducible example,然后我们可以尝试帮助解决具体问题。您还应该阅读How to Ask
  • @DanMašek 它输出错误:在 cv::findNonZero 中断言失败 (src.type() == CV_8UC1)。会不会是因为图片是位图扩展的?

标签: c++ opencv bitmap coordinate


【解决方案1】:

您可以使用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);
}

示例输出

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-04-30
    • 2018-01-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多