cv::circle 的奇怪行为

Posted

技术标签:

【中文标题】cv::circle 的奇怪行为【英文标题】:Weird behaviour of cv::circle 【发布时间】:2015-12-01 10:49:11 【问题描述】:

我正在尝试使用 OpenCV 3 在从 Kinect v2 传感器获得的图像上绘制几个圆圈。

cv::circle 似乎有一个奇怪的错误,或者我不明白该函数是如何工作的。让我们看一些代码:

if(kinectDataManager.IsColorStreamEnabled())

    cv::Mat colorFrameMat = kinectDataManager.GetFrame().GetColorFrame()  

    cv::imshow("Color", colorFrameMat)

这段代码运行良好,使用 ImageWatch Visual Studio 插件检查 OpenCV 图像,我可以看到 colorFrameMat 矩阵没有损坏。

让我们再看一些代码:

if(kinectDataManager.IsColorStreamEnabled())

    cv::Mat colorFrameMat = kinectDataManager.GetFrame().GetColorFrame()  

    int radius = 2;
    int y = 1068;

    for (int x = 0; x < 1920; ++x)
    
        cv::circle(colorFrameMat, cv::Point(x,y), radius, cv::Scalar(255, 0, 0), -1, CV_AA);
    

    cv::imshow("Color", colorFrameMat)

循环执行完成后,ImageWatch 插件显示图像的最后一行丢失。奇怪的是,程序仍然执行。但是,对于y 的不同值,程序会由于访问冲突而崩溃,例如对于y = 1067,程序会因x = 1917 而崩溃。对于y = 1069,它在x = 988 处崩溃。

有人知道问题可能是什么吗?

编辑: ImageWatch 插件当然会显示最后一行丢失了,因为圆圈是从左到右在这些位置绘制的,请原谅错误!

编辑2: 存储一帧并读入后,具有相同代码的cv::circle 方法工作正常:

cv::Mat test = cv::imread("test.jpg", CV_LOAD_IMAGE_COLOR);
cv::namedWindow("test", CV_WINDOW_NORMAL);
int radius = 10;
int y = 1067;

for (int x = 0; x < 1920; ++x)

    cv::circle(test, cv::Point(x, y), radius, cv::Scalar(0, 0, 255, 255), -1, CV_AA);


cv::imshow("test", test);
cv::waitKey(0);

【问题讨论】:

你为什么不按照Mat.rowsMat.cols(或Mat.size().width/Math.size().height)工作?? 我不明白这与我的问题有什么关系。我使用 Kinect SDK 函数获取图像帧的宽度和高度。在 imshow 调用之前,Mat.rowsMat.cols 分别是 10801920 因为没有任何日志、崩溃日志或常量,所以有点难以帮助 我完全可以理解,但是我不知道我可以提供什么样的日志。在cv::circle 调用之前,图像看起来非常好。在循环的某个地方,最后一行丢失了...... 你的图片占用的内存是固定的。如果您假设错误的图像宽度或高度,您假设的像素线从一个非常错误的位置开始。这就是为什么您的代码在不同的 x 坐标处崩溃的原因。拍摄 4 行 512 列的图像。现在,如果您要求第一行将从内存位置 0 开始,第二行将从 512 开始,依此类推。但是,如果您假设图像有 1024 列,则您希望第二行从位置 1024 开始。如果您现在尝试访问该行中不存在的 1024 像素,您将在第 4 行的最后一个位置结束。 【参考方案1】:

Kinect SDK 仅提供读取 4 通道图像(即 RGBA)的功能,但是,cv::circle 函数似乎以一种奇怪的方式崩溃此类图像。通过调用 cvtImage 删除 alpha 通道,我可以解决问题。

【讨论】:

【参考方案2】:

由于您说图像在cv::circle 调用之前看起来不错,因此GetColorFrame() 返回的数据可能会在循环运行时发生变化。 试试:

GetColorFrame().clone() 看看这是否能解决问题,或者 改变GetColorFrame 的工作方式。

【讨论】:

这是个好主意!但是,即使是第一帧,问题仍然存在。

以上是关于cv::circle 的奇怪行为的主要内容,如果未能解决你的问题,请参考以下文章

parseInt() 函数的奇怪行为

removeFromParent() 奇怪的行为

QLcdNumber 奇怪的行为

iOS奇怪的委托行为?

AdditionalSafeAreaInsets 的奇怪行为

TextBlock 的重写样式的奇怪行为