Hi, I am new to image processing and have an interesting problem that I'm hoping to get guidance on before I wander aimlessly through the many possible solutions. I am attempting to automatically extract banklines from a meandering river in the Amazon from Landsat imagery. I already have an algorithm to classify each pixel as either part of river (1) or not part of river (0). Of course, the algorithm returns a noisy image, and there are natural features (tributaries, connecting channels, point bars, etc.) that complicate the process. I have many Landsat scenes to process, and each scene has 30+ years of data with ~1 realization/year, so obviously I'd like to automate the process as much as possible. The desired ultimate output is a set of two polylines for each image: one tracing the left bank, and one the right bank. (I have tools to compute channel widths and migration rates that require vector inputs.)
Here I will show an attempt I made using Matlab's morphological operations and to give you an idea of the kinds of problems I face. Any advice is much appreciated!
Here is the classified image (i.e., what I'm starting with):
I would like to extract the left and right banklines of the main channel. Resolution is 30m, so I'd like to retain as much fidelity to the original image as possible so I can accurately compute migration rates. You can see some of the problems already: small connecting channels between lobes, chunks of 0's at the apex of the bends, some places where the river splits into two roughly-equal channels before rejoining, tributaries, mid-channel islands, etc. I would be happy to just get the inner and outer banks, although it would be nice to (automatically) detect where tributaries enter, or where a mid-channel island was…
So as a first-cut, I ran the following codes:
load BWoBW1 = bwareaopen(BWo, 20000); % remove small patches of 1s
BW2 = bwmorph(BW1,'erode',2);BW3 = bwareaopen(BW2, 20000); % remove small patches of 1sBWclean = bwmorph(BW3, 'dilate',2);% The rest of this code is just to add back some of the details lost above
% Now subtract cleaned image from original
BWdiff = logical(imsubtract(double(BWo),double(BWclean)));% Remove large pixel groups (tribs, connecting channels) from BWdiff
CC = bwconncomp(BWdiff);numPixels = cellfun(@numel,CC.PixelIdxList);idx = find(numPixels>250);for g = 1:numel(idx) BWdiff(CC.PixelIdxList{idx(g)}) = 0;end% Add the small groups back to cleaned image to better resolve banklines
BW4 = BWclean | BWdiff;% Remove the little stuff not adjacent to river
BWf = bwareaopen(BW4, 20000);
And this is what resulted:
This result isn't perfect, but it's pretty good (and I have been playing with ways to reinsert the lost features adjacent to the channels). Now I am stuck on how to extract the banklines from this image (it would be nice to have a centerline, too, but not necessary). I know how to get the extents using bwperimm but how can I separate into left and right banks?
I also have a few other general questions about my methodology; any advice from more experienced users would be greatly appreciated!
1. The above code works for that particular scene, but I have to adjust the order and number of operations for other scenes (even for the same scene, different year). Is there a more robust way to go about extracting the main channel from scenes that have different features?
2. (Asked above) After de-noising the image, how can I pull out the left and right banks automatically?
3. Is there better methodology that would preserve more of the original image? For instance, I thought of constructing left and right banks by creating some kind of cost function and finding geodesic curves (one left, one right) that minimize that cost function…
4. Would you take a totally different approach?
Any hints, tips, tricks, or advice would be great!
Best Answer