我正在尝试使用OpenCV 3.2绘制箭头:
#include <opencv2/core.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
using namespace cv;
int main()
{
Mat image(480, 640, CV_8UC3, Scalar(255, 255, 255)); //White background
Point from(320, 240); //Middle
Point to(639, 240); //Right border
arrowedLine(image, from, to, Vec3b(0, 0, 0), 1, LINE_AA, 0, 0.1);
imshow("Arrow", image);
waitKey(0);
return 0;
}
绘制了一个箭头,但在顶端缺少一些像素:
更准确地说,两列像素未正确着色(缩放):
如果我禁用抗锯齿,即,如果我使用
arrowedLine(image, from, to, Vec3b(0, 0, 0), 1, LINE_8, 0, 0.1);
而不是(注意LINE_8而不是LINE_AA),像素在那里,虽然没有抗锯齿:
我知道抗锯齿可能依赖于相邻的像素,但奇怪的是,边框处根本不绘制像素,而不是在没有抗锯齿的情况下绘制像素。这个问题有解决方法吗?
增加X坐标,例如至640或641)使问题更严重,即更多的箭头像素消失,而尖端仍然缺少近两个完整的像素列。
扩展和裁剪图像可以解决相邻的像素问题,但在我原来的用例中,问题出现了,我无法放大图像,即它的大小必须保持不变。
答案 0 :(得分:2)
经过快速审核后,我发现OpenCV draws AA lines using a Gaussian filter,合同最终图片。
正如我在评论中建议的那样,您可以为AA模式实现自己的功能(如果禁用AA,您可以调用原始功能)手动扩展点(请参阅下面的代码以了解主意)。
其他选项可能是在使用AA时增加线宽。
您也可以模拟OpenCV的AA效果,但是在最终图像上(如果您有许多箭头,可能会更慢但很有帮助)。我不是OpenCV专家所以我会写一个通用的方案:
// Filter radius, the higher the stronger
const int kRadius = 3;
// Image is extended to fit pixels that are not going to be blurred
Mat blurred(480 + kRadius * 2, 640 + kRadius * 2, CV_8UC3, Scalar(255, 255, 255));
// Points moved a according to filter radius (need testing, but the idea is that)
Point from(320, 240 + kRadius);
Point to(639 + kRadius * 2, 240 + kRadius);
// Extended non-AA arrow
arrowedLine(blurred, ..., LINE_8, ...);
// Simulate AA
GaussianBlur(blurred, blurred, Size(kRadius, kRadius), ...);
// Crop image (be careful, it doesn't copy data)
Mat image = blurred(Rect(kRadius, kRadius, 640, 480));
另一种选择可能是在图像中绘制两倍大的箭头,并使用良好的平滑滤镜将其缩小。
显然,只有在图像上没有任何先前数据时,最后两个选项才有效。如果是这样,那么使用透明图像进行时间绘制并在最后覆盖它。