From 016aafdb03ec4ab5b5b41e0e889f57d1aecb232f Mon Sep 17 00:00:00 2001 From: breezedeus Date: Sat, 11 Feb 2023 20:06:46 +0800 Subject: [PATCH 1/7] add `post_post_process` to optimize the latex result --- pix2text/latex_ocr.py | 208 ++++++++++++++++++++++------------------- tests/test_pix2text.py | 7 ++ 2 files changed, 120 insertions(+), 95 deletions(-) diff --git a/pix2text/latex_ocr.py b/pix2text/latex_ocr.py index c75c3e5..4c934d2 100644 --- a/pix2text/latex_ocr.py +++ b/pix2text/latex_ocr.py @@ -82,6 +82,116 @@ def minmax_size( return img +def find_all_left_or_right(latex, left_or_right='left'): + left_bracket_infos = [] + prefix_len = len(left_or_right) + 1 + # 匹配出latex中所有的 '\left' 后面跟着的第一个非空格字符,定位它们所在的位置 + for m in re.finditer(rf'\\{left_or_right}\s*\S', latex): + start, end = m.span() + # 如果最后一个字符为 "\",则往前继续匹配,直到匹配到一个非字母的字符 + # 如 "\left \big(" + while latex[end - 1] in ('\\', ' '): + end += 1 + while latex[end].isalpha(): + end += 1 + ori_str = latex[start + prefix_len : end].strip() + # FIXME: ori_str中可能出现多个 '\left',此时需要分隔开 + + left_bracket_infos.append({'str': ori_str, 'start': start, 'end': end}) + left_bracket_infos.sort(key=lambda x: x['start']) + return left_bracket_infos + + +def match_left_right(left_str, right_str): + """匹配左右括号,如匹配 `\left(` 和 `\right)`。""" + left_str = left_str.strip().replace(' ', '')[len('left') + 1 :] + right_str = right_str.strip().replace(' ', '')[len('right') + 1 :] + # 去掉开头的相同部分 + while left_str and right_str and left_str[0] == right_str[0]: + left_str = left_str[1:] + right_str = right_str[1:] + + match_pairs = [ + ('', ''), + ('(', ')'), + ('⟮', '⟯'), + ('[', ']'), + ('⟨', '⟩'), + ('{', '}'), + ('⌈', '⌉'), + ('┌', '┐'), + ('⌊', '⌋'), + ('└', '┘'), + ('⎰', '⎱'), + ('lt', 'gt'), + ('lang', 'rang'), + (r'langle', r'rangle'), + (r'lbrace', r'rbrace'), + ('lBrace', 'rBrace'), + (r'lbracket', r'rbracket'), + (r'lceil', r'rceil'), + ('lcorner', 'rcorner'), + (r'lfloor', r'rfloor'), + (r'lgroup', r'rgroup'), + (r'lmoustache', r'rmoustache'), + (r'lparen', r'rparen'), + (r'lvert', r'rvert'), + (r'lVert', r'rVert'), + ] + return (left_str, right_str) in match_pairs + + +def post_post_process_latex(latex: str) -> str: + """对识别结果做进一步处理和修正。""" + # 把latex中的中文括号全部替换成英文括号 + latex = latex.replace('(', '(').replace(')', ')') + # 把latex中的中文逗号全部替换成英文逗号 + latex = latex.replace(',', ',') + + left_bracket_infos = find_all_left_or_right(latex, left_or_right='left') + right_bracket_infos = find_all_left_or_right(latex, left_or_right='right') + # left 和 right 找配对,left找位置比它靠前且最靠近他的right配对 + for left_bracket_info in left_bracket_infos: + for right_bracket_info in right_bracket_infos: + if ( + not right_bracket_info.get('matched', False) + and right_bracket_info['start'] > left_bracket_info['start'] + and match_left_right( + right_bracket_info['str'], left_bracket_info['str'] + ) + ): + left_bracket_info['matched'] = True + right_bracket_info['matched'] = True + break + + for left_bracket_info in left_bracket_infos: + # 把没有匹配的 '\left'替换为等长度的空格 + left_len = len('left') + 1 + if not left_bracket_info.get('matched', False): + start_idx = left_bracket_info['start'] + end_idx = start_idx + left_len + latex = ( + latex[: left_bracket_info['start']] + + ' ' * (end_idx - start_idx) + + latex[end_idx:] + ) + for right_bracket_info in right_bracket_infos: + # 把没有匹配的 '\right'替换为等长度的空格 + right_len = len('right') + 1 + if not right_bracket_info.get('matched', False): + start_idx = right_bracket_info['start'] + end_idx = start_idx + right_len + latex = ( + latex[: right_bracket_info['start']] + + ' ' * (end_idx - start_idx) + + latex[end_idx:] + ) + + # 把 latex 中的连续空格替换为一个空格 + latex = re.sub(r'\s+', ' ', latex) + return latex + + class LatexOCR(object): """Get a prediction of an image in the easiest way""" @@ -192,7 +302,8 @@ def __call__(self, img=None, resize=True) -> str: :1 ].unsqueeze(0) w = ( - self.image_resizer(t.to(self.args.device)).argmax(-1).item() + 1 + self.image_resizer(t.to(self.args.device)).argmax(-1).item() + + 1 ) * 32 logger.debug((r, img.size, (w, int(input_image.size[1] * r)))) except Exception as e: @@ -211,98 +322,5 @@ def __call__(self, img=None, resize=True) -> str: im.to(self.args.device), temperature=self.args.get('temperature', 0.25) ) pred = post_process(token2str(dec, self.tokenizer)[0]) + pred = post_post_process_latex(pred) return pred - - -# def output_prediction(pred, args): -# print(pred, '\n') -# if args.show or args.katex: -# try: -# if args.katex: -# raise ValueError -# tex2pil([f'$${pred}$$'])[0].show() -# except Exception as e: -# # render using katex -# import webbrowser -# from urllib.parse import quote -# url = 'https://katex.org/?data=' + \ -# quote('{"displayMode":true,"leqno":false,"fleqn":false,"throwOnError":true,"errorColor":"#cc0000",\ -# "strict":"warn","output":"htmlAndMathml","trust":false,"code":"%s"}' % pred.replace('\\', '\\\\')) -# webbrowser.open(url) -# -# -# def main(): -# parser = argparse.ArgumentParser(description='Use model') -# parser.add_argument('-t', '--temperature', type=float, default=.333, help='Softmax sampling frequency') -# parser.add_argument('-c', '--config', type=str, default='settings/config.yaml') -# parser.add_argument('-m', '--checkpoint', type=str, default='checkpoints/weights.pth') -# parser.add_argument('-s', '--show', action='store_true', help='Show the rendered predicted latex code') -# parser.add_argument('-f', '--file', type=str, default=None, help='Predict LaTeX code from image file instead of clipboard') -# parser.add_argument('-k', '--katex', action='store_true', help='Render the latex code in the browser') -# parser.add_argument('--no-cuda', action='store_true', help='Compute on CPU') -# parser.add_argument('--no-resize', action='store_true', help='Resize the image beforehand') -# arguments = parser.parse_args() -# with in_model_path(): -# model = LatexOCR(arguments) -# file = None -# while True: -# instructions = input('Predict LaTeX code for image ("?"/"h" for help). ') -# possible_file = instructions.strip() -# ins = possible_file.lower() -# if ins == 'x': -# break -# elif ins in ['?', 'h', 'help']: -# print('''pix2tex help: -# -# Usage: -# On Windows and macOS you can copy the image into memory and just press ENTER to get a prediction. -# Alternatively you can paste the image file path here and submit. -# -# You might get a different prediction every time you submit the same image. If the result you got was close you -# can just predict the same image by pressing ENTER again. If that still does not work you can change the temperature -# or you have to take another picture with another resolution (e.g. zoom out and take a screenshot with lower resolution). -# -# Press "x" to close the program. -# You can interrupt the model if it takes too long by pressing Ctrl+C. -# -# Visualization: -# You can either render the code into a png using XeLaTeX (see README) to get an image file back. -# This is slow and requires a working installation of XeLaTeX. To activate type 'show' or set the flag --show -# Alternatively you can render the expression in the browser using katex.org. Type 'katex' or set --katex -# -# Settings: -# to toggle one of these settings: 'show', 'katex', 'no_resize' just type it into the console -# Change the temperature (default=0.333) type: "t=0.XX" to set a new temperature. -# ''') -# continue -# elif ins in ['show', 'katex', 'no_resize']: -# setattr(arguments, ins, not getattr(arguments, ins, False)) -# print('set %s to %s' % (ins, getattr(arguments, ins))) -# continue -# elif os.path.isfile(os.path.realpath(possible_file)): -# file = possible_file -# else: -# t = re.match(r't=([\.\d]+)', ins) -# if t is not None: -# t = t.groups()[0] -# model.args.temperature = float(t)+1e-8 -# print('new temperature: T=%.3f' % model.args.temperature) -# continue -# try: -# img = None -# if file: -# img = Image.open(file) -# else: -# try: -# img = ImageGrab.grabclipboard() -# except: -# pass -# pred = model(img) -# output_prediction(pred, arguments) -# except KeyboardInterrupt: -# pass -# file = None -# -# -# if __name__ == "__main__": -# main() diff --git a/tests/test_pix2text.py b/tests/test_pix2text.py index 4fe6f06..ddd918a 100644 --- a/tests/test_pix2text.py +++ b/tests/test_pix2text.py @@ -1,6 +1,7 @@ # coding: utf-8 from pix2text import Pix2Text +from pix2text.latex_ocr import post_post_process_latex def test_mfd(): @@ -17,3 +18,9 @@ def test_mfd(): save_analysis_res='./analysis_res.jpg', ) print(res) + + +def test_post_post_process(): + latex = r'\log(p(x\mid q(x)))+||\mathrm{sg}\left[z_{e}(x)\right]-e||_{2}^{2}+\beta\left||z_{e}(x)-\mathrm{sg}[e]|_{2}^{2}' + out = post_post_process_latex(latex) + # 其他的测试字符串 latex From e9bbdc465785498a6e42bf153868edc691b40b8c Mon Sep 17 00:00:00 2001 From: breezedeus Date: Sat, 11 Feb 2023 20:22:23 +0800 Subject: [PATCH 2/7] bump version --- Makefile | 2 +- pix2text/__version__.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index cc528b3..0ba0cf9 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ package: rm -rf build python setup.py sdist bdist_wheel -VERSION = 0.2 +VERSION = 0.2.1 upload: python -m twine upload dist/pix2text-$(VERSION)* --verbose diff --git a/pix2text/__version__.py b/pix2text/__version__.py index d10b157..c002f76 100644 --- a/pix2text/__version__.py +++ b/pix2text/__version__.py @@ -1,4 +1,4 @@ # coding: utf-8 # Copyright (C) 2022, [Breezedeus](https://github.com/breezedeus). -__version__ = '0.2' +__version__ = '0.2.1' From 9444041384d96e6337754f4d261e4ce1031e0fce Mon Sep 17 00:00:00 2001 From: breezedeus Date: Sun, 19 Feb 2023 15:17:10 +0800 Subject: [PATCH 3/7] refactor --- pix2text/cli.py | 33 +++++++++++++++++++-------- pix2text/latex_ocr.py | 1 + pix2text/pix_to_text.py | 49 +++++++++++++++++++++-------------------- 3 files changed, 50 insertions(+), 33 deletions(-) diff --git a/pix2text/cli.py b/pix2text/cli.py index b4bd187..02b86b3 100644 --- a/pix2text/cli.py +++ b/pix2text/cli.py @@ -36,6 +36,14 @@ def cli(): help="使用哪个Analyzer,MFD还是版面分析", show_default=True, ) +@click.option( + "-t", + "--analyzer-type", + type=str, + default='yolov7_tiny', + help="Analyzer使用哪个模型,'yolov7_tiny' or 'yolov7'", + show_default=True, +) @click.option( "-d", "--device", @@ -45,7 +53,10 @@ def cli(): show_default=True, ) @click.option( - "--resized-shape", help="把图片宽度resize到此大小再进行处理", type=int, default=700, + "--resized-shape", + help="把图片宽度resize到此大小再进行处理", + type=int, + default=600, show_default=True, ) @click.option("-i", "--img-file-or-dir", required=True, help="输入图片的文件路径或者指定的文件夹") @@ -53,8 +64,8 @@ def cli(): "--save-analysis-res", default=None, help="把解析结果存储到此文件或目录中" - "(如果'--img-file-or-dir'为文件/文件夹,则'--save-analysis-res'也应该是文件/文件夹)。" - "取值为 `None` 表示不存储", + "(如果'--img-file-or-dir'为文件/文件夹,则'--save-analysis-res'也应该是文件/文件夹)。" + "取值为 `None` 表示不存储", show_default=True, ) @click.option( @@ -67,6 +78,7 @@ def cli(): def predict( use_analyzer, analyzer_name, + analyzer_type, device, resized_shape, img_file_or_dir, @@ -76,7 +88,10 @@ def predict( """模型预测""" logger = set_logger(log_level=log_level) - p2t = Pix2Text(analyzer_config=dict(model_name=analyzer_name), device=device) + p2t = Pix2Text( + analyzer_config=dict(model_name=analyzer_name, model_type=analyzer_type), + device=device, + ) fp_list = [] if os.path.isfile(img_file_or_dir): @@ -88,7 +103,9 @@ def predict( fp_list = [os.path.join(img_file_or_dir, fn) for fn in fn_list] if save_analysis_res: os.makedirs(save_analysis_res, exist_ok=True) - save_analysis_res = [os.path.join(save_analysis_res, 'analysis-' + fn) for fn in fn_list] + save_analysis_res = [ + os.path.join(save_analysis_res, 'analysis-' + fn) for fn in fn_list + ] for idx, fp in enumerate(fp_list): analysis_res = save_analysis_res[idx] if save_analysis_res is not None else None @@ -104,12 +121,10 @@ def predict( @cli.command('serve') @click.option( - '-H', '--host', type=str, default='0.0.0.0', help='server host', - show_default=True, + '-H', '--host', type=str, default='0.0.0.0', help='server host', show_default=True, ) @click.option( - '-p', '--port', type=int, default=8503, help='server port', - show_default=True, + '-p', '--port', type=int, default=8503, help='server port', show_default=True, ) @click.option( '--reload', diff --git a/pix2text/latex_ocr.py b/pix2text/latex_ocr.py index 4c934d2..2336dca 100644 --- a/pix2text/latex_ocr.py +++ b/pix2text/latex_ocr.py @@ -114,6 +114,7 @@ def match_left_right(left_str, right_str): match_pairs = [ ('', ''), ('(', ')'), + ('\{', '.'), # 大括号那种 ('⟮', '⟯'), ('[', ']'), ('⟨', '⟩'), diff --git a/pix2text/pix_to_text.py b/pix2text/pix_to_text.py index 82a9102..fdf7fc1 100644 --- a/pix2text/pix_to_text.py +++ b/pix2text/pix_to_text.py @@ -14,7 +14,7 @@ from cnocr import CnOcr, ImageClassifier from cnstd import LayoutAnalyzer from cnstd.yolov7.consts import CATEGORY_DICT -from cnstd.yolov7.layout_analyzer import sort_boxes +from cnstd.utils.utils import sort_boxes from cnstd.yolov7.general import xyxy24p, box_partial_overlap from .consts import IMAGE_TYPES, LATEX_CONFIG_FP, MODEL_VERSION, CLF_MODEL_URL_FMT @@ -322,28 +322,6 @@ def _to_iou_box(ori): 0 ) - def _split_line_image(line_box, embed_mfs): - # 利用embedding formula所在位置,把单行文字图片切割成多个小段,之后这些小段会分别扔进OCR进行文字识别 - line_box = line_box[0] - if not embed_mfs: - return [{'position': line_box.int().tolist(), 'type': 'text'}] - embed_mfs.sort(key=lambda x: x['position'][0]) - - outs = [] - start = int(line_box[0]) - xmax, ymin, ymax = int(line_box[2]), int(line_box[1]), int(line_box[-1]) - for mf in embed_mfs: - _xmax = min(xmax, int(mf['position'][0]) + 1) - if start + 8 < _xmax: - outs.append( - {'position': [start, ymin, _xmax, ymax], 'type': 'text'} - ) - outs.append(mf) - start = int(mf['position'][2]) - if start < xmax: - outs.append({'position': [start, ymin, xmax, ymax], 'type': 'text'}) - return outs - outs = [box_info for box_info in mf_out if box_info['type'] == 'isolated'] for crop_img_info in box_infos['detected_texts']: line_box = _to_iou_box(crop_img_info['box']) @@ -360,7 +338,7 @@ def _split_line_image(line_box, embed_mfs): } ) - ocr_boxes = _split_line_image(line_box, embed_mfs) + ocr_boxes = self._split_line_image(line_box, embed_mfs) text = [] for box in ocr_boxes: @@ -393,6 +371,29 @@ def _split_line_image(line_box, embed_mfs): return outs + @classmethod + def _split_line_image(cls, line_box, embed_mfs): + # 利用embedding formula所在位置,把单行文字图片切割成多个小段,之后这些小段会分别扔进OCR进行文字识别 + line_box = line_box[0] + if not embed_mfs: + return [{'position': line_box.int().tolist(), 'type': 'text'}] + embed_mfs.sort(key=lambda x: x['position'][0]) + + outs = [] + start = int(line_box[0]) + xmax, ymin, ymax = int(line_box[2]), int(line_box[1]), int(line_box[-1]) + for mf in embed_mfs: + _xmax = min(xmax, int(mf['position'][0]) + 1) + if start + 8 < _xmax: + outs.append( + {'position': [start, ymin, _xmax, ymax], 'type': 'text'} + ) + outs.append(mf) + start = int(mf['position'][2]) + if start < xmax: + outs.append({'position': [start, ymin, xmax, ymax], 'type': 'text'}) + return outs + def recognize_by_layout( self, img: Union[str, Path, Image.Image], **kwargs ) -> List[Dict[str, Any]]: From a81f7d268dfcbf7ad56d5c8fcb92890c200eb625 Mon Sep 17 00:00:00 2001 From: breezedeus Date: Sun, 19 Feb 2023 15:17:31 +0800 Subject: [PATCH 4/7] test for post_post --- tests/test_pix2text.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/test_pix2text.py b/tests/test_pix2text.py index ddd918a..4bb4ead 100644 --- a/tests/test_pix2text.py +++ b/tests/test_pix2text.py @@ -21,6 +21,16 @@ def test_mfd(): def test_post_post_process(): - latex = r'\log(p(x\mid q(x)))+||\mathrm{sg}\left[z_{e}(x)\right]-e||_{2}^{2}+\beta\left||z_{e}(x)-\mathrm{sg}[e]|_{2}^{2}' + latex = r'\log(p(x\mid q(x)))+||\mathrm{sg}\left[z_{e}(x)\right]-e||_{2}^{2}+\beta\left||z_{e}(x)-\mathrm{sg}[e]|_{2}^{2}' # noqa: E501 out = post_post_process_latex(latex) - # 其他的测试字符串 latex + print(f'{latex}\n->\n{out}\n') + # 以下是其他的测试字符串来测试此接口功能是否符合预期 + latex = r'(a+b)^2 +(a-b)^2' + out = post_post_process_latex(latex) + print(f'{latex}\n->\n{out}\n') + + # 下面这个Latex是正确的,不应该被修改 + latex = r'\left\{\begin{array}{ll}1 & \text { if } x>0 \\0 & \text { if } x \leq 0\end{array}\right.' + out = post_post_process_latex(latex) + assert out == latex + print(f'{latex}\n==\n{out}\n') From 7a5082b9cb54069e70632abb1b4cef7dc8fa415e Mon Sep 17 00:00:00 2001 From: breezedeus Date: Sun, 19 Feb 2023 15:19:15 +0800 Subject: [PATCH 5/7] update dependencies --- requirements.in | 4 ++-- requirements.txt | 8 ++++---- setup.py | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/requirements.in b/requirements.in index 5625fec..0b7c933 100644 --- a/requirements.in +++ b/requirements.in @@ -6,6 +6,6 @@ torch torchvision pillow>=5.3.0 opencv-python -cnstd>=1.2.1 -cnocr>=2.2.2.1 +cnstd>=1.2.2 +cnocr>=2.2.2.2 pix2tex==0.0.29 diff --git a/requirements.txt b/requirements.txt index f15ba93..6cd5964 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ # -# This file is autogenerated by pip-compile with python 3.8 -# To update, run: +# This file is autogenerated by pip-compile with Python 3.8 +# by the following command: # # pip-compile --output-file=requirements.txt requirements.in # @@ -32,9 +32,9 @@ click==8.1.3 # -r requirements.in # cnocr # cnstd -cnocr==2.2.2.1 +cnocr==2.2.2.2 # via -r requirements.in -cnstd==1.2.1 +cnstd==1.2.2 # via # -r requirements.in # cnocr diff --git a/setup.py b/setup.py index 8cc1bfe..9927cd6 100644 --- a/setup.py +++ b/setup.py @@ -25,8 +25,8 @@ "tqdm", "numpy<1.24", "opencv-python", - "cnocr>=2.2.2.1", - "cnstd>=1.2.1", + "cnocr>=2.2.2.2", + "cnstd>=1.2.2", "torch", "torchvision", "pix2tex", From 350e9538532b853d4cbf18df8826f6cf9c766fab Mon Sep 17 00:00:00 2001 From: breezedeus Date: Sun, 19 Feb 2023 15:19:40 +0800 Subject: [PATCH 6/7] update doc --- README.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index b29fda7..92a3c79 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ ![last-commit](https://img.shields.io/github/last-commit/breezedeus/pix2text) [![Twitter](https://img.shields.io/twitter/url?url=https%3A%2F%2Ftwitter.com%2Fbreezedeus)](https://twitter.com/breezedeus) -[🛀🏻 在线Demo](https://huggingface.co/spaces/breezedeus/pix2text) | +[👩🏻‍💻网页版](https://p2t.behye.com) | [💬 交流群](https://cnocr.readthedocs.io/zh/latest/contact/) @@ -24,11 +24,11 @@ # Pix2Text (P2T) -【Update 2023.02.10: **[P2T网页版](https://p2t.behye.com)** 开放免费试用】 +【Update 2023.02.10: **[P2T网页版](https://p2t.behye.com)** 开放免费使用】 -* P2T作为Python包,对于不熟悉Python的朋友还是太不友好,所以我们也开发了 [P2T网页版](https://p2t.behye.com)。 - 限于服务器资源有限,网页版前期只开放少量 key 供有需要的朋友使用,优先在校师生(MathPix 每月要5美元,对在校生来说还是蛮贵的)。 -* 更多信息:[Pix2Text (P2T) 新版发布,离Mathpix又近了一大步 - 知乎](https://zhuanlan.zhihu.com/p/604999678) 。 +* P2T作为Python包,对于不熟悉Python的朋友还是太不友好,所以我们也开发了 [P2T网页版](https://p2t.behye.com),可直接免费使用,欢迎帮忙推荐分享。 +* 视频介绍:[Pix2Text 新版和网页版发布,离Mathpix又近了一大步_bilibili](https://www.bilibili.com/video/BV1U24y1q7n3) 。 +* 文字版介绍:[Pix2Text (P2T) 新版发布,离Mathpix又近了一大步 - 知乎](https://zhuanlan.zhihu.com/p/604999678) 。 【Update 2023.02.03:**V0.2** 发布】 @@ -398,13 +398,15 @@ Options: analyzer] -a, --analyzer-name [mfd|layout] 使用哪个Analyzer,MFD还是版面分析 [default: mfd] + -t, --analyzer-type TEXT Analyzer使用哪个模型,'yolov7_tiny' or 'yolov7' + [default: yolov7_tiny] -d, --device TEXT 使用 `cpu` 还是 `gpu` 运行代码,也可指定为特定gpu,如`cuda:0` [default: cpu] - --resized-shape INTEGER 把图片宽度resize到此大小再进行处理 [default: 700] + --resized-shape INTEGER 把图片宽度resize到此大小再进行处理 [default: 600] -i, --img-file-or-dir TEXT 输入图片的文件路径或者指定的文件夹 [required] - --save-analysis-res TEXT 把解析结果存储到此文件或目录中(如果"--img-file-or-dir" - 为文件/文件夹,则"--save-analysis-res" - 也应该是文件/文件夹)。取值为 `None` 表示不存储 [default: None] + --save-analysis-res TEXT 把解析结果存储到此文件或目录中(如果'--img-file-or- + dir'为文件/文件夹,则'--save-analysis- + res'也应该是文件/文件夹)。取值为 `None` 表示不存储 -l, --log-level TEXT Log Level, such as `INFO`, `DEBUG` [default: INFO] -h, --help Show this message and exit. From 6cb49adfa3fac70585bde910d30c31a6ad60b596 Mon Sep 17 00:00:00 2001 From: breezedeus Date: Sun, 19 Feb 2023 15:36:48 +0800 Subject: [PATCH 7/7] update doc --- README.md | 2 ++ RELEASE.md | 12 +++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 92a3c79..1f7e46e 100644 --- a/README.md +++ b/README.md @@ -34,6 +34,8 @@ * 利用 **[CnSTD](https://github.com/breezedeus/cnstd)** 新版的**数学公式检测**(**Mathematical Formula Detection**,简称 **MFD**)能力,**P2T V0.2** 支持**识别既包含文字又包含公式的混合图片**。 +了解更多:[RELEASE.md](./RELEASE.md) 。 + --- diff --git a/RELEASE.md b/RELEASE.md index e535df8..74eefd0 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -1,14 +1,20 @@ # Release Notes -# Update 2023.02.03:发布 **V0.2** +## Update 2023.02.19:发布 **V0.2.1** + +主要变更: +* 增加后处理机制优化Latex-OCR的识别结果; +* 使用最新的 [CnSTD](https://github.com/breezedeus/cnstd) 和 [CnOCR](https://github.com/breezedeus/cnocr),它们修复了一些bug。 + +## Update 2023.02.03:发布 **V0.2** 主要变更: * 利用 **[CnSTD](https://github.com/breezedeus/cnstd)** 新版的**数学公式检测**(**Mathematical Formula Detection**,简称 **MFD**)能力,**P2T V0.2** 支持**识别既包含文字又包含公式的混合图片**。 -# Update 2022.10.21:发布 V0.1.1 +## Update 2022.10.21:发布 V0.1.1 主要变更: * Fix: remove the character which causes error on Windows -# Update 2022.09.11:发布 V0.1 +## Update 2022.09.11:发布 V0.1 * 初版发布