package org.neuroph.contrib.ocr;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import org.neuroph.contrib.imgrec.ColorMode;
import org.neuroph.contrib.imgrec.ImageRecognitionPlugin;
import org.neuroph.core.Neuron;
import org.neuroph.util.plugins.PluginBase;
/**
* Provides OCR interface for neural network.
*
* @author Zoran Sevarac, Ivana Jovicic, Vladimir Kolarevic, Marko Ivanovic,
* Boris Horvat, Damir Kocic, Nemanja Jovanovic
*/
public class OcrPlugin extends PluginBase implements Serializable {
private static final long serialVersionUID = 1L;
/**
* Ocr plugin name field used for getting plugin from parent neural network.
*/
public static final String OCR_PLUGIN_NAME = "OCR Plugin";
/**
* Image sampling resolution (image dimensions)
*/
private Dimension samplingResolution;
/**
* Color mode used for recognition (full color or black and white)
*/
private ColorMode colorMode;
/**
* Constructor, creates new OCR Plugin for specified sampling resolution and color mode
*
* @param samplingResolution
* image sampling resolution (dimensions)
* @param colorMode recognition color mode
*/
public OcrPlugin(Dimension samplingResolution, ColorMode colorMode) {
super(OCR_PLUGIN_NAME);
this.samplingResolution = samplingResolution;
this.colorMode = colorMode;
}
/**
* This method scales character image to the given dimensions and then does the character recognition.
* Returns recognized character.
* @param charImage character image
* @param scaleToDim dimensions to scale the image before character recognition is done
* @return recognized character
*/
public Character recognizeCharacter(BufferedImage charImage, Dimension scaleToDim) {
BufferedImage resizedImage = this.resizeImage(charImage, scaleToDim.width, scaleToDim.height);
return recognizeCharacter(resizedImage);
}
/**
* Recognizes character from the image and returns character
* @param charImage character image
* @return recognized character
*/
public Character recognizeCharacter(BufferedImage charImage) {
// get the image recognition plugin from neural network
ImageRecognitionPlugin imageRecognition = (ImageRecognitionPlugin) this.getParentNetwork().getPlugin(ImageRecognitionPlugin.class);
HashMap<String, Double> output = imageRecognition.recognizeImage(charImage);
HashMap<String, Neuron> n = imageRecognition.getMaxOutput();
String ch = n.toString().substring(1, 2);
return Character.valueOf(ch.charAt(0));
}
/**
* Recogize the character from the image and returns HashMap with keys as
* characters and recognition probability as values sorted descending by probability.
*
* @param charImage character image
* @return HashMap with keys as characters and recognition probability as values
*/
public HashMap recognizeCharacterProbabilities(BufferedImage charImage) {
// get the image recognition plugin from neural network
ImageRecognitionPlugin imageRecognition =
(ImageRecognitionPlugin) this.getParentNetwork().getPlugin(ImageRecognitionPlugin.class);
// image recognition is done here
HashMap<String, Double> output = imageRecognition.recognizeImage(charImage);
HashMap<Character, Double> recognized = sortHashMapByValues(output);
return recognized;
}
/**
* Resize image to given dimensions (width and height)
* @param image image to resize
* @param width width to resize to
* @param height height to resize to
* @return scaled image
*/
private BufferedImage resizeImage(BufferedImage image, int width, int height) {
BufferedImage resizedImage = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(image, 0, 0, width, height, null);
g.dispose();
return resizedImage;
}
/**
* This private method sorts the result of the recogntion, in order to
* see which letter has the highest probability
*
* @param passedMap the HashMap that holds the resault of the recognition process
*
* @return LinkedHashMap that represents the combination of letters with the
* probability of the correct recognition
*/
private LinkedHashMap sortHashMapByValues(HashMap passedMap) {
List mapKeys = new ArrayList(passedMap.keySet());
List mapValues = new ArrayList(passedMap.values());
Collections.sort(mapValues);
Collections.sort(mapKeys);
Collections.reverse(mapValues);
LinkedHashMap sortedMap = new LinkedHashMap();
Iterator valueIt = mapValues.iterator();
while (valueIt.hasNext()) {
Object val = valueIt.next();
Iterator keyIt = mapKeys.iterator();
while (keyIt.hasNext()) {
Object key = keyIt.next();
String comp1 = passedMap.get(key).toString();
String comp2 = val.toString();
if (comp1.equals(comp2)) {
passedMap.remove(key);
mapKeys.remove(key);
Character charKey = Character.valueOf(key.toString().charAt(0));
sortedMap.put(charKey, (Double) val);
break;
}
}
}
return sortedMap;
}
/**
* Returns color mode used for OCR
* @return color mode used for OCR
*/
public ColorMode getColorMode() {
return colorMode;
}
/**
* Returns sampling resolution used for OCR
* @return sampling resolution used for OCR
*/
public Dimension getSamplingResolution() {
return samplingResolution;
}
}