-
Notifications
You must be signed in to change notification settings - Fork 359
Enhance Multilingual Support with Chinese and German Label Recognition #447
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
Closed
Changes from 5 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
f12bd3e
🍗 Add new feature: Implement Chinese label recognition with PaddleOCR
neozhu 49bc04a
🍒 add recognition support for both German and Chinese languages.
neozhu bb537d8
Merge branch 'master' of https://github.com/neozhu/label-studio-ml-ba…
neozhu e032e5c
✨ Support Basic Auth support
neozhu c85b0e8
✨ change readme
neozhu 6038a7e
🐛 fixed comments and refactoring code
neozhu 44c8efc
reverted
neozhu d8a5dad
Update README.md
neozhu File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
Dockerfile | ||
README.md | ||
*.pyc | ||
*.pyo | ||
*.pyd | ||
__pycache__ | ||
.pytest_cache | ||
.idea | ||
docker-compose.yml | ||
data | ||
logs |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
FROM python:3.10 | ||
|
||
WORKDIR /tmp | ||
COPY requirements.txt . | ||
|
||
ENV PYTHONUNBUFFERED=True \ | ||
PORT=${PORT:-9090} \ | ||
PIP_CACHE_DIR=/.cache | ||
|
||
# Installing libGL | ||
RUN apt-get update && apt-get install -y \ | ||
libgl1-mesa-dev | ||
|
||
RUN apt-get install -y poppler-utils libpoppler-cpp-dev libglib2.0-0 | ||
|
||
|
||
RUN pip install --upgrade pip \ | ||
&& pip install -r requirements.txt | ||
|
||
|
||
#COPY uwsgi.ini /etc/uwsgi/ | ||
COPY supervisord.conf /etc/supervisor/conf.d/ | ||
|
||
WORKDIR /app | ||
|
||
COPY * /app/ | ||
|
||
EXPOSE 9090 | ||
|
||
CMD ["/usr/local/bin/supervisord", \ | ||
"-c", \ | ||
"/etc/supervisor/conf.d/supervisord.conf"] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
## Interactive BBOX OCR using PaddleOCR | ||
Using an OCR engine for Interactive ML-Assisted Labelling, this functionality | ||
can speed up annotation for layout detection, classification and recognition | ||
models. | ||
|
||
PaddleOCR is used for OCR but minimal adaptation is needed to connect other OCR | ||
engines or models. | ||
|
||
Tested againt Label Studio 1.10.1, with basic support for both Label Studio | ||
Local File Storage and S3-compatible storage, with a example data storage with | ||
Minio. | ||
|
||
### Setup process | ||
0. Download and install Docker with Docker Compose. For MacOS and Windows users, | ||
we suggest using Docker Desktop. You will also need to have git installed. | ||
|
||
1. Launch LabelStudio. | ||
|
||
``` | ||
docker run -it \ | ||
-p 8080:8080 \ | ||
-v `pwd`/mydata:/label-studio/data \ | ||
heartexlabs/label-studio:latest | ||
``` | ||
|
||
Optionally, you may enable local file serving in Label Studio | ||
|
||
``` | ||
docker run -it \ | ||
-p 8080:8080 \ | ||
-v `pwd`/mydata:/label-studio/data \ | ||
--env LABEL_STUDIO_LOCAL_FILES_SERVING_ENABLED=true \ | ||
--env LABEL_STUDIO_LOCAL_FILES_DOCUMENT_ROOT=/label-studio/data/images \ | ||
heartexlabs/label-studio:latest | ||
``` | ||
If you're using local file serving, be sure to get a copy of the API token from | ||
Label Studio to connect the model. | ||
|
||
2. Create a new project for PaddleOCR OCR. In the project **Settings** set up the **Labeling Interface**. | ||
|
||
Fill in the following template code. It's important to specify `smart="true"` in RectangleLabels. | ||
``` | ||
<View> | ||
<Image name="image" value="$ocr" zoom="true" zoomControl="false" | ||
rotateControl="true" width="100%" height="100%" | ||
maxHeight="auto" maxWidth="auto"/> | ||
|
||
<RectangleLabels name="bbox" toName="image" strokeWidth="1" smart="true"> | ||
<Label value="Label1" background="green"/> | ||
<Label value="Label2" background="blue"/> | ||
<Label value="Label3" background="red"/> | ||
</RectangleLabels> | ||
|
||
<TextArea name="transcription" toName="image" | ||
editable="true" perRegion="true" required="false" | ||
maxSubmissions="1" rows="5" placeholder="Recognized Text" | ||
displayMode="region-list"/> | ||
</View> | ||
``` | ||
|
||
3. Download the Label Studio Machine Learning backend backend repository. | ||
``` | ||
git clone https://github.com/humansignal/label-studio-ml-backend | ||
cd label-studio-ml-backend/label_studio_ml/examples/paddleocr | ||
``` | ||
|
||
4. Configure the backend and the Minio server by editing the `example.env` file. If you opted to use Label Studio | ||
Local File Storage, be sure to set the `LABEL_STUDIO_HOST` and `LABEL_STUDIO_ACCESS_TOKEN` variables. If you're | ||
using the Minio storage example, set the `MINIO_ROOT_USER` AND `MINIO_ROOT_PASSWORD` variables, and make the | ||
`AWS_ACCESS_KEY_ID` AND `AWS_SECRET_ACCESS_KEY` variables equal to those values. You may optionally connect to your | ||
own AWS cloud storage by setting those variables. Note that you may need to make additional software changes to the | ||
`paddleocr_ch.py` file to match your particular infrastructure configuration. | ||
|
||
``` | ||
LABEL_STUDIO_HOST=http://host.docker.internal:8080 | ||
LABEL_STUDIO_ACCESS_TOKEN=<optional token for local file access> | ||
|
||
AWS_ACCESS_KEY_ID=<set to MINIO_ROOT_USER for minio example> | ||
AWS_SECRET_ACCESS_KEY=<set to MINIO_ROOT_PASSWORD for minio example> | ||
AWS_ENDPOINT=http://host.docker.internal:9000 | ||
|
||
MINIO_ROOT_USER=<username> | ||
MINIO_ROOT_PASSWORD=<password> | ||
MINIO_API_CORS_ALLOW_ORIGIN=* | ||
``` | ||
|
||
5. Start the PaddleOCR and minio servers. | ||
|
||
``` | ||
# build image | ||
sudo docker build . -t paddleocr-backend:latest | ||
# or | ||
sudo docker compose build . | ||
|
||
# only start paddleocr-backend | ||
sudo docker compose up paddleocr-backend | ||
# or and start with minio | ||
docker compose up -d | ||
# shutdown container | ||
docker compose down | ||
|
||
|
||
``` | ||
|
||
6. Upload tasks. | ||
|
||
If you're using the Label Studio Local File Storage option, upload images | ||
directly to Label Studio using the Label Studio interface. | ||
|
||
If you're using minio for task storage, log into the minio control panel at | ||
`http://localhost:9001`. Create a new bucket, making a note of the name, and | ||
upload your tasks to minio. Set the visibility of the tasks to be public. | ||
Furtner configuration of your cloud storage is beyond the scope of this | ||
tutorial, and you will want to configure your storage according to your | ||
particular needs. | ||
|
||
7. If using minio, In the project **Settings**, set up the **Cloud storage**. | ||
|
||
Add your source S3 storage by connecting to the S3 Endpoint | ||
`http://host.docker.internal:9000`, using the bucket name from the previous | ||
step, and Access Key ID and Secret Access Key as configured in the previous | ||
steps. For the minio example, uncheck **Use pre-signed URLS**. Check the | ||
connection and save the storage. | ||
|
||
8. Open the **Machine Learning** settings and click **Add Model**. | ||
|
||
Add the URL `http://host.docker.internal:9090` and save the model as an ML backend. | ||
|
||
9. To use this functionality, activate `Auto-Annotation` and use `Autotdetect` rectangle for drawing boxes | ||
|
||
Example below : | ||
|
||
 | ||
