在OpenCV中使用CV_AA标志绘制直线时,未生成抗锯齿直线。

10

我无法使用CV_AA标志使cv::line绘制抗锯齿线。以下是示例代码:

#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)传递到线函数中进行比较)
我想目前的解决方法是从CV_8U图像开始转换,但是否有一种简单的方法可以只使用CV_32F图像来完成,而不需要编写自己的抗锯齿功能?
我错过了什么吗?
OpenCV文档:cv :: line reference

1
可能是OpenCV的问题,但我想指出一个奇怪的代码片段:你可以将cv::namedWindow和cv::imshow移动到循环外部,保持相同的功能,以获得更好的速度。 - Sam
啊,是的,说得好。我只是为了回答问题而匆忙拼凑出来的。 - Matteo Mannino
1
实际上,您可以编写 c = cv::waitKey(); return 0; 当您按下一个键时,waitKey() 将返回并关闭程序。 - Sam
是的,但你不能用鼠标光标调整图像大小并更近距离地查看线条。这就是循环的目的所在。另一种选择是使用窗口的线程版本,但我想保持简单。 - Matteo Mannino
嗯,我试过了,你仍然可以用那种方式调整窗口大小。所以,你是对的。对于其他应用程序,通常会将一个大于0的数字传递给cv::waitKey,比如显示视频,这种方法不起作用,因为在分配的时间之后没有更多的更新。我不记得过去有这个功能。按照你的建议修改了代码。 - Matteo Mannino
2个回答

12
./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连通方法进行绘制。


1
那么,在非CV-8U图像中有没有使用CV_AA的方法呢? - Jay Wang

7

你能提供一个样例图片吗?我自己也尝试了一下,这个代码可以完美运行:

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

这是我的结果:
这里输入图片描述。 这与it技术有关。请注意,我已保留HTML标记。

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接