Ver Fonte

det_db_unclip_ratio=2

zeke-chin há 2 anos atrás
pai
commit
cdf1d482ba

+ 119 - 119
Dockerfile

@@ -1,119 +1,119 @@
-FROM nvidia/cuda:11.0-cudnn8-devel-ubuntu18.04 AS builder
-
-RUN sed -i 's#archive.ubuntu.com#mirrors.aliyun.com#g' /etc/apt/sources.list  \
-    && sed -i 's#security.ubuntu.com#mirrors.aliyun.com#g' /etc/apt/sources.list
-
-ENV LANG=zh_CN.UTF-8 LANGUAGE=zh_CN:zh LC_ALL=zh_CN.UTF-8 DEBIAN_FRONTEND=noninteractive
-
-RUN rm -rf  /etc/apt/sources.list.d/  && apt update
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
-    supervisor \
-    iputils-ping \
-    wget \
-    zsh \
-    build-essential \
-    cmake \
-    git \
-    curl \
-    vim \
-    ca-certificates \
-    libjpeg-dev \
-    zip \
-    unzip \
-    libpng-dev \
-    openssh-server \
-    autojump \
-    language-pack-zh-hans \
-    ttf-wqy-zenhei \
-    libgl1-mesa-glx  \
-    libglib2.0-0 \
-    locales &&\
-    rm -rf /var/lib/apt/lists/*
-
-
-RUN locale-gen zh_CN.UTF-8
-RUN dpkg-reconfigure locales
-
-
-CMD ["supervisord", "-n"]
-
-FROM builder as builder1
-
-ENV PYTHON_VERSION 3
-RUN chsh -s `which zsh`
-RUN curl -o ~/miniconda.sh -O  https://repo.anaconda.com/miniconda/Miniconda${PYTHON_VERSION}-latest-Linux-x86_64.sh  && \
-    chmod +x ~/miniconda.sh && \
-    ~/miniconda.sh -b -p /opt/conda && \
-    rm ~/miniconda.sh
-
-RUN ln /opt/conda/bin/conda /usr/local/bin/conda
-RUN conda init zsh
-RUN conda install mamba -n base -c conda-forge
-RUN ln /opt/conda/bin/mamba /usr/local/bin/mamba && mamba init zsh
-
-
-
-FROM builder1 as builder2
-
-RUN apt-get update && apt-get install -y --no-install-recommends openssh-server && rm -rf /var/lib/apt/lists/*
-RUN mkdir /var/run/sshd
-RUN echo 'root:root' | chpasswd
-RUN sed -i 's/.*PermitRootLogin .*/PermitRootLogin yes/' /etc/ssh/sshd_config
-# SSH login fix. Otherwise user is kicked off after login
-RUN sed -i 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' /etc/pam.d/sshd
-
-RUN echo "\
-[program:sshd] \n\
-command=/usr/sbin/sshd -D\n\
-autorestart=True\n\
-autostart=True\n\
-redirect_stderr = true\n\
-" > /etc/supervisor/conf.d/sshd.conf
-
-EXPOSE 22
-
-FROM builder2 as builder3
-
-WORKDIR /workspace
-ADD environment.yml /environment.yml
-RUN sed -i 's#- paddlepaddle#- paddlepaddle-gpu==2.3.0.post110#g' /environment.yml && cat /environment.yml
-RUN mamba update -n base -c defaults conda -y && mamba env create -f /environment.yml && rm -rf /root/.cache
-
-# RUN /opt/conda/envs/py38/bin/python -m ipykernel install --name py38 --display-name "py38"
-# RUN echo "c.MultiKernelManager.default_kernel_name = 'py38'">>/root/.jupyter/jupyter_notebook_config.py
-RUN echo "\
-[program:be]\n\
-directory=/workspace\n\
-command=/opt/conda/envs/py38/bin/gunicorn server:app --workers 1 --worker-class=uvicorn.workers.UvicornWorker  --bind 0.0.0.0:8080 --reload \n\
-autorestart=true\n\
-startretries=0\n\
-redirect_stderr=true\n\
-stdout_logfile=/var/log/be.log\n\
-stdout_logfile_maxbytes=0\n\
-" > /etc/supervisor/conf.d/be.conf
-
-ARG VERSION
-ENV USE_CUDA $VERSION
-Add . /workspace
-EXPOSE 8080
-
-
-
-# RUN mamba install -y jupyterlab -n base && mamba init zsh
-# RUN /opt/conda/bin/jupyter notebook --generate-config && \
-#     echo "c.NotebookApp.password='argon2:\$argon2id\$v=19\$m=10240,t=10,p=8\$+zIUCF9Uk2FiCHlV8njX5A\$I5Mm/64DORArcXYTXWRVng'">>/root/.jupyter/jupyter_notebook_config.py
-
-
-# RUN mkdir -p /data && echo "\
-# [program:jupyter]\n\
-# directory=/data\n\
-# command=/opt/conda/bin/jupyter lab --ip 0.0.0.0 --port 8888 --allow-root --no-browser \n\
-# autorestart=true\n\
-# startretries=0\n\
-# redirect_stderr=true\n\
-# stdout_logfile=/dev/stdout\n\
-# stdout_logfile_maxbytes=0\n\
-# " > /etc/supervisor/conf.d/jupyter.conf
-
-# EXPOSE 8888
+FROM nvidia/cuda:11.0-cudnn8-devel-ubuntu18.04 AS builder
+
+RUN sed -i 's#archive.ubuntu.com#mirrors.aliyun.com#g' /etc/apt/sources.list  \
+    && sed -i 's#security.ubuntu.com#mirrors.aliyun.com#g' /etc/apt/sources.list
+
+ENV LANG=zh_CN.UTF-8 LANGUAGE=zh_CN:zh LC_ALL=zh_CN.UTF-8 DEBIAN_FRONTEND=noninteractive
+
+RUN rm -rf  /etc/apt/sources.list.d/  && apt update
+
+RUN apt-get update && apt-get install -y --no-install-recommends \
+    supervisor \
+    iputils-ping \
+    wget \
+    zsh \
+    build-essential \
+    cmake \
+    git \
+    curl \
+    vim \
+    ca-certificates \
+    libjpeg-dev \
+    zip \
+    unzip \
+    libpng-dev \
+    openssh-server \
+    autojump \
+    language-pack-zh-hans \
+    ttf-wqy-zenhei \
+    libgl1-mesa-glx  \
+    libglib2.0-0 \
+    locales &&\
+    rm -rf /var/lib/apt/lists/*
+
+
+RUN locale-gen zh_CN.UTF-8
+RUN dpkg-reconfigure locales
+
+
+CMD ["supervisord", "-n"]
+
+FROM builder as builder1
+
+ENV PYTHON_VERSION 3
+RUN chsh -s `which zsh`
+RUN curl -o ~/miniconda.sh -O  https://repo.anaconda.com/miniconda/Miniconda${PYTHON_VERSION}-latest-Linux-x86_64.sh  && \
+    chmod +x ~/miniconda.sh && \
+    ~/miniconda.sh -b -p /opt/conda && \
+    rm ~/miniconda.sh
+
+RUN ln /opt/conda/bin/conda /usr/local/bin/conda
+RUN conda init zsh
+RUN conda install mamba -n base -c conda-forge
+RUN ln /opt/conda/bin/mamba /usr/local/bin/mamba && mamba init zsh
+
+
+
+FROM builder1 as builder2
+
+RUN apt-get update && apt-get install -y --no-install-recommends openssh-server && rm -rf /var/lib/apt/lists/*
+RUN mkdir /var/run/sshd
+RUN echo 'root:root' | chpasswd
+RUN sed -i 's/.*PermitRootLogin .*/PermitRootLogin yes/' /etc/ssh/sshd_config
+# SSH login fix. Otherwise user is kicked off after login
+RUN sed -i 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' /etc/pam.d/sshd
+
+RUN echo "\
+[program:sshd] \n\
+command=/usr/sbin/sshd -D\n\
+autorestart=True\n\
+autostart=True\n\
+redirect_stderr = true\n\
+" > /etc/supervisor/conf.d/sshd.conf
+
+EXPOSE 22
+
+FROM builder2 as builder3
+
+WORKDIR /workspace
+ADD environment.yml /environment.yml
+RUN sed -i 's#- paddlepaddle#- paddlepaddle-gpu==2.3.0.post110#g' /environment.yml && cat /environment.yml
+RUN mamba update -n base -c defaults conda -y && mamba env create -f /environment.yml && rm -rf /root/.cache
+
+# RUN /opt/conda/envs/py38/bin/python -m ipykernel install --name py38 --display-name "py38"
+# RUN echo "c.MultiKernelManager.default_kernel_name = 'py38'">>/root/.jupyter/jupyter_notebook_config.py
+RUN echo "\
+[program:be]\n\
+directory=/workspace\n\
+command=/opt/conda/envs/py38/bin/gunicorn server:app --workers 1 --worker-class=uvicorn.workers.UvicornWorker  --bind 0.0.0.0:8080 --reload \n\
+autorestart=true\n\
+startretries=0\n\
+redirect_stderr=true\n\
+stdout_logfile=/var/log/be.log\n\
+stdout_logfile_maxbytes=0\n\
+" > /etc/supervisor/conf.d/be.conf
+
+ARG VERSION
+ENV USE_CUDA $VERSION
+Add . /workspace
+EXPOSE 8080
+
+
+
+# RUN mamba install -y jupyterlab -n base && mamba init zsh
+# RUN /opt/conda/bin/jupyter notebook --generate-config && \
+#     echo "c.NotebookApp.password='argon2:\$argon2id\$v=19\$m=10240,t=10,p=8\$+zIUCF9Uk2FiCHlV8njX5A\$I5Mm/64DORArcXYTXWRVng'">>/root/.jupyter/jupyter_notebook_config.py
+
+
+# RUN mkdir -p /data && echo "\
+# [program:jupyter]\n\
+# directory=/data\n\
+# command=/opt/conda/bin/jupyter lab --ip 0.0.0.0 --port 8888 --allow-root --no-browser \n\
+# autorestart=true\n\
+# startretries=0\n\
+# redirect_stderr=true\n\
+# stdout_logfile=/dev/stdout\n\
+# stdout_logfile_maxbytes=0\n\
+# " > /etc/supervisor/conf.d/jupyter.conf
+
+# EXPOSE 8888

