feat: 切换后端至PaddleOCR-NCNN,切换工程为CMake

1.项目后端整体迁移至PaddleOCR-NCNN算法,已通过基本的兼容性测试
2.工程改为使用CMake组织,后续为了更好地兼容第三方库,不再提供QMake工程
3.重整权利声明文件,重整代码工程,确保最小化侵权风险

Log: 切换后端至PaddleOCR-NCNN,切换工程为CMake
Change-Id: I4d5d2c5d37505a4a24b389b1a4c5d12f17bfa38c
This commit is contained in:
wangzhengyang
2022-05-10 09:54:44 +08:00
parent ecdd171c6f
commit 718c41634f
10018 changed files with 3593797 additions and 186748 deletions

View File

@ -0,0 +1,99 @@
"""
This code adds Python/Java signatures to the docs.
TODO: Do the same thing for Java
* using javadoc/ get all the methods/classes/constants to a json file
TODO:
* clarify when there are several C++ signatures corresponding to a single Python function.
i.e: calcHist():
http://docs.opencv.org/3.2.0/d6/dc7/group__imgproc__hist.html#ga4b2b5fd75503ff9e6844cc4dcdaed35d
* clarify special case:
http://docs.opencv.org/3.2.0/db/de0/group__core__utils.html#ga4910d7f86336cd4eff9dd05575667e41
"""
from __future__ import print_function
import sys
sys.dont_write_bytecode = True # Don't generate .pyc files / __pycache__ directories
import os
from pprint import pprint
import re
import logging
import json
import html_functions
import doxygen_scan
loglevel=os.environ.get("LOGLEVEL", None)
if loglevel:
logging.basicConfig(level=loglevel)
ROOT_DIR = sys.argv[1]
PYTHON_SIGNATURES_FILE = sys.argv[2]
JAVA_OR_PYTHON = sys.argv[3]
ADD_JAVA = False
ADD_PYTHON = False
if JAVA_OR_PYTHON == "python":
ADD_PYTHON = True
python_signatures = dict()
with open(PYTHON_SIGNATURES_FILE, "rt") as f:
python_signatures = json.load(f)
print("Loaded Python signatures: %d" % len(python_signatures))
import xml.etree.ElementTree as ET
root = ET.parse(ROOT_DIR + 'opencv.tag')
files_dict = {}
# constants and function from opencv.tag
namespaces = root.findall("./compound[@kind='namespace']")
#print("Found {} namespaces".format(len(namespaces)))
for ns in namespaces:
ns_name = ns.find("./name").text
#print('NS: {}'.format(ns_name))
doxygen_scan.scan_namespace_constants(ns, ns_name, files_dict)
doxygen_scan.scan_namespace_functions(ns, ns_name, files_dict)
# class methods from opencv.tag
classes = root.findall("./compound[@kind='class']")
#print("Found {} classes".format(len(classes)))
for c in classes:
c_name = c.find("./name").text
file = c.find("./filename").text
#print('Class: {} => {}'.format(c_name, file))
doxygen_scan.scan_class_methods(c, c_name, files_dict)
print('Doxygen files to scan: %s' % len(files_dict))
files_processed = 0
files_skipped = 0
symbols_processed = 0
for file in files_dict:
#if file != "dd/d9e/classcv_1_1VideoWriter.html":
#if file != "d4/d86/group__imgproc__filter.html":
#if file != "df/dfb/group__imgproc__object.html":
# continue
#print('File: ' + file)
anchor_list = files_dict[file]
active_anchors = [a for a in anchor_list if a.cppname in python_signatures]
if len(active_anchors) == 0: # no linked Python symbols
#print('Skip: ' + file)
files_skipped = files_skipped + 1
continue
active_anchors_dict = {a.anchor: a for a in active_anchors}
if len(active_anchors_dict) != len(active_anchors):
logging.info('Duplicate entries detected: %s -> %s (%s)' % (len(active_anchors), len(active_anchors_dict), file))
files_processed = files_processed + 1
#pprint(active_anchors)
symbols_processed = symbols_processed + len(active_anchors_dict)
logging.info('File: %r' % file)
html_functions.insert_python_signatures(python_signatures, active_anchors_dict, ROOT_DIR + file)
print('Done (processed files %d, symbols %d, skipped %d files)' % (files_processed, symbols_processed, files_skipped))

