// Catalano Imaging Library
// The Catalano Framework
//
// Copyright © Diego Catalano, 2012-2016
// diego.catalano at live.com
//
//
//    This library is free software; you can redistribute it and/or
//    modify it under the terms of the GNU Lesser General Public
//    License as published by the Free Software Foundation; either
//    version 2.1 of the License, or (at your option) any later version.
//
//    This library is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//    Lesser General Public License for more details.
//
//    You should have received a copy of the GNU Lesser General Public
//    License along with this library; if not, write to the Free Software
//    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
//

package Catalano.Imaging.Filters;

import Catalano.Imaging.FastBitmap;
import Catalano.Imaging.IApplyInPlace;
import Catalano.Imaging.Tools.ImageHistogram;
import Catalano.Imaging.Tools.ImageStatistics;
import Catalano.Math.Distances.Distance;
import Catalano.Math.Matrix;

/**
 * Rosin Threshold.
 * 
 *  Unimodal thresholding is an algorithm for automatic image threshold selection in image processing.
 * Most threshold selection algorithms assume that the intensity histogram is multi-modal; 
 * typically bimodal. However, some types of images are essentially unimodal since a much
 * larger proportion of just one class of pixels (e.g. the background) is present in the image,
 * and dominates the histogram. 
 * 
 *  Rosin Threshod uses Maximum deviation algorithm: a straight line is drawn
 * from the histogram peak to the end of the tail, and the
 * threshold is selected at the point of the histogram furthest from the straight line 
 * 
 * @author Diego Catalano
 */
public class RosinThreshold implements IApplyInPlace{

    /**
     * Initialize a new instance of the RosinThreshold class.
     */
    public RosinThreshold() {}

    @Override
    public void applyInPlace(FastBitmap fastBitmap) {
        if(fastBitmap.isGrayscale()){
            int value = CalculateThreshold(fastBitmap);
            
            Threshold t = new Threshold(value);
            t.applyInPlace(fastBitmap);
            
        }
        else{
            throw new IllegalArgumentException("Rosin Threshold only works in grayscale images.");
        }
    }
    
    /**
     * Calculate binarization threshold for the given image.
     * @param fastBitmap FastBitmap.
     * @return Threshold value.
     */
    public int CalculateThreshold(FastBitmap fastBitmap){
        
        if(fastBitmap.isGrayscale()) {
            
            ImageStatistics stat = new ImageStatistics(fastBitmap);
            ImageHistogram hist = stat.getHistogramGray();
            
            int[] values = hist.getValues();
            
            int maxIndex = Matrix.MaxIndex(values);
            int maxValue = values[maxIndex];

            int lastIndex = maxIndex;
            for (int i = lastIndex; i < values.length; i++) {
                if (values[i] > 0){
                    lastIndex = i;
                }
            }

            int lastValue = values[lastIndex];

            double d = Distance.Euclidean(maxIndex, maxValue, lastIndex, lastValue);

            int threshold = lastIndex;
            if (d != 0){
                
                double t = -1;
                
                for (int i = maxIndex; i < lastIndex; i++) {
                    
                    int tempIndex = i;
                    int tempVal = values[i];
                    
                    double p = ((lastIndex - maxIndex) * (maxValue - tempVal) - (maxIndex - tempIndex) * (lastValue - maxValue));
                    p /= d;
                    
                    if ((p > t) && (values[i] > 0)){
                        t = (int)p;
                        threshold = i;
                    }
                }
            }
            return threshold;
        }
        else{
            throw new IllegalArgumentException("Rosin Threshold only works in grayscale images.");
        }
    }
}
 

Ads help maintain this website.