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

时间:2018-04-26 02:39:59

标签: c++ opencv kalman-filter

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

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

当球是静止且无延迟的时候,任何人都可以帮助我static中心和半径吗?

1 个答案:

答案 0 :(得分:0)

你确定这是导致延迟的卡尔曼滤波器吗? 否则你可以尝试这个懒惰的过滤器,只有噪音拒绝,但非常快。但我怀疑这是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);
    }
};