Windows下Tesseract训练音符识别
背景
开局一张图:现在有这么一个需求,要将数字简谱中的数字带点的内容识别出来做进一步的处理,比如
6 1 6 641 533
. . ...
识别成
F 1 F FDA 5 3 3
其实就是通过下面的映射关系识别
# 原简谱
.
1 2 3 4 5 6 7 1 2 3 4 5 6 7 1
. . . . . . .
# 映射
A B C D E F G 1 2 3 4 5 6 7 a
识别成什么无所谓,只要能区分带点的数字和不带点的数字即可,带点的这种数字是简谱的特殊字符,纯字符是打不出来的,这也是难点,有以下思路
- 打开调试工具,观察dom结构,用js来区分,但是上面的截图是小程序,小程序目前还不能用chrome打开,因为微信小程序的浏览器封装了很多浏览器没有的功能,所以这个方案暂时放弃
- 通过OCR文字识别,识别曲谱中的数字,但是带点的数字识别不了,可以通过训练样本,然后制作成字库文件进行识别,将带点的数字用英文表示(上面的映射关系)
准备工作
素材准备
首先需要找到样本,上面截图中的键盘很不错,字符很全,就拿这个当做训练样本,首先进行二值化(Binarization)操作,二值化可参考维基百科
:https://zh.wikipedia.org/zh-hans/%E4%BA%8C%E5%80%BC%E5%8C%96
二值化的目的主要是为了简化背景,提供识别度,下面是Java的二值化代码
public void binaryImage(String in,String out) throws IOException{
File file = new File(in);
BufferedImage image = ImageIO.read(file);
int width = image.getWidth();
int height = image.getHeight();
BufferedImage grayImage = new BufferedImage(width, height, BufferedImage.TYPE_BYTE_BINARY);//重点,技巧在这个参数BufferedImage.TYPE_BYTE_BINARY
for(int i= 0 ; i < width ; i++){
for(int j = 0 ; j < height; j++){
int rgb = image.getRGB(i, j);
grayImage.setRGB(i, j, rgb);
}
}
File newFile = new File(out);
ImageIO.write(grayImage, "png", newFile);
}
调用方式如下,输出一个图片文件,输出二值化后的图片文件
public static void main(String[] args) throws IOException {
ImageBinaryzation demo = new ImageBinaryzation();
demo.binaryImage("D:\\20210626102826.jpg","D:\\20210626102826二值化.png");
}
二值化前后对比如下
用PS等工具把它水平切分成三个文件备用,如下
Tesseract软件准备
Tesseract是一个光学字符识别引擎,支持多种操作系统。[1]Tesseract是基于Apache许可证的自由软件[2],自2006 年起由Google赞助开发[3]。
Tesseract读音为 /ˈtesəˌrækt/,为啥用它?因为它开源,教程多
首先安装Tesseract 4.0,安装地址如下,一路next即可
- http://digi.bib.uni-mannheim.de/tesseract/tesseract-ocr-setup-4.00.00dev.exe
然后添加环境变量
- 将C:\Program Files (x86)\Tesseract-OCR添加到PATH,方便调用里面的命令
- 将C:\Program Files (x86)\Tesseract-OCR\tessdata添加到TESSDATA_PREFIX(新建一个)&