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

boofcv.alg.feature.detect.edge.impl.ImplEdgeNonMaxSuppression_MT Maven / Gradle / Ivy

Go to download

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

There is a newer version: 1.1.7
Show newest version
/*
 * Copyright (c) 2011-2019, 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.feature.detect.edge.impl;

import boofcv.concurrency.BoofConcurrency;
import boofcv.core.image.border.FactoryImageBorderAlgs;
import boofcv.struct.border.ImageBorder_F32;
import boofcv.struct.image.GrayF32;
import boofcv.struct.image.GrayS8;


/**
 * Algorithms for performing non-max suppression.  Edge intensities are set to zero if adjacent pixels
 * have a value greater than the current value.  Adjacency is determined by the gradients
 * discretized direction.
 *
 * NOTE: This is technically not true non-maximum suppression because equal values are allowed.
 *
 * @author Peter Abeles
 */
@SuppressWarnings("Duplicates")
public class ImplEdgeNonMaxSuppression_MT {

	/**
	 * Only processes the inner image.  Ignoring the border.
	 */
	static public void inner4(GrayF32 intensity , GrayS8 direction , GrayF32 output )
	{
		final int w = intensity.width;
		final int h = intensity.height-1;

		BoofConcurrency.loopFor(1,h,y->{
			int indexI = intensity.startIndex + y*intensity.stride+1;
			int indexD = direction.startIndex + y*direction.stride+1;
			int indexO = output.startIndex + y*output.stride+1;

			int end = indexI + w - 2;
			for( ; indexI < end; indexI++ , indexD++, indexO++ ) {
				int dir = direction.data[indexD];
				int dx,dy;
				
				if( dir == 0 ) {
					dx = 1; dy = 0;
				} else if( dir == 1 ) {
					dx = 1; dy = 1;
				} else if( dir == 2 ) {
					dx = 0; dy = 1;
				} else {
					dx = 1; dy = -1;
				}

				float middle = intensity.data[indexI];

				// suppress the value if either of its neighboring values are more than or equal to it
				if( intensity.data[indexI-dx-dy*intensity.stride] > middle || intensity.data[indexI+dx+dy*intensity.stride] > middle ) {
					output.data[indexO] = 0;
				} else {
					output.data[indexO] = middle;
				}
			}
		});
	}

	/**
	 * Slow algorithm which processes the whole image.
	 */
	static public void naive4(GrayF32 _intensity , GrayS8 direction , GrayF32 output )
	{
		final int w = _intensity.width;
		final int h = _intensity.height;

		ImageBorder_F32 intensity = (ImageBorder_F32)FactoryImageBorderAlgs.value(_intensity, 0);

		BoofConcurrency.loopFor(0,h,y->{
			for( int x = 0; x < w; x++ ) {
				int dir = direction.get(x,y);
				int dx,dy;

				if( dir == 0 ) {
					dx = 1; dy = 0;
				} else if( dir == 1 ) {
					dx = 1; dy = 1;
				} else if( dir == 2 ) {
					dx = 0; dy = 1;
				} else {
					dx = 1; dy = -1;
				}

				float left = intensity.get(x-dx,y-dy);
				float middle = intensity.get(x,y);
				float right = intensity.get(x+dx,y+dy);

				// suppress the value if either of its neighboring values are more than or equal to it
				if( left > middle || right > middle ) {
					output.set(x,y,0);
				} else {
					output.set(x,y,middle);
				}
			}
		});

	}

