在 OpenCV 中使用 CV_AA 标志绘制一条线不会产生抗锯齿线

Posted

技术标签:

【中文标题】在 OpenCV 中使用 CV_AA 标志绘制一条线不会产生抗锯齿线【英文标题】:Drawing a line in OpenCV with CV_AA flags is not producing an anti-aliased line 【发布时间】:2012-06-15 17:54:56 【问题描述】:

我无法让 cv::line 绘制一条设置了 CV_AA 标志的抗锯齿线。下面是示例代码来说明:

#include<iostream>
#include<opencv2/opencv.hpp>

using namespace std;

int main(int argc, char* argv[])

    cv::Mat base(100, 100, CV_32F);

    cv::Point2i p1(20, 20);
    cv::Point2i p2(70, 90);

    cv::line(base, p1, p2, cv::Scalar(1.0), 1, CV_AA); // 1 pixel thick, CV_AA == Anti-aliased flag

    cv::namedWindow("line test", CV_NORMAL);
    cv::imshow("line test", base);
    cv::waitKey(0);

    return 0;

我尝试使用 cv::Point2d 代替 cv::Point2i 并没有发现任何区别。 (i == integer, d == double) 我也试过让像素宽度大于1,但还是没有AA。

但是,这确实适用于 CV_8U(8 位无符号)图像,而不是我这里的 CV_32F(32 位浮点)图像。 (对于 CV_8U,您必须将 cv::Scalar(255) 而不是 cv::Scalar(1.0) 传递给 line 函数进行比较)

我想当前的解决方法是从 CV_8U 图像开始然后进行转换,但有没有一种直接的方法可以只使用不需要我编写自己的抗锯齿功能的 CV_32F 图像来实现?

我错过了什么吗?

OpenCV 文档:cv::line reference

【问题讨论】:

这可能是 OpenCV 中的一个问题,但我想指出一段奇怪的代码:您可以将 cv::namedWindow 和 cv::imshow 移到循环外,保持相同的功能速度更快。 啊,是的,好点。我把这个问题放在一起。 其实可以这样写 c = cv::waitKey();返回0;当你按下一个键时,waitKey() 将返回并关闭程序。 是的,但是您无法使用鼠标光标调整图像大小并仔细查看线条。这就是循环背后的目的。另一种方法是使用窗口的线程版本,但我想保持简单。 嗯,我试过了,你仍然可以这样调整窗口大小。所以,你是对的。对于通常将数字 > 0 传递给 cv::waitKey 的其他应用程序,例如显示视频,它不起作用,因为在分配的时间之后没有更多更新。我不记得过去在那里。按照您的建议修改了代码。 【参考方案1】:
./core/src/drawing.cpp:1569
void line( Mat& img, Point pt1, Point pt2, const Scalar& color,
       int thickness, int line_type, int shift )

    if( line_type == CV_AA && img.depth() != CV_8U )
        line_type = 8;
    //omitted

源码说明只要深度不是CV_8U,都会使用8-connected方法绘制。

【讨论】:

那么有什么方法可以在非 CV-8U 图像中使用 CV_AA 吗?【参考方案2】:

你能提供一个示例图像吗?我自己也试过了,这段代码运行得很好:

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

int main(int argc, char *argv[])

  cv::Mat img = cv::Mat::zeros(500, 500, CV_8UC3);

  // red line, which is not anti-aliased
  cv::line(img, cv::Point(100, 100), cv::Point(400, 105), cv::Scalar(0,0,200), 3, 4);  

  // green line, which is not anti-aliased
  cv::line(img, cv::Point(100, 200), cv::Point(400, 205), cv::Scalar(0,200,0), 5, 8);

  // blue line, which is anti-aliased
  cv::line(img, cv::Point(100, 300), cv::Point(400, 305), cv::Scalar(200,0,0), 10, CV_AA);

  cv::namedWindow("drawing", CV_WINDOW_AUTOSIZE|CV_WINDOW_FREERATIO);
  cv::imshow("drawing", img);

  cv::waitKey(0);

这就是我的结果:

【讨论】:

这是一条 AA 线,将基本映像设置为 CV_8U 时得到的结果:imgur.com/4wlea。这是一条非 AA 线,尽管 CV_AA 被传递到 cv::line 函数中,但我在将基本图像设置为 CV_32F 时得到了什么:imgur.com/MSogk。您在示例中使用了 CV_8U 图像。我希望该功能适用​​于 CV_32F。

以上是关于在 OpenCV 中使用 CV_AA 标志绘制一条线不会产生抗锯齿线的主要内容,如果未能解决你的问题,请参考以下文章

在opencv Python中拖动鼠标绘制一条线并获取线的端点坐标

OpenCV:如何绘制一条颜色与其应绘制的表面相反的线?

无法使用 OpenCV2 检测面部标志

详解OpenCV的线段绘制函数line()

如何使用opencv在图像上动态画一条线? [提供的代码,无法找出错误]

如何使用 c++ 在带有 opencv 3.0.0 的视频中画一条线