我的任务是在视频中检测橙色球。我通过HSV色彩空间和边界框上的阈值图像进行检测。然后我有球的中心和半径,单位是像素。
当球是静止的时候,我期待中心和半径也是静态的,但是现实,它有噪音。我使用Kalman Filter
来过滤噪音,效果很好。但它实时延迟。我尝试优化协方差参数但不起作用。
当球是静止且无延迟的时候,任何人都可以帮助我static
中心和半径吗?
答案 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);
}
};