diff --git a/.gitea/workflows/build.yaml b/.gitea/workflows/build.yaml new file mode 100644 index 0000000..1966567 --- /dev/null +++ b/.gitea/workflows/build.yaml @@ -0,0 +1,47 @@ +name: Build +run-name: ${{ github.actor }} is upgrade release π +on: [push] +env: + REPOSITORY: ${{ github.repository }} + COMMIT_ID: ${{ github.sha }} +jobs: + Build-Deploy-Actions: + runs-on: ubuntu-latest + steps: + - run: echo "π The job was automatically triggered by a ${{ github.event_name }} event." + - run: echo "π§ This job is now running on a ${{ runner.os }} server hosted by Gitea!" + - run: echo "π The name of your branch is ${{ github.ref }} and your repository is ${{ github.repository }}." + - name: Check out repository code + uses: actions/checkout@v3 + - + name: Setup Git LFS + run: | + git lfs install + git lfs fetch + git lfs checkout + - name: List files in the repository + run: | + ls ${{ github.workspace }} + - + name: Docker Image Info + id: image-info + run: | + echo "::set-output name=image_name::$(echo $REPOSITORY | tr '[:upper:]' '[:lower:]')" + echo "::set-output name=image_tag::${COMMIT_ID:0:10}" + - + name: Login to Docker Hub + uses: docker/login-action@v2 + with: + registry: artifacts.iflytek.com + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - + name: Build and push + run: | + docker version + docker buildx build -t artifacts.iflytek.com/docker-private/atp/${{ steps.image-info.outputs.image_name }}:${{ steps.image-info.outputs.image_tag }} . --file ${{ github.workspace }}/Dockerfile --load + docker push artifacts.iflytek.com/docker-private/atp/${{ steps.image-info.outputs.image_name }}:${{ steps.image-info.outputs.image_tag }} + docker rmi artifacts.iflytek.com/docker-private/atp/${{ steps.image-info.outputs.image_name }}:${{ steps.image-info.outputs.image_tag }} + - run: echo "π This job's status is ${{ job.status }}." diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..199f4b3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,18 @@ +FROM python:3.8.13 + +WORKDIR /app + +COPY . /app + +RUN pip config set global.index-url https://pypi.mirrors.ustc.edu.cn/simple + +ENV PYHTONUNBUFFERED=1 +RUN apt-get update && apt-get -y install tesseract-ocr + +RUN pip install pyyaml==5.1 + +RUN pip install -r requirements.txt + +RUN pip install 'git+https://ghproxy.com/https://github.com/facebookresearch/detectron2.git' + +CMD ["python", "app.py"] diff --git a/app.py b/app.py new file mode 100644 index 0000000..ec1d42f --- /dev/null +++ b/app.py @@ -0,0 +1,84 @@ +import gradio as gr +import numpy as np +from transformers import LayoutLMv2Processor, LayoutLMv2ForTokenClassification +from datasets import load_dataset +from PIL import Image, ImageDraw, ImageFont +from gradio.themes.utils import sizes + + +theme = gr.themes.Default(radius_size=sizes.radius_none).set( + block_label_text_color = '#4D63FF', + block_title_text_color = '#4D63FF', + button_primary_text_color = '#4D63FF', + button_primary_background_fill='#FFFFFF', + button_primary_border_color='#4D63FF', + button_primary_background_fill_hover='#EDEFFF', +) + +processor = LayoutLMv2Processor.from_pretrained("microsoft/layoutlmv2-base-uncased") +model = LayoutLMv2ForTokenClassification.from_pretrained("nielsr/layoutlmv2-finetuned-funsd") + +labels = ['O', 'B-HEADER', 'I-HEADER', 'B-QUESTION', 'I-QUESTION', 'B-ANSWER', 'I-ANSWER'] +id2label = {0: 'O', 1: 'B-HEADER', 2: 'I-HEADER', 3: 'B-QUESTION', 4: 'I-QUESTION', 5: 'B-ANSWER', 6: 'I-ANSWER'} +label2color = {'question':'blue', 'answer':'green', 'header':'orange', 'other':'violet'} + +def unnormalize_box(bbox, width, height): + return [ + width * (bbox[0] / 1000), + height * (bbox[1] / 1000), + width * (bbox[2] / 1000), + height * (bbox[3] / 1000), + ] + +def iob_to_label(label): + label = label[2:] + if not label: + return 'other' + return label + +def process_image(image): + width, height = image.size + + # encode + encoding = processor(image, truncation=True, return_offsets_mapping=True, return_tensors="pt") + offset_mapping = encoding.pop('offset_mapping') + + # forward pass + outputs = model(**encoding) + + # get predictions + predictions = outputs.logits.argmax(-1).squeeze().tolist() + token_boxes = encoding.bbox.squeeze().tolist() + + # only keep non-subword predictions + is_subword = np.array(offset_mapping.squeeze().tolist())[:,0] != 0 + true_predictions = [id2label[pred] for idx, pred in enumerate(predictions) if not is_subword[idx]] + true_boxes = [unnormalize_box(box, width, height) for idx, box in enumerate(token_boxes) if not is_subword[idx]] + + # draw predictions over the image + draw = ImageDraw.Draw(image) + font = ImageFont.load_default() + for prediction, box in zip(true_predictions, true_boxes): + predicted_label = iob_to_label(prediction).lower() + draw.rectangle(box, outline=label2color[predicted_label]) + draw.text((box[0]+10, box[1]-10), text=predicted_label, fill=label2color[predicted_label], font=font) + + return image + +with gr.Blocks(theme=theme, css="footer {visibility: hidden}") as demo: + gr.Markdown(""" +