diff --git a/README.md b/README.md index 4162812..b4023ab 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ Для распознавания используется OCR Tesseract 5 https://github.com/tesseract-ocr/tesseract -Для Windows 7, я использую https://github.com/UB-Mannheim/tesseract/wiki +Для Windows 7, используется https://github.com/UB-Mannheim/tesseract/wiki Для работы с djvu используется DjVuLibre https://djvu.sourceforge.net/index.html + +Документация по командам https://djvu.sourceforge.net/doc/man/ddjvu.html \ No newline at end of file diff --git a/src/main/java/ru/mcs/udk/UDKSearcher.java b/src/main/java/ru/mcs/udk/UDKSearcher.java index 5a3aa72..4712d69 100644 --- a/src/main/java/ru/mcs/udk/UDKSearcher.java +++ b/src/main/java/ru/mcs/udk/UDKSearcher.java @@ -6,7 +6,7 @@ import org.apache.commons.cli.HelpFormatter; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; -import ru.mcs.udk.document.DocumentScanner; +import ru.mcs.udk.scanner.DocumentScanner; import ru.mcs.udk.factory.DocumentScannerFactory; import ru.mcs.udk.wrapper.DocumentInfo; @@ -66,9 +66,9 @@ System.out.println("Результаты записаны в файл: " + outputFile); } - // проходимся по всем найденым файлам и ищем УДК + // проходимся по всем найденным файлам и ищем УДК // findUdk(outputFile); - findUdk2(outputFile, foundFiles.size()); + findUdk(outputFile, foundFiles.size()); } catch (ParseException e) { System.out.println("Ошибка при разборе аргументов: " + e.getMessage()); printHelp(options); @@ -114,7 +114,7 @@ formatter.printHelp("UDKSearcher", options); } - private static void findUdk2(String fileCsv, int totalFiles) { + private static void findUdk(String fileCsv, int totalFiles) { Path inputPath = Paths.get(fileCsv); Path outputPath = inputPath.resolveSibling(inputPath.getFileName() + ".out"); DocumentInfo documentInfo; @@ -141,22 +141,20 @@ // Вычисляем процент завершения double progress = (double) processedFiles / totalFiles * 100; System.out.printf("Прогресс: %.2f%%\r", progress); - writer.write(String.format("%s;%s;%s;%s;%s;%s", line, documentInfo.getFileSize(), documentInfo.getTime(), documentInfo.getLanguage(), documentInfo.getUdk(), documentInfo.getError())); + writer.write(String.format("%s;%s;%s;%s;%s;%s;%s", line, documentInfo.getFileSize(), documentInfo.getTime(), documentInfo.getLanguage(), documentInfo.getUdk(), documentInfo.getError(), documentInfo.getDocumentFormat())); } else { - writer.write(String.format("%s;%s;%s;%s;%s;%s", line, "File not found", "", "", "", "")); // Если файл не найден + writer.write(String.format("%s;%s;%s;%s;%s;%s;%s", line, "File not found", "", "", "", "", "")); // Если файл не найден } writer.newLine(); } } catch (Exception e) { System.err.println("Error: " + e.getMessage()); - e.printStackTrace(); - System.exit(2); } try { replaceOriginalFile(inputPath, outputPath); } catch (Exception e) { - e.printStackTrace(); + System.err.println("Error: " + e.getMessage()); } } @@ -172,6 +170,7 @@ // Удаляем бэкап после успешной замены Files.deleteIfExists(backup); } catch (Exception e) { + System.err.println("Error: " + e.getMessage()); // Восстанавливаем из бэкапа при ошибке Files.move(backup, original, StandardCopyOption.REPLACE_EXISTING); throw e; diff --git a/src/main/java/ru/mcs/udk/document/DocumentScanner.java b/src/main/java/ru/mcs/udk/document/DocumentScanner.java deleted file mode 100644 index 567f5c9..0000000 --- a/src/main/java/ru/mcs/udk/document/DocumentScanner.java +++ /dev/null @@ -1,10 +0,0 @@ -package ru.mcs.udk.document; - -import ru.mcs.udk.wrapper.DocumentInfo; - -import java.io.File; - -public interface DocumentScanner { - - DocumentInfo getUDK(File file); -} diff --git a/src/main/java/ru/mcs/udk/document/impl/DJVUScanner.java b/src/main/java/ru/mcs/udk/document/impl/DJVUScanner.java deleted file mode 100644 index c4466b4..0000000 --- a/src/main/java/ru/mcs/udk/document/impl/DJVUScanner.java +++ /dev/null @@ -1,52 +0,0 @@ -package ru.mcs.udk.document.impl; - -import net.sourceforge.tess4j.TesseractException; -import ru.mcs.udk.wrapper.DocumentInfo; -import ru.mcs.udk.document.DocumentScanner; -import ru.mcs.udk.utils.DocumentUtils; - -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; - -import static ru.mcs.udk.utils.DocumentUtils.findUDK; - -public class DJVUScanner implements DocumentScanner { - @Override - public DocumentInfo getUDK(File djvuFile) { - // Засекаем время начала поиска - long startTime = System.currentTimeMillis(); - DocumentInfo documentInfo = new DocumentInfo(); - documentInfo.setError(""); - documentInfo.setUdk(""); - for (int pageIndex = 1; pageIndex < 7; pageIndex++) { - String outputFile = String.format("temp/page_%d.tiff", pageIndex); - Process process; - try { - process = new ProcessBuilder("ddjvu", - "-format=tiff", - "-quality=90", - "-page=" + pageIndex, - djvuFile.getAbsolutePath(), - outputFile).start(); - int exitCode = process.waitFor(); - if (exitCode == 0) { - BufferedImage image = ImageIO.read(new File(outputFile)); - String text = DocumentUtils.getText(image); - String udk = findUDK(text); - documentInfo.setUdk(udk); - if (udk != null && !udk.isEmpty()) { - documentInfo.setLanguage("ru"); - break; - } - } - } catch (InterruptedException | IOException | TesseractException e) { - documentInfo.setError(e.getMessage()); - } - } - long endTime = System.currentTimeMillis(); - documentInfo.setTime(endTime - startTime); - return documentInfo; - } -} diff --git a/src/main/java/ru/mcs/udk/document/impl/PDFScanner.java b/src/main/java/ru/mcs/udk/document/impl/PDFScanner.java deleted file mode 100644 index d4ac5d8..0000000 --- a/src/main/java/ru/mcs/udk/document/impl/PDFScanner.java +++ /dev/null @@ -1,71 +0,0 @@ -package ru.mcs.udk.document.impl; - -import net.sourceforge.tess4j.TesseractException; -import org.apache.pdfbox.Loader; -import org.apache.pdfbox.pdmodel.PDDocument; -import org.apache.pdfbox.rendering.PDFRenderer; -import org.apache.pdfbox.text.PDFTextStripper; -import ru.mcs.udk.wrapper.DocumentInfo; -import ru.mcs.udk.document.DocumentScanner; -import ru.mcs.udk.utils.DocumentUtils; - -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.text.DecimalFormat; - -import static ru.mcs.udk.utils.DocumentUtils.findUDK; -import static ru.mcs.udk.utils.DocumentUtils.isCyrillic; - -public class PDFScanner implements DocumentScanner { - - @Override - public DocumentInfo getUDK(File file) { - // Засекаем время начала поиска - long startTime = System.currentTimeMillis(); - DocumentInfo documentInfo = new DocumentInfo(); - documentInfo.setError(""); - documentInfo.setUdk(""); - documentInfo.setFileSize(getSizeFile(file)); - try (PDDocument document = Loader.loadPDF(file)) { - PDFTextStripper stripper = new PDFTextStripper(); - // Устанавливаем диапазон страниц для анализа (первые три страницы) - stripper.setStartPage(1); - stripper.setEndPage(Math.min(3, document.getNumberOfPages())); - String text = stripper.getText(document); - documentInfo.setUdk(findUDK(text)); - - documentInfo.setLanguage(isCyrillic(file.getName()) ? "ru" : "en"); - - if ((documentInfo.getUdk() == null || documentInfo.getUdk().isBlank()) && documentInfo.getLanguage().equals("ru")) { - documentInfo.setUdk(getUdkByImage(document)); - } - } catch (IOException | TesseractException e) { - documentInfo.setError(e.getMessage()); - } - long endTime = System.currentTimeMillis(); - documentInfo.setTime(endTime - startTime); - return documentInfo; - } - - private String getSizeFile(File file) { - double sizeInMB = (double) file.length() / (1024 * 1024); // Размер в мегабайтах - DecimalFormat df = new DecimalFormat("#.##"); // Форматирование до двух знаков после запятой - - return df.format(sizeInMB) + " Mb"; - } - - private static String getUdkByImage(PDDocument document) throws IOException, TesseractException { - PDFRenderer renderer = new PDFRenderer(document); - - for (int pageIndex = 0; pageIndex < 6; pageIndex++) { - BufferedImage image = renderer.renderImageWithDPI(pageIndex, 300); - String text = DocumentUtils.getText(image); - String udk = findUDK(text); - if (udk != null) { - return udk; - } - } - return ""; - } -} diff --git a/src/main/java/ru/mcs/udk/factory/DocumentScannerFactory.java b/src/main/java/ru/mcs/udk/factory/DocumentScannerFactory.java index 9389a34..881df17 100644 --- a/src/main/java/ru/mcs/udk/factory/DocumentScannerFactory.java +++ b/src/main/java/ru/mcs/udk/factory/DocumentScannerFactory.java @@ -1,8 +1,9 @@ package ru.mcs.udk.factory; -import ru.mcs.udk.document.DocumentScanner; -import ru.mcs.udk.document.impl.DJVUScanner; -import ru.mcs.udk.document.impl.PDFScanner; + +import ru.mcs.udk.scanner.DocumentScanner; +import ru.mcs.udk.scanner.impl.DJVUScanner; +import ru.mcs.udk.scanner.impl.PDFScanner; public class DocumentScannerFactory { public static DocumentScanner getScanner(String filePath) { diff --git a/src/main/java/ru/mcs/udk/utils/DocumentUtils.java b/src/main/java/ru/mcs/udk/utils/DocumentUtils.java index 1782ece..ad34cf3 100644 --- a/src/main/java/ru/mcs/udk/utils/DocumentUtils.java +++ b/src/main/java/ru/mcs/udk/utils/DocumentUtils.java @@ -9,10 +9,26 @@ import java.util.regex.Pattern; public class DocumentUtils { + private static volatile Tesseract instance; + + public static Tesseract getInstance() { + Tesseract localInstance = instance; + if (localInstance == null) { + synchronized (Tesseract.class) { + localInstance = instance; + if (localInstance == null) { + System.setProperty("TESSDATA_PREFIX", "/windows"); + instance = localInstance = new Tesseract(); + instance.setDatapath("windows\\tessdata\\");; + instance.setLanguage("rus"); + } + } + } + return localInstance; + } + public static void main(String[] args) { - Tesseract tesseract = new Tesseract(); - tesseract.setDatapath("d:\\program\\Tesseract-OCR\\tessdata\\"); - tesseract.setLanguage("rus"); + Tesseract tesseract = getInstance(); try { String text = tesseract.doOCR(new File("book3.PNG")); @@ -20,7 +36,7 @@ String udk = findUDK(text); System.out.println("UDK " + udk); } catch (TesseractException e) { - e.printStackTrace(); + System.err.println("Error: " + e.getMessage()); } } diff --git a/src/main/java/ru/mcs/udk/wrapper/DocumentInfo.java b/src/main/java/ru/mcs/udk/wrapper/DocumentInfo.java index c2298ef..b791823 100644 --- a/src/main/java/ru/mcs/udk/wrapper/DocumentInfo.java +++ b/src/main/java/ru/mcs/udk/wrapper/DocumentInfo.java @@ -6,6 +6,7 @@ long time; String error; String fileSize; + DocumentFormat documentFormat; public String getLanguage() { return language; @@ -46,4 +47,12 @@ public void setFileSize(String fileSize) { this.fileSize = fileSize; } + + public DocumentFormat getDocumentFormat() { + return documentFormat; + } + + public void setDocumentFormat(DocumentFormat documentFormat) { + this.documentFormat = documentFormat; + } } diff --git a/windows.cmd b/windows.cmd new file mode 100644 index 0000000..be0e376 --- /dev/null +++ b/windows.cmd @@ -0,0 +1,33 @@ +@echo off +setlocal enabledelayedexpansion + +:: Пути +set "ROOT_DIR=%~dp0" +set "WGET=%ROOT_DIR%program\wget.exe" +set "TARGET_DIR=%ROOT_DIR%windows" +set "TESSDATA_DIR=%TARGET_DIR%\tessdata" + +:: 1. Создаем папку windows +if not exist "%TARGET_DIR%" mkdir "%TARGET_DIR%" + +:: 2. Скачиваем Tesseract 5.5.0 +echo Загрузка Tesseract... +"%WGET%" -O "%TARGET_DIR%\tesseract.exe" "https://github.com/tesseract-ocr/tesseract/releases/download/5.5.0/tesseract-ocr-w64-setup-5.5.0.20241111.exe" + +:: 3. Установка Tesseract в портабельном режиме (если требуется) +:: Примечание: Для реальной портабельности используйте ZIP-архив, но здесь пример с установщиком +:: start /wait "" "%TARGET_DIR%\tesseract.exe" /SILENT /DIR="%TARGET_DIR%" + +:: 4. Создаем папку для языковых пакетов +if not exist "%TESSDATA_DIR%" mkdir "%TESSDATA_DIR%" + +:: 5. Скачиваем языковые пакеты (ru и en) +echo Загрузка русской языковой модели... +"%WGET%" -O "%TESSDATA_DIR%\rus.traineddata" "https://github.com/tesseract-ocr/tessdata/raw/main/rus.traineddata" + +echo Загрузка английской языковой модели... +"%WGET%" -O "%TESSDATA_DIR%\eng.traineddata" "https://github.com/tesseract-ocr/tessdata/raw/main/eng.traineddata" + + +echo Готово! Портабельная версия создана в: +echo %TARGET_DIR% \ No newline at end of file