简体   繁体   English

使用卡尔曼滤波器无延迟地过滤噪声opencv c ++

[英]Use Kalman Filter to filt noise without delay opencv c++

My task is to detect an orange ball in video. 我的任务是检测视频中的橙色球。 I detected by thresholding image on HSV colorspace and bounding box. 我通过在HSV色彩空间和边界框上对图像进行阈值检测。 Then I have center and radius of ball, with unit is pixel. 然后我有球的中心和半径,单位是像素。

When ball is static, I expect center and radius will be static too, but reality, it has noise. 当球是静态的时,我希望中心和半径也将是静态的,但是现实中它会产生噪音。 I use Kalman Filter to filter noise and it works well. 我使用Kalman Filter来过滤噪声,并且效果很好。 But it delay in real-time. 但是它会实时延迟。 I try to optimize covariance parameters but not work. 我尝试优化协方差参数,但不起作用。

So could anyone help me static center and radius when ball is static and without delay? 因此,当球静止且没有延迟时,有人可以帮助我保持static中心和半径吗?

Are you sure it is the Kalman Filter witch is causing the delay. 您确定是造成延迟的原因是卡尔曼滤波器。 Otherwise you can try this lazy filter witch only is noise rejecting but blazingly fast. 否则,您可以尝试使用这种懒惰的过滤器,它不仅可以抑制噪音,而且速度非常快。 My suspicion however it is the HSV conversion. 但是我怀疑是HSV转换。

class noiseFilter
{
private:
    cv::Point2f ptLast;
    float ptMaxTol;
public:
    noiseFilter(float maxTol = 1.5f)
    {
        ptMaxTol = maxTol * maxTol;             // we do the pow(2) here so we don't have to do a square root on every update
        ptLast = cv::Point2f(0.0f, 0.0f);
    }
    cv::Point2f update(cv::Point2f &ptNew)      // update filter with new found point
    {
        float dist = pDistance2(ptLast, ptNew);
        if (dist > ptMaxTol) ptLast = ptNew;    // update only if distance is more than threshold
        return ptLast;
    }
    cv::Point2f getResult()                     // get result of filter
    {
        return ptLast;
    }
private:
    // calculate distance between 2 point without doing a sqrt
    float pDistance2(cv::Point2f &p1, cv::Point2f &p2)
    {
        float dx = p1.x - p2.x;
        float dy = p1.y - p2.y;
        return (dx * dx + dy * dy);
    }
};

int main()
{
    cv::Point2f pt;
    noiseFilter filter(2.1f);           // initialize filter wit max 2.1 pixels noise rejection.
    int x = 100, y = 120;

    for (int i = 0; i < 100; i++)
    {
        // generate some noise with 2 pixels variation
        pt.x = ((rand() % 200) - 100) * 0.01f + x;
        pt.y = ((rand() % 200) - 100) * 0.01f + y;

        cv::Point2f pts = filter.update(pt);
        printf("input x=%6.2f y=%6.2f  output x=%6.2f y=%6.2f\r\n", pt.x, pt.y, pts.x, pts.y);

        // do som random big update on random intervals
        if ((rand() % 50) == 1) {
            x += 15;
            printf("big update on X\r\n");
        }
        if ((rand() % 50) == 1){
            y += 25;
            printf("big update on Y\r\n");
        }

    }
    return 0;
}

Below a noise filter with smoothing. 下面的噪声过滤器具有平滑性。 Works on slow and fast moving objects. 适用于缓慢和快速移动的对象。

class noiseFilterSmooth
{
private:
    static const int maxHist = 10;
    cv::Point2f ptLast;
    float ptMaxTol;
    cv::Point2f hist[maxHist];
    int histHead,histSize;
public:
    noiseFilterSmooth(float maxTol = 1.5f)
    {
        histHead = histSize = 0;
        ptMaxTol = maxTol * maxTol;             // we do the pow(2) here so we don't have to do a square root on every update
        ptLast = cv::Point2f(0.0f, 0.0f);
    }
    cv::Point2f& update(cv::Point2f &ptNew)     // update filter with new found point
    {
        float dist = pDistance2(ptLast, ptNew);
        if (dist > ptMaxTol)  histSize = histHead = 0;      // reset smoothing filter if distance is more than threshold
        // update smoothing filter with last result
        hist[histHead] = ptNew;                 // update smoothing filter with last 
        histHead = (histHead + 1) % maxHist;
        if (histSize < maxHist) histSize++;
        return getResult();
    }
    cv::Point2f& getResult()                        // get result of filter
    {
        float sumx = 0, sumy = 0;
        for (int i = 0; i < histSize; i++)
        {
            sumx += hist[i].x;
            sumy += hist[i].y;
        }
        ptLast.x = sumx / histSize;
        ptLast.y = sumy / histSize;
        return ptLast;
    }
private:
    // calculate distance between 2 point without doing a sqrt
    float pDistance2(cv::Point2f &p1, cv::Point2f &p2)
    {
        float dx = p1.x - p2.x;
        float dy = p1.y - p2.y;
        return (dx * dx + dy * dy);
    }
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM