# Removing noise from Contour features in Real time

Hi,

In my project, I apply findcontours function to detect a rectangular object within a region of interest in the image. I am doing it in real time. Subsequently, I enclose the detected contour by a boundedrect which gives me its four vertices. However, the position of these vertices is not stable, it is changing very fast. Looks like the contour area is growing and shrinking, and have variations which causes the vertices' position to change. I have tried following solutions, but to no avail.

1. Low pass filtering on the output of pixel positions.
2. Median and Gaussian blur within the ROI.
3. FastNlmeansDenoising: which is too slow for my application.

I am including my code snippet where I find contours below:

  //medianBlur(img, img, 21);
cvtColor (img, img, COLOR_BGR2GRAY);
//fastNlMeansDenoising (img, img, 3, 7, 21);
threshold(img, img, 0, 255, CV_THRESH_BINARY_INV | CV_THRESH_OTSU);
//medianBlur(img, img, 21);
Mat dilateElement = getStructuringElement( MORPH_RECT,Size(11,11));
//Mat erodeElement = getStructuringElement ( MORPH_RECT, Size(8,8) );
dilate(img,img,dilateElement);
//erode (img, img, erodeElement);
floodFill (img, Point(0,0), Scalar(0));
//  namedWindow("dilated",CV_WINDOW_NORMAL);
//  imshow("dilated",img);
//  cout << "Inside corrected corners p3" << endl;

//GaussianBlur (img, img, Size(15,15), 0, 0);
Canny (img, img, 0, 10, 5);
dilate(img, img, Mat(), Point(-1,-1));

//cout << "Inside corrected corners p3.5" << endl;

findContours(img, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);
// cout<<contours.size()<<endl;
//  Mat tempimg(img.rows, img.cols, CV_8U, cv::Scalar(0));
//  drawContours( tempimg, contours, -1, Scalar(255), 3, CV_AA );
//  namedWindow("contours", CV_WINDOW_NORMAL);
//  imshow("contours", tempimg);
//  cout << "Inside corrected corners p4" << endl;


I would appreciate any help in this regard. I have tried googling a lot but couldn't find a good post which might direct me towards removal of noise from detected contours in real time. I think the nature of noise is Impulse.

edit retag close merge delete

Just some remarks to your code

• I always find it weird for people to use dilation filters, but no following erode filters. You are adding extra noise without reducing it back.
• Getting a stable (no shifting in pixels) contour in a video sequence is quite hard. Especially since small movements of the object get stabled by our eyes, but since we process pixels, we actually have a different contour.
• What you could do is try to add a Kalman filter to the contour pixels to smooth everything out. But that again might be to computationallty heavy.

Could you add a video / image to show how worse the jitter is?

( 2017-04-14 04:28:18 -0500 )edit
1

Thank you very much for your response Steven! Even applying erosion doesn't give me a good response. I have uploaded a video on youtube which shows the jitter. You can see it at: https://youtu.be/5bpoDsImkvM

I differentiate the distance between red and blue spots in order to get the feature velocity. The velocity vector besides the image window (red text on black) shows the change, which should be zero since the camera is at rest.

( 2017-04-15 02:49:36 -0500 )edit

Sort by » oldest newest most voted

filtering the image is one option, filtering the point positions(over time) another.

alternatively to the kalman filter, one could use a simple lowpass interpolation:

//
// e.g. to smooth noisy landmarks ;)
//
template<class T>
struct Ipol
{
size_t N;
std::deque<T> q;

Ipol(size_t n=10) : N(n) {}

T operator ()(T t)
{
q.push_back(t);
if (q.size() > N)
q.pop_front();

T acc(0,0,0);
for (size_t i=0; i<q.size(); ++i)
acc += q[i];
return acc / double(q.size());
}
};

int nInterpolations = 5;
vector<Ipol<Point>> ipo(4, nInterpolations); // one for each box corner

while(true) {
... process image, find contours, retrieve box points
for each box point:
Point newVertex = ipo[i](oldVertex);
}

more

Thank for your reply! I tried using your code with a random generation of points. However, I am not able to understand, how to use it! I am sharing my code here: https://gist.github.com/denoza/13412cc470445c60cc3b7f5009519a2f (https://gist.github.com/denoza/13412c...)

The output is something like this: Before[1804289383, 846930886] After[1804289383, 846930886] Before[1681692777, 1714636915] After[1681692777, 1714636915] Before[1957747793, 424238335] After[1957747793, 424238335] Before[719885386, 1649760492] After[719885386, 1649760492]

( 2017-04-16 01:00:41 -0500 )edit

Thank for your reply! I tried using your code with a random generation of points. However, I am not able to understand, how to use it! I am sharing my code here: https://gist.github.com/denoza/13412cc470445c60cc3b7f5009519a2f (https://gist.github.com/denoza/13412c...)

The output is something like this: Before[1804289383, 846930886] After[1804289383, 846930886] Before[1681692777, 1714636915] After[1681692777, 1714636915] Before[1957747793, 424238335] After[1957747793, 424238335] Before[719885386, 1649760492] After[719885386, 1649760492]

( 2017-04-16 01:00:56 -0500 )edit

Official site

GitHub

Wiki

Documentation