Ask Your Question
0

Removing noise from Contour features in Real time

asked 2017-04-13 23:13:18 -0600

denoza gravatar image

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 flag offensive close merge delete

Comments

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?

StevenPuttemans gravatar imageStevenPuttemans ( 2017-04-14 04:28:18 -0600 )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.

denoza gravatar imagedenoza ( 2017-04-15 02:49:36 -0600 )edit

1 answer

Sort by ยป oldest newest most voted
1

answered 2017-04-15 02:09:58 -0600

berak gravatar image

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);
 }
edit flag offensive delete link more

Comments

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]

denoza gravatar imagedenoza ( 2017-04-16 01:00:41 -0600 )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]

denoza gravatar imagedenoza ( 2017-04-16 01:00:56 -0600 )edit

Question Tools

1 follower

Stats

Asked: 2017-04-13 23:13:18 -0600

Seen: 3,480 times

Last updated: Apr 15 '17