	/**
	 * Just processes the image border.
	 */
	static public void border4(GrayF32 _intensity , GrayS8 direction , GrayF32 output )
	{
		int w = _intensity.width;
		int h = _intensity.height-1;

		ImageBorder_F32 intensity = (ImageBorder_F32)FactoryImageBorderAlgs.value(_intensity, 0);

		// top border
		BoofConcurrency.loopFor(0,w,x->{
			int dir = direction.get(x,0);
			int dx,dy;

			if( dir == 0 ) {
				dx = 1; dy = 0;
			} else if( dir == 1 ) {
				dx = 1; dy = 1;
			} else if( dir == 2 ) {
				dx = 0; dy = 1;
			} else {
				dx = 1; dy = -1;
			}

			float left = intensity.get(x-dx,-dy);
			float middle = intensity.get(x,0);
			float right = intensity.get(x+dx,dy);

			if( left > middle || right > middle ) {
				output.set(x,0,0);
			} else {
				output.set(x,0,middle);
			}
		});

		// bottom border
		BoofConcurrency.loopFor(0,w,x->{
			int dir = direction.get(x,h);
			int dx,dy;

			if( dir == 0 ) {
				dx = 1; dy = 0;
			} else if( dir == 1 ) {
				dx = 1; dy = 1;
			} else if( dir == 2 ) {
				dx = 0; dy = 1;
			} else {
				dx = 1; dy = -1;
			}

			float left = intensity.get(x-dx,h-dy);
			float middle = intensity.get(x,h);
			float right = intensity.get(x+dx,h+dy);

			if( left > middle || right > middle ) {
				output.set(x,h,0);
			} else {
				output.set(x,h,middle);
			}
		});

		// left border
		BoofConcurrency.loopFor(1,h,y->{
			int dir = direction.get(0,y);
			int dx,dy;

			if( dir == 0 ) {
				dx = 1; dy = 0;
			} else if( dir == 1 ) {
				dx = 1; dy = 1;
			} else if( dir == 2 ) {
				dx = 0; dy = 1;
			} else {
				dx = 1; dy = -1;
			}

			float left = intensity.get(-dx,y-dy);
			float middle = intensity.get(0,y);
			float right = intensity.get(dx,y+dy);

			if( left > middle || right > middle ) {
				output.set(0,y,0);
			} else {
				output.set(0,y,middle);
			}
		});

		// right border
		int _w = w - 1;
		BoofConcurrency.loopFor(1,h,y->{
			int dir = direction.get(_w,y);
			int dx,dy;

			if( dir == 0 ) {
				dx = 1; dy = 0;
			} else if( dir == 1 ) {
				dx = 1; dy = 1;
			} else if( dir == 2 ) {
				dx = 0; dy = 1;
			} else {
				dx = 1; dy = -1;
			}

			float left = intensity.get(_w-dx,y-dy);
			float middle = intensity.get(_w,y);
			float right = intensity.get(_w+dx,y+dy);

			if( left > middle || right > middle ) {
				output.set(_w,y,0);
			} else {
				output.set(_w,y,middle);
			}
		});
	}

	/**
	 * Only processes the inner image.  Ignoring the border.
	 */
	static public void inner8(GrayF32 intensity , GrayS8 direction , GrayF32 output )
	{
		final int w = intensity.width;
		final int h = intensity.height-1;

		BoofConcurrency.loopFor(1,h,y->{
			int indexI = intensity.startIndex + y*intensity.stride+1;
			int indexD = direction.startIndex + y*direction.stride+1;
			int indexO = output.startIndex + y*output.stride+1;

			int end = indexI + w - 2;
			for( ; indexI < end; indexI++ , indexD++, indexO++ ) {
				int dir = direction.data[indexD];
				int dx,dy;

				if( dir == 0 || dir == 4) {
					dx = 1; dy = 0;
				} else if( dir == 1 || dir == -3) {
					dx = 1; dy = 1;
				} else if( dir == 2 || dir == -2) {
					dx = 0; dy = 1;
				} else {
					dx = 1; dy = -1;
				}

				float middle = intensity.data[indexI];

				// suppress the value if either of its neighboring values are more than or equal to it
				if( intensity.data[indexI-dx-dy*intensity.stride] > middle || intensity.data[indexI+dx+dy*intensity.stride] > middle ) {
					output.data[indexO] = 0;
				} else {
					output.data[indexO] = middle;
				}
			}
		});
	}