+ 17 - 17
Makefile

@@ -1,17 +1,17 @@
-NAME=paddle
-VERSION=latest
-BUILD_TIME      := $(shell date "+%F %T")
-COMMIT_SHA1     := $(shell git rev-parse HEAD)
-AUTHOR          := $(shell git show -s --format='%an')
-
-
-.PHONY: all gpu cpu
-
-all: gpu
-gpu:
-	@docker build -t registry.cn-hangzhou.aliyuncs.com/sxtest/$(NAME):gpu --build-arg VERSION=gpu .
-	# @docker push registry.cn-hangzhou.aliyuncs.com/sxtest/$(NAME):gpu
-
-cpu:
-	@docker build -f cpu.Dockerfile -t registry.cn-hangzhou.aliyuncs.com/sxtest/$(NAME):cpu --build-arg VERSION=cpu .
-	# @docker push registry.cn-hangzhou.aliyuncs.com/sxtest/$(NAME):cpu
+NAME=paddle
+VERSION=latest
+BUILD_TIME      := $(shell date "+%F %T")
+COMMIT_SHA1     := $(shell git rev-parse HEAD)
+AUTHOR          := $(shell git show -s --format='%an')
+
+
+.PHONY: all gpu cpu
+
+all: gpu
+gpu:
+	@docker build -t registry.cn-hangzhou.aliyuncs.com/sxtest/$(NAME):gpu --build-arg VERSION=gpu .
+	@docker push registry.cn-hangzhou.aliyuncs.com/sxtest/$(NAME):gpu
+
+cpu:
+	@docker build -f cpu.Dockerfile -t registry.cn-hangzhou.aliyuncs.com/sxtest/$(NAME):cpu --build-arg VERSION=cpu .
+	# @docker push registry.cn-hangzhou.aliyuncs.com/sxtest/$(NAME):cpu

