我正在尝试将cv::InRange()与HSV图像配合使用。因为色相值是循环的,所以我需要处理最小/最大值,其中最小色相可能大于最大色相值。到目前为止,我已使用以下代码来计算范围掩码:

cv::Mat InRangeMask(const cv::Mat &hsv, cv::Scalar min, cv::Scalar max)
{
    cv::Mat rangeMask;
    if(min[0]<=max[0])
    {
        cv::inRange(hsv, min, max, rangeMask);
    }
    else
    {
        cv::Mat rangeMask2;
        cv::Scalar min1(0, min[1], min[2]);
        cv::Scalar max1(min[0], max[1], max[2]);
        cv::Scalar min2(max[0], min[1], min[2]);
        cv::Scalar max2(179, max[1], max[2]);

        cv::inRange(hsv, min1, max1, rangeMask);
        cv::inRange(hsv, min2, max2, rangeMask2);
        rangeMask |= rangeMask2;
    }
    return rangeMask;
}

但是,在其他情况下,此解决方案需要两倍的时间(在经过优化的版本中)。我认为可以通过某种方式反转范围或反转图像来获得更有效的代码。但是由于我使用的是全hsv范围,而不仅仅是色相通道,所以我还没有找到更好的解决方案。

在hsv范围内计算像素的更有效的实现方法是什么?我确定有人已经对这个问题有很好的解决方案。使用openCV函数还是重写算法?

最佳答案

您可以随时重写算法,这对于inRange函数来说并不复杂。

另一种解决方案是在inRange时简单地使用min[0]<=max[0],否则执行以下操作:

  • 使用{hchan,schan,vchan}切开图像的通道cv::split
  • inRange应用于三个通道并获取maskH,maskS,maskV
  • inRange(hchan,max[0],min[0],maskH)
  • inRange(schan,min[1],max[1],maskS)
  • inRange(vchan,min[2],max[2],maskV)
  • 像这样重新组合三个口罩
  • bitwise_and(maskS,maskV,rangeMask)
  • bitwise_not(maskH,maskH)
  • bitwise_and(maskH,rangeMask)

  • 但是我个人认为这是一个过冲(并且比重写算法效率低)。

    10-02 02:33