I am currently doing a project where I need to locate ink drops in a video, perform measurements such as volume estimation, velocity, and distance travelled before it becomes spherical.
Firstly, I would like to know whether I am along the right tracks in tackling this project. At the moment I have:
1.) Converted the original image to grayscale
2.) Applied Gaussian Blur then Canny edge detection (Click here for image)
3.) Located the white pixels using findNonZero()
then calculated the sum of blocks of rows and the block with the highest concentration of white pixels and all the rows above it are cropped out). This removes the print heads in the image so the ROI is only the droplets below it.
4.) Used the findContours
to find the contours. (Click here for image)
The above 4 steps are what I have done so far. Are the following steps below what I should do next?
floodFill()
every closed circlescontourArea()
(Can I then estimate the volume of the drop after this step with a few assumptions like its shape, pixel to volume ratio, etc?)I am also unsure of how I can give a drop an ID so I can be sure I am tracking it properly and know when a new drop has entered the ROI.
Any help would be greatly appreciated, Thank You.
I think that your idea is good and can be quite easily extended to something that will satisfy you.
For clarification i will call red ROI from your image "redROI".
Note few things:
-size of the rectangle depends on how fast droplets move and whether they can move only vertical or diagonal (wind can change direction of move) too.
-before searching for droplets, check whether all rectangles are disjoint (the don't have any common area -> (Rect1 & Rect2).area() == 0 for each pair of rectangles).
-before searching for droplets in ROI make sure this ROI is inside redROI. So just use this code: roi = roi & redROI;
After finding new positions of every old droplet, search for droplets in whole redROI, so you won't miss any new droplet.
Let me know if you don't understand some part of this idea - i will try to explain it better.
Maybe ignore the ones that are very open? (Any tips on how to actually do this?)
I'm not sure about it, so check it. Try to use CV_RETR_LIST
as the third parameter of findContours
and check the distance between first and the last point from returned (by findContours
) contour - if the distance is big than the contour is open, if no - it is closed.
floodFill() every closed circles
You can just use drawContours
and set thickness
parameter to -1
- simpler and faster solution.
edit:
You can try to use optical flow as well - it's already implemented in openCV, here you can read nice tutorial about that: http://robotics.stanford.edu/~dstavens/cs223b/ (start from .pdf files)