Class StrongQuadruple3x5ThinningSkeleton2D
- All Implemented Interfaces:
ArrayProcessor,IterativeArrayProcessor<Matrix<? extends UpdatableBitArray>>,ThinningSkeleton
Stronger version of Quadruple3x5ThinningSkeleton2D skeletonization algorithm.
This class implements almost the same algorithm as Quadruple3x5ThinningSkeleton2D,
but the thinning method is more aggressive (and slow: it is the slowest thinning skeleton in this package). This class is also based on analysis of 3x5 aperture.
This algorithm also guarantees that 8-connected "objects"
(areas filled by 1 elements) always stay 8-connected:
see ThinningSkeleton interface about the precise sense of this state.
The main difference from Quadruple3x5ThinningSkeleton2D is that this class never keeps
3x3 and 3x2 rectangles, filled by 1 — they are successfully skeletonized.
(More precisely, there is only one degenerated case, when such rectangles can appear in the
skeletonization result: if all pixels of the bit matrix,
supposed to be infinitely pseudo-cyclically continued, are filled by 1.
All skeletonization algorithms do nothing in this case.)
The corresponding "bad" cases of Quadruple3x5ThinningSkeleton2D will be skeletonized
in the following or similar way:
. . . . . . . . . . . . . . . . 1 . . 1 . . 1 . 1 . . 1 . . 1 . . 1 . 1 . 1 . . . 1 . 1 . 1 . . . . 1 1 1 . . . is transformed to . . 1 . 1 . . . . . 1 1 1 . . . . . 1 . 1 . . . . 1 . 1 . 1 . . . 1 . 1 . 1 . . 1 . . 1 . . 1 . 1 . . 1 . . 1 . 1 . . 1 . . 1 . 1 . . 1 . . 1 . . 1 . 1 . 1 . . . 1 . 1 . 1 . . . . 1 1 1 . . . . . 1 1 1 . . . 1 1 1 1 1 1 1 . is transformed to 1 1 . 1 . 1 1 . . . 1 1 1 . . . . . 1 1 1 . . . . 1 . 1 . 1 . . . 1 . 1 . 1 . . 1 . . 1 . . 1 . 1 . . 1 . . 1 .
Below are some "bad" cases, when some areas cannot be "thinned" by this algorithm:
. . . . . . . . . . . . . . . . . . 1 . . . . . . . . . . . . 1 . . 1 . . . 1 . 1 . 1 . . . 1 . . 1 . . . . 1 1 . . . . . 1 1 1 . . . . . 1 1 . . . . . 1 1 1 1 . . . . 1 . . . . . . 1 1 . . . . 1 . 1 . . . . 1 1 1 1 1 . . . 1 . . 1 . . . . . 1 . . . . . . 1 . . . . . . . . . . . . . . . . . . . . . 1 . . .
It is obvious that the left configuration cannot be thinned more without breaking connectivity. Other configurations, theoretically, can be reduced by removing pixels in intersections of horizontal and vertical lines, for example:
. . . ? . . . . ? . ? . ? . . . ? . ? . . . . . ? . . . . ? ? . ? ? . . . . ? . . . . . . ? . . .
But it means appearing strange 1-pixels "holes" in any intersection of horizontal and vertical lines and seems to be a bad idea for most applications.
I recommend to run this algorithm after finishing OctupleThinningSkeleton2D
and WeakOctupleThinningSkeleton2D algorithms
(for example, with help of IterativeArrayProcessor.chain(IterativeArrayProcessor, double) method).
This class is based on Matrices.asShifted method
with some elementwise logical operations (AND, OR, NOT).
So, the matrix is supposed to be infinitely pseudo-cyclically continued, as well
Matrices.asShifted method supposes it.
You can change this behavior by appending the source matrix with zero elements
by calling Matrix.subMatrix(long[], long[], Matrix.ContinuationMode)Matrix.ContinuationMode.ZERO_CONSTANT.
This class may be applied to a matrix with any number of dimensions, but it is designed for 2-dimensional case: all other dimensions will be ignored.
This class is not thread-safe, but is thread-compatible and can be synchronized manually, if multithread access is necessary.
- Author:
- Daniel Alievsky
-
Field Summary
Fields inherited from class net.algart.arrays.AbstractIterativeArrayProcessor
context, memoryModel -
Method Summary
Modifier and TypeMethodDescriptionasThinning(int directionIndex) Returns currentresult()matrix thinned along the given direction.final booleandone()Returns true if and only if the algorithm was successfully finished and there is no sense to perform further iterations.longEstimates the number of iterations, that should be performed from this moment to finish the algorithm.final voidfreeResources(ArrayContext context) If there are some resources, allocated by this object, which are not controlled by Java garbage collectors — files, streams, sockets, locks, etc. — this method tries to release them (for example, to close any files).getInstance(ArrayContext context, Matrix<? extends UpdatableBitArray> matrix) Creates new instance of this class.final booleanisThinningRequired(int directionIndex) Returns true if and only ifperformIteration(ArrayContext)method really callsThinningSkeleton.asThinning(int directionIndex)for this direction and copies its result to the result matrix.final voidperformIteration(ArrayContext context) Performs the next iteration of the iterative algorithm.final Matrix<? extends UpdatableBitArray>result()Returns the result of the previous iteration.toString()Returns a brief string description of this object.Methods inherited from class net.algart.arrays.AbstractIterativeArrayProcessor
chain, context, limitIterations, part, processMethods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, waitMethods inherited from interface net.algart.arrays.ArrayProcessor
contextMethods inherited from interface net.algart.arrays.IterativeArrayProcessor
chain, done, freeResources, limitIterations, performIteration, process, resultMethods inherited from interface net.algart.matrices.skeletons.ThinningSkeleton
isThinningRequired
-
Method Details
-
getInstance
public static StrongQuadruple3x5ThinningSkeleton2D getInstance(ArrayContext context, Matrix<? extends UpdatableBitArray> matrix) Creates new instance of this class.- Parameters:
context- thecontextthat will be used by this object; may be null, then it will be ignored.matrix- the bit matrix that should be processed and returned byIterativeArrayProcessor.result()method.- Returns:
- new instance of this class.
- Throws:
NullPointerException- if matrix argument is null.
-
estimatedNumberOfIterations
public long estimatedNumberOfIterations()Description copied from interface:IterativeArrayProcessorEstimates the number of iterations, that should be performed from this moment to finish the algorithm. Returns 0 if it is impossible or too difficult to estimate this number: it means that the remaining number of iteration is unknown.This method may require some time for its execution.
You usually don't need to call this method: it is automatically called from time to time by
IterativeArrayProcessor.process()method. It is used for creating subcontexts, describing apartof the full task.This method must be implemented while creating a new iterative array-processing algorithm.
- Specified by:
estimatedNumberOfIterationsin interfaceIterativeArrayProcessor<Matrix<? extends UpdatableBitArray>>- Returns:
- the estimated number of iterations, that should be performed from this moment to finish the algorithm.
-
asThinning
Returns currentresult()matrix thinned along the given direction. The result is "lazy": it is only a view of the current matrix.All said about
Quadruple3x5ThinningSkeleton2D.asThinning(int)method is correct also in this case, but this method perform little "stronger" thinning. directionIndex specifies the "eroded side" of objects, or the direction of thinning:- 0 means removing elements from the left, i.e. from the side
(x−1,y) , - 2 means removing elements from the side
(x,y−1) , - 4 means removing elements from the right, i.e. from the side
(x+1,y) , - 6 means removing elements from the side
(x,y+1) .
result()matrix is returned.- Specified by:
asThinningin interfaceThinningSkeleton- Parameters:
directionIndex- the direction of thinning, from 0 to 7.- Returns:
- the thinned view if the current
IterativeArrayProcessor.result()matrix. - Throws:
IllegalArgumentException- if directionIndex is not in 0..7 range.
- 0 means removing elements from the left, i.e. from the side
-
toString
Returns a brief string description of this object. -
performIteration
Description copied from interface:IterativeArrayProcessorPerforms the next iteration of the iterative algorithm. If the algorithm isIterativeArrayProcessor.done(), the results are unspecified: please never call this method ifIterativeArrayProcessor.done()returns true.You usually don't need to call this method: please call
IterativeArrayProcessor.process()instead. If you need to perform only one or n iterations, you may uselimitIterations(n)call.Warning: this method should ignore the
current execution contextof this object. Instead, this method should use the context of execution specified by context argument. This method is called byIterativeArrayProcessor.process()method with the argument, describinga subtraskof the full algorithm. The context argument may be null: this method should work properly in this case (ignore the context).This method must be implemented while creating a new iterative array-processing algorithm.
- Specified by:
performIterationin interfaceIterativeArrayProcessor<Matrix<? extends UpdatableBitArray>>- Specified by:
performIterationin classAbstractIterativeArrayProcessor<Matrix<? extends UpdatableBitArray>>- Parameters:
context- the context used by this instance for all operations; may be null.
-
done
public final boolean done()Description copied from interface:IterativeArrayProcessorReturns true if and only if the algorithm was successfully finished and there is no sense to perform further iterations.This method usually does not perform actual calculations and works very quickly (just returns and internal flag). However, this condition is not strict.
You usually don't need to call this method: it is automatically called by
IterativeArrayProcessor.process()method.This method must be implemented while creating a new iterative array-processing algorithm.
- Specified by:
donein interfaceIterativeArrayProcessor<Matrix<? extends UpdatableBitArray>>- Specified by:
donein classAbstractIterativeArrayProcessor<Matrix<? extends UpdatableBitArray>>- Returns:
- true if and only if the algorithm was successfully finished.
-
result
Description copied from interface:IterativeArrayProcessorReturns the result of the previous iteration. Usually it isUpdatableArrayorMatrix<? extendsUpdatableArray>. This method returns valid result even if no iterations were performed yet. IfIterativeArrayProcessor.done()method returns true, the result of this method is the final result of iterative processing performed by this instance.This method may return null. In this case, the concrete implementation of this interface should provide additional methods for returning calculation results.
This method does not perform actual calculations and works very quickly.
This method must be implemented while creating a new iterative array-processing algorithm.
- Specified by:
resultin interfaceIterativeArrayProcessor<Matrix<? extends UpdatableBitArray>>- Specified by:
resultin classAbstractIterativeArrayProcessor<Matrix<? extends UpdatableBitArray>>- Returns:
- the result of the previous iteration (may be null).
-
freeResources
Description copied from interface:IterativeArrayProcessorIf there are some resources, allocated by this object, which are not controlled by Java garbage collectors — files, streams, sockets, locks, etc. — this method tries to release them (for example, to close any files). The object stays alive: if the resources will be necessary for following operations, they will be automatically re-acquired.Usually, this method just calls
Array.freeResources(context)andMatrix.freeResources(context)for all temporary arrays and matrices, allocated by this object for storing work data.If
IterativeArrayProcessor.result()method returns AlgART array or matrix (typical situation), this method callsArray.freeResources(context)/Matrix.freeResources(context)methods for this array / matrix.This method may be used in situations when the instance of this object has long time life and will be reused in future.
This method must be implemented while creating a new iterative array-processing algorithm.
- Specified by:
freeResourcesin interfaceIterativeArrayProcessor<Matrix<? extends UpdatableBitArray>>- Specified by:
freeResourcesin classAbstractIterativeArrayProcessor<Matrix<? extends UpdatableBitArray>>- Parameters:
context- the context of execution; may be null, then it will be ignored.
-
isThinningRequired
public final boolean isThinningRequired(int directionIndex) Description copied from interface:ThinningSkeletonReturns true if and only ifperformIteration(ArrayContext)method really callsThinningSkeleton.asThinning(int directionIndex)for this direction and copies its result to the result matrix. It depends on the implementation of this interface.- Specified by:
isThinningRequiredin interfaceThinningSkeleton- Parameters:
directionIndex- the direction of thinning, from 0 to 7.- Returns:
- whether the matrix should be thinned along this direction.
-