├── .gitignore ├── README.md ├── app.py ├── config.py ├── dataset ├── images │ ├── 123.jpg │ ├── ─■A0C93F.jpg │ ├── ─■A1D775.jpg │ ├── ─■A1K002.jpg │ ├── ─■A1Q070.jpg │ ├── ─■A3J484.jpg │ ├── ─■A3Q779.jpg │ ├── ─■A4H981.jpg │ └── ─■A6H335.jpg └── labels │ ├── data.mdb │ └── lock.mdb ├── enviroment.yaml ├── logger_manager.py ├── models ├── __init__.py └── user.py ├── requirement.txt ├── static ├── build │ ├── css │ │ ├── custom.css │ │ └── imagelabel.css │ ├── images │ │ ├── back_disabled.png │ │ ├── back_enabled.png │ │ ├── back_enabled_hover.png │ │ ├── forward_disabled.png │ │ ├── forward_enabled.png │ │ ├── forward_enabled_hover.png │ │ └── loading.gif │ └── js │ │ ├── bootstrap-3.3.7 │ │ ├── css │ │ │ ├── bootstrap-theme.css │ │ │ ├── bootstrap-theme.css.map │ │ │ ├── bootstrap-theme.min.css │ │ │ ├── bootstrap-theme.min.css.map │ │ │ ├── bootstrap.css │ │ │ ├── bootstrap.css.map │ │ │ ├── bootstrap.min.css │ │ │ └── bootstrap.min.css.map │ │ ├── fonts │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ └── glyphicons-halflings-regular.woff2 │ │ └── js │ │ │ ├── bootstrap.js │ │ │ ├── bootstrap.min.js │ │ │ └── npm.js │ │ ├── custom.js │ │ ├── draw_roi.js │ │ ├── laydate-v5.0.9 │ │ ├── laydate.js │ │ └── theme │ │ │ └── default │ │ │ ├── font │ │ │ ├── iconfont.eot │ │ │ ├── iconfont.svg │ │ │ ├── iconfont.ttf │ │ │ └── iconfont.woff │ │ │ └── laydate.css │ │ └── layer-v3.1.1 │ │ └── layer │ │ ├── layer.js │ │ ├── mobile │ │ ├── layer.js │ │ └── need │ │ │ └── layer.css │ │ └── theme │ │ └── default │ │ ├── icon-ext.png │ │ ├── icon.png │ │ ├── layer.css │ │ ├── loading-0.gif │ │ ├── loading-1.gif │ │ └── loading-2.gif ├── images │ ├── american-express.png │ ├── cropper.jpg │ ├── favicon.ico │ ├── img.jpg │ ├── inbox.png │ ├── logo-simple.png │ ├── logo.png │ ├── mastercard.png │ ├── media.jpg │ ├── paypal.png │ ├── picture.jpg │ ├── user.png │ └── visa.png └── layer │ ├── layer.js │ ├── mobile │ ├── layer.js │ └── need │ │ └── layer.css │ └── theme │ └── default │ ├── icon-ext.png │ ├── icon.png │ ├── layer.css │ ├── loading-0.gif │ ├── loading-1.gif │ └── loading-2.gif ├── templates ├── index.html └── test.html └── utils ├── __init__.py ├── db_helper.py ├── tool.py └── xml2dict.py /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | __pycache__/ 3 | logs 4 | *.pid 5 | .vscode/ 6 | docs/ 7 | annotation/ 8 | test.py 9 | *.pyc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ocr标注工具 2 | 3 | 采用python-flask框架开发图像标注工具,主要思路是在标注的过程中先调用百度/阿里等免费的api进行标注,并进行人工的验证或目标矩形框的修正,同时支持单张图片多个目标的标注。整理想法很简单,但是实现起来还是很麻烦的。大概用了2周的时间(而且是在开源项目上修改来的)。 4 | 5 | ## 原特点 6 | * B/S方式交互 7 | * 支持多人同时标注(可分配不同标注人员的标注范围,或不同人员标注不同类别) 8 | * 类别采用选择方式,免去手工输入类别工作 9 | * 支持拖拽方式修正标注区域 10 | * 支持键盘方向键切换标注样本 11 | 12 | ## 增加特性 13 | * 增加百度api/自用api调用的接口 14 | * 支持百度api检测结果的调整 15 | * 采用lmdb做数据库,用图片名做key进行保存 16 | * 支持单张图片,多目标的标注 17 | 18 | 19 | 20 | ## 使用方法 21 | 1. 根据`requirements.txt`安装环境依赖,其中有些依赖可能没有使用,也可以装了相应python与flask版本后,根据报错安装其他依赖 22 | ```buildoutcfg 23 | $ cd od-annotation 24 | $ pip3 install -r requirements.txt # use pip 25 | # or create a new conda enviroment 26 | conda env create -f enviroment.yaml 27 | ``` 28 | 2. 将需要标注的图片放到:'dataset/images/' 29 | 30 | 3. 启动/停止/重启标注工具: 31 | ```buildoutcfg 32 | $ cd od-annotation 33 | $ python3 app.py --start|stop|restart # 前台进程方式运行 34 | $ python3 app.py --start|restart --daemon # 以后台进程方式(重新)启动 35 | ``` 36 | 4. 访问`http://localhost:5000`开始标注。整个标注流程是:1.先调用百度api; 2.将百度的结果画出来,并调整; 3.保存结果/下一张。其中可以用左键移动矩形框,并可以在矩形框右下角进行大小调整。右键点击矩形框可以删除当前标注的矩形框。`当前样本标注状态`会同步更新标注信息。 `所有样本标注状态`用的原作者的,没有调整其显示,可能会有错误,没有关系。 37 | 38 | 5. 点击左右方向按钮或通过键盘方向键切换标注样本。切换时自动提交标注结果,或手动点击`保存`按钮提交标注结果。 39 | 40 | 6. 标注文件在`dataset/labels/`中,是lmdb数据库。标注格式为:`{'img_name': 'x1,y1,x2,y2,label\nx12,y12,x22,y22,label2\n'}`,标注的一个矩形,采用左上和右下的坐标 41 | 42 | ## 更改预训练API 43 | 按同样的返回格式,修改[app.py](./app.py)中的第81行到102行 44 | 45 | 46 | ## reference 47 | borrowed code from [od-annotation](https://github.com/hzylmf/od-annotation),thanks! 48 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | import codecs 2 | import hashlib 3 | import json 4 | import threading 5 | import time 6 | import os 7 | import argparse 8 | import traceback 9 | import requests 10 | from flask import Flask, render_template, jsonify, send_file 11 | from flask import request 12 | from io import BytesIO 13 | import base64 14 | from PIL import Image 15 | import lmdb 16 | 17 | import config as sys_config 18 | import utils.tool as tool 19 | 20 | app = Flask(__name__) 21 | app.config.from_object('config') 22 | 23 | mu = threading.Lock() # 创建一个锁 24 | labels = dict() 25 | 26 | # Route to any template 27 | @app.route('/') 28 | def index(): 29 | names = [name for name in os.listdir(sys_config.SAMPLE_FILE_PATH) \ 30 | if name.split('.')[-1].lower() in sys_config.SAMPLE_TYPE_SET] 31 | return render_template('index.html', \ 32 | sample_count=len(names), \ 33 | sample_type=sys_config.SAMPLE_FILE_TYPE) 34 | 35 | 36 | @app.route('/