All Downloads are FREE. Search and download functionalities are using the official Maven repository.

boofcv.alg.segmentation.watershed.RemoveWatersheds Maven / Gradle / Ivy

Go to download

BoofCV is an open source Java library for real-time computer vision and robotics applications.

The newest version!
/*
 * Copyright (c) 2021, Peter Abeles. All Rights Reserved.
 *
 * This file is part of BoofCV (http://boofcv.org).
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package boofcv.alg.segmentation.watershed;

import boofcv.struct.image.GrayS32;
import org.ddogleg.struct.DogArray_I32;

/**
 * Examines a segmented image created by {@link WatershedVincentSoille1991} and merged watershed pixels
 * into neighboring regions. Since there is no good rule for which region the pixel should be
 * merged into, it is merged into the first valid one.
 *
 * @author Peter Abeles
 */
public class RemoveWatersheds {

	// relative indexes of connected pixels
	private final int[] connect = new int[4];

	// list of watershed pixels which have yet to be merged.
	private DogArray_I32 open = new DogArray_I32();
	private DogArray_I32 open2 = new DogArray_I32();

	/**
	 * Removes watersheds from the segmented image. The input image must be the entire original
	 * segmented image and assumes the outside border is filled with values < 0. To access
	 * this image call {@link boofcv.alg.segmentation.watershed.WatershedVincentSoille1991#getOutputBorder()}.
	 * Each watershed is assigned the value of an arbitrary neighbor. 4-connect rule is used for neighbors.
	 * Doesn't matter if initial segmented was done using another connectivity rule. The value of each region i
	 * s reduced by one at the very end.
	 *
	 * @param segmented Entire segmented image (including border of -1 values) with watersheds
	 */
	public void remove( GrayS32 segmented ) {
		// very quick sanity check
		if (segmented.get(0, 0) >= 0)
			throw new IllegalArgumentException("The segmented image must contain a border of -1 valued pixels. See" +
					" JavaDoc for important details you didn't bother to read about.");

		open.reset();

		connect[0] = -1;
		connect[1] = 1;
		connect[2] = segmented.stride;
		connect[3] = -segmented.stride;

		// step through the inner pixels and find watershed pixels
		for (int y = 1; y < segmented.height - 1; y++) {
			int index = y*segmented.stride + 1;
			for (int x = 1; x < segmented.width - 1; x++, index++) {
				if (segmented.data[index] == 0) {
					open.add(index);
				}
			}
		}

		// assign region values to watersheds until they are all assigned
		while (open.size != 0) {
			open2.reset();
			for (int i = 0; i < open.size; i++) {
				int index = open.get(i);
				// assign it to the first valid region it finds
				for (int j = 0; j < 4; j++) {
					// the outside border in the enlarged segmented image will have -1 and watersheds are 0
					int r = segmented.data[index + connect[j]];
					if (r > 0) {
						segmented.data[index] = r;
						break;
					}
				}

				// see if it was not assigned a region
				if (segmented.data[index] == 0) {
					open2.add(index);
				}
			}

			// swap open and open2
			DogArray_I32 tmp = open;
			open = open2;
			open2 = tmp;
		}

		// watershed pixels have a value of 0 and have been removed. So change the region ID numbers by 1
		for (int y = 1; y < segmented.height - 1; y++) {
			int index = y*segmented.stride + 1;
			for (int x = 1; x < segmented.width - 1; x++, index++) {
				segmented.data[index]--;
			}
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy