Просмотр исходного кода

add video project

release_toaliyun_real
xiaohanzi 5 лет назад
Родитель
Сommit
98a0e6ff66
3 измененных файлов: 443 добавлений и 0 удалений
  1. +18
    -0
      mallinkVideo/pom.xml
  2. +290
    -0
      mallinkVideo/src/main/java/com/iformall/video/FormallTess4j.java
  3. +135
    -0
      mallinkVideo/src/main/java/com/iformall/video/FormallTess4jTrain.java

+ 18
- 0
mallinkVideo/pom.xml Просмотреть файл

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>mallink</artifactId>
<groupId>com.iformall</groupId>
<version>1.0</version>
</parent>
<modelVersion>4.0.0</modelVersion>

<artifactId>mallinkVideo</artifactId>

<dependencies>
</dependencies>
</project>

+ 290
- 0
mallinkVideo/src/main/java/com/iformall/video/FormallTess4j.java Просмотреть файл

@@ -0,0 +1,290 @@
package com.iformall.ocr;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.recognition.software.jdeskew.ImageDeskew;
import net.sourceforge.tess4j.ITessAPI.TessPageIteratorLevel;
import net.sourceforge.tess4j.ITesseract;
import net.sourceforge.tess4j.ITesseract.RenderedFormat;
import net.sourceforge.tess4j.Tesseract;
import net.sourceforge.tess4j.Word;
import net.sourceforge.tess4j.util.ImageHelper;
import net.sourceforge.tess4j.util.LoggHelper;
import net.sourceforge.tess4j.util.Utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
* https://www.cnblogs.com/pejsidney/p/9487881.html
* Tess4J是对Tesseract OCR API.的Java JNA 封装。使java能够通过调用Tess4J的API来使用Tesseract OCR。支持的格式:TIFF,JPEG,GIF,PNG,BMP,JPEG,and PDF
Tesseract 的github地址:https://github.com/tesseract-ocr/tesseract
Tess4J的github地址:https://github.com/nguyenq/tess4j
Tess4J API 提供的功能:
1、直接识别支持的文件
2、识别图片流
3、识别图片的某块区域
4、将识别结果保存为 TEXT/ HOCR/ PDF/ UNLV/ BOX
5、通过设置取词的等级,提取识别出来的文字
6、获得每一个识别区域的具体坐标范围
7、调整倾斜的图片
8、裁剪图片
9、调整图片分辨率
10、从粘贴板获得图像
11、克隆一个图像(目的:创建一份一模一样的图片,与原图在操作修改上,不相 互影响)
12、图片转换为二进制、黑白图像、灰度图像
13、反转图片颜色
* @author alascor
*/
public class FormallTess4j {

private static final Logger logger = LoggerFactory.getLogger(new LoggHelper().toString());
static final double MINIMUM_DESKEW_THRESHOLD = 0.05d;
private static final String datapath = "src/main/resources";
private static final String testResourcesLanguagePath = datapath+"/tessdata";
private static final String tempfile = "/ocrtempfile/";
private static ITesseract instance = new Tesseract();
static {
instance.setDatapath(new File(datapath).getPath());
}

private static File urlImgToFile(String fileUrl) {
InputStream ins = null;
OutputStream os = null;
try {
URL url = new URL(fileUrl);
URLConnection c = url.openConnection();
ins = c.getInputStream();
File folder = new File (tempfile) ;
if (!folder.exists()) {
folder.mkdirs();
}
File f = new File(tempfile+System.currentTimeMillis()+"-"+IdWorker.get32UUID()+".jpg");
if (f.exists()) {
f.delete();
}
f.createNewFile();
os = new FileOutputStream(f);
int bytesRead = 0;
byte[] buffer = new byte[8192];
while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
ins.close();
return f;
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}finally {
if (null != os) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != ins) {
try {
ins.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return null;
}
private static void deletetempFile(File file) {
if (file.exists()) {
file.delete();
}
}
private static String ocrLocalImgFile(String languagePath,String filePath,String fontName) throws Exception {
File imageFile = new File(filePath);
String result = testDoOCR_File(languagePath,imageFile,fontName);
deletetempFile(imageFile);
return result;
}
public static String ocrNetImgFile(String languagePath,String fileUrl,String fontName) throws Exception {
File imageFile = urlImgToFile(fileUrl);
String result = testDoOCR_File(languagePath,imageFile,fontName);
deletetempFile(imageFile);
return result;
}
/**
* Test of doOCR method, of class Tesseract.
* 根据图片文件进行识别
* @throws Exception while processing image.
*/
public static String testDoOCR_File(String languagePath,File imageFile,String fontName) throws Exception {
logger.info("doOCR on a jpg image");
//set language
instance.setDatapath(languagePath);
instance.setLanguage(fontName);
String result = instance.doOCR(imageFile);
return result;
}
public static void main(String[] args) {
try {
//System.out.println(ocrNetImgFile(testResourcesLanguagePath,"https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.my0832.com%2Fattachments%2Fbbs%2F20140424%2F201442413083356803_740_1186.jpg&refer=http%3A%2F%2Fimg.my0832.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1613903848&t=985fc4c6c7b7ee82cb98f97ab5bf1459","test1"));
System.out.println(ocrLocalImgFile(testResourcesLanguagePath,"C:\\Users\\iformall\\Desktop\\01.jpg","test1"));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//
// /**
// * Test of doOCR method, of class Tesseract.
// * 根据图片流进行识别
// * @throws Exception while processing image.
// */
// public void testDoOCR_BufferedImage() throws Exception {
// logger.info("doOCR on a buffered image of a PNG");
// File imageFile = new File(this.testResourcesDataPath, "ocr.png");
// BufferedImage bi = ImageIO.read(imageFile);
//
// //set language
// instance.setDatapath(testResourcesLanguagePath);
// instance.setLanguage("chi_sim");
//
// String result = instance.doOCR(bi);
// logger.info(result);
// }
//
// /**
// * Test of getSegmentedRegions method, of class Tesseract.
// * 得到每一个划分区域的具体坐标
// * @throws java.lang.Exception
// */
// public void testGetSegmentedRegions() throws Exception {
// logger.info("getSegmentedRegions at given TessPageIteratorLevel");
// File imageFile = new File(testResourcesDataPath, "ocr.png");
// BufferedImage bi = ImageIO.read(imageFile);
// int level = TessPageIteratorLevel.RIL_SYMBOL;
// logger.info("PageIteratorLevel: " + Utils.getConstantName(level, TessPageIteratorLevel.class));
// List<Rectangle> result = instance.getSegmentedRegions(bi, level);
// for (int i = 0; i < result.size(); i++) {
// Rectangle rect = result.get(i);
// logger.info(String.format("Box[%d]: x=%d, y=%d, w=%d, h=%d", i, rect.x, rect.y, rect.width, rect.height));
// }
//
// assertTrue(result.size() > 0);
// }
//
//
// /**
// * Test of doOCR method, of class Tesseract.
// * 根据定义坐标范围进行识别
// * @throws Exception while processing image.
// */
// public void testDoOCR_File_Rectangle() throws Exception {
// logger.info("doOCR on a BMP image with bounding rectangle");
// File imageFile = new File(this.testResourcesDataPath, "ocr.png");
// //设置语言库
// instance.setDatapath(testResourcesLanguagePath);
// instance.setLanguage("chi_sim");
// //划定区域
// // x,y是以左上角为原点,width和height是以xy为基础
// Rectangle rect = new Rectangle(84, 21, 15, 13);
// String result = instance.doOCR(imageFile, rect);
// logger.info(result);
// }
//
// /**
// * Test of createDocuments method, of class Tesseract.
// * 存储结果
// * @throws java.lang.Exception
// */
// public void testCreateDocuments() throws Exception {
// logger.info("createDocuments for png");
// File imageFile = new File(this.testResourcesDataPath, "ocr.png");
// String outputbase = "target/test-classes/docrenderer-2";
// List<RenderedFormat> formats = new ArrayList<RenderedFormat>(Arrays.asList(RenderedFormat.HOCR, RenderedFormat.TEXT));
//
// //设置语言库
// instance.setDatapath(testResourcesLanguagePath);
// instance.setLanguage("chi_sim");
//
// instance.createDocuments(new String[]{imageFile.getPath()}, new String[]{outputbase}, formats);
// }
//
// /**
// * Test of getWords method, of class Tesseract.
// * 取词方法
// * @throws java.lang.Exception
// */
// public void testGetWords() throws Exception {
// logger.info("getWords");
// File imageFile = new File(this.testResourcesDataPath, "ocr.png");
//
// //设置语言库
// instance.setDatapath(testResourcesLanguagePath);
// instance.setLanguage("chi_sim");
//
// //按照每个字取词
// int pageIteratorLevel = TessPageIteratorLevel.RIL_SYMBOL;
// logger.info("PageIteratorLevel: " + Utils.getConstantName(pageIteratorLevel, TessPageIteratorLevel.class));
// BufferedImage bi = ImageIO.read(imageFile);
// List<Word> result = instance.getWords(bi, pageIteratorLevel);
//
// //print the complete result
// for (Word word : result) {
// logger.info(word.toString());
// }
// }
//
// /**
// * Test of Invalid memory access.
// * 处理倾斜
// * @throws Exception while processing image.
// */
// public void testDoOCR_SkewedImage() throws Exception {
// //设置语言库
// instance.setDatapath(testResourcesLanguagePath);
// instance.setLanguage("chi_sim");
//
// logger.info("doOCR on a skewed PNG image");
// File imageFile = new File(this.testResourcesDataPath, "ocr_skewed.jpg");
// BufferedImage bi = ImageIO.read(imageFile);
// ImageDeskew id = new ImageDeskew(bi);
// double imageSkewAngle = id.getSkewAngle(); // determine skew angle
// if ((imageSkewAngle > MINIMUM_DESKEW_THRESHOLD || imageSkewAngle < -(MINIMUM_DESKEW_THRESHOLD))) {
// bi = ImageHelper.rotateImage(bi, -imageSkewAngle); // deskew image
// }
//
// String result = instance.doOCR(bi);
// logger.info(result);
// }
}

+ 135
- 0
mallinkVideo/src/main/java/com/iformall/video/FormallTess4jTrain.java Просмотреть файл

@@ -0,0 +1,135 @@
package com.iformall.ocr;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;

/**
* 训练
* @author iformall
*/
public class FormallTess4jTrain {

private static final String newFileFolder = "C:\\Users\\iformall\\Desktop\\newfile";
private static final String huanhangstr = " \n ";
private static String getprefix(String lang,String fontName) {
String realFileName = lang+"."+fontName+".exp0";
return realFileName;
}
private static String createBoxFile(String tifFileName,String lang,String fontName) {
String prefix = getprefix(lang,fontName);
String realFileName = prefix+".tif";
if (tifFileName.equals(realFileName)) {
String cmdstr = "tesseract "+tifFileName+" "+prefix+" -l chi_sim batch.nochop makebox";
return cmdstr;
//String result = executeLocalCmd(cmdstr, null);
//System.out.println("Done createBoxFile"+result);
}else {
return "文件必须是.tif";
}
}
private static String createTranFile(String lang,String fontName) {
String prefix = getprefix(lang,fontName);
String realFileName = prefix+".tif";
String trainCmdstr = "tesseract "+realFileName+" "+prefix+" nobatch box.train";
return trainCmdstr;
}
private static String getBoxFont(String lang,String fontName) {
String prefix = getprefix(lang,fontName);
String extractorCmdstr = "unicharset_extractor "+prefix+".box [other .box files...]";
return extractorCmdstr;
}
/**
* 第六步,执行完成后生成以下几个文件加前缀
* unicharset、inttemp、pffmtable、shapetable、normproto 添加这几个文件的前缀为fontName
* @param lang
* @param fontName
* @return
*/
private static String renameTrainFiles(String fontName) {
StringBuffer sb = new StringBuffer();
String renCmdstr = "REN unicharset "+fontName+".unicharset";
sb.append(renCmdstr).append(huanhangstr);
renCmdstr = "REN inttemp "+fontName+".inttemp";
sb.append(renCmdstr).append(huanhangstr);
renCmdstr = "REN pffmtable "+fontName+".pffmtable";
sb.append(renCmdstr).append(huanhangstr);
renCmdstr = "REN shapetable "+fontName+".shapetable";
sb.append(renCmdstr).append(huanhangstr);
renCmdstr = "REN normproto "+fontName+".normproto";
sb.append(renCmdstr).append(huanhangstr);
return sb.toString();
}
/**
* 第七步:合并5个文件
* @param lang
* @param fontName
* @return
*/
private static String mergeTrainFiles(String fontName) {
String mergeCmdstr = "combine_tessdata "+fontName+".";
return mergeCmdstr;
}
public static String getTrainSteps(String lang,String fontName) {
StringBuffer sb = new StringBuffer("请先安装tess4j(4.0以上),配置好环境变量. 下载jTessBoxEditor(用于训练,带FX的支持中文)").append(huanhangstr);
sb.append("请进入到样本图片文件夹用doc命令执行.").append(huanhangstr);
sb.append("第一步,用jTessBoxEditor --> Tools --> Merge 多选图片,保存为tif格式 .命名格式为[lang].[fontName].exp0.tif. 命名:").append(lang).append(".").append(fontName).append(".exp0.tif ").append(huanhangstr);
sb.append("............ ").append(huanhangstr);
sb.append("第二步,用tif生成box ").append(huanhangstr);
sb.append(createBoxFile(lang+"."+fontName+".exp0.tif", lang, fontName)).append(huanhangstr);
sb.append("............ ").append(huanhangstr);
sb.append("第三步,用jTessBoxEditor 打开.box文件进行矫正 ").append(huanhangstr);
sb.append("............ ").append(huanhangstr);
sb.append("第四步:用box文件生成。tr文件 ").append(huanhangstr);
sb.append(createTranFile(lang,fontName)).append(huanhangstr);
sb.append("............ ").append(huanhangstr);
sb.append("@@@!!!!从此处开始,可以处理多个字库处理。如原来的字库现在做升级,需要把老的字库的。tif,.box,.tr文件重新命名也放到同目录文件夹, ").append(huanhangstr);
sb.append("............ ").append(huanhangstr);
sb.append("第五步:提取box字符 ").append(huanhangstr);
sb.append(getBoxFont(lang,fontName)).append(huanhangstr);
sb.append("............ ").append(huanhangstr);
sb.append("第六步:新建font_properties(没有.txt后缀), 把所有box对应的字体特征加进去。").append(huanhangstr);
sb.append("fontname为字体名称,保持和 图片集文件 .tif 和.box文件的前缀名一致 .<italic> 、<bold> 、<fixed> 、<serif>、 <fraktur>的取值为1或0,表示字体是否具有这些属性。 ").append(huanhangstr);
sb.append("如以下内容: ").append(huanhangstr);
sb.append("fontName1 0 0 0 0 0 ").append(huanhangstr);
sb.append("fontName2 0 1 0 0 0 ").append(huanhangstr);
sb.append("fontName3 1 1 0 0 0 ").append(huanhangstr);
sb.append("............ ").append(huanhangstr);
sb.append("第六步:批量执行系列命令。多个文件在后面累加。 ").append(huanhangstr);
String prefix = getprefix(lang,fontName);
String shapeCmdStr = "### shapeclustering -F font_properties -U unicharset "+prefix+".tr [other .tr files...] ";
sb.append(shapeCmdStr).append(huanhangstr);
String mftraingCmdstr = "mftraining -F font_properties -U unicharset -O unicharset "+prefix+".tr [other .tr files...] ";
sb.append(mftraingCmdstr).append(huanhangstr);
String cntrainCmdstr = "cntraining "+prefix+".tr [other .tr files...] ";
sb.append(cntrainCmdstr).append(huanhangstr);
sb.append("............ ").append(huanhangstr);
sb.append("第七步,执行完成后生成以下几个文件加前缀: unicharset、inttemp、pffmtable、shapetable、normproto 添加这几个文件的前缀为[fontName] ").append(huanhangstr);
sb.append(renameTrainFiles(fontName));
sb.append("............ ").append(huanhangstr);
sb.append("第七步:合并5个文件").append(huanhangstr);
sb.append(mergeTrainFiles(fontName)).append(huanhangstr);
sb.append("............ ").append(huanhangstr);
sb.append("第八步:将").append(fontName).append(".traineddata 文件拷贝到后端服务器ocr_data(项目配置fm.ocr_data)目录下。 .tif、。box、。tr文件也需要保留,后面如果这个字库有更新,需要用到这些文件。").append(huanhangstr);
return sb.toString();
}
}

Загрузка…
Отмена
Сохранить