【问题标题】:Use Kalman Filter to filt noise without delay opencv c++使用卡尔曼滤波器无延迟过滤噪声opencv c ++
【发布时间】:2018-04-26 02:39:58
【问题描述】:

我的任务是检测视频中的橙色球。我通过在 HSV 颜色空间和边界框上对图像进行阈值检测来检测。然后我有球的中心和半径,单位是像素。

当球是静态的时,我希望中心和半径也会是静态的,但实际上,它有噪音。我使用Kalman Filter 过滤噪音,效果很好。但它会实时延迟。我尝试优化协方差参数但不起作用。

那么任何人都可以帮助我static当球静止且没有延迟时的中心和半径?

【问题讨论】:

    标签: c++ opencv kalman-filter


    【解决方案1】:

    您确定是卡尔曼滤波器女巫导致了延迟吗? 否则你可以试试这个懒惰的过滤器,它只是抑制噪音,但速度非常快。我怀疑它是 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;
    }
    

    低于带有平滑的噪声过滤器。 适用于慢速和快速移动的物体。

    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);
        }
    };
    

    【讨论】:

    • 感谢您的回答。我确信卡尔曼滤波器会导致延迟。当我增加过滤器的“measurementNoiseCov”属性时,它可以很好地过滤噪声,但延迟也会增加。反之亦然,当减小时,它对噪声的过滤效果不好,延迟减小。关于您的过滤器,我认为当对象移动非常缓慢时会出错
    • 慢速移动并没有错,而是以噪声阈值的步长移动。我将添加另一个示例,它对缓慢移动的物体响应更顺畅
    • 添加了平滑噪声过滤器,女巫应该可以满足您的需求
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-14
    • 2017-08-11
    • 2017-02-06
    • 2013-11-01
    • 2012-05-14
    相关资源
    最近更新 更多