+ 27 - 27
README.md

@@ -1,28 +1,28 @@
-
-# 表格识别
-
-基于paddleocr v2, 用于识别文字。
-
-## 环境
-
-- python >= 3.7
-- paddleocr
-- paddlepaddle
-- cv2
-
-```shell
-conda env create -f environment.yml
-```
-
-## 服务端
-
-```shell
-# port 8080
-python server.py --port 8080
-```
-
-## 镜像打包
-
-```shell
-make all
+
+# 表格识别
+
+基于paddleocr v2, 用于识别文字。
+
+## 环境
+
+- python >= 3.7
+- paddleocr
+- paddlepaddle
+- cv2
+
+```shell
+conda env create -f environment.yml
+```
+
+## 服务端
+
+```shell
+# port 8080
+python server.py --port 8080
+```
+
+## 镜像打包
+
+```shell
+make all
 ```

+ 14 - 14
docker-compose.yml

@@ -1,14 +1,14 @@
-version: '2'
-services:
-  paddle:
-    hostname: paddle
-    container_name: paddle
-    restart: always
-    image: registry.cn-hangzhou.aliyuncs.com/sxtest/paddle:gpu
-    privileged: true
-    ipc: host
-    tty: true
-    working_dir: /workspace
-    ports:
-      - '19022:8080'
-      - '18022:22'
+version: '2'
+services:
+  paddle:
+    hostname: paddle
+    container_name: paddle
+    restart: always
+    image: registry.cn-hangzhou.aliyuncs.com/sxtest/paddle:gpu
+    privileged: true
+    ipc: host
+    tty: true
+    working_dir: /workspace
+    ports:
+      - '19022:8080'
+      - '18022:22'

+ 31 - 31
environment.yml

@@ -1,31 +1,31 @@
-name: py38
-channels:
-  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ # Anocanda清华镜像
-  - defaults
-  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/
-dependencies:
-  - python=3.8
-  - ipython
-  - pip
-  - ipykernel
-  - pip:
-      - cmake
-      - opencv-python
-      - cython
-      - paddleocr
-      - paddlehub
-      - fastapi
-      - uvicorn
-      - jinja2
-      - aiofiles
-      - python-multipart
-      - requests
-      - cpca
-      - gunicorn
-      - -i https://mirror.baidu.com/pypi/simple
-      - yacs
-      - seqeval
-      - paddlenlp>=2.2.1
-      - paddlepaddle  # gpu==2.3.0.post110
-      - -f https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.html
-prefix: /opt/conda/envs/py38
+name: py38
+channels:
+  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ # Anocanda清华镜像
+  - defaults
+  - https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/
+dependencies:
+  - python=3.8
+  - ipython
+  - pip
+  - ipykernel
+  - pip:
+      - cmake
+      - opencv-python
+      - cython
+      - paddleocr
+      - paddlehub
+      - fastapi
+      - uvicorn
+      - jinja2
+      - aiofiles
+      - python-multipart
+      - requests
+      - cpca
+      - gunicorn
+      - -i https://mirror.baidu.com/pypi/simple
+      - yacs
+      - seqeval
+      - paddlenlp>=2.2.1
+      - paddlepaddle  # gpu==2.3.0.post110
+      - -f https://www.paddlepaddle.org.cn/whl/linux/mkl/avx/stable.html
+prefix: /opt/conda/envs/py38

+ 10 - 10
run.py

@@ -1,11 +1,11 @@
-if __name__ == '__main__':
-    import uvicorn
-    import argparse
-
-    parser = argparse.ArgumentParser()
-    parser.add_argument('--host', default='0.0.0.0')
-    parser.add_argument('--port', default=8080)
-    opt = parser.parse_args()
-
-    app_str = 'server:app'  # make the app string equal to whatever the name of this file is
+if __name__ == '__main__':
+    import uvicorn
+    import argparse
+
+    parser = argparse.ArgumentParser()
+    parser.add_argument('--host', default='0.0.0.0')
+    parser.add_argument('--port', default=8080)
+    opt = parser.parse_args()
+
+    app_str = 'server:app'  # make the app string equal to whatever the name of this file is
     uvicorn.run(app_str, host=opt.host, port=int(opt.port), reload=True)

+ 111 - 110
server.py

@@ -1,110 +1,111 @@
-import io
-import json
-import re
-from fastapi import FastAPI, Request, File, UploadFile, Body
-from fastapi.middleware.cors import CORSMiddleware
-from sx_utils.sximage import *
-from sx_utils.sxtime import sxtimeit
-from sx_utils.sxweb import web_try
-import requests
-from PIL import Image
-from pydantic import BaseModel
-import sys
-import logging
-import os
-import cv2
-from paddleocr import PaddleOCR
-
-logger = logging.getLogger('log')
-logger.setLevel(logging.DEBUG)
-
-# 调用模块时,如果错误引用,比如多次调用,每次会添加Handler,造成重复日志,这边每次都移除掉所有的handler,后面在重新添加,可以解决这类问题
-while logger.hasHandlers():
-    for i in logger.handlers:
-        logger.removeHandler(i)
-
-# file log 写入文件配置
-formatter = logging.Formatter('%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s')  # 日志的格式
-# 本地运行时,这部分需注释
-# fh = logging.FileHandler(r'/var/log/be.log', encoding='utf-8')  # 日志文件路径文件名称,编码格式
-# fh.setLevel(logging.DEBUG)  # 日志打印级别
-# fh.setFormatter(formatter)
-# logger.addHandler(fh)
-
-# console log 控制台输出控制
-ch = logging.StreamHandler(sys.stdout)
-ch.setLevel(logging.DEBUG)
-ch.setFormatter(formatter)
-logger.addHandler(ch)
-
-app = FastAPI()
-
-origins = ["*"]
-
-app.add_middleware(
-    CORSMiddleware,
-    allow_origins=origins,
-    allow_credentials=True,
-    allow_methods=["*"],
-    allow_headers=["*"],
-)
-use_gpu = False
-if os.getenv('USE_CUDA') == 'gpu':
-    use_gpu = True
-
-logger.info(f"->是否使用GPU:{use_gpu}")
-
-ocr = PaddleOCR(use_angle_cls=True,
-                rec_model_dir="./table_rec_infer/",
-                det_model_dir="./table_det_infer/",
-                cls_model_dir="./table_cls_infer/",
-                lang="ch")
-
-
-@app.get("/ping")
-def ping():
-    return "pong!"
-
-
-
-
-class ImageListInfo(BaseModel):
-    images: list
-    img_type: str
-
-@app.post("/ocr_system/paddle")
-@sxtimeit
-@web_try()
-def paddle(request: Request,info: ImageListInfo):
-    logger.info(f"->图片数量:{len(info.images)}")
-    res_list = []
-    for b_img in info.images:
-        img = base64_to_np(b_img)
-        result=ocr.ocr(img,cls=True)
-        r_list = []
-        for text_list in result:
-            if len(text_list) >= 1:
-                data = {}
-                data["confidence"] = text_list[1][1]
-                data["text"] = text_list[1][0]
-                data["type"] = info.img_type
-                data["text_region"] = text_list[0]
-                r_list.append(data)
-        res_list.append(r_list)
-    return res_list
-
-
-
-
-if __name__ == '__main__':
-    import uvicorn
-    import argparse
-
-    parser = argparse.ArgumentParser()
-    parser.add_argument('--host', default='0.0.0.0')
-    parser.add_argument('--port', default=8080)
-    opt = parser.parse_args()
-
-
-    app_str = 'server:app'  # make the app string equal to whatever the name of this file is
-    uvicorn.run(app_str, host=opt.host, port=int(opt.port), reload=True)
+import io
+import json
+import re
+from fastapi import FastAPI, Request, File, UploadFile, Body
+from fastapi.middleware.cors import CORSMiddleware
+from sx_utils.sximage import *
+from sx_utils.sxtime import sxtimeit
+from sx_utils.sxweb import web_try
+import requests
+from PIL import Image
+from pydantic import BaseModel
+import sys
+import logging
+import os
+import cv2
+from paddleocr import PaddleOCR
+
+logger = logging.getLogger('log')
+logger.setLevel(logging.DEBUG)
+
+# 调用模块时,如果错误引用,比如多次调用,每次会添加Handler,造成重复日志,这边每次都移除掉所有的handler,后面在重新添加,可以解决这类问题
+while logger.hasHandlers():
+    for i in logger.handlers:
+        logger.removeHandler(i)
+
+# file log 写入文件配置
+formatter = logging.Formatter('%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s')  # 日志的格式
+# 本地运行时,这部分需注释
+# fh = logging.FileHandler(r'/var/log/be.log', encoding='utf-8')  # 日志文件路径文件名称,编码格式
+# fh.setLevel(logging.DEBUG)  # 日志打印级别
+# fh.setFormatter(formatter)
+# logger.addHandler(fh)
+
+# console log 控制台输出控制
+ch = logging.StreamHandler(sys.stdout)
+ch.setLevel(logging.DEBUG)
+ch.setFormatter(formatter)
+logger.addHandler(ch)
+
+app = FastAPI()
+
+origins = ["*"]
+
+app.add_middleware(
+    CORSMiddleware,
+    allow_origins=origins,
+    allow_credentials=True,
+    allow_methods=["*"],
+    allow_headers=["*"],
+)
+use_gpu = False
+if os.getenv('USE_CUDA') == 'gpu':
+    use_gpu = True
+
+logger.info(f"->是否使用GPU:{use_gpu}")
+
+ocr = PaddleOCR(use_angle_cls=True,
+                #rec_model_dir="./rec_1012",
+                #det_model_dir="./det_1009",
+		det_db_unclip_ratio=2,
+                #cls_model_dir="./table_cls_infer/",
+                lang="ch")
+
+
+@app.get("/ping")
+def ping():
+    return "pong!"
+
+
+
+
+class ImageListInfo(BaseModel):
+    images: list
+    img_type: str
+
+@app.post("/ocr_system/paddle")
+@sxtimeit
+@web_try()
+def paddle(request: Request,info: ImageListInfo):
+    logger.info(f"->图片数量:{len(info.images)}")
+    res_list = []
+    for b_img in info.images:
+        img = base64_to_np(b_img)
+        result=ocr.ocr(img,cls=True)
+        r_list = []
+        for text_list in result:
+            if len(text_list) >= 1:
+                data = {}
+                data["confidence"] = text_list[1][1]
+                data["text"] = text_list[1][0]
+                data["type"] = info.img_type
+                data["text_region"] = text_list[0]
+                r_list.append(data)
+        res_list.append(r_list)
+    return res_list
+
+
+
+
+if __name__ == '__main__':
+    import uvicorn
+    import argparse
+
+    parser = argparse.ArgumentParser()
+    parser.add_argument('--host', default='0.0.0.0')
+    parser.add_argument('--port', default=8080)
+    opt = parser.parse_args()
+
+
+    app_str = 'server:app'  # make the app string equal to whatever the name of this file is
+    uvicorn.run(app_str, host=opt.host, port=int(opt.port), reload=True)

+ 9 - 9
sx_utils/sximage.py

@@ -1,9 +1,9 @@
-from base64 import b64decode
-import numpy as np
-import cv2
-
-def base64_to_np(img_data):
-    color_image_flag = 1
-    img_data = img_data.split(',',1)[-1]
-    return cv2.imdecode(np.fromstring(b64decode(img_data), dtype=np.uint8), color_image_flag)
-
+from base64 import b64decode
+import numpy as np
+import cv2
+
+def base64_to_np(img_data):
+    color_image_flag = 1
+    img_data = img_data.split(',',1)[-1]
+    return cv2.imdecode(np.fromstring(b64decode(img_data), dtype=np.uint8), color_image_flag)
+

+ 121 - 121
sx_utils/sxtime.py

@@ -1,122 +1,122 @@
-# coding=utf-8
-# Powered by SoaringNova Technology Company
-import errno
-import os
-import signal
-import time
-from collections import defaultdict
-from functools import wraps
-timer_counts = defaultdict(int)
-
-class SXTimeoutError(Exception):
-    pass
-
-
-def sxtimeout(seconds=10, error_message=os.strerror(errno.ETIME)):
-    def decorator(func):
-        def _handle_timeout(signum, frame):
-            raise SXTimeoutError(error_message)
-
-        def wrapper(*args, **kwargs):
-            signal.signal(signal.SIGALRM, _handle_timeout)
-            signal.alarm(seconds)
-            try:
-                result = func(*args, **kwargs)
-            finally:
-                signal.alarm(0)
-            return result
-
-        return wraps(func)(wrapper)
-
-    return decorator
-
-
-class SXTIMELIMIT:
-    def __init__(self, limit_time=0):
-        self.st = None
-        self.et = None
-        self.limit_time = limit_time
-
-    def __enter__(self):
-        self.st = time.time()
-
-    def __exit__(self, exc_type, exc_val, exc_tb):
-        self.et = time.time()
-        dt = self.limit_time - (self.et - self.st) * 1000
-        if dt > 0: time.sleep(float(dt) / 1000)
-
-
-class SXTIMER:
-    total_time = {}  # type: dict
-
-    def __init__(self, tag='', enable_total=False, threshold_ms=0):
-        self.st = None
-        self.et = None
-        self.tag = tag
-        # self.tag = tag if not hasattr(g,'request_id') else '{} {}'.format(getattr(g,'request_id'),tag)
-
-        self.thr = threshold_ms
-        self.enable_total = enable_total
-        if self.enable_total:
-            if self.tag not in self.total_time.keys():
-                self.total_time[self.tag] = []
-
-    def __enter__(self):
-        self.st = time.time()
-
-    def __exit__(self, exc_type, exc_val, exc_tb):
-        self.et = time.time()
-        dt = (self.et - self.st) * 1000
-        if self.enable_total:
-            self.total_time[self.tag].append(dt)
-
-        if dt > self.thr:
-            print ("{}: {}s".format(self.tag, round(dt / 1000, 4)))
-
-    @staticmethod
-    def output():
-        for k, v in SXTIMER.total_time.items():
-            print ('{} : {}s, avg{}s'.format(k, round(sum(v) / 1000, 2), round(sum(v) / len(v) / 1000, 2)))
-
-
-def sxtimeit(func):
-    @wraps(func)
-    def wrapper(*args, **kwargs):
-        st = time.time()
-        ret = func(*args, **kwargs)
-        dt = time.time() - st
-        endpoint = '{}.{}'.format(func.__module__, func.__name__)
-        timer_counts[endpoint] += 1
-        print ('{}[{}] finished, exec {}s'.format(endpoint,'%05d' % timer_counts[endpoint], round(dt, 4)))
-        return ret
-
-    return wrapper  # 返回
-
-# def sxtimeit(func):
-#     @wraps(func)
-#     def wrapper(*args, **kwargs):
-#         endpoint = '{}.{}'.format(func.__module__, func.__name__)
-#         setattr(g,'request_id','{}[{}]'.format(endpoint,'%05d' % timer_counts[endpoint]))
-#         timer_counts[endpoint] += 1
-#         st = time.time()
-#         ret = func(*args, **kwargs)
-#         dt = time.time() - st
-#         print ('{} finished, exec {}s'.format(getattr(g,'request_id'), round(dt, 4)))
-#         return ret
-#
-#     return wrapper  # 返回
-
-def t2date(t):
-    import datetime
-    date = datetime.datetime.fromtimestamp(t)
-    return '{}_{}_{}_{}:{}:{}'.format(date.year, date.month, date.day, date.hour, date.minute,date.second)
-
-
-def day_begin(t):
-    dsecs = 24 * 3600
-    return (int(t) + 8 * 3600) // dsecs * dsecs - 8 * 3600
-
-
-def hour_begin(t):
-    hsecs = 3600
+# coding=utf-8
+# Powered by SoaringNova Technology Company
+import errno
+import os
+import signal
+import time
+from collections import defaultdict
+from functools import wraps
+timer_counts = defaultdict(int)
+
+class SXTimeoutError(Exception):
+    pass
+
+
+def sxtimeout(seconds=10, error_message=os.strerror(errno.ETIME)):
+    def decorator(func):
+        def _handle_timeout(signum, frame):
+            raise SXTimeoutError(error_message)
+
+        def wrapper(*args, **kwargs):
+            signal.signal(signal.SIGALRM, _handle_timeout)
+            signal.alarm(seconds)
+            try:
+                result = func(*args, **kwargs)
+            finally:
+                signal.alarm(0)
+            return result
+
+        return wraps(func)(wrapper)
+
+    return decorator
+
+
+class SXTIMELIMIT:
+    def __init__(self, limit_time=0):
+        self.st = None
+        self.et = None
+        self.limit_time = limit_time
+
+    def __enter__(self):
+        self.st = time.time()
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        self.et = time.time()
+        dt = self.limit_time - (self.et - self.st) * 1000
+        if dt > 0: time.sleep(float(dt) / 1000)
+
+
+class SXTIMER:
+    total_time = {}  # type: dict
+
+    def __init__(self, tag='', enable_total=False, threshold_ms=0):
+        self.st = None
+        self.et = None
+        self.tag = tag
+        # self.tag = tag if not hasattr(g,'request_id') else '{} {}'.format(getattr(g,'request_id'),tag)
+
+        self.thr = threshold_ms
+        self.enable_total = enable_total
+        if self.enable_total:
+            if self.tag not in self.total_time.keys():
+                self.total_time[self.tag] = []
+
+    def __enter__(self):
+        self.st = time.time()
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        self.et = time.time()
+        dt = (self.et - self.st) * 1000
+        if self.enable_total:
+            self.total_time[self.tag].append(dt)
+
+        if dt > self.thr:
+            print ("{}: {}s".format(self.tag, round(dt / 1000, 4)))
+
+    @staticmethod
+    def output():
+        for k, v in SXTIMER.total_time.items():
+            print ('{} : {}s, avg{}s'.format(k, round(sum(v) / 1000, 2), round(sum(v) / len(v) / 1000, 2)))
+
+
+def sxtimeit(func):
+    @wraps(func)
+    def wrapper(*args, **kwargs):
+        st = time.time()
+        ret = func(*args, **kwargs)
+        dt = time.time() - st
+        endpoint = '{}.{}'.format(func.__module__, func.__name__)
+        timer_counts[endpoint] += 1
+        print ('{}[{}] finished, exec {}s'.format(endpoint,'%05d' % timer_counts[endpoint], round(dt, 4)))
+        return ret
+
+    return wrapper  # 返回
+
+# def sxtimeit(func):
+#     @wraps(func)
+#     def wrapper(*args, **kwargs):
+#         endpoint = '{}.{}'.format(func.__module__, func.__name__)
+#         setattr(g,'request_id','{}[{}]'.format(endpoint,'%05d' % timer_counts[endpoint]))
+#         timer_counts[endpoint] += 1
+#         st = time.time()
+#         ret = func(*args, **kwargs)
+#         dt = time.time() - st
+#         print ('{} finished, exec {}s'.format(getattr(g,'request_id'), round(dt, 4)))
+#         return ret
+#
+#     return wrapper  # 返回
+
+def t2date(t):
+    import datetime
+    date = datetime.datetime.fromtimestamp(t)
+    return '{}_{}_{}_{}:{}:{}'.format(date.year, date.month, date.day, date.hour, date.minute,date.second)
+
+
+def day_begin(t):
+    dsecs = 24 * 3600
+    return (int(t) + 8 * 3600) // dsecs * dsecs - 8 * 3600
+
+
+def hour_begin(t):
+    hsecs = 3600
     return (int(t) + 8 * 3600) // hsecs * hsecs - 8 * 3600

+ 43 - 43
sx_utils/sxweb.py

@@ -1,43 +1,43 @@
-import traceback
-import numpy as np
-from decorator import decorator
-from fastapi.responses import JSONResponse
-
-
-def json_compatible(data):
-    if isinstance(data,dict):
-        return {k:json_compatible(v) for k,v in data.items()}
-    if isinstance(data,bytes):
-        return str(data)
-    if isinstance(data,np.ndarray):
-        return data.tolist()
-    return data
-
-def web_try(exception_ret=None):
-    @decorator
-    def f(func, *args, **kwargs):
-        error_code = "000"
-        ret = None
-        msg = ''
-        try:
-            ret = func(*args, **kwargs)
-        except Exception as e:
-            msg = traceback.format_exc()
-            if len(e.args) > 0 and isinstance(e.args[0], int):
-                error_code = e.args[0]
-            else:
-                error_code = "101"
-            print('--------------------------------')
-            print ('Get Exception in web try :( \n{}\n'.format(msg))
-            print('--------------------------------')
-            if callable(exception_ret):
-                ret = exception_ret()
-            else:
-                ret = exception_ret
-        finally:
-            if ret is not None and isinstance(ret, JSONResponse):
-                return ret
-            return json_compatible({"status": error_code,
-                                    "result": ret,
-                                    "msg": msg.split('\n')[-2] if msg is not '' else msg})
-    return f
+import traceback
+import numpy as np
+from decorator import decorator
+from fastapi.responses import JSONResponse
+
+
+def json_compatible(data):
+    if isinstance(data,dict):
+        return {k:json_compatible(v) for k,v in data.items()}
+    if isinstance(data,bytes):
+        return str(data)
+    if isinstance(data,np.ndarray):
+        return data.tolist()
+    return data
+
+def web_try(exception_ret=None):
+    @decorator
+    def f(func, *args, **kwargs):
+        error_code = "000"
+        ret = None
+        msg = ''
+        try:
+            ret = func(*args, **kwargs)
+        except Exception as e:
+            msg = traceback.format_exc()
+            if len(e.args) > 0 and isinstance(e.args[0], int):
+                error_code = e.args[0]
+            else:
+                error_code = "101"
+            print('--------------------------------')
+            print ('Get Exception in web try :( \n{}\n'.format(msg))
+            print('--------------------------------')
+            if callable(exception_ret):
+                ret = exception_ret()
+            else:
+                ret = exception_ret
+        finally:
+            if ret is not None and isinstance(ret, JSONResponse):
+                return ret
+            return json_compatible({"status": error_code,
+                                    "result": ret,
+                                    "msg": msg.split('\n')[-2] if msg is not '' else msg})
+    return f

BIN
table_cls_infer/inference.pdiparams


BIN
table_cls_infer/inference.pdiparams.info


BIN
table_cls_infer/inference.pdmodel


BIN
table_det_infer/inference.pdiparams


BIN
table_det_infer/inference.pdiparams.info


BIN
table_det_infer/inference.pdmodel


BIN
table_ocr_infer/._inference.pdiparams


BIN
table_ocr_infer/._inference.pdiparams.info


BIN
table_ocr_infer/._inference.pdmodel


BIN
table_ocr_infer/inference.pdiparams


BIN
table_ocr_infer/inference.pdiparams.info


BIN
table_ocr_infer/inference.pdmodel


BIN
table_rec_infer/inference.pdiparams


BIN
table_rec_infer/inference.pdiparams.info


BIN
table_rec_infer/inference.pdmodel


+ 54 - 54
testing/paddle_test.py

@@ -1,55 +1,55 @@
-import unittest
-import base64
-import requests
-
-url = 'http://localhost:8080'
-
-
-def send_request(image_path):
-    with open(image_path, 'rb') as f:
-        img_str: str = base64.encodebytes(f.read()).decode('utf-8')
-        r = requests.post(f'{url}/ocr_system/paddle', json={'images': [img_str],'img_type':'text'})
-        print(r.json())
-        return r.json()
-
-
-class TestpaddleOcr(unittest.TestCase):
-    def test_it_work(self):
-        pong = requests.request("GET", '/'.join([url, 'ping']))
-        self.assertEqual('"pong!"', pong.text, 'Not work')
-
-    def test_paddle_01(self):
-        print("被旋转的图片")
-        res = send_request('./images/01.jpeg')
-        self.assertEqual('000', res['status'], 'Not work')
-
-    def test_paddle_02(self):
-        res = send_request('./images/02.jpg')
-        self.assertEqual('000', res['status'], 'Not work')
-
-    def test_paddle_03(self):
-        res = send_request('./images/03.jpg')
-        self.assertEqual('000', res['status'], 'Not work')
-
-    def test_paddle_04(self):
-        res = send_request('./images/04.jpg')
-        self.assertEqual('000', res['status'], 'Not work')
-
-    def test_paddle_05(self):
-        res = send_request('./images/05.jpeg')
-        self.assertEqual('000', res['status'], 'Not work')
-
-    def test_paddle_06(self):
-        res = send_request('./images/06.jpeg')
-        self.assertEqual('000', res['status'], 'Not work')
-
-    def test_paddle_07(self):
-        res = send_request('./images/07.jpeg')
-        self.assertEqual('000', res['status'], 'Not work')
-
-    def test_paddle_08(self):
-        res = send_request('./images/08.jpg')
-        self.assertEqual('000', res['status'], 'Not work')
-
-if __name__ == '__main__':
+import unittest
+import base64
+import requests
+
+url = 'http://localhost:8080'
+
+
+def send_request(image_path):
+    with open(image_path, 'rb') as f:
+        img_str: str = base64.encodebytes(f.read()).decode('utf-8')
+        r = requests.post(f'{url}/ocr_system/paddle', json={'images': [img_str],'img_type':'text'})
+        print(r.json())
+        return r.json()
+
+
+class TestpaddleOcr(unittest.TestCase):
+    def test_it_work(self):
+        pong = requests.request("GET", '/'.join([url, 'ping']))
+        self.assertEqual('"pong!"', pong.text, 'Not work')
+
+    def test_paddle_01(self):
+        print("被旋转的图片")
+        res = send_request('./images/01.jpeg')
+        self.assertEqual('000', res['status'], 'Not work')
+
+    def test_paddle_02(self):
+        res = send_request('./images/02.jpg')
+        self.assertEqual('000', res['status'], 'Not work')
+
+    def test_paddle_03(self):
+        res = send_request('./images/03.jpg')
+        self.assertEqual('000', res['status'], 'Not work')
+
+    def test_paddle_04(self):
+        res = send_request('./images/04.jpg')
+        self.assertEqual('000', res['status'], 'Not work')
+
+    def test_paddle_05(self):
+        res = send_request('./images/05.jpeg')
+        self.assertEqual('000', res['status'], 'Not work')
+
+    def test_paddle_06(self):
+        res = send_request('./images/06.jpeg')
+        self.assertEqual('000', res['status'], 'Not work')
+
+    def test_paddle_07(self):
+        res = send_request('./images/07.jpeg')
+        self.assertEqual('000', res['status'], 'Not work')
+
+    def test_paddle_08(self):
+        res = send_request('./images/08.jpg')
+        self.assertEqual('000', res['status'], 'Not work')
+
+if __name__ == '__main__':
     unittest.main()