在OpenCV中使用HSV有效地阈值红色

Ian*_*Ian 22 c++ opencv image-processing

我正在尝试使用OpenCV来限制视频流中的红色像素.我有其他颜色很好地工作,但红色带来问题,因为它包裹在色调轴周围(即HSV(0,255,255)和HSV(179,255,255)都是红色).我现在使用的技术不太理想.基本上:

cvInRangeS(src, cvScalar(0, 135, 135), cvScalar(20, 255, 255), dstA);
cvInRangeS(src, cvScalar(159, 135, 135), cvScalar(179, 255, 255), dstB);
cvOr(dstA, dstB, dst);
Run Code Online (Sandbox Code Playgroud)

这是次优的,因为它需要代码中的分支用于红色(潜在的错误),两个额外图像的分配,以及与蓝色的简单情况相比的两个额外操作:

cvInRangeS(src, cvScalar(100, 135, 135), cvScalar(140, 255, 255), dst);
Run Code Online (Sandbox Code Playgroud)

我遇到的更好的选择是"旋转"图像的颜色,使目标色调为90度.例如.

int rotation = 90 - 179; // 179 = red
cvAddS(src, cvScalar(rotation, 0, 0), dst1);
cvInRangeS(dst1, cvScalar(70, 135, 135), cvScalar(110, 255, 255), dst);
Run Code Online (Sandbox Code Playgroud)

这允许我类似地对待所有颜色.

但是,cvAddS当它们低于0时,操作不会将色调值包装回180,因此会丢失数据.我看着转换图像,CvMat以便我可以减去它,然后使用模数将负值包回到范围的顶部,但CvMat似乎不支持模数.当然,我可以迭代每个像素,但我担心这会非常慢.


我已经阅读了很多教程和代码示例,但它们似乎只是方便地查看不包含色调频谱的范围,或者使用甚至更加丑陋的解决方案(例如,cvInRangeS通过遍历每个像素重新实现并执行手动比较颜色表).

那么,通常的解决方法是什么?什么是最好的方式?每个人的权衡是什么?迭代像素比使用内置CV函数慢得多吗?

小智 7

这有点晚了,但这就是我要尝试的.

进行转换:cvCvtColor(imageBgr,imageHsv,CV_RGB2HSV);

注意,RGB与Bgr是有目的地交叉的.

这样,红色将在蓝色通道中处理,并将以170左右为中心.也会有一个方向翻转,但只要你知道它就可以了.


Art*_*huk 1

你不会相信,但我遇到了完全相同的问题,我通过 Hue(不是整个 HSV)图像进行简单迭代解决了它。

迭代像素是否比使用内置 CV 函数慢得多?

我只是试图理解cv::inRange函数,但根本没有理解它(似乎作者使用了一些特定的迭代)。