|
||
Reference links : | ||
- https://labelstud.io/blog/Improve-OCR-quality-with-Tesseract-and-Label-Studio.html | ||
- https://labelstud.io/blog/release-130.html |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
import json | ||
import os | ||
import argparse | ||
import logging | ||
import logging.config | ||
|
||
logging.config.dictConfig({ | ||
"version": 1, | ||
"formatters": { | ||
"standard": { | ||
"format": "[%(asctime)s] [%(levelname)s] [%(name)s::%(funcName)s::%(lineno)d] %(message)s" | ||
} | ||
}, | ||
"handlers": { | ||
"console": { | ||
"class": "logging.StreamHandler", | ||
"level": "DEBUG", | ||
"stream": "ext://sys.stdout", | ||
"formatter": "standard" | ||
} | ||
}, | ||
"root": { | ||
"level": "ERROR", | ||
"handlers": [ | ||
"console" | ||
], | ||
"propagate": True | ||
} | ||
}) | ||
|
||
from label_studio_ml.api import init_app | ||
from paddleocr_ch import paddleocrLabeling | ||
|
||
|
||
_DEFAULT_CONFIG_PATH = os.path.join(os.path.dirname(__file__), 'config.json') | ||
|
||
|
||
def get_kwargs_from_config(config_path=_DEFAULT_CONFIG_PATH): | ||
if not os.path.exists(config_path): | ||
return dict() | ||
with open(config_path) as f: | ||
config = json.load(f) | ||
assert isinstance(config, dict) | ||
return config | ||
|
||
|
||
if __name__ == "__main__": | ||
parser = argparse.ArgumentParser(description='Label studio') | ||
parser.add_argument( | ||
'-p', '--port', dest='port', type=int, default=9090, | ||
help='Server port') | ||
parser.add_argument( | ||
'--host', dest='host', type=str, default='0.0.0.0', | ||
help='Server host') | ||
parser.add_argument( | ||
'--kwargs', '--with', dest='kwargs', metavar='KEY=VAL', nargs='+', type=lambda kv: kv.split('='), | ||
help='Additional LabelStudioMLBase model initialization kwargs') | ||
parser.add_argument( | ||
'-d', '--debug', dest='debug', action='store_true', | ||
help='Switch debug mode') | ||
parser.add_argument( | ||
'--log-level', dest='log_level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR'], default=None, | ||
help='Logging level') | ||
parser.add_argument( | ||
'--model-dir', dest='model_dir', default=os.path.dirname(__file__), | ||
help='Directory where models are stored (relative to the project directory)') | ||
parser.add_argument( | ||
'--check', dest='check', action='store_true', | ||
help='Validate model instance before launching server') | ||
|
||
parser.add_argument('--basic-auth-user', | ||
default=os.environ.get('ML_SERVER_BASIC_AUTH_USER', None), | ||
help='Basic auth user') | ||
|
||
parser.add_argument('--basic-auth-pass', | ||
default=os.environ.get('ML_SERVER_BASIC_AUTH_PASS', None), | ||
help='Basic auth pass') | ||
|
||
args = parser.parse_args() | ||
|
||
# setup logging level | ||
if args.log_level: | ||
logging.root.setLevel(args.log_level) | ||
|
||
def isfloat(value): | ||
try: | ||
float(value) | ||
return True | ||
except ValueError: | ||
return False | ||
|
||
def parse_kwargs(): | ||
param = dict() | ||
for k, v in args.kwargs: | ||
if v.isdigit(): | ||
param[k] = int(v) | ||
elif v == 'True' or v == 'true': | ||
param[k] = True | ||
elif v == 'False' or v == 'False': | ||
param[k] = False | ||
elif isfloat(v): | ||
param[k] = float(v) | ||
else: | ||
param[k] = v | ||
return param | ||
|
||
kwargs = get_kwargs_from_config() | ||
|
||
if args.kwargs: | ||
kwargs.update(parse_kwargs()) | ||
|
||
if args.check: | ||
print('Check "' + paddleocrLabeling.__name__ + '" instance creation..') | ||
model = paddleocrLabeling(**kwargs) | ||
|
||
app = init_app( | ||
model_class=paddleocrLabeling, | ||
basic_auth_user=args.basic_auth_user, | ||
basic_auth_pass=args.basic_auth_pass, | ||
**kwargs | ||
) | ||
|
||
app.run(host=args.host, port=args.port, debug=args.debug) | ||
|
||
else: | ||
# for uWSGI use | ||
app = init_app( | ||
model_class=paddleocrLabeling | ||
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
version: "3.8" | ||
|
||
services: | ||
|
||
paddleocr-backend: | ||
container_name: paddleocr-backend | ||
build: . | ||
env_file: | ||
- example.env | ||
ports: | ||
- 9090:9090 | ||
volumes: | ||
- "./data/server:/data" | ||
- "./logs:/tmp" | ||
|
||
minio: | ||
container_name: minio | ||
image: bitnami/minio:latest | ||
env_file: | ||
- example.env | ||
ports: | ||
- 9003:9000 | ||
- 9004:9001 | ||
volumes: | ||
- ".data/storage:/data" | ||
command: server /data --console-address ":9001" | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
LABEL_STUDIO_HOST=http://10.33.1.37:8089 | ||
LABEL_STUDIO_ACCESS_TOKEN=9075ad7f2794f7d670a752dcf0eb1b6d177d08ff | ||
|
||
AWS_ACCESS_KEY_ID=admin | ||
AWS_SECRET_ACCESS_KEY=9075ad7f2 | ||
AWS_ENDPOINT=http://10.33.1.37:9000 | ||
|
||
MINIO_ROOT_USER=admin | ||
MINIO_ROOT_PASSWORD=9075ad7f2 | ||
MINIO_API_CORS_ALLOW_ORIGIN=* | ||
MINIO_OPTS="--console-address :9001" |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.