	/**
	 * Slow algorithm which processes the whole image.
	 */
	static public void naive8(GrayF32 _intensity , GrayS8 direction , GrayF32 output )
	{
		final int w = _intensity.width;
		final int h = _intensity.height;

		ImageBorder_F32 intensity = (ImageBorder_F32)FactoryImageBorderAlgs.value(_intensity, 0);

		BoofConcurrency.loopFor(0,h,y->{
			for( int x = 0; x < w; x++ ) {
				int dir = direction.get(x,y);
				int dx,dy;

				if( dir == 0 || dir == 4) {
					dx = 1; dy = 0;
				} else if( dir == 1 || dir == -3) {
					dx = 1; dy = 1;
				} else if( dir == 2 || dir == -2) {
					dx = 0; dy = 1;
				} else {
					dx = 1; dy = -1;
				}

				float left = intensity.get(x-dx,y-dy);
				float middle = intensity.get(x,y);
				float right = intensity.get(x+dx,y+dy);

				// suppress the value if either of its neighboring values are more than or equal to it
				if( left > middle || right > middle ) {
					output.set(x,y,0);
				} else {
					output.set(x,y,middle);
				}
			}
		});

	}

	/**
	 * Just processes the image border.
	 */
	static public void border8(GrayF32 _intensity , GrayS8 direction , GrayF32 output )
	{
		int w = _intensity.width;
		int h = _intensity.height-1;

		ImageBorder_F32 intensity = (ImageBorder_F32)FactoryImageBorderAlgs.value(_intensity, 0);

		// top border
		BoofConcurrency.loopFor(0,w,x->{
			int dir = direction.get(x,0);
			int dx,dy;

			if( dir == 0 || dir == 4) {
				dx = 1; dy = 0;
			} else if( dir == 1 || dir == -3) {
				dx = 1; dy = 1;
			} else if( dir == 2 || dir == -2) {
				dx = 0; dy = 1;
			} else {
				dx = 1; dy = -1;
			}

			float left = intensity.get(x-dx,-dy);
			float middle = intensity.get(x,0);
			float right = intensity.get(x+dx,dy);

			if( left > middle || right > middle ) {
				output.set(x,0,0);
			} else {
				output.set(x,0,middle);
			}
		});

		// bottom border
		BoofConcurrency.loopFor(0,w,x->{
			int dir = direction.get(x,h);
			int dx,dy;

			if( dir == 0 || dir == 4) {
				dx = 1; dy = 0;
			} else if( dir == 1 || dir == -3) {
				dx = 1; dy = 1;
			} else if( dir == 2 || dir == -2) {
				dx = 0; dy = 1;
			} else {
				dx = 1; dy = -1;
			}

			float left = intensity.get(x-dx,h-dy);
			float middle = intensity.get(x,h);
			float right = intensity.get(x+dx,h+dy);

			if( left > middle || right > middle ) {
				output.set(x,h,0);
			} else {
				output.set(x,h,middle);
			}
		});

		// left border
		BoofConcurrency.loopFor(1,h,y->{
			int dir = direction.get(0,y);
			int dx,dy;

			if( dir == 0 || dir == 4) {
				dx = 1; dy = 0;
			} else if( dir == 1 || dir == -3) {
				dx = 1; dy = 1;
			} else if( dir == 2 || dir == -2) {
				dx = 0; dy = 1;
			} else {
				dx = 1; dy = -1;
			}

			float left = intensity.get(-dx,y-dy);
			float middle = intensity.get(0,y);
			float right = intensity.get(dx,y+dy);

			if( left > middle || right > middle ) {
				output.set(0,y,0);
			} else {
				output.set(0,y,middle);
			}
		});

		// right border
		int _w = w - 1;
		BoofConcurrency.loopFor(1,h,y->{
			int dir = direction.get(_w,y);
			int dx,dy;

			if( dir == 0 || dir == 4) {
				dx = 1; dy = 0;
			} else if( dir == 1 || dir == -3) {
				dx = 1; dy = 1;
			} else if( dir == 2 || dir == -2) {
				dx = 0; dy = 1;
			} else {
				dx = 1; dy = -1;
			}

			float left = intensity.get(_w-dx,y-dy);
			float middle = intensity.get(_w,y);
			float right = intensity.get(_w+dx,y+dy);

			if( left > middle || right > middle ) {
				output.set(_w,y,0);
			} else {
				output.set(_w,y,middle);
			}
		});
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy