ConnectedComponents-like function for grayscale image

asked 2018-04-16 04:33:10 -0500

theaniolad gravatar image

updated 2018-04-16 04:41:37 -0500

I'm looking for help, because I wasn't successful finding a function in OpenCV that is able to perform a labelling of connected components on a grayscale image.

Input: The input image is an image where there are several larger areas (>500px) with different grayscale intensities, e.g. 0, 50, 100, 150. There are several areas with the same intensity (not touching each other).

Goal: output a label mask where each area has it's own label ID, similar to the output of connectedComponentLabelling.

Problems: I would have supposed that there is a single function for this in OpenCV, but couldn't find one. I know of very similar functions. I'm pretty much looking for a cv::ConnectedComponents that is able to work on a grayscale image like cv::floodfill does:

  • ConnectedComponents: extracts connected components from a binary image. I need it for a grayscale image.

  • FindContours: extracts connected components from a binary image by Canny Edge detection (but for some reason doesn't complain when a grayscale image is the input). This is not very reliable.

  • SimpleBlobDetector: loops through all intensites and extracts connectedComponents (but the output are keypoints where the area shape is lost).

  • Floodfill: fills a grayscale connected component with a single color, exactly what I need. But to use this function as a full area extractor I would have to build a loop around it that tests different points etc.. This does not sound like the easiest solution.

  • Distance-Transform and Watershed: I've seen several solutions with these functions. I don't think this is the right approach for my problem.

  • Meanshift and K-Means: these functions perform the first filtering step but not the actual label mask.

My current solution: A sort-of manual multi-peak Otsu-Threshold or manual meanShift-Filter

  • Step 1: get the histogram and find the significant peaks, i.e. all peaks that have x pixels within a delta-range. x is the minimum area, delta is the maximum expected color difference expected within a connected area.

  • Step 2: Loop through each peak and perform a cv::inRange() with lowerbound=peak-delta and upperbound=peak+delta. Perform cv::connectedComponents and save the resulting label mask.

  • Step 3: combine all label masks to one label mask.

PS: My actual goal is to segment areas by texture and intensity. I have written a function that transforms areas with different textures into areas with different intensity. If somebody knows of a reliable function that segments areas by texture and intensity, even better.

edit retag flag offensive close merge delete

Comments

Does it work well? If your solution works well, then it is okay to use it. If you think it is worth sharing your source code with other people (and if you are not constrained by an employment contract or non-disclosure agreement that prevents you from sharing code) then there are several routes: (1) just post the source code somewhere, e.g. a personal public repository on GitHub or similar site; (2) create a pull-request on the opencv_contrib project on GitHub. Image processing algorithms can be as general (widely-applicable) or as specific (narrowly-applicable) as it needs to be. Academic publications need a proof of generality. Personal use of algorithms do not need a proof of generality; if it works for you then it is sufficient.

rwong gravatar imagerwong ( 2018-04-16 23:30:03 -0500 )edit

Thank you for answer! I'm actually asking because I don't think my solution is very reliable and I would have imagined there to be an algorithm in OpenCV that does this better.

theaniolad gravatar imagetheaniolad ( 2018-04-18 01:22:07 -0500 )edit

Each method has shortcomings; for example, some are sensitive to random pixel noise (fluctuations), some are sensitive to gaps in pixel connectivity. To diagnose these kinds of issues, the picture is needed.

Consider posting a sample picture, or a sample picture close enough to the type of pictures you need to work with. Words cannot describe pictures. If the image is too big then post to an image hosting site and post the URL here. If it is necessary to crop or hide part of picture (i.e. to keep the picture to the minimum size and amount of information) feel free to do so, as long as the cropped picture is still helpful for the discussion.

rwong gravatar imagerwong ( 2018-04-18 06:41:37 -0500 )edit

Ok, yeah it's easier to just show it than to describe it: Pretty much this picture as grayscale and without the lines separating the fields from each other. The goal would be that each field is labelled as a connected component.. Different colored Fields

theaniolad gravatar imagetheaniolad ( 2018-04-18 09:52:51 -0500 )edit