py2ls 0.2.4.32__py3-none-any.whl → 0.2.4.33__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- py2ls/.git/index +0 -0
- py2ls/ips.py +736 -164
- py2ls/netfinder.py +99 -0
- py2ls/ocr.py +140 -126
- py2ls/plot.py +612 -376
- {py2ls-0.2.4.32.dist-info → py2ls-0.2.4.33.dist-info}/METADATA +1 -1
- {py2ls-0.2.4.32.dist-info → py2ls-0.2.4.33.dist-info}/RECORD +8 -8
- {py2ls-0.2.4.32.dist-info → py2ls-0.2.4.33.dist-info}/WHEEL +0 -0
py2ls/netfinder.py
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
from bs4 import BeautifulSoup
|
2
|
+
import scrapy
|
2
3
|
import requests
|
3
4
|
import os
|
4
5
|
import pandas as pd
|
@@ -332,6 +333,94 @@ def parse_cookies(cookies_str):
|
|
332
333
|
|
333
334
|
return cookies_dict
|
334
335
|
|
336
|
+
class FetchSpider(scrapy.Spider):
|
337
|
+
name = "fetch_spider"
|
338
|
+
|
339
|
+
def __init__(self, url, parser="html.parser", cookies=None, headers=None, *args, **kwargs):
|
340
|
+
super(FetchSpider, self).__init__(*args, **kwargs)
|
341
|
+
self.start_urls = [url]
|
342
|
+
self.cookies = cookies
|
343
|
+
self.headers = headers
|
344
|
+
self.parser = parser
|
345
|
+
|
346
|
+
def start_requests(self):
|
347
|
+
for url in self.start_urls:
|
348
|
+
yield scrapy.Request(
|
349
|
+
url,
|
350
|
+
cookies=self.cookies,
|
351
|
+
headers=self.headers,
|
352
|
+
callback=self.parse
|
353
|
+
)
|
354
|
+
|
355
|
+
def parse(self, response):
|
356
|
+
# Use the desired parser (default: html.parser)
|
357
|
+
from bs4 import BeautifulSoup
|
358
|
+
soup = BeautifulSoup(response.text, self.parser)
|
359
|
+
yield {"content": soup}
|
360
|
+
|
361
|
+
|
362
|
+
def fetch_scrapy(
|
363
|
+
url,
|
364
|
+
parser="html.parser",
|
365
|
+
cookies=None,
|
366
|
+
headers=None,
|
367
|
+
settings=None,
|
368
|
+
):
|
369
|
+
"""
|
370
|
+
Fetches content using Scrapy.
|
371
|
+
|
372
|
+
Args:
|
373
|
+
url (str): The URL to scrape.
|
374
|
+
parser (str): Parser for BeautifulSoup (e.g., "lxml", "html.parser").
|
375
|
+
cookies (dict): Cookies to pass in the request.
|
376
|
+
headers (dict): HTTP headers for the request.
|
377
|
+
settings (dict): Scrapy settings, if any.
|
378
|
+
|
379
|
+
Returns:
|
380
|
+
dict: Parsed content as a dictionary.
|
381
|
+
"""
|
382
|
+
from scrapy.utils.project import get_project_settings
|
383
|
+
from scrapy.crawler import CrawlerProcess
|
384
|
+
from scrapy.signalmanager import dispatcher
|
385
|
+
from scrapy import signals
|
386
|
+
import scrapy
|
387
|
+
|
388
|
+
# Container for scraped content
|
389
|
+
content = []
|
390
|
+
|
391
|
+
# Callback function for item scraped signal
|
392
|
+
def handle_item(item, response, spider):
|
393
|
+
content.append(item["content"])
|
394
|
+
|
395
|
+
# Scrapy settings
|
396
|
+
process_settings = settings or get_project_settings()
|
397
|
+
process_settings.update(
|
398
|
+
{
|
399
|
+
"USER_AGENT": "CustomUserAgent/1.0", # Use a custom user agent
|
400
|
+
"DOWNLOAD_DELAY": 1, # Prevent overloading servers
|
401
|
+
"COOKIES_ENABLED": bool(cookies),
|
402
|
+
"LOG_LEVEL": "ERROR", # Minimize log verbosity
|
403
|
+
}
|
404
|
+
)
|
405
|
+
|
406
|
+
# Initialize and configure Scrapy process
|
407
|
+
process = CrawlerProcess(settings=process_settings)
|
408
|
+
dispatcher.connect(handle_item, signal=signals.item_scraped)
|
409
|
+
|
410
|
+
# Start the Scrapy crawl
|
411
|
+
process.crawl(
|
412
|
+
FetchSpider,
|
413
|
+
url=url,
|
414
|
+
parser=parser,
|
415
|
+
cookies=cookies,
|
416
|
+
headers=headers,
|
417
|
+
)
|
418
|
+
process.start() # Blocks until all crawls are finished
|
419
|
+
|
420
|
+
# Return the first scraped content or None if empty
|
421
|
+
return content[0] if content else None
|
422
|
+
|
423
|
+
|
335
424
|
def fetch_all(
|
336
425
|
url,
|
337
426
|
parser="lxml",
|
@@ -558,6 +647,16 @@ def fetch_all(
|
|
558
647
|
else:
|
559
648
|
logger.warning("Selenium could not fetch content")
|
560
649
|
return None, None
|
650
|
+
elif 'scr' in driver.lower():
|
651
|
+
settings = {
|
652
|
+
"USER_AGENT": user_agent(),
|
653
|
+
"DOWNLOAD_DELAY": 1, # Prevent overloading the server
|
654
|
+
"COOKIES_ENABLED": True if cookies else False,
|
655
|
+
"LOG_LEVEL": "WARNING", # Reduce log verbosity
|
656
|
+
}
|
657
|
+
content=fetch_scrapy(url, parser=parser, cookies=cookies, headers=headers, settings=settings)
|
658
|
+
return parser, content
|
659
|
+
|
561
660
|
except requests.RequestException as e:
|
562
661
|
logger.error(f"Error fetching URL '{url}': {e}")
|
563
662
|
return None, None
|
py2ls/ocr.py
CHANGED
@@ -1,23 +1,16 @@
|
|
1
|
-
|
1
|
+
|
2
2
|
import cv2
|
3
3
|
import numpy as np
|
4
4
|
import matplotlib.pyplot as plt
|
5
5
|
from py2ls.ips import (
|
6
6
|
strcmp,
|
7
7
|
detect_angle,
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
from PIL import Image, ImageDraw, ImageFont
|
13
|
-
import PIL.PngImagePlugin
|
14
|
-
import pytesseract
|
15
|
-
from paddleocr import PaddleOCR
|
8
|
+
str2words,
|
9
|
+
isa
|
10
|
+
)
|
16
11
|
import logging
|
17
|
-
|
18
|
-
logging.getLogger("ppocr").setLevel(
|
19
|
-
logging.WARNING
|
20
|
-
) # or logging.ERROR to show only error messages
|
12
|
+
#logging.getLogger("ppocr").setLevel(logging.ERROR)
|
13
|
+
logging.getLogger("ppocr").setLevel(logging.WARNING)
|
21
14
|
|
22
15
|
"""
|
23
16
|
Optical Character Recognition (OCR)
|
@@ -285,10 +278,12 @@ def add_text_pil(
|
|
285
278
|
image,
|
286
279
|
text,
|
287
280
|
position,
|
281
|
+
cvt_cmp=True,
|
288
282
|
font_size=12,
|
289
283
|
color=(0, 0, 0),
|
290
284
|
bg_color=(133, 203, 245, 100),
|
291
285
|
):
|
286
|
+
from PIL import Image, ImageDraw, ImageFont
|
292
287
|
# Convert the image to PIL format
|
293
288
|
pil_image = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB)).convert("RGBA")
|
294
289
|
# Define the font (make sure to use a font that supports Chinese characters)
|
@@ -337,7 +332,7 @@ def add_text_pil(
|
|
337
332
|
overlay = overlay.convert("RGBA")
|
338
333
|
combined = Image.alpha_composite(pil_image, overlay)
|
339
334
|
# Convert the image back to OpenCV format
|
340
|
-
image = cv2.cvtColor(np.array(combined), cv2.COLOR_RGBA2BGR)
|
335
|
+
image = cv2.cvtColor(np.array(combined), cv2.COLOR_RGBA2BGR) #if cvt_cmp else np.array(combined)
|
341
336
|
return image
|
342
337
|
|
343
338
|
|
@@ -348,7 +343,7 @@ def preprocess_img(
|
|
348
343
|
threshold_method="adaptive",
|
349
344
|
rotate="auto",
|
350
345
|
skew=False,
|
351
|
-
blur=True,
|
346
|
+
blur=False,#True,
|
352
347
|
blur_ksize=(5, 5),
|
353
348
|
morph=True,
|
354
349
|
morph_op="open",
|
@@ -384,12 +379,14 @@ def preprocess_img(
|
|
384
379
|
clahe_grid_size: CLAHE 的网格大小。
|
385
380
|
edge_detection: 是否进行边缘检测。
|
386
381
|
"""
|
382
|
+
import PIL.PngImagePlugin
|
387
383
|
if isinstance(image, PIL.PngImagePlugin.PngImageFile):
|
388
384
|
image = np.array(image)
|
389
385
|
if isinstance(image, str):
|
390
386
|
image = cv2.imread(image)
|
391
387
|
if not isinstance(image, np.ndarray):
|
392
388
|
image = np.array(image)
|
389
|
+
|
393
390
|
try:
|
394
391
|
if image.shape[1] == 4: # Check if it has an alpha channel
|
395
392
|
# Drop the alpha channel (if needed), or handle it as required
|
@@ -507,6 +504,8 @@ def text_postprocess(
|
|
507
504
|
pattern=None,
|
508
505
|
merge=True,
|
509
506
|
):
|
507
|
+
import re
|
508
|
+
from spellchecker import SpellChecker
|
510
509
|
|
511
510
|
def correct_spelling(text_list):
|
512
511
|
spell = SpellChecker()
|
@@ -531,9 +530,9 @@ def text_postprocess(
|
|
531
530
|
return merged_text
|
532
531
|
|
533
532
|
results = text
|
534
|
-
print(results)
|
535
533
|
if spell_check:
|
536
|
-
results = correct_spelling(results)
|
534
|
+
# results = correct_spelling(results)
|
535
|
+
results=str2words(results)
|
537
536
|
if clean:
|
538
537
|
results = clean_text(results)
|
539
538
|
if filter:
|
@@ -552,42 +551,39 @@ def get_text(
|
|
552
551
|
image,
|
553
552
|
lang=["ch_sim", "en"],
|
554
553
|
model="paddleocr", # "pytesseract","paddleocr","easyocr"
|
555
|
-
thr=0.1,
|
554
|
+
thr=0.1,
|
556
555
|
gpu=True,
|
557
556
|
decoder="wordbeamsearch", #'greedy', 'beamsearch' and 'wordbeamsearch'(hightly accurate)
|
558
557
|
output="txt",
|
559
558
|
preprocess=None,
|
560
|
-
postprocess=
|
559
|
+
postprocess=False,# do not check spell
|
561
560
|
show=True,
|
562
561
|
ax=None,
|
563
562
|
cmap=cv2.COLOR_BGR2RGB, # draw_box
|
564
|
-
font=cv2.FONT_HERSHEY_SIMPLEX
|
565
|
-
|
566
|
-
|
567
|
-
box_color=(0, 255, 0), # draw_box
|
568
|
-
|
569
|
-
bg_color=(133, 203, 245, 100)
|
563
|
+
font=cv2.FONT_HERSHEY_SIMPLEX,# draw_box
|
564
|
+
fontsize=8,# draw_box
|
565
|
+
figsize=[10,10],
|
566
|
+
box_color = (0, 255, 0), # draw_box
|
567
|
+
fontcolor = (0, 0, 0),# draw_box
|
568
|
+
bg_color=(133, 203, 245, 100),# draw_box
|
570
569
|
usage=False,
|
571
570
|
**kwargs,
|
572
571
|
):
|
573
572
|
"""
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
585
|
-
|
586
|
-
font_color: 文本的颜色。
|
587
|
-
kwargs: 传递给 EasyOCR readtext 函数的其他参数。
|
588
|
-
|
589
|
-
# Uage
|
573
|
+
image: 输入的图像路径或图像数据。
|
574
|
+
lang: OCR 语言列表。
|
575
|
+
thr: 置信度阈值,低于此阈值的检测结果将被过滤。
|
576
|
+
gpu: 是否使用 GPU。
|
577
|
+
output: 输出类型,可以是 'all'(返回所有检测结果)、'text'(返回文本)、'score'(返回置信度分数)、'box'(返回边界框)。
|
578
|
+
preprocess: 预处理参数字典,传递给 preprocess_img 函数。
|
579
|
+
show: 是否显示结果图像。
|
580
|
+
ax: 用于显示图像的 Matplotlib 子图。
|
581
|
+
cmap: 用于显示图像的颜色映射。
|
582
|
+
box_color: 边界框的颜色。
|
583
|
+
fontcolor: 文本的颜色。
|
584
|
+
kwargs: 传递给 EasyOCR readtext 函数的其他参数。
|
590
585
|
"""
|
586
|
+
from PIL import Image
|
591
587
|
if usage:
|
592
588
|
print(
|
593
589
|
"""
|
@@ -612,16 +608,20 @@ def get_text(
|
|
612
608
|
"edge_detection": False
|
613
609
|
},
|
614
610
|
adjust_contrast=0.7
|
615
|
-
)
|
616
|
-
"""
|
617
|
-
)
|
611
|
+
)""")
|
618
612
|
|
619
|
-
models = ["easyocr", "paddleocr", "pytesseract","ddddocr"]
|
613
|
+
models = ["easyocr", "paddleocr", "pytesseract","ddddocr","zerox"]
|
620
614
|
model = strcmp(model, models)[0]
|
621
615
|
lang = lang_auto_detect(lang, model)
|
622
|
-
|
623
|
-
|
616
|
+
cvt_cmp=True
|
617
|
+
if isinstance(image, str) and isa(image,'file'):
|
624
618
|
image = cv2.imread(image)
|
619
|
+
elif isa(image,'image'):
|
620
|
+
cvt_cmp=False
|
621
|
+
print(1)
|
622
|
+
image = np.array(image)
|
623
|
+
else:
|
624
|
+
raise ValueError(f"not support image with {type(image)} type")
|
625
625
|
|
626
626
|
# Ensure lang is always a list
|
627
627
|
if isinstance(lang, str):
|
@@ -631,110 +631,94 @@ def get_text(
|
|
631
631
|
if preprocess is None:
|
632
632
|
preprocess = {}
|
633
633
|
image_process = preprocess_img(image, **preprocess)
|
634
|
+
plt.figure(figsize=figsize) if show else None
|
635
|
+
# plt.subplot(131)
|
636
|
+
# plt.imshow(cv2.cvtColor(image, cmap)) if cvt_cmp else plt.imshow(image)
|
637
|
+
# plt.subplot(132)
|
638
|
+
# plt.imshow(image_process)
|
639
|
+
# plt.subplot(133)
|
634
640
|
if "easy" in model.lower():
|
641
|
+
import easyocr
|
635
642
|
print(f"detecting language(s):{lang}")
|
636
643
|
# Perform OCR on the image
|
637
644
|
reader = easyocr.Reader(lang, gpu=gpu)
|
638
645
|
detections = reader.readtext(image_process, decoder=decoder, **kwargs)
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
pattern=None,
|
645
|
-
merge=True,
|
646
|
-
)
|
647
|
-
text_corr = []
|
648
|
-
[
|
649
|
-
text_corr.extend(text_postprocess(text, **postprocess))
|
650
|
-
for _, text, _ in detections
|
651
|
-
]
|
646
|
+
|
647
|
+
text_corr = []
|
648
|
+
for _, text, _ in detections:
|
649
|
+
text_corr.append(text_postprocess(text) if postprocess else text)
|
650
|
+
|
652
651
|
if show:
|
653
652
|
if ax is None:
|
654
653
|
ax = plt.gca()
|
655
|
-
for bbox, text, score in detections:
|
654
|
+
for i, (bbox, text, score) in enumerate(detections):
|
656
655
|
if score > thr:
|
657
656
|
top_left = tuple(map(int, bbox[0]))
|
658
657
|
bottom_right = tuple(map(int, bbox[2]))
|
659
|
-
image = cv2.rectangle(image, top_left, bottom_right, box_color, 2)
|
660
|
-
# image = cv2.putText(
|
661
|
-
# image, text, top_left, font, font_scale, font_color, thickness_text
|
662
|
-
# )
|
658
|
+
image = cv2.rectangle(image, top_left, bottom_right, box_color, 2)
|
663
659
|
image = add_text_pil(
|
664
660
|
image,
|
665
|
-
|
661
|
+
text_corr[i],
|
666
662
|
top_left,
|
667
|
-
|
668
|
-
|
663
|
+
cvt_cmp=cvt_cmp,
|
664
|
+
font_size=fontsize *6,
|
665
|
+
color=fontcolor,
|
669
666
|
)
|
670
|
-
|
671
|
-
|
667
|
+
try:
|
668
|
+
img_cmp = cv2.cvtColor(image, cmap) if cvt_cmp else image
|
669
|
+
except:
|
670
|
+
img_cmp=image
|
671
|
+
|
672
|
+
ax.imshow(img_cmp) if cvt_cmp else ax.imshow(image)
|
672
673
|
ax.axis("off")
|
673
|
-
|
674
|
-
# 根据输出类型返回相应的结果
|
674
|
+
|
675
675
|
if output == "all":
|
676
676
|
return ax, detections
|
677
677
|
elif "t" in output.lower() and "x" in output.lower():
|
678
|
-
# 提取文本,过滤低置信度的结果
|
679
678
|
text = [text_ for _, text_, score_ in detections if score_ >= thr]
|
680
679
|
if postprocess:
|
681
680
|
return ax, text
|
682
681
|
else:
|
683
682
|
return text_corr
|
684
683
|
elif "score" in output.lower() or "prob" in output.lower():
|
685
|
-
# 提取分数
|
686
684
|
scores = [score_ for _, _, score_ in detections]
|
687
685
|
return ax, scores
|
688
686
|
elif "box" in output.lower():
|
689
|
-
# 提取边界框,过滤低置信度的结果
|
690
687
|
bboxes = [bbox_ for bbox_, _, score_ in detections if score_ >= thr]
|
691
688
|
return ax, bboxes
|
692
689
|
else:
|
693
|
-
# 默认返回所有检测信息
|
694
690
|
return ax, detections
|
695
691
|
else:
|
696
|
-
# 根据输出类型返回相应的结果
|
697
692
|
if output == "all":
|
698
693
|
return detections
|
699
694
|
elif "t" in output.lower() and "x" in output.lower():
|
700
|
-
# 提取文本,过滤低置信度的结果
|
701
695
|
text = [text_ for _, text_, score_ in detections if score_ >= thr]
|
702
696
|
return text
|
703
697
|
elif "score" in output.lower() or "prob" in output.lower():
|
704
|
-
# 提取分数
|
705
698
|
scores = [score_ for _, _, score_ in detections]
|
706
699
|
return scores
|
707
700
|
elif "box" in output.lower():
|
708
|
-
# 提取边界框,过滤低置信度的结果
|
709
701
|
bboxes = [bbox_ for bbox_, _, score_ in detections if score_ >= thr]
|
710
702
|
return bboxes
|
711
703
|
else:
|
712
|
-
# 默认返回所有检测信息
|
713
704
|
return detections
|
714
705
|
elif "pad" in model.lower():
|
706
|
+
from paddleocr import PaddleOCR
|
707
|
+
lang=strcmp(lang, ['ch','en','french','german','korean','japan'])[0]
|
715
708
|
ocr = PaddleOCR(
|
716
709
|
use_angle_cls=True,
|
717
710
|
cls=True,
|
711
|
+
lang=lang
|
718
712
|
) # PaddleOCR supports only one language at a time
|
719
|
-
|
713
|
+
cls=kwargs.pop('cls',True)
|
714
|
+
result = ocr.ocr(image_process,cls=cls, **kwargs)
|
720
715
|
detections = []
|
721
716
|
if result[0] is not None:
|
722
717
|
for line in result[0]:
|
723
718
|
bbox, (text, score) = line
|
719
|
+
text = str2words(text) if postprocess else text # check spell
|
724
720
|
detections.append((bbox, text, score))
|
725
|
-
|
726
|
-
postprocess = dict(
|
727
|
-
spell_check=True,
|
728
|
-
clean=True,
|
729
|
-
filter=dict(min_length=2),
|
730
|
-
pattern=None,
|
731
|
-
merge=True,
|
732
|
-
)
|
733
|
-
text_corr = []
|
734
|
-
[
|
735
|
-
text_corr.extend(text_postprocess(text, **postprocess))
|
736
|
-
for _, text, _ in detections
|
737
|
-
]
|
721
|
+
|
738
722
|
if show:
|
739
723
|
if ax is None:
|
740
724
|
ax = plt.gca()
|
@@ -746,60 +730,48 @@ def get_text(
|
|
746
730
|
) # Bottom-left for more accurate placement
|
747
731
|
bottom_right = tuple(map(int, bbox[2]))
|
748
732
|
image = cv2.rectangle(image, top_left, bottom_right, box_color, 2)
|
749
|
-
# image = cv2.putText(
|
750
|
-
# image, text, top_left, font, font_scale, font_color, thickness_text
|
751
|
-
# )
|
752
733
|
image = add_text_pil(
|
753
734
|
image,
|
754
735
|
text,
|
755
736
|
top_left,
|
756
|
-
|
757
|
-
|
737
|
+
cvt_cmp=cvt_cmp,
|
738
|
+
font_size=fontsize *6,
|
739
|
+
color=fontcolor,
|
758
740
|
bg_color=bg_color,
|
759
741
|
)
|
760
|
-
|
761
|
-
|
742
|
+
try:
|
743
|
+
img_cmp = cv2.cvtColor(image, cmap) if cvt_cmp else image
|
744
|
+
except:
|
745
|
+
img_cmp = image
|
746
|
+
|
747
|
+
ax.imshow(img_cmp)
|
762
748
|
ax.axis("off")
|
763
|
-
# plt.show()
|
764
|
-
# 根据输出类型返回相应的结果
|
765
749
|
if output == "all":
|
766
750
|
return ax, detections
|
767
751
|
elif "t" in output.lower() and "x" in output.lower():
|
768
|
-
# 提取文本,过滤低置信度的结果
|
769
752
|
text = [text_ for _, text_, score_ in detections if score_ >= thr]
|
770
|
-
|
771
|
-
return ax, text
|
772
|
-
else:
|
773
|
-
return text_corr
|
753
|
+
return ax, text
|
774
754
|
elif "score" in output.lower() or "prob" in output.lower():
|
775
|
-
# 提取分数
|
776
755
|
scores = [score_ for _, _, score_ in detections]
|
777
756
|
return ax, scores
|
778
757
|
elif "box" in output.lower():
|
779
|
-
# 提取边界框,过滤低置信度的结果
|
780
758
|
bboxes = [bbox_ for bbox_, _, score_ in detections if score_ >= thr]
|
781
759
|
return ax, bboxes
|
782
760
|
else:
|
783
|
-
# 默认返回所有检测信息
|
784
761
|
return ax, detections
|
785
762
|
else:
|
786
|
-
# 根据输出类型返回相应的结果
|
787
763
|
if output == "all":
|
788
764
|
return detections
|
789
765
|
elif "t" in output.lower() and "x" in output.lower():
|
790
|
-
# 提取文本,过滤低置信度的结果
|
791
766
|
text = [text_ for _, text_, score_ in detections if score_ >= thr]
|
792
767
|
return text
|
793
768
|
elif "score" in output.lower() or "prob" in output.lower():
|
794
|
-
# 提取分数
|
795
769
|
scores = [score_ for _, _, score_ in detections]
|
796
770
|
return scores
|
797
771
|
elif "box" in output.lower():
|
798
|
-
# 提取边界框,过滤低置信度的结果
|
799
772
|
bboxes = [bbox_ for bbox_, _, score_ in detections if score_ >= thr]
|
800
773
|
return bboxes
|
801
774
|
else:
|
802
|
-
# 默认返回所有检测信息
|
803
775
|
return detections
|
804
776
|
elif "ddddocr" in model.lower():
|
805
777
|
import ddddocr
|
@@ -844,7 +816,51 @@ def get_text(
|
|
844
816
|
ax.imshow(image_vis)
|
845
817
|
ax.axis("off")
|
846
818
|
return detections
|
819
|
+
|
820
|
+
elif "zerox" in model.lower():
|
821
|
+
from pyzerox import zerox
|
822
|
+
result = zerox(image_process)
|
823
|
+
detections = [(bbox, text, score) for bbox, text, score in result]
|
824
|
+
# Postprocess and visualize
|
825
|
+
if postprocess is None:
|
826
|
+
postprocess = dict(
|
827
|
+
spell_check=True,
|
828
|
+
clean=True,
|
829
|
+
filter=dict(min_length=2),
|
830
|
+
pattern=None,
|
831
|
+
merge=True,
|
832
|
+
)
|
833
|
+
text_corr = [text_postprocess(text, **postprocess) for _, text, _ in detections]
|
834
|
+
|
835
|
+
# Display results if 'show' is True
|
836
|
+
if show:
|
837
|
+
if ax is None:
|
838
|
+
ax = plt.gca()
|
839
|
+
for bbox, text, score in detections:
|
840
|
+
if score > thr:
|
841
|
+
top_left = tuple(map(int, bbox[0]))
|
842
|
+
bottom_right = tuple(map(int, bbox[2]))
|
843
|
+
image = cv2.rectangle(image, top_left, bottom_right, box_color, 2)
|
844
|
+
image = add_text_pil(image, text, top_left, cvt_cmp=cvt_cmp,font_size=fontsize *6, color=fontcolor, bg_color=bg_color)
|
845
|
+
ax.imshow(image)
|
846
|
+
ax.axis("off")
|
847
|
+
|
848
|
+
# Return result based on 'output' type
|
849
|
+
if output == "all":
|
850
|
+
return ax, detections
|
851
|
+
elif "t" in output.lower() and "x" in output.lower():
|
852
|
+
text = [text_ for _, text_, score_ in detections if score_ >= thr]
|
853
|
+
return ax, text
|
854
|
+
elif "score" in output.lower() or "prob" in output.lower():
|
855
|
+
scores = [score_ for _, _, score_ in detections]
|
856
|
+
return ax, scores
|
857
|
+
elif "box" in output.lower():
|
858
|
+
bboxes = [bbox_ for bbox_, _, score_ in detections if score_ >= thr]
|
859
|
+
return ax, bboxes
|
860
|
+
else:
|
861
|
+
return detections
|
847
862
|
else: # "pytesseract"
|
863
|
+
import pytesseract
|
848
864
|
if ax is None:
|
849
865
|
ax = plt.gca()
|
850
866
|
text = pytesseract.image_to_string(image_process, lang="+".join(lang), **kwargs)
|
@@ -869,8 +885,9 @@ def get_text(
|
|
869
885
|
image,
|
870
886
|
char,
|
871
887
|
left,
|
872
|
-
|
873
|
-
|
888
|
+
cvt_cmp=cvt_cmp,
|
889
|
+
font_size=fontsize *6,
|
890
|
+
color=fontcolor,
|
874
891
|
)
|
875
892
|
img_cmp = cv2.cvtColor(image, cmap)
|
876
893
|
ax.imshow(img_cmp)
|
@@ -906,8 +923,8 @@ def draw_box(
|
|
906
923
|
thr=0.25,
|
907
924
|
cmap=cv2.COLOR_BGR2RGB,
|
908
925
|
box_color=(0, 255, 0), # draw_box
|
909
|
-
|
910
|
-
|
926
|
+
fontcolor=(0, 0, 255), # draw_box
|
927
|
+
fontsize=8,
|
911
928
|
show=True,
|
912
929
|
ax=None,
|
913
930
|
**kwargs,
|
@@ -924,12 +941,9 @@ def draw_box(
|
|
924
941
|
if score > thr:
|
925
942
|
top_left = tuple(map(int, bbox[0]))
|
926
943
|
bottom_right = tuple(map(int, bbox[2]))
|
927
|
-
image = cv2.rectangle(image, top_left, bottom_right, box_color, 2)
|
928
|
-
# image = cv2.putText(
|
929
|
-
# image, text, top_left, font, font_scale, font_color, thickness_text
|
930
|
-
# )
|
944
|
+
image = cv2.rectangle(image, top_left, bottom_right, box_color, 2)
|
931
945
|
image = add_text_pil(
|
932
|
-
image, text, top_left, font_size=
|
946
|
+
image, text, top_left, cvt_cmp=cvt_cmp,font_size=fontsize *6, color=fontcolor
|
933
947
|
)
|
934
948
|
|
935
949
|
img_cmp = cv2.cvtColor(image, cmap)
|