Hello,
I am tracking gas bubble plumes (CO2/Methane) rising from a seafloor source, filmed in 4K (downsampled to 1080p). There are many different short video clips, taken over the course of 153 days, from a camera stationed on the seafloor near a mound where these methane plumes are active and sporadic- i.e. the plumes are spontaneous and short lasting, so there’s much variation between clips. For the most part, they are maybe 6 inches to a foot away from the camera (rough guess). The bubble size is mostly the same aside from a few outlier cases.
The Goal: I need to extract clean binary masks of the bubbles (per frame) to eventually perform Centroid Tracking for rise-velocity calculations, as well as calculating total methane output estimate.
The camera is stationary, but the environment has significant “marine snow” and sensor noise. In some clips, the bubbles are “dark-on-dark” or “light-on-light” with very low contrast deltas (pixel value changes of <10). If you pause the video at a specific frame, you won’t be able to distinguish a bubble. They are very shadowy and blend in quite well (hence why I mainly use frame differencing or background averaging methods). They can also occasionally be quite smaller than what is common, and move at varying speeds.
What I’ve tried:
- Simple Frame Differencing (absdiff) + Thresholding.
- Area-based contour filtering (Min Area 4–10).
- Max Intensity Z Projection (won’t work, since this technique is based on brightness and the bubbles aren’t always bright).
- MOG2 with 0.001 learning value and 500 frames max
The main issues:
-
A few difficult plumes that don’t get captured- maybe you can see the bubbles at their base but then as you go up, maybe they aren’t close enough to the camera lights so the dark, un-shiny methane bubbles don’t stand out enough from the background.
-
Also the resulting output masks either being too blobby (looks like too much dilation) or too choppy (looks like too much erosion).
-
If you relax the settings too much to make a “one size fits all” detection for the plumes, you get too much noise introduces.
The Question: > For particles that are nearly indistinguishable from background noise, what is the best “pre-processing” or “background-model” approach in OpenCV to suppress sensor grain without losing low-contrast moving particles? And to ensure that all particles are being preserved/captured in the final output mask(s)?
I’m willing to not capture every single plume, so I could live with the few difficult/problematic ones experienced currently. But I’d like to ensure the method I’m using are the right/best ones for the job.
Examples below: Taken from a variety of different techniques / versions of the script, so it won’t be consistent but the problems described are.
Note This is 4 different output masks condensed into 1 image for convenience.
(Top Left: Example of too choppy)
(Top Right: Example of too blobby)
(Bottom Left: Note how the plume on the right is disconnected in the middle. In reality, it rises to the top of the frame, but we can only see the bubbles at the base).
(Bottom Right: *Bonus* Shows the unintentional “V” shape of some plume masks. This plume actually moves ~straight upwards, but the 2 lights on either side of the camera cause shadows on either side that get picked up by my algorithm, causing this. But I could implement a fix later based on velocity/tracking direction or something.)
Any help would be appreciated.
Thank you.