View File

@ -0,0 +1,48 @@
import traceback
class Symbol(object):
def __init__(self, anchor, type, cppname):
self.anchor = anchor
self.type = type
self.cppname = cppname
#if anchor == 'ga586ebfb0a7fb604b35a23d85391329be':
# print(repr(self))
# traceback.print_stack()
def __repr__(self):
return '%s:%s@%s' % (self.type, self.cppname, self.anchor)
def add_to_file(files_dict, file, anchor):
anchors = files_dict.setdefault(file, [])
anchors.append(anchor)
def scan_namespace_constants(ns, ns_name, files_dict):
constants = ns.findall("./member[@kind='enumvalue']")
for c in constants:
c_name = c.find("./name").text
name = ns_name + '::' + c_name
file = c.find("./anchorfile").text
anchor = c.find("./anchor").text
#print(' CONST: {} => {}#{}'.format(name, file, anchor))
add_to_file(files_dict, file, Symbol(anchor, "const", name))
def scan_namespace_functions(ns, ns_name, files_dict):
functions = ns.findall("./member[@kind='function']")
for f in functions:
f_name = f.find("./name").text
name = ns_name + '::' + f_name
file = f.find("./anchorfile").text
anchor = f.find("./anchor").text
#print(' FN: {} => {}#{}'.format(name, file, anchor))
add_to_file(files_dict, file, Symbol(anchor, "fn", name))
def scan_class_methods(c, c_name, files_dict):
methods = c.findall("./member[@kind='function']")
for m in methods:
m_name = m.find("./name").text
name = c_name + '::' + m_name
file = m.find("./anchorfile").text
anchor = m.find("./anchor").text
#print(' Method: {} => {}#{}'.format(name, file, anchor))
add_to_file(files_dict, file, Symbol(anchor, "method", name))

View File

@ -0,0 +1,127 @@
from __future__ import print_function
import sys
import logging
import os
import re
from pprint import pprint
import traceback
try:
import bs4
from bs4 import BeautifulSoup
except ImportError:
raise ImportError('Error: '
'Install BeautifulSoup (bs4) for adding'
' Python & Java signatures documentation')
def load_html_file(file_dir):
""" Uses BeautifulSoup to load an html """
with open(file_dir, 'rb') as fp:
data = fp.read()
if os.name == 'nt' or sys.version_info[0] == 3:
data = data.decode(encoding='utf-8', errors='strict')
data = re.sub(r'(\>)([ ]+)', lambda match: match.group(1) + ('!space!' * len(match.group(2))), data)
data = re.sub(r'([ ]+)(\<)', lambda match: ('!space!' * len(match.group(1))) + match.group(2), data)
if os.name == 'nt' or sys.version_info[0] == 3:
data = data.encode('utf-8', 'ignore')
soup = BeautifulSoup(data, 'html.parser')
return soup
def update_html(file, soup):
s = str(soup)
s = s.replace('!space!', ' ')
if os.name == 'nt' or sys.version_info[0] == 3:
s = s.encode('utf-8', 'ignore')
with open(file, 'wb') as f:
f.write(s)
def insert_python_signatures(python_signatures, symbols_dict, filepath):
soup = load_html_file(filepath)
entries = soup.find_all(lambda tag: tag.name == "a" and tag.has_attr('id'))
for e in entries:
anchor = e['id']
if anchor in symbols_dict:
s = symbols_dict[anchor]
logging.info('Process: %r' % s)
if s.type == 'fn' or s.type == 'method':
process_fn(soup, e, python_signatures[s.cppname], s)
elif s.type == 'const':
process_const(soup, e, python_signatures[s.cppname], s)
else:
logging.error('unsupported type: %s' % s);
update_html(filepath, soup)
def process_fn(soup, anchor, python_signature, symbol):
try:
r = anchor.find_next_sibling(class_='memitem').find(class_='memproto').find('table')
insert_python_fn_signature(soup, r, python_signature, symbol)
except:
logging.error("Can't process: %s" % symbol)
traceback.print_exc()
pprint(anchor)
def process_const(soup, anchor, python_signature, symbol):
try:
#pprint(anchor.parent)
description = append(soup.new_tag('div', **{'class' : ['python_language']}),
'Python: ' + python_signature[0]['name'])
old = anchor.find_next_sibling('div', class_='python_language')
if old is None:
anchor.parent.append(description)
else:
old.replace_with(description)
#pprint(anchor.parent)
except:
logging.error("Can't process: %s" % symbol)
traceback.print_exc()
pprint(anchor)
def insert_python_fn_signature(soup, table, variants, symbol):
description = create_python_fn_description(soup, variants)
description['class'] = 'python_language'
soup = insert_or_replace(table, description, 'table', 'python_language')
return soup
def create_python_fn_description(soup, variants):
language = 'Python:'
table = soup.new_tag('table')
heading_row = soup.new_tag('th')
table.append(
append(soup.new_tag('tr'),
append(soup.new_tag('th', colspan=999, style="text-align:left"), language)))
for v in variants:
#logging.debug(v)
add_signature_to_table(soup, table, v, language, type)
#print(table)
return table
def add_signature_to_table(soup, table, signature, language, type):
""" Add a signature to an html table"""
row = soup.new_tag('tr')
row.append(soup.new_tag('td', style='width: 20px;'))
row.append(append(soup.new_tag('td'), signature['name'] + '('))
row.append(append(soup.new_tag('td', **{'class': 'paramname'}), signature['arg']))
row.append(append(soup.new_tag('td'), ') -> '))
row.append(append(soup.new_tag('td'), signature['ret']))
table.append(row)
def append(target, obj):
target.append(obj)
return target
def insert_or_replace(element_before, new_element, tag, tag_class):
old = element_before.find_next_sibling(tag, class_=tag_class)
if old is None:
element_before.insert_after(new_element)
else:
old.replace_with(new_element)

