OpenCV - 奇数HSV范围检测

时间:2015-05-27 13:03:43

标签: c++ opencv detect hsv

我有一个Qt应用程序,我必须在点击坐标周围找到几个像素的HSV范围,以便稍后跟踪。我就是这样做的:

    cv::Mat temp;
    cv::cvtColor(frame, temp, CV_BGR2HSV); //frame is pulled from a video or jpeg
    cv::Vec3b hsv=temp.at<cv::Vec3b>(frameX,frameY); //sometimes SIGSEGV?
    qDebug() << hsv.val[0]; //look up H
    qDebug() << hsv.val[1]; //look up S
    qDebug() << hsv.val[2]; //look up V
    //just base values so far, will work on range later
    emit hsvDownloaded(hsv.val[0], hsv.val[0]+5, hsv.val[1], 255, hsv.val[2], 255); //send to GUI which automaticly updates worker thread

现在,事情很奇怪。这些是结果(红色圆圈表示点击位置): clicking blue clicked red - correct

红色很奇怪,上半部分形状被正确检测到,下半部分没有,尽管它是相同颜色的固体质量。 green completly screws up

进行实际测试 enter image description here

它检测到坦率地荒谬的HSV {95,196,248}(基值太高)。没有检测到的像素甚至不是被点击的像素。在100%的时间内检测到该球的最佳值是H:35-141 S:0-238 V:65-255。我想从标准化的直方图中获得HSV范围,但我甚至无法获得正确的基本值。怎么了?当OpenCV使用kalibrowanyPlik.read(frame);拉取帧时,默认的配色方案是BGR,对吧?

为什么颜色检测会如此随机地工作?

1 个答案:

答案 0 :(得分:3)

正如berak所提到的,您的代码看起来像是使用索引以错误的顺序访问像素。

这意味着您的像素位置是错误的,除了位于对角线上的像素,因此将正确检测对角线周围的点击对象,而其他所有对象都不会。

为了不让一次又一次困惑,我想让你理解为什么OpenCV使用(row,col)索引排序:

OpenCV使用矩阵来表示图像。在数学中,2D矩阵使用(row,col)索引,查看http://en.wikipedia.org/wiki/Index_notation#Two-dimensional_arrays并观察索引。因此,对于矩阵,通常首先使用行索引,然后使用列索引。

不幸的是,图像和像素通常具有(x,y)索引,其对应于数学图和坐标系中的x / y轴/方向。所以这里首先使用x位置,然后是y位置。

幸运的是,OpenCV提供了两种不同版本的.at方法,一种用于访问像素位置,另一种用于访问矩阵元素(最终是完全相同的元素)。

matrix.at<type>(row,column) // matrix indexing to access elements
// which equals
matrix.at<type>(y,x)

matrix.at<type>(cv::Point(x,y)) // pixel/position indexing to access elements

因为第一个版本应该稍微更高效,所以如果这些位置还没有作为cv :: Point对象给出,那么应该首选。因此,最好的方法是记住,openCV使用矩阵来表示图像,并使用矩阵索引表示法来访问元素。

顺便说一下,我看到有人想知道为什么matrix.at<type>(cv::Point(y,x))在他们得知openCV图像使用“错误排序”之后无法正常工作。我希望在我的解释之后不会出现这个问题。

再多一点顺便说一下:在学校我已经想知道,为什么矩阵首先索引行,而函数图则首先索引x轴。我发现两者都不使用“相同”的顺序是愚蠢的,但我仍然不得不忍受它:D(最后,两者都没有太大的关系)