Beispiel für die Verwendung einer OCR-Engine zur Verarbeitung von Textausschitten.
Jadice-Viewer bietet die Möglichkeit mittels des TextSelectionTools einen Bereich eines Textes aus zu wählen. Dieser Bereich kann beispielsweise als Bild gerendert und in der Zwischenablage gespeichert werden. Mit ein paar Anpassungen lässt sich das so erzeugte Bild an eine OCR-Engine weiterleiten die dann den enthaltenen Text extrahieren kann. Um diese Funktionalität mit der jadice documentplatform zu nutzten genügt es ein eigenes Command zu erstellen, dass die obengenannten Schritte durchfürht. Das folgende Beispiel zeigt eine solche Implementierung des AbstractSelectionCommands:
public class OCRSelectedAreaCommand extends AbstractSelectionCommand { Logger log = LoggerFactory.getLogger(OCRSelectedAreaCommand.class); private boolean canExecute = true; private int exportResolution = 72; @Override protected boolean canExecute() { return canExecute; }; private PageView pageView; @Override protected void execute() { canExecute = false; final Selection selection = getFirstSelection(); final Page page = selection.getPage(); final Rectangle2D bounds = selection.getBounds(); // Resolution for image // Default value Resolution imgResolution = new Resolution(200.0f); SimpleTesseractWrapper wrapper = new SimpleTesseractWrapper(); BufferedImage image = getRendering(page, bounds); wrapper.doOcr(image, bounds, imgResolution); String text = wrapper.loadResult(); Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(text), null); canExecute = true; } protected BufferedImage getRendering(Page page, Rectangle2D area) { PageImageRenderer renderer = new PageImageRenderer(page); if (null != pageView) renderer.setRenderControls(pageView.getPageControls(page).createSnapshot()); RenderControls rc = renderer.getRenderControls(); rc.getBaseRenderSettings().setDeviceResolution(getExportResolution()); Rectangle roi = createTransformedBounds(rc.getBaseRenderSettings().getAffineTransform(page.getSize()), area); roi = roi.intersection(new Rectangle(Pages.getRenderedSize(page, rc))); renderer.setRenderArea(roi); renderer.setEnableCaching(true); return renderer.renderImage(); } public int getExportResolution() { return exportResolution; } public void setExportResolution(int exportResolution) { this.exportResolution = exportResolution; } }
Des weitern wird eine Klasse für die Kommunikation mit der Tesseract-Ocr Engine benötigt. Diese Kommunikation wird in diesem Beispiel über die Ansteuerung des Command-line Interfaces realisiert.
Die Klasse hat folgende Aufgaben:
- Anstreuerung des CLI- der OCR-Engine (Tesseract-ocr).
- Einlesen des Ergebnisses der OCR-Verarbeitung als String.
public class SimpleTesseractWrapper { Logger LOGGER = LoggerFactory.getLogger(SimpleTesseractWrapper.class); final String installPath = "C:/Program Files (x86)/Tesseract-OCR/"; private File outputFile = new File("c:/tmp/ocr-out/"); private File tempFile = new File("c:/tmp/ocr-in/"); private final String language = "eng"; public SimpleTesseractWrapper() { try { tempFile = File.createTempFile("temp_ocr", ".png"); outputFile = File.createTempFile("temp_ocr", ".txt"); } catch (IOException e) { LOGGER.error("Could not create temp file", e); } } public void doOcr(BufferedImage image, Rectangle2D roi, Resolution resolution) { InputStream stderr = null; String outputFileName = outputFile.getParent() + File.separator + outputFile.getName().replace(".txt", ""); BufferedReader br = null; try { ImageIO.write(image, "PNG", tempFile); } catch (IOException e1) { LOGGER.error("Error writing File", e1); } try { ProcessBuilder builder = new ProcessBuilder(installPath +File.separator+ "tesseract.exe", tempFile.getAbsolutePath(), outputFileName, "-l " + language); Process proc = builder.start(); stderr = proc.getErrorStream(); InputStreamReader isr = new InputStreamReader(stderr); br = new BufferedReader(isr); String line = null; while ((line = br.readLine()) != null) System.out.println(line); int exitVal = proc.waitFor(); if (exitVal != 0) { LOGGER.debug("Process exitValue: " + exitVal); } } catch (Exception e) { // TODO Error Handling } finally { try { stderr.close(); tempFile.delete(); br.close(); } catch (IOException e) { LOGGER.error("Couldn't close Streams", e); } } } public String loadResult() { String content = null; File file = outputFile; try { FileReader reader = new FileReader(file); char[] chars = new char[(int) file.length()]; reader.read(chars); content = new String(chars); reader.close(); } catch (IOException e) { e.printStackTrace(); } return content; } }
Related articles