View File

@ -0,0 +1,96 @@
#!/usr/bin/env python
from pathlib import Path
import re
# Tasks
# 1. Find all tutorials
# 2. Generate tree (@subpage)
# 3. Check prev/next nodes
class Tutorial(object):
def __init__(self, path):
self.path = path
self.title = None # doxygen title
self.children = [] # ordered titles
self.prev = None
self.next = None
with open(path, "rt") as f:
self.parse(f)
def parse(self, f):
rx_title = re.compile(r"\{#(\w+)\}")
rx_subpage = re.compile(r"@subpage\s+(\w+)")
rx_prev = re.compile(r"@prev_tutorial\{(\w+)\}")
rx_next = re.compile(r"@next_tutorial\{(\w+)\}")
for line in f:
if self.title is None:
m = rx_title.search(line)
if m:
self.title = m.group(1)
continue
if self.prev is None:
m = rx_prev.search(line)
if m:
self.prev = m.group(1)
continue
if self.next is None:
m = rx_next.search(line)
if m:
self.next = m.group(1)
continue
m = rx_subpage.search(line)
if m:
self.children.append(m.group(1))
continue
def verify_prev_next(self, storage):
res = True
if self.title is None:
print("[W] No title")
res = False
prev = None
for one in self.children:
c = storage[one]
if c.prev is not None and c.prev != prev:
print("[W] Wrong prev_tutorial: expected {} / actual {}".format(c.prev, prev))
res = False
prev = c.title
next = None
for one in reversed(self.children):
c = storage[one]
if c.next is not None and c.next != next:
print("[W] Wrong next_tutorial: expected {} / actual {}".format(c.next, next))
res = False
next = c.title
if len(self.children) == 0 and self.prev is None and self.next is None:
print("[W] No prev and next tutorials")
res = False
return res
if __name__ == "__main__":
p = Path('tutorials')
print("Looking for tutorials in: '{}'".format(p))
all_tutorials = dict()
for f in p.glob('**/*'):
if f.suffix.lower() in ('.markdown', '.md'):
t = Tutorial(f)
all_tutorials[t.title] = t
res = 0
print("Found: {}".format(len(all_tutorials)))
print("------")
for title, t in all_tutorials.items():
if not t.verify_prev_next(all_tutorials):
print("[E] Verification failed: {}".format(t.path))
print("------")
res = 1
exit(res)