py2ls 0.2.4.32__py3-none-any.whl → 0.2.4.33__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|