commit
a72954a90e
@ -0,0 +1,36 @@
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
.ipynb_checkpoints/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
inference/
|
||||
inference_results/
|
||||
output/
|
||||
train_data/
|
||||
log/
|
||||
*.DS_Store
|
||||
*.vs
|
||||
*.user
|
||||
*~
|
||||
*.vscode
|
||||
*.idea
|
||||
|
||||
*.log
|
||||
.clang-format
|
||||
.clang_format.hook
|
||||
|
||||
build/
|
||||
dist/
|
||||
paddleocr.egg-info/
|
||||
/deploy/android_demo/app/OpenCV/
|
||||
/deploy/android_demo/app/PaddleLite/
|
||||
/deploy/android_demo/app/.cxx/
|
||||
/deploy/android_demo/app/cache/
|
||||
test_tipc/web/models/
|
||||
test_tipc/web/node_modules/
|
||||
Images/
|
||||
ImagesSmall/
|
@ -0,0 +1,45 @@
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v5.0.0
|
||||
hooks:
|
||||
- id: check-added-large-files
|
||||
args: ['--maxkb=512']
|
||||
- id: check-case-conflict
|
||||
- id: check-merge-conflict
|
||||
- id: check-symlinks
|
||||
- id: detect-private-key
|
||||
- id: end-of-file-fixer
|
||||
- id: trailing-whitespace
|
||||
files: \.(c|cc|cxx|cpp|cu|h|hpp|hxx|py)$
|
||||
- repo: https://github.com/Lucas-C/pre-commit-hooks
|
||||
rev: v1.5.5
|
||||
hooks:
|
||||
- id: remove-crlf
|
||||
- id: remove-tabs
|
||||
files: \.(c|cc|cxx|cpp|cu|h|hpp|hxx|py)$
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: clang-format
|
||||
name: clang-format
|
||||
description: Format files with ClangFormat
|
||||
entry: bash .clang_format.hook -i
|
||||
language: system
|
||||
files: \.(c|cc|cxx|cpp|cu|h|hpp|hxx|cuh|proto)$
|
||||
# For Python files
|
||||
- repo: https://github.com/psf/black.git
|
||||
rev: 24.10.0
|
||||
hooks:
|
||||
- id: black
|
||||
files: (.*\.(py|pyi|bzl)|BUILD|.*\.BUILD|WORKSPACE)$
|
||||
|
||||
# Flake8
|
||||
- repo: https://github.com/pycqa/flake8
|
||||
rev: 7.1.1
|
||||
hooks:
|
||||
- id: flake8
|
||||
args:
|
||||
- --count
|
||||
- --select=E9,F63,F7,F82,E721
|
||||
- --show-source
|
||||
- --statistics
|
||||
exclude: ^benchmark/|^test_tipc/
|
@ -0,0 +1,3 @@
|
||||
[style]
|
||||
based_on_style = pep8
|
||||
column_limit = 80
|
@ -0,0 +1,15 @@
|
||||
import datetime
|
||||
|
||||
import fitz # PyMuPDF
|
||||
|
||||
# 导入配置
|
||||
from Config import source_pdf, images_dir, time_format
|
||||
|
||||
# 打开PDF文件
|
||||
pdf = fitz.open(source_pdf)
|
||||
for page_num in range(len(pdf)):
|
||||
page = pdf.load_page(page_num)
|
||||
pix = page.get_pixmap(dpi=300)
|
||||
pix.save(f"{images_dir}\\page_{page_num}.png")
|
||||
# 输出当前时间,格式:年月日时分秒 和 提示信息
|
||||
print(f"{datetime.datetime.now().strftime(time_format)} 正在处理第{page_num}页")
|
@ -0,0 +1,66 @@
|
||||
[{'input_path': 'D:\\dsWork\\PaddleOCR\\ImagesSmall\\page_0_compressed.jpg', 'page_index': None, 'doc_preprocessor_res': {'output_img': array([[[104, ..., 217],
|
||||
...,
|
||||
[ 48, ..., 56]],
|
||||
|
||||
...,
|
||||
|
||||
[[ 21, ..., 32],
|
||||
...,
|
||||
[ 14, ..., 19]]], shape=(862, 587, 3), dtype=uint8)}, 'layout_det_res': {'input_path': None, 'page_index': None, 'input_img': array([[[104, ..., 217],
|
||||
...,
|
||||
[ 48, ..., 56]],
|
||||
|
||||
...,
|
||||
|
||||
[[ 21, ..., 32],
|
||||
...,
|
||||
[ 14, ..., 19]]], shape=(862, 587, 3), dtype=uint8), 'boxes': [{'cls_id': 1, 'label': 'image', 'score': 0.5590275526046753, 'coordinate': [np.float32(146.0109), np.float32(63.905975), np.float32(259.0317), np.float32(180.34189)]}, {'cls_id': 2, 'label': 'text', 'score': 0.4184643626213074, 'coordinate': [np.float32(155.71976), np.float32(3.9154816), np.float32(514.49243), np.float32(34.9183)]}, {'cls_id': 0, 'label': 'paragraph_title', 'score': 0.39416977763175964, 'coordinate': [np.float32(84.17284), np.float32(231.3527), np.float32(140.27222), np.float32(686.1651)]}]}, 'region_det_res': {'input_path': None, 'page_index': None, 'input_img': array([[[104, ..., 217],
|
||||
...,
|
||||
[ 48, ..., 56]],
|
||||
|
||||
...,
|
||||
|
||||
[[ 21, ..., 32],
|
||||
...,
|
||||
[ 14, ..., 19]]], shape=(862, 587, 3), dtype=uint8), 'boxes': [{'cls_id': 0, 'label': 'Region', 'score': 0.9720134139060974, 'coordinate': array([ 84.17284, ..., 686.1651 ], shape=(4,), dtype=float32)}]}, 'overall_ocr_res': {'input_path': None, 'page_index': None, 'doc_preprocessor_res': {'output_img': array([[[104, ..., 217],
|
||||
...,
|
||||
[ 48, ..., 56]],
|
||||
|
||||
...,
|
||||
|
||||
[[ 21, ..., 32],
|
||||
...,
|
||||
[ 14, ..., 19]]], shape=(862, 587, 3), dtype=uint8)}, 'dt_polys': [array([[155, 7],
|
||||
...,
|
||||
[156, 34]], shape=(4, 2), dtype=int16), array([[ 85, 234],
|
||||
...,
|
||||
[ 85, 685]], shape=(4, 2), dtype=int16)], 'model_settings': {'use_doc_preprocessor': False, 'use_textline_orientation': True}, 'text_det_params': {'limit_side_len': 736, 'limit_type': 'min', 'thresh': 0.3, 'max_side_limit': 4000, 'box_thresh': 0.6, 'unclip_ratio': 1.5}, 'text_type': 'general', 'text_rec_score_thresh': 0.0, 'rec_texts': ['中國古典文學基本叢書', '蘇轼詞编年校注'], 'rec_scores': [0.8946498036384583, 0.7676457762718201], 'rec_polys': [array([[155, 7],
|
||||
...,
|
||||
[156, 34]], shape=(4, 2), dtype=int16), array([[ 85, 234],
|
||||
...,
|
||||
[ 85, 685]], shape=(4, 2), dtype=int16)], 'textline_orientation_angles': [0, 0], 'rec_boxes': array([[155, ..., 34],
|
||||
[ 85, ..., 685]], shape=(2, 4), dtype=int16), 'rec_labels': ['text', 'text']}, 'table_res_list': [], 'seal_res_list': [], 'chart_res_list': [], 'formula_res_list': [], 'parsing_res_list': [
|
||||
|
||||
#################
|
||||
index: 1
|
||||
label: text
|
||||
region_label: normal_text
|
||||
bbox: [155, 3, 514, 34]
|
||||
content: 中國古典文學基本叢書
|
||||
#################,
|
||||
|
||||
#################
|
||||
index: 2
|
||||
label: doc_title
|
||||
region_label: doc_title
|
||||
bbox: [84, 231, 140, 686]
|
||||
content: 蘇轼詞编年校注
|
||||
#################,
|
||||
|
||||
#################
|
||||
index: 0
|
||||
label: image
|
||||
region_label: vision
|
||||
bbox: [146, 63, 259, 180]
|
||||
content:
|
||||
#################], 'imgs_in_doc': [{'path': 'imgs/img_in_image_box_146_63_259_180.jpg', 'img': <PIL.Image.Image image mode=RGB size=113x117 at 0x25466A74910>, 'coordinate': (146, 63, 259, 180), 'score': 0.5590275526046753}], 'model_settings': {'use_doc_preprocessor': False, 'use_seal_recognition': True, 'use_table_recognition': True, 'use_formula_recognition': True, 'use_chart_recognition': False, 'use_region_detection': True}}]
|
After Width: | Height: | Size: 9.9 KiB |
@ -0,0 +1,5 @@
|
||||
中國古典文學基本叢書
|
||||
|
||||
# 蘇轼詞编年校注
|
||||
|
||||
<div style="text-align: center;"><img src="imgs/img_in_image_box_146_63_259_180.jpg" alt="Image" width="19%" /></div>
|
After Width: | Height: | Size: 10 KiB |
@ -0,0 +1,6 @@
|
||||
中国古典文學基本叢書
|
||||
|
||||
<div style="text-align: center;"><img src="imgs/img_in_image_box_150_66_263_182.jpg" alt="Image" width="19%" /></div>
|
||||
|
||||
|
||||
蘇轼詞编年校注
|
@ -0,0 +1,19 @@
|
||||
蘇轼铜编年校註
|
||||
|
||||
寫景、記,以及愛國思想農村生活說理談禪等等,都是晚唐五代以來詞人反映較少或完全没有涉及工時,成功的具有豪放風格作品的出現,也有利於詞的内容的繼續擴大。從蘇軾開始,通過他的實践,終
|
||||
|
||||
工
|
||||
|
||||
豪情,他在(沁圆春》(孤館燈青)中说:
|
||||
|
||||
|
||||
|
||||
正是由於有這樣的自信和自豪,才寫出了[妥帖排的豪放之作。也正因為如此,次年在密州出獵時,店英勇豪行為下阕進一步寫道:
|
||||
|
||||
酒酣胸膽尚開张赞微霜,又何妨。持節雲中,何日遣馮唐?會挽雕弓如满月,西北望,射天
|
||||
|
||||
狼!
|
||||
|
||||
|
||||
|
||||
把狩獵時的豪情上升為保衛邊疆殺敵報國的激昂壯志,成為豪放詞的代表作大概與此同時,他又寫手
|
@ -0,0 +1,11 @@
|
||||
沙〉(怪見眉间一點黄),其下闕云:
|
||||
|
||||
贊揚梁左藏奉詔從軍的光榮。同時還有一首(南鄉子》(旌旆满江湖),寫道:
|
||||
|
||||
等愛國詞人導夫先路,至辛棄疾而臻其極,厥功甚偉。
|
||||
|
||||
|
||||
|
||||
,,宗讀至[瓊樓玉宇」二句,嘆日:「蘇軾終是愛君。以之相參,劉說是深刻的。
|
||||
|
||||
蘇軾在登臨懷古詞中也流露出同類的心情。這一题材始于王安石的(桂枝香》〔金陵懷古]蘇軾於元豐五年在黄州貶所寫的(念奴嬌》赤壁懷古],歷來舉為豪放詞的代表作。黄夢國云:「题是赤壁,手手手手(即[故國三句從周郎拍到自己,撫古傷今,抒發自己遭誣被貶,白首無成的沉重苦悶。其下雖有消極情緒,但從他對周瑜的讚美欽慕中仍然可以看到他要求為國建功立業的爱國熱情。辛棄疾曾四次和韻①
|
@ -0,0 +1,11 @@
|
||||
萬頃風濤不記蘇,雪晴江上麥千車。但令人飽我愁無。
|
||||
|
||||
|
||||
|
||||
(景蘇圖帖》第五石刻此詞,首句下注:[公田在蘇州,今年風潮蕩盡。據此,詞的意思是說:儘管我蘇現了作者忘記自身困苦,只對人民的生計關切。這種精神境界使我們想起杜甫的(茅屋為秋風所破歌〉和白居易的(新製布裘》詩,這不但是他以前詞人中所未見,他以後的詞人中也是没有的
|
||||
|
||||
之作。上阕寫十年來對其亡妻一直難忘的思念和自己仕途的凄凉下関寫幽夢還鄉,夢中相見,宛如平生。醒來想到如亡妻有靈,一定在年年月明之夜,为思念千里之外尘面赞霜的丈夫而柔腸寸断。通((友的(感皇恩(案上敷编書)°
|
||||
|
||||
|
||||
|
||||
中風清,一枕初寒夢不成。今夜残燈斜照處,熒熒。秋雨晴時淚不晴表現别後思念之深又如寫别李
|
@ -0,0 +1,7 @@
|
||||
蘇轼詞编年校注
|
||||
|
||||
,器我情至意切,給人以强烈的悵邑之感。尤其是以下四首,更有高度的藝術特色與藝術見解:(水龍境,空靈中雜以凄。過片始言情,有滄波浩渺之致,真高格也。[雲夢二句,妙能寫聞中情景。煞拍,车(歸朝歡〉(我夢扁舟浮震澤),這是紹聖元年(一〇九四)蘇軾貶惠州途中,行至九江,與蘇堅分别時所創作新詞。向民歌學習的進步思想和見解,在當時有劃時代的意義。
|
||||
|
||||
|
||||
|
||||
和他的詩一樣,蘇軾有許多抒發個人感情和歌詠自然景物的優美詞作。在元豐二年(一九七)烏(関「沙河塘裹燈初上,水調誰家唱?夜闌風静欲歸時,惟有一江明月碧琉璃。寫出了杭州的風物之美。(望江南》(春未老)寫春天登密州超然臺所見到的[風细柳絲斜「半壕春水一城花,煙雨暗千家的動
|
@ -0,0 +1 @@
|
||||
人景色。而在赴湖州途中的(南鄉子〉「雨暗初疑夜,風回便報晴,淡雲斜照著山明。细草軟沙溪路、,但是,儒家人世的思想始終居於主導地位,因而没有走向消極颓廢的道路。即如他的(卜算子(缺月掛江仙》(夜飲東坡醒復醉),有衝破黑暗、走向自由的熱望。(水調歌頭》(落日繡簾捲),面對快哉亭下的的思想。他在(浣溪沙〉(山下蘭芽短浸溪)中,看到清泉寺門前溪水西流,就想到人生也能再少,青春可中蘇軾於[技藜徐步中消磨壯志,與辛棄疾同調詞(枕簟溪堂冷欲秋)的在「一丘一壑中消磨壯志,用意無乃相似。其中[紅蓮白鳥二句,当非偶合。即在他六十四歲謫居儋耳所寫的(减字木蘭花》(春牛
|
@ -0,0 +1,17 @@
|
||||
蘇轼詞编年校注
|
||||
|
||||
人衰憊之氣。
|
||||
|
||||
|
||||
|
||||
杜甫以議論為詩,詞壇上王安石始見端倪,如(浪淘沙令〉(伊吕兩衰翁)雨霖鈴〉(孜孜矻矻)望大如(水調歌頭》(明月幾時有),王閱運說:[人有三句,大開大闔之筆,他人所不能。永遇樂〉(明月如,,無迹矣。二是通篇議論。如〈满庭芳》(蝸角虚名)減字木蘭花〉(賢哉令尹)(如夢令〉(水垢何曾相受)(自净方能净彼)等皆是,遂開後人以詞論文論政論禪、論道之先河。
|
||||
|
||||
總之,詞至蘇軾,其體始尊。其思想性和藝術性不僅超越前人,亦有後人所未及者。雄篇奇製,照
|
||||
|
||||
耀寰宇,若李杜之於詩歌,韓柳之於文章,蔚為大宗,影響深遠。元好問云:「自東坡一出,情性之外,不
|
||||
|
||||
知有文字,真有一洗萬古凡馬空氣象。誠非過言。
|
||||
|
||||
|
||||
|
||||
鄒同慶王宗堂二同志致力蘇詞研究,從事編年箋註,引證時事,比檢史籍,力求言之有據。注释中请中者之良友编纂既成,屬為弁言。聊述管窺,以供参考一九九一年高文
|
@ -0,0 +1,11 @@
|
||||
凡例
|
||||
|
||||
(,,()一()(),(),,「箋註」參考資料」等欄目誤人蘇集詞只列[考辨不校不註。
|
||||
|
||||
|
||||
|
||||
二、本書正编文字,以天津國書館藏天一阁鈔明吴訥编唐宋名賢百家詞》本(東坡詞》三卷為底本(下吴本)以北京圖書館藏清鈔本宋傅幹(注坡詞》十二卷(下称傅本)元延祐庚申刊(东坡樂府)二卷(下稱元本)明茅維编(蘇東坡全集》本(東坡詞》二卷(下稱明刊全集)焦编(蘇長公二妙集)本(彊村叢書》本(東坡樂府》三卷(下稱朱本)龍榆生(東坡樂府箋)三卷(下稱龍本)唐圭璋编(全宋)記詞話、詞譜等以定是非凡此,均在校記中説明。
|
||||
|
||||
|
||||
|
||||
三校勘力求簡明凡底本不誤而校本誤者不出校凡底本不誤而校本異文有参考價值者,出異文校
|
@ -0,0 +1,15 @@
|
||||
蘇轼詞编年校註
|
||||
|
||||
後
|
||||
|
||||
|
||||
|
||||
一五七首,拾遗四十首,計得三一一首。凡他本有吴本無者,均予採録。其中確為蘇詞者,予以增中
|
||||
|
||||
。比,以便比較。资料搜集範图,自宋至清。近代当代有代表性的考評,酌情選録。
|
||||
|
||||
八、附録墓誌銘、傳記(蘇軾詞集版本綜述》序跋等,供研究蘇詞者參考。九、為便於讀者翻檢查尋,另编蘇詞篇目索引附在書末。
|
||||
|
||||
校註者
|
||||
|
||||
一九八八年五月
|
After Width: | Height: | Size: 9.8 KiB |
@ -0,0 +1,5 @@
|
||||
中國古典文學基本叢書
|
||||
|
||||
# 蘇軾詞编年校注
|
||||
|
||||
<div style="text-align: center;"><img src="imgs/img_in_image_box_147_67_261_184.jpg" alt="Image" width="19%" /></div>
|
@ -0,0 +1,9 @@
|
||||
又(未倦長卿遊)……二六〇江城子(天涯流落思無窮)………二六二减字木蘭花(玉無味)……二六五江城子(墨雲拖雨西樓)……二六六南歌子(山雨瀟過)………二六八漁家傲(皎皎牽牛河漢女)……二七〇元豐三年庚申(一〇八〇年)
|
||||
|
||||
臨江仙(細馬遠馱雙侍女)…二七二卜算子(·月掛疏桐)……二七五南歌子(寸恨云短)……二八六南鄉子(晚景落瓊杯)……二八八菩薩蠻(檐初掛彎月)……二九一其二(風迴仙馭開扇)……二九三定風波(與客攜壺上翠微)…二九五水龍吟(楚山修竹如)……二九八菩薩蠻(翠鬟斜幔雲垂耳)……三〇四
|
||||
|
||||
目
|
||||
|
||||
其二(柳庭風静人眠畫)……三〇七其三(井雙照新妝冷)……三〇八其四(雪花飛暖融香頰)……三〇九元豐四年辛酉(一〇八一年)
|
||||
|
||||
少年遊(玉肌鉛粉傲秋霜)……三水龍吟(似花似非花)……三一四()少年(銀塘朱檻麴塵波)……三二九南鄉子(霜降水痕收)……三三一滿江红(江漢西來)…浣溪沙(块青青麥·未蘇)……三三九其二(醉夢蘸曉未蘇)……三四一其三(雪裹餐例蘇)……三四三其四(半夜銀山上積蘇)………三四四其五(萬頃風濤不記蘇)…·三四六江城子(黄昏猶是雨纖織)……三四七
|
@ -0,0 +1,11 @@
|
||||
## 蘇轼詞编年校注
|
||||
|
||||
元豐五年壬戌(一〇八二年)
|
||||
|
||||
水龍吟(小舟截春江)…三四九江城子(夢中了了醉中醒)……三五二定風波(莫聽穿林打葉聲)三五六浣溪沙(山下蘭芽短侵溪).……三五八西江月(照野淺浪)………三六〇南歌子(日出山雨……三六四又(雨暗初疑夜)……三六七又(帶酒·山雨)…………三六八浣溪沙(西塞山白鷺飛).…三七〇漁父(父.)…三七六又(漁父醉)……三七七又(漁父醒)……三七八又(漁笑)…三七九調笑令父)…三八〇又(雁)……三八一
|
||||
|
||||
中册
|
||||
|
||||
念奴娇(大江東去)洞仙歌(冰肌玉骨)念奴娇(憑高眺遠)
|
||||
|
||||
三三三六三八三九三九六三九八$\fr0$ 四三四三四二四二四四四二
|
@ -0,0 +1,11 @@
|
||||
又(雙墜)…四三九又(天真雅麗)…四四又柔和.)…四四二又(天然宅院)……四四三西江月(龍焙今年絶品)……四四五菩薩蠻(碧紗微露纖纖玉)……四四九醉翁操(琅然)四五一滿庭芳.(角虚名)……四五八定風波(好睡慵開莫厭).…四六二元豐六年癸亥(一〇八三年)
|
||||
|
||||
|
||||
|
||||
木蘭花令(烏啼鹊噪昏喬木)……四六四臨江仙(夜飲東坡醒復醉)……四六七好事近(红粉莫悲啼)…四六九滿庭芳(三十三年今誰存者)……四七一鸪天(林断山明竹牆).…四七四十拍子(白酒新開九)………四七六
|
||||
|
||||
目録
|
||||
|
||||
浣溪沙(傾蓋相逢勝白頭)………四七八又(炙手無人傍屋頭)………四八一水調歌頭(落日簾捲)……四八三南歌子(…霍元後)…四八七臨江仙(詩句端來磨我鈍)……四九减字木蘭花(江南遊女)…四九五阜羅特(采菱拾)……四九六元豐七年甲子(一〇八四年)
|
||||
|
||||
减字木蘭花(神聞意定)……四九九無愁可解.(景百年)……〇一滿庭芳(歸去來兮吾歸何處)……五〇六阮郎歸(綠槐高咽新蟬)……五一〇西江月(别已随流水)……五一二漁家傲(千古龍蟠並虎踞)……五一五水龍吟(露寒煙冷葭老)…五一八减字木蘭花(鄭莊好客)…二一
|
@ -0,0 +1,15 @@
|
||||
蘇轼詞编年校注
|
||||
|
||||
南歌子(欲執河梁手)…五二六菩薩(買田陽羨吾將老)…五二七南歌子(見說東圓好)……三〇西江月(三過平山堂下)……五三三浣溪沙(學鴉兒正妙年)…五三七又(一夢江湖費五年)……五三九虞美人(波聲拍枕長淮曉)…五四一如夢令(城上層樓叠)……五四四又(水垢何曾相受)…五四六其二(自净方能.彼)…五四九浣溪沙(細雨斜風作曉寒)……五五〇行香子(北望平川)水龍吟(古來海茫茫)………五五六满庭芳(三十三年漂流江海)……五六三元豐八年乙丑(一〇八五年)
|
||||
|
||||
|
||||
|
||||
南鄉子(千騎試春遊)………五六六
|
||||
|
||||
滿庭芳(歸去來兮清溪無底)……五六八二…(器回头)又(昨夜秋風來萬里)…五七四又(自古漣漪佳绝地)……五七六宋哲宗元祐元年丙寅(一〇八六年)定風波(誰羨人間琢玉郎)………五七八如夢令(為向東坡傳語)……五八三其二(手種堂前桃李)·…五八六元祐二年丁卯(一〇八七年)
|
||||
|
||||
蘇遮(暑晴)…五八八元祐三年戊辰(一〇八八年)
|
||||
|
||||
哨徧(睡畫堂)…五九〇西江月(莫欺平·落落)…五九七元祐四年己巳(一〇八九年)
|
||||
|
||||
行香子(綺席終)……五九九漁家傲(送客歸來燈火盡)……六〇二
|
@ -0,0 +1,9 @@
|
||||
浣溪沙(珠檜絲杉冷欲霜)………六〇五其二(霜真堪拒霜)…六〇七點绛(我輩情鍾)……六〇九元祐五年庚午(一〇九〇年)
|
||||
|
||||
臨江仙(多病休文都瘦損)……六一一南歌子(山與歌眉斂)……一三又古岸開青)…六一六鹊橋仙(…槎去)…六一八南歌子(海上乘槎侣)…二其二(再再中秋………六二四點.(不用悲秋)……六二五又(莫唱陽關……六二八又(聞倚牀……六三〇好事近(湖上雨晴時)………六三三浣溪沙(門外東風雪灑裾)……六三五南歌子(師唱家曲)…………六三七
|
||||
|
||||
四绿
|
||||
|
||||
元祐六年辛未(一〇九一年)
|
||||
|
||||
浣溪沙(雪颔霜不自驚)……六四一又(料峭東風翠驚)…六四三又(陽羨姑蘇已買田)……六四五木蘭花令(元宵似是歡遊好)…六四八减字木蘭花(雲容皓白)……六五一西江月(公子眼花亂發)……六五三其二(小院朱蘭幾曲)……六五七其三(怪此花枝怨泣)……六五八木蘭花令(知君仙骨無寒暑)……六六虞美人(歸心正似三春草)……六六三臨江仙(一别都門三改火)…六六五八聲甘州(有情風萬里捲潮來)…六六三减字木蘭花(天台舊路)……六七三西江月(昨夜舟京口)…六七五定風波(月滿溪照夜堂)……六七七
|
@ -0,0 +1,17 @@
|
||||
## 蘇轼詞编年校注
|
||||
|
||||
臨江仙(我勸髯張歸去好)……六八三蝶戀花(春事蘭珊芳草歇)……六八六臨江仙(尊酒何人懷李白)…六八九南歌子(雲裁新綠)……六九二滿江紅(清潁東流)……六九五木蘭花令(霜餘已失長淮闊)……六九九减字木蘭花(空牀響琢)……七〇一元祐七年壬申(一〇九二年)
|
||||
|
||||
|
||||
|
||||
减字木蘭花(春庭月午)……七〇四木蘭花令(高平四面開雄壘)……七〇七浣溪沙(芍藥樱桃雨新)……七〇八减字木蘭花(回風落景)……七一二生查子(三度别君來)·…七一四青玉案(三年枕上昊中路)…七一六元祐八年癸酉(一〇九三年)
|
||||
|
||||
|
||||
|
||||
行香子(三人明)………七二
|
||||
|
||||
又(清夜無·)……七二五紹聖元年甲戌(一〇九四年)
|
||||
|
||||
戚氏(玉龜山)…二八歸朝歡(我夢扁舟浮震澤)……七三七木蘭花令(梧桐葉上三更雨)……七四一浣溪沙(幾共查梨到雪霜).七四三又(菊暗荷枯一夜霜)……七四五又(羅襪空飛洛浦塵)……七四七西江月(馬趁香微路遠)………七五紹聖二年乙亥(一〇九五年)
|
||||
|
||||
臨江仙(九十日春都過了)………七五一蝶戀花(花褪殘紅青杏小)……七五三减字木蘭花(閩溪珍)·…七五七人娇(白顏)………七五九浣溪沙(輕汗微微透碧紈)……七六二又(人袂輕風不破塵)………七六四
|
@ -0,0 +1,5 @@
|
||||
中國古典文學基本叢書
|
||||
|
||||
# 蘇軾詞編年校註
|
||||
|
||||
鄒同慶王宗堂著
|
@ -0,0 +1,7 @@
|
||||
蘇轼詞编年校注
|
||||
|
||||
又(寒玉細凝)…八三四又(悵望春杯)…八三五又(何處倚干)……八三六菩薩蠻(落花聞院春衫薄)………八三九又(火凝汗揮珠顆)……八四〇又(蟠南江浅红梅小)…·八四一又(塗香莫惜莲承步)…八四二又(玉爨墜耳黄金飾)…··八四四浣溪沙(畫华横江喜再)……八四五又(風捲珠簾自上鈎)…·…八四七又(花滿銀塘水漫流)……八四八又(風壓輕雲貼水飛)……八五〇南歌子(紫陌春去)……八五三又(笑怕薇胃)……八五五蝶戀花(一顆樱桃樊素口)……八五七减字木蘭花(玉房金蕊)……八五九
|
||||
|
||||
又(鶯初.語)…八六一行香子(昨夜霜風)………八六二點绛膺(红杏飄香)……八六三虞美人(.杯遥勸天月)…八六六阮郎歸(暗香浮月黄昏)……八六七謁金門(帷裹)…八六九又(秋池·)………八七〇又(今夜雨)…八七一好事近(煙外倚危樓)……八七二天仙子(走馬探花花发未)…八七三翻香令(金爐猶靡煤殘)……八七五桃源憶故人(华胥夢断人何處)……八七六沁春(情若連環)…八七七残句十一.八七九
|
||||
|
||||
## 蘇轼年校附…八八五
|
@ -0,0 +1,9 @@
|
||||
一、他集互見詞八首
|
||||
|
||||
菩薩蠻(娟娟侵鬢妝痕淺)……八八七江城子(銀濤無際捲蓬瀛)………八八九減字木蘭花(誰妙筆)……八九三點絳.(醉漾輕舟)……八九六又(月轉烏)………八九八訴衷情(海棠珠綴一重重)………九〇醉落魄(醉醒醒醉)……九〇二瑶池燕(飛花成陣春心困)………九〇五二、蘇轼存疑詞十一首
|
||||
|
||||
蝶戀花(記得畫屏初會遇)……九〇九又(雨疏疏經潑火)…九一〇又(蝶懶慵春過半)………九一一雨中花慢(院重簾何處).…九一二浣溪沙(山色横侵蘸霞)……九一四江城子(腻紅匀臉襯檀屑)………九一七
|
||||
|
||||
目
|
||||
|
||||
虞美人(冰肌自是生來瘦)………九一八又(深深庭院.明過)……九二〇西江月(碧輕兩鳳)……九二二踏莎行(个禿奴)…九二三麟鸪天(羅帶雙垂不成)……九二五三誤入蘇集詞五十三首及残句九則鸪天(塞山白鷺飛)………九二九江城子(南來飛燕北歸鴻)……九三一沁春(小·深沈)……九三二虞美人(落花已作風前舞)………九三三蝶戀花(玉枕冰寒消暑氣)……九三五又(梨…初紅蟬韻歇)………九三六又(簾幕風輕雙語燕)……九三七又(一雾秋風驚畫扇)……九三八又(紫菊初生朱槿墜)……九三八永遇樂(天山)………九三九
|
@ -0,0 +1,5 @@
|
||||
蘇轼编年校
|
||||
|
||||
意難忘(花摊鴛房)蒲庭芳(北苑龍圃)…九四二定風波(痛飲形骸騎蹇驢)…九四四人嬌(解了癡)…九四四浣溪沙(晚菊花前斂翠蛾……九四六又(玉冰寒滴露华)………九四七又(樓依江百尺高)……九四八阮郎歸(歌停檀板舞停鸞)……九四九菩薩蠻(濕雲不動溪橋冷)……九五〇木蘭花(檀槽碎響金絲撥)………九五一又(個人豐韻真堪羨)………九五二玉樓春(東風就腰兒細)……九五三如夢令(嘗記溪亭日暮)……九五四又(曾宴桃源深洞)……九五五點绛膺(高柳蟬晰)…九五六又(蹴丽秋千)…九八
|
||||
|
||||
又(春雨)………九九又(鶯踏花)…………九六〇祝英臺近()……九六一水調歌頭(已過一番雨)……九六二離别一久九六二洞仙歌(飛梁水)…九六三金菊對芙蓉(花則一名)……九六五踏青遊(·人人…九六六西江月(雨過輕風弄柳)…九六七探春令(玉窗蠅字記春寒)………九六八億秦娥(香馥馥)九六八滿江紅(不作三公)…九七〇卜算子(水是波.)……九七〇更漏子(柳絲長)……九七一又(春夜阐)…九七二清平調引(陌上花開蝴蝶飛).…九七三
|
@ -0,0 +1 @@
|
||||
# 蘇軾詞編年校註正編
|
@ -0,0 +1,17 @@
|
||||
## 一、 蘇軾编年詞二九二首
|
||||
|
||||
華清引感首1
|
||||
|
||||
平時十月幸蓮湯三①玉甃瓊梁②°五家車馬如水③,珠璣满路旁④°牀⑤°獨留煙樹蒼蒼⑥°至今清夜月,依前過繚牆(三①°
|
||||
|
||||
## 【】
|
||||
|
||||
翠華一去掩方
|
||||
|
||||
,,(華清引〉前後片各四句,共四十五字,用平聲韻°二調無涉。傅本、元本無題。
|
||||
|
||||
三「前」毛本作[舊
|
||||
|
||||
【编年】
|
||||
|
||||
一蘇轼编年詞二九二首华清引三
|
@ -0,0 +1,11 @@
|
||||
蘇轼詞编年校注
|
||||
|
||||
手车)年丙寅(一〇八六年)逆数二十三年,恰為治平元年甲辰公以是年罷鳳翔任,過長安,游驪山,作〈驪山三絕句》詩,(華清引》詞亦應作於此時
|
||||
|
||||
|
||||
|
||||
,月戊申,改温泉宫為華清宫。至天寶十四载,每年十月均[幸華清宫°「幸漢·蔡邕(獨断〉上:「天子所至,,日室。此指华清池的温泉浴室。
|
||||
|
||||
|
||||
|
||||
工工工,,水日,中
|
@ -0,0 +1,17 @@
|
||||
瓷:本指井壁,此指温泉浴池池壁。
|
||||
|
||||
车绿,領袖正白,顧視御者,不及邀矣。」
|
||||
|
||||
|
||||
|
||||
珠满路旁:(舊唐書》卷五一(楊貴妃傳》「玄宗每年十月幸華清宫,國忠姊妹五家息從,每家為一隊,著一色,,出
|
||||
|
||||
|
||||
|
||||
。,
|
||||
|
||||
·。,。毁廢已久,今所存者,唯繚垣耳。」
|
||||
|
||||
|
||||
|
||||
## 一 蘇轼编年詞二九二首華清引
|
@ -0,0 +1,13 @@
|
||||
蘇轼铜编年校注
|
||||
|
||||
一斛珠]
|
||||
|
||||
洛城春晚垂楊亂掩紅樓半①小池輕浪紋如篆②燭下花前,曾醉離歌宴流雲雨散關山有限情無限③待君重見尋芳伴為説相思,目断西樓燕④。
|
||||
|
||||
【校勘】
|
||||
|
||||
(一傅本、元本未收°案:調名(一斛珠)即(醉落魄〉°【编年】
|
||||
|
||||
|
||||
|
||||
氏父子三人赴京應試,三月從眉州出發,途經成都閩中,出褒斜谷,發横渠鎮,人鳳翔驛,過長安、洛陽,五、六月間到達汴京。此次經過洛陽時當在五月下旬二是嘉祐二年(一〇五七年),蘇軾母親病故,父子三人于是年五月離汴京,赴喪返家此次途經洛陽時亦當在五月三是嘉祐六年(一〇六一年),蘇轼在京,被任命為大理評事簽書鳳翔府判官。十一月離京赴任,十二月十四日到逹鳳翔,途經
|
@ -0,0 +1,5 @@
|
||||
# 蘇軾詞編年校註 中
|
||||
|
||||
中國古典文學基本叢書
|
||||
|
||||
鄒同慶王宗堂著
|
@ -0,0 +1,5 @@
|
||||
中國古典文學基本叢書
|
||||
|
||||
蘇軾詞編年校註下
|
||||
|
||||
鄒同慶王宗堂著
|
@ -0,0 +1,7 @@
|
||||
序
|
||||
|
||||
地位。
|
||||
|
||||
|
||||
|
||||
大家知道,公元九六年北宋王朝建立,結束了唐末五代長期分裂割據的局面。到了仁宗慶暦時期,一方面,由於將近百年的承平,社會經濟繁榮,促進了文化的繁榮。另一方面,由於國家内外危機的晏殊張先柳永等的詞依舊盛行。儘管如此,詩文革新運動也為詞的革新準備了條件,在范仲淹、歐陽大中工
|
@ -0,0 +1,22 @@
|
||||
蘇轼詞编年校注
|
||||
|
||||
上起了迥狂攔於既倒,障百川而東之的作用
|
||||
|
||||
詞人,卒於元豐元年(一〇七八),蘇軾這年四十三歲。他在(祭張子野文》中説:
|
||||
|
||||
(,並進一步說:詞即是古人的詩。在(與蔡景繁簡》中說:
|
||||
|
||||
頒示新詞,此古人長短句詩也。得之驚喜。試勉繼之,晚即面呈。((東坡續集》卷十一)
|
||||
|
||||
又在(答陈季常簡》中云:
|
||||
|
||||
|
||||
|
||||
又惠新詞,句句警拔,詩人之雄,非小詞也。但豪放太過,恐造物者不容人如此快活。((東坡
|
||||
|
||||
續集》卷十一)
|
||||
|
||||
|
||||
|
||||
這些可以說是蘇軾詞體革新的理論網領。在這裹他告訴我們兩點:(一)詞是詩的一體,當與詩同等看手工(無愁可解》(光景百年)一首,唐注:「案此詞向載各本東坡詞中,今據(山谷题跋》卷九、魏衍(後山詩註》卷九(答田生詩註》陳應行(于湖先生長短句序》移出錄此。詞序乃蘇軾所撰。蘇軾[簡中所云[豪放太過者,当即此作。詞的内容亦與[如此快活之意相合
|
||||
|
@ -0,0 +1,11 @@
|
||||
中工中)寒)(詩題為(中秋作》),(生查子(三度别君來)(詩題為(古别離送蘇伯固》),過去皆收人詩集。其二是集句詞此體始於王安石的(菩薩蠻》(数間茅屋閑臨水)(海棠亂發皆臨水),蘇軾用此體寫了三首(南鄉子》,乃集杜甫、韓愈、白居易劉禹錫、鄭谷、許渾、杜牧、李商隱、崔塗、韓、吴融等人的詩句為之又有(定風波》(雨洗娟娟嫩葉光),是集杜甫與白居易詩句為之王作豪放,蘇作近于婉約。其三是括詞。這是蘇軾的創舉,也有可能是受韓愈(月蝕詩效玉川子作》括盧仝(月蝕詩》的啟發。在此體中,他以(臨江仙》(冬夜夜寒冰合井)括李白的(夜坐吟》,(定風波》(與客攜壶上翠微)括杜牧的(九日齊安登高》(好睡慵開莫厭运)括他自己的(紅梅〉,(水調歌頭》(昵昵兒女語)括韓愈的(聽穎師兩篇引進許多散文句式,合文人樂,遂開以文為詞的新路。至於他詞中直接引用或暗中化用古人詩句,俯拾即是。這些都可以說明蘇軾是在突破詩詞的畛域,他的填詞,實際上是在詞的形式下作詩。
|
||||
|
||||
他開始填詞的時間,從現存的作品看,是在任杭州通判時期,這是在他已經寫過(鳳翔八觀)的(石
|
||||
|
||||
鼓歌王維吴道子畫》等名作以後,也就是在他詩的清雄風格形成以後。因而他初試詞筆,為表達内容
|
||||
|
||||
的需要,就帶着詩的風格人詞。可以說,這是他以詩為詞的開始,也是他建立豪放風格的開始。
|
||||
|
||||
|
||||
|
||||
工
|
@ -0,0 +1,7 @@
|
||||
https://github.com/PaddlePaddle/PaddleOCR
|
||||
|
||||
【2023.4.29】OCR识别__百度飞桨PaddleOCR测试及环境搭建详解
|
||||
https://www.bilibili.com/video/BV1w14y1Z7bD/?vd_source=13b33731bb79a73783e9f2c0e11857ae
|
||||
|
||||
【安装文档】
|
||||
https://github.com/PaddlePaddle/PaddleOCR/blob/main/docs/quick_start.md
|
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright (c) 2016 PaddlePaddle Authors. All Rights Reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
@ -0,0 +1,22 @@
|
||||
prune .github
|
||||
prune applications
|
||||
prune benchmark
|
||||
prune configs
|
||||
prune deploy
|
||||
prune doc
|
||||
prune docs
|
||||
prune overrides
|
||||
prune ppocr/ext_op
|
||||
prune ppocr/losses
|
||||
prune ppocr/metrics
|
||||
prune ppocr/modeling
|
||||
prune ppocr/optimizer
|
||||
prune ppstructure/docs
|
||||
prune test_tipc
|
||||
prune tests
|
||||
exclude .clang_format.hook
|
||||
exclude .gitignore
|
||||
exclude .pre-commit-config.yaml
|
||||
exclude .style.yapf
|
||||
exclude mkdocs.yml
|
||||
exclude train.sh
|
@ -0,0 +1 @@
|
||||
移步[docs](https://paddlepaddle.github.io/PaddleOCR/latest/applications/overview.html)
|
@ -0,0 +1,2 @@
|
||||
*.html linguist-language=python
|
||||
*.ipynb linguist-language=python
|
@ -0,0 +1,16 @@
|
||||
.DS_Store
|
||||
*.pth
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.log
|
||||
*.tmp
|
||||
*.pkl
|
||||
__pycache__/
|
||||
.idea/
|
||||
output/
|
||||
test/*.jpg
|
||||
datasets/
|
||||
index/
|
||||
train_log/
|
||||
log/
|
||||
profiling_log/
|
@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
@ -0,0 +1,2 @@
|
||||
from .base_trainer import BaseTrainer
|
||||
from .base_dataset import BaseDataSet
|
@ -0,0 +1,269 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2019/8/23 21:50
|
||||
# @Author : zhoujun
|
||||
|
||||
import os
|
||||
import pathlib
|
||||
import shutil
|
||||
from pprint import pformat
|
||||
|
||||
import anyconfig
|
||||
import paddle
|
||||
import numpy as np
|
||||
import random
|
||||
from paddle.jit import to_static
|
||||
from paddle.static import InputSpec
|
||||
|
||||
from utils import setup_logger
|
||||
|
||||
|
||||
class BaseTrainer:
|
||||
def __init__(
|
||||
self,
|
||||
config,
|
||||
model,
|
||||
criterion,
|
||||
train_loader,
|
||||
validate_loader,
|
||||
metric_cls,
|
||||
post_process=None,
|
||||
):
|
||||
config["trainer"]["output_dir"] = os.path.join(
|
||||
str(pathlib.Path(os.path.abspath(__name__)).parent),
|
||||
config["trainer"]["output_dir"],
|
||||
)
|
||||
config["name"] = config["name"] + "_" + model.name
|
||||
self.save_dir = config["trainer"]["output_dir"]
|
||||
self.checkpoint_dir = os.path.join(self.save_dir, "checkpoint")
|
||||
|
||||
os.makedirs(self.checkpoint_dir, exist_ok=True)
|
||||
|
||||
self.global_step = 0
|
||||
self.start_epoch = 0
|
||||
self.config = config
|
||||
self.criterion = criterion
|
||||
# logger and tensorboard
|
||||
self.visualdl_enable = self.config["trainer"].get("visual_dl", False)
|
||||
self.epochs = self.config["trainer"]["epochs"]
|
||||
self.log_iter = self.config["trainer"]["log_iter"]
|
||||
if paddle.distributed.get_rank() == 0:
|
||||
anyconfig.dump(config, os.path.join(self.save_dir, "config.yaml"))
|
||||
self.logger = setup_logger(os.path.join(self.save_dir, "train.log"))
|
||||
self.logger_info(pformat(self.config))
|
||||
|
||||
self.model = self.apply_to_static(model)
|
||||
|
||||
# device
|
||||
if (
|
||||
paddle.device.cuda.device_count() > 0
|
||||
and paddle.device.is_compiled_with_cuda()
|
||||
):
|
||||
self.with_cuda = True
|
||||
random.seed(self.config["trainer"]["seed"])
|
||||
np.random.seed(self.config["trainer"]["seed"])
|
||||
paddle.seed(self.config["trainer"]["seed"])
|
||||
else:
|
||||
self.with_cuda = False
|
||||
self.logger_info("train with and paddle {}".format(paddle.__version__))
|
||||
# metrics
|
||||
self.metrics = {
|
||||
"recall": 0,
|
||||
"precision": 0,
|
||||
"hmean": 0,
|
||||
"train_loss": float("inf"),
|
||||
"best_model_epoch": 0,
|
||||
}
|
||||
|
||||
self.train_loader = train_loader
|
||||
if validate_loader is not None:
|
||||
assert post_process is not None and metric_cls is not None
|
||||
self.validate_loader = validate_loader
|
||||
self.post_process = post_process
|
||||
self.metric_cls = metric_cls
|
||||
self.train_loader_len = len(train_loader)
|
||||
|
||||
if self.validate_loader is not None:
|
||||
self.logger_info(
|
||||
"train dataset has {} samples,{} in dataloader, validate dataset has {} samples,{} in dataloader".format(
|
||||
len(self.train_loader.dataset),
|
||||
self.train_loader_len,
|
||||
len(self.validate_loader.dataset),
|
||||
len(self.validate_loader),
|
||||
)
|
||||
)
|
||||
else:
|
||||
self.logger_info(
|
||||
"train dataset has {} samples,{} in dataloader".format(
|
||||
len(self.train_loader.dataset), self.train_loader_len
|
||||
)
|
||||
)
|
||||
|
||||
self._initialize_scheduler()
|
||||
|
||||
self._initialize_optimizer()
|
||||
|
||||
# resume or finetune
|
||||
if self.config["trainer"]["resume_checkpoint"] != "":
|
||||
self._load_checkpoint(
|
||||
self.config["trainer"]["resume_checkpoint"], resume=True
|
||||
)
|
||||
elif self.config["trainer"]["finetune_checkpoint"] != "":
|
||||
self._load_checkpoint(
|
||||
self.config["trainer"]["finetune_checkpoint"], resume=False
|
||||
)
|
||||
|
||||
if self.visualdl_enable and paddle.distributed.get_rank() == 0:
|
||||
from visualdl import LogWriter
|
||||
|
||||
self.writer = LogWriter(self.save_dir)
|
||||
|
||||
# 混合精度训练
|
||||
self.amp = self.config.get("amp", None)
|
||||
if self.amp == "None":
|
||||
self.amp = None
|
||||
if self.amp:
|
||||
self.amp["scaler"] = paddle.amp.GradScaler(
|
||||
init_loss_scaling=self.amp.get("scale_loss", 1024),
|
||||
use_dynamic_loss_scaling=self.amp.get("use_dynamic_loss_scaling", True),
|
||||
)
|
||||
self.model, self.optimizer = paddle.amp.decorate(
|
||||
models=self.model,
|
||||
optimizers=self.optimizer,
|
||||
level=self.amp.get("amp_level", "O2"),
|
||||
)
|
||||
|
||||
# 分布式训练
|
||||
if paddle.device.cuda.device_count() > 1:
|
||||
self.model = paddle.DataParallel(self.model)
|
||||
# make inverse Normalize
|
||||
self.UN_Normalize = False
|
||||
for t in self.config["dataset"]["train"]["dataset"]["args"]["transforms"]:
|
||||
if t["type"] == "Normalize":
|
||||
self.normalize_mean = t["args"]["mean"]
|
||||
self.normalize_std = t["args"]["std"]
|
||||
self.UN_Normalize = True
|
||||
|
||||
def apply_to_static(self, model):
|
||||
support_to_static = self.config["trainer"].get("to_static", False)
|
||||
if support_to_static:
|
||||
specs = None
|
||||
print("static")
|
||||
specs = [InputSpec([None, 3, -1, -1])]
|
||||
model = to_static(model, input_spec=specs)
|
||||
self.logger_info(
|
||||
"Successfully to apply @to_static with specs: {}".format(specs)
|
||||
)
|
||||
return model
|
||||
|
||||
def train(self):
|
||||
"""
|
||||
Full training logic
|
||||
"""
|
||||
for epoch in range(self.start_epoch + 1, self.epochs + 1):
|
||||
self.epoch_result = self._train_epoch(epoch)
|
||||
self._on_epoch_finish()
|
||||
if paddle.distributed.get_rank() == 0 and self.visualdl_enable:
|
||||
self.writer.close()
|
||||
self._on_train_finish()
|
||||
|
||||
def _train_epoch(self, epoch):
|
||||
"""
|
||||
Training logic for an epoch
|
||||
|
||||
:param epoch: Current epoch number
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def _eval(self, epoch):
|
||||
"""
|
||||
eval logic for an epoch
|
||||
|
||||
:param epoch: Current epoch number
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def _on_epoch_finish(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def _on_train_finish(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def _save_checkpoint(self, epoch, file_name):
|
||||
"""
|
||||
Saving checkpoints
|
||||
|
||||
:param epoch: current epoch number
|
||||
:param log: logging information of the epoch
|
||||
:param save_best: if True, rename the saved checkpoint to 'model_best.pth.tar'
|
||||
"""
|
||||
state_dict = self.model.state_dict()
|
||||
state = {
|
||||
"epoch": epoch,
|
||||
"global_step": self.global_step,
|
||||
"state_dict": state_dict,
|
||||
"optimizer": self.optimizer.state_dict(),
|
||||
"config": self.config,
|
||||
"metrics": self.metrics,
|
||||
}
|
||||
filename = os.path.join(self.checkpoint_dir, file_name)
|
||||
paddle.save(state, filename)
|
||||
|
||||
def _load_checkpoint(self, checkpoint_path, resume):
|
||||
"""
|
||||
Resume from saved checkpoints
|
||||
:param checkpoint_path: Checkpoint path to be resumed
|
||||
"""
|
||||
self.logger_info("Loading checkpoint: {} ...".format(checkpoint_path))
|
||||
checkpoint = paddle.load(checkpoint_path)
|
||||
self.model.set_state_dict(checkpoint["state_dict"])
|
||||
if resume:
|
||||
self.global_step = checkpoint["global_step"]
|
||||
self.start_epoch = checkpoint["epoch"]
|
||||
self.config["lr_scheduler"]["args"]["last_epoch"] = self.start_epoch
|
||||
# self.scheduler.load_state_dict(checkpoint['scheduler'])
|
||||
self.optimizer.set_state_dict(checkpoint["optimizer"])
|
||||
if "metrics" in checkpoint:
|
||||
self.metrics = checkpoint["metrics"]
|
||||
self.logger_info(
|
||||
"resume from checkpoint {} (epoch {})".format(
|
||||
checkpoint_path, self.start_epoch
|
||||
)
|
||||
)
|
||||
else:
|
||||
self.logger_info("finetune from checkpoint {}".format(checkpoint_path))
|
||||
|
||||
def _initialize(self, name, module, *args, **kwargs):
|
||||
module_name = self.config[name]["type"]
|
||||
module_args = self.config[name].get("args", {})
|
||||
assert all(
|
||||
[k not in module_args for k in kwargs]
|
||||
), "Overwriting kwargs given in config file is not allowed"
|
||||
module_args.update(kwargs)
|
||||
return getattr(module, module_name)(*args, **module_args)
|
||||
|
||||
def _initialize_scheduler(self):
|
||||
self.lr_scheduler = self._initialize("lr_scheduler", paddle.optimizer.lr)
|
||||
|
||||
def _initialize_optimizer(self):
|
||||
self.optimizer = self._initialize(
|
||||
"optimizer",
|
||||
paddle.optimizer,
|
||||
parameters=self.model.parameters(),
|
||||
learning_rate=self.lr_scheduler,
|
||||
)
|
||||
|
||||
def inverse_normalize(self, batch_img):
|
||||
if self.UN_Normalize:
|
||||
batch_img[:, 0, :, :] = (
|
||||
batch_img[:, 0, :, :] * self.normalize_std[0] + self.normalize_mean[0]
|
||||
)
|
||||
batch_img[:, 1, :, :] = (
|
||||
batch_img[:, 1, :, :] * self.normalize_std[1] + self.normalize_mean[1]
|
||||
)
|
||||
batch_img[:, 2, :, :] = (
|
||||
batch_img[:, 2, :, :] * self.normalize_std[2] + self.normalize_mean[2]
|
||||
)
|
||||
|
||||
def logger_info(self, s):
|
||||
if paddle.distributed.get_rank() == 0:
|
||||
self.logger.info(s)
|
@ -0,0 +1,65 @@
|
||||
name: DBNet
|
||||
base: ['config/SynthText.yaml']
|
||||
arch:
|
||||
type: Model
|
||||
backbone:
|
||||
type: resnet18
|
||||
pretrained: true
|
||||
neck:
|
||||
type: FPN
|
||||
inner_channels: 256
|
||||
head:
|
||||
type: DBHead
|
||||
out_channels: 2
|
||||
k: 50
|
||||
post_processing:
|
||||
type: SegDetectorRepresenter
|
||||
args:
|
||||
thresh: 0.3
|
||||
box_thresh: 0.7
|
||||
max_candidates: 1000
|
||||
unclip_ratio: 1.5 # from paper
|
||||
metric:
|
||||
type: QuadMetric
|
||||
args:
|
||||
is_output_polygon: false
|
||||
loss:
|
||||
type: DBLoss
|
||||
alpha: 1
|
||||
beta: 10
|
||||
ohem_ratio: 3
|
||||
optimizer:
|
||||
type: Adam
|
||||
args:
|
||||
lr: 0.001
|
||||
weight_decay: 0
|
||||
amsgrad: true
|
||||
lr_scheduler:
|
||||
type: WarmupPolyLR
|
||||
args:
|
||||
warmup_epoch: 3
|
||||
trainer:
|
||||
seed: 2
|
||||
epochs: 1200
|
||||
log_iter: 10
|
||||
show_images_iter: 50
|
||||
resume_checkpoint: ''
|
||||
finetune_checkpoint: ''
|
||||
output_dir: output
|
||||
visual_dl: false
|
||||
amp:
|
||||
scale_loss: 1024
|
||||
amp_level: O2
|
||||
custom_white_list: []
|
||||
custom_black_list: ['exp', 'sigmoid', 'concat']
|
||||
dataset:
|
||||
train:
|
||||
dataset:
|
||||
args:
|
||||
data_path: ./datasets/SynthText
|
||||
img_mode: RGB
|
||||
loader:
|
||||
batch_size: 2
|
||||
shuffle: true
|
||||
num_workers: 6
|
||||
collate_fn: ''
|
@ -0,0 +1,82 @@
|
||||
name: DBNet
|
||||
base: ['config/icdar2015.yaml']
|
||||
arch:
|
||||
type: Model
|
||||
backbone:
|
||||
type: deformable_resnet18
|
||||
pretrained: true
|
||||
neck:
|
||||
type: FPN
|
||||
inner_channels: 256
|
||||
head:
|
||||
type: DBHead
|
||||
out_channels: 2
|
||||
k: 50
|
||||
post_processing:
|
||||
type: SegDetectorRepresenter
|
||||
args:
|
||||
thresh: 0.3
|
||||
box_thresh: 0.7
|
||||
max_candidates: 1000
|
||||
unclip_ratio: 1.5 # from paper
|
||||
metric:
|
||||
type: QuadMetric
|
||||
args:
|
||||
is_output_polygon: false
|
||||
loss:
|
||||
type: DBLoss
|
||||
alpha: 1
|
||||
beta: 10
|
||||
ohem_ratio: 3
|
||||
optimizer:
|
||||
type: Adam
|
||||
args:
|
||||
lr: 0.001
|
||||
weight_decay: 0
|
||||
amsgrad: true
|
||||
lr_scheduler:
|
||||
type: WarmupPolyLR
|
||||
args:
|
||||
warmup_epoch: 3
|
||||
trainer:
|
||||
seed: 2
|
||||
epochs: 1200
|
||||
log_iter: 10
|
||||
show_images_iter: 50
|
||||
resume_checkpoint: ''
|
||||
finetune_checkpoint: ''
|
||||
output_dir: output
|
||||
visual_dl: false
|
||||
amp:
|
||||
scale_loss: 1024
|
||||
amp_level: O2
|
||||
custom_white_list: []
|
||||
custom_black_list: ['exp', 'sigmoid', 'concat']
|
||||
dataset:
|
||||
train:
|
||||
dataset:
|
||||
args:
|
||||
data_path:
|
||||
- ./datasets/train.txt
|
||||
img_mode: RGB
|
||||
loader:
|
||||
batch_size: 1
|
||||
shuffle: true
|
||||
num_workers: 6
|
||||
collate_fn: ''
|
||||
validate:
|
||||
dataset:
|
||||
args:
|
||||
data_path:
|
||||
- ./datasets/test.txt
|
||||
pre_processes:
|
||||
- type: ResizeShortSize
|
||||
args:
|
||||
short_size: 736
|
||||
resize_text_polys: false
|
||||
img_mode: RGB
|
||||
loader:
|
||||
batch_size: 1
|
||||
shuffle: true
|
||||
num_workers: 6
|
||||
collate_fn: ICDARCollectFN
|
@ -0,0 +1,82 @@
|
||||
name: DBNet
|
||||
base: ['config/icdar2015.yaml']
|
||||
arch:
|
||||
type: Model
|
||||
backbone:
|
||||
type: resnet18
|
||||
pretrained: true
|
||||
neck:
|
||||
type: FPN
|
||||
inner_channels: 256
|
||||
head:
|
||||
type: DBHead
|
||||
out_channels: 2
|
||||
k: 50
|
||||
post_processing:
|
||||
type: SegDetectorRepresenter
|
||||
args:
|
||||
thresh: 0.3
|
||||
box_thresh: 0.7
|
||||
max_candidates: 1000
|
||||
unclip_ratio: 1.5 # from paper
|
||||
metric:
|
||||
type: QuadMetric
|
||||
args:
|
||||
is_output_polygon: false
|
||||
loss:
|
||||
type: DBLoss
|
||||
alpha: 1
|
||||
beta: 10
|
||||
ohem_ratio: 3
|
||||
optimizer:
|
||||
type: Adam
|
||||
args:
|
||||
lr: 0.001
|
||||
weight_decay: 0
|
||||
amsgrad: true
|
||||
lr_scheduler:
|
||||
type: WarmupPolyLR
|
||||
args:
|
||||
warmup_epoch: 3
|
||||
trainer:
|
||||
seed: 2
|
||||
epochs: 1200
|
||||
log_iter: 10
|
||||
show_images_iter: 50
|
||||
resume_checkpoint: ''
|
||||
finetune_checkpoint: ''
|
||||
output_dir: output
|
||||
visual_dl: false
|
||||
amp:
|
||||
scale_loss: 1024
|
||||
amp_level: O2
|
||||
custom_white_list: []
|
||||
custom_black_list: ['exp', 'sigmoid', 'concat']
|
||||
dataset:
|
||||
train:
|
||||
dataset:
|
||||
args:
|
||||
data_path:
|
||||
- ./datasets/train.txt
|
||||
img_mode: RGB
|
||||
loader:
|
||||
batch_size: 1
|
||||
shuffle: true
|
||||
num_workers: 6
|
||||
collate_fn: ''
|
||||
validate:
|
||||
dataset:
|
||||
args:
|
||||
data_path:
|
||||
- ./datasets/test.txt
|
||||
pre_processes:
|
||||
- type: ResizeShortSize
|
||||
args:
|
||||
short_size: 736
|
||||
resize_text_polys: false
|
||||
img_mode: RGB
|
||||
loader:
|
||||
batch_size: 1
|
||||
shuffle: true
|
||||
num_workers: 6
|
||||
collate_fn: ICDARCollectFN
|
@ -0,0 +1,83 @@
|
||||
name: DBNet
|
||||
base: ['config/icdar2015.yaml']
|
||||
arch:
|
||||
type: Model
|
||||
backbone:
|
||||
type: resnet18
|
||||
pretrained: true
|
||||
neck:
|
||||
type: FPN
|
||||
inner_channels: 256
|
||||
head:
|
||||
type: DBHead
|
||||
out_channels: 2
|
||||
k: 50
|
||||
post_processing:
|
||||
type: SegDetectorRepresenter
|
||||
args:
|
||||
thresh: 0.3
|
||||
box_thresh: 0.7
|
||||
max_candidates: 1000
|
||||
unclip_ratio: 1.5 # from paper
|
||||
metric:
|
||||
type: QuadMetric
|
||||
args:
|
||||
is_output_polygon: false
|
||||
loss:
|
||||
type: DBLoss
|
||||
alpha: 1
|
||||
beta: 10
|
||||
ohem_ratio: 3
|
||||
optimizer:
|
||||
type: Adam
|
||||
args:
|
||||
lr: 0.001
|
||||
weight_decay: 0
|
||||
amsgrad: true
|
||||
lr_scheduler:
|
||||
type: StepLR
|
||||
args:
|
||||
step_size: 10
|
||||
gama: 0.8
|
||||
trainer:
|
||||
seed: 2
|
||||
epochs: 500
|
||||
log_iter: 10
|
||||
show_images_iter: 50
|
||||
resume_checkpoint: ''
|
||||
finetune_checkpoint: ''
|
||||
output_dir: output
|
||||
visual_dl: false
|
||||
amp:
|
||||
scale_loss: 1024
|
||||
amp_level: O2
|
||||
custom_white_list: []
|
||||
custom_black_list: ['exp', 'sigmoid', 'concat']
|
||||
dataset:
|
||||
train:
|
||||
dataset:
|
||||
args:
|
||||
data_path:
|
||||
- ./datasets/train.txt
|
||||
img_mode: RGB
|
||||
loader:
|
||||
batch_size: 1
|
||||
shuffle: true
|
||||
num_workers: 6
|
||||
collate_fn: ''
|
||||
validate:
|
||||
dataset:
|
||||
args:
|
||||
data_path:
|
||||
- ./datasets/test.txt
|
||||
pre_processes:
|
||||
- type: ResizeShortSize
|
||||
args:
|
||||
short_size: 736
|
||||
resize_text_polys: false
|
||||
img_mode: RGB
|
||||
loader:
|
||||
batch_size: 1
|
||||
shuffle: true
|
||||
num_workers: 6
|
||||
collate_fn: ICDARCollectFN
|
@ -0,0 +1,79 @@
|
||||
name: DBNet
|
||||
base: ['config/icdar2015.yaml']
|
||||
arch:
|
||||
type: Model
|
||||
backbone:
|
||||
type: resnet50
|
||||
pretrained: true
|
||||
neck:
|
||||
type: FPN
|
||||
inner_channels: 256
|
||||
head:
|
||||
type: DBHead
|
||||
out_channels: 2
|
||||
k: 50
|
||||
post_processing:
|
||||
type: SegDetectorRepresenter
|
||||
args:
|
||||
thresh: 0.3
|
||||
box_thresh: 0.7
|
||||
max_candidates: 1000
|
||||
unclip_ratio: 1.5 # from paper
|
||||
metric:
|
||||
type: QuadMetric
|
||||
args:
|
||||
is_output_polygon: false
|
||||
loss:
|
||||
type: DBLoss
|
||||
alpha: 1
|
||||
beta: 10
|
||||
ohem_ratio: 3
|
||||
optimizer:
|
||||
type: Adam
|
||||
lr_scheduler:
|
||||
type: Polynomial
|
||||
args:
|
||||
learning_rate: 0.001
|
||||
warmup_epoch: 3
|
||||
trainer:
|
||||
seed: 2
|
||||
epochs: 1200
|
||||
log_iter: 10
|
||||
show_images_iter: 50
|
||||
resume_checkpoint: ''
|
||||
finetune_checkpoint: ''
|
||||
output_dir: output/fp16_o2
|
||||
visual_dl: false
|
||||
amp:
|
||||
scale_loss: 1024
|
||||
amp_level: O2
|
||||
custom_white_list: []
|
||||
custom_black_list: ['exp', 'sigmoid', 'concat']
|
||||
dataset:
|
||||
train:
|
||||
dataset:
|
||||
args:
|
||||
data_path:
|
||||
- ./datasets/train.txt
|
||||
img_mode: RGB
|
||||
loader:
|
||||
batch_size: 16
|
||||
shuffle: true
|
||||
num_workers: 6
|
||||
collate_fn: ''
|
||||
validate:
|
||||
dataset:
|
||||
args:
|
||||
data_path:
|
||||
- ./datasets/test.txt
|
||||
pre_processes:
|
||||
- type: ResizeShortSize
|
||||
args:
|
||||
short_size: 736
|
||||
resize_text_polys: false
|
||||
img_mode: RGB
|
||||
loader:
|
||||
batch_size: 1
|
||||
shuffle: true
|
||||
num_workers: 6
|
||||
collate_fn: ICDARCollectFN
|
@ -0,0 +1,86 @@
|
||||
name: DBNet
|
||||
base: ['config/open_dataset.yaml']
|
||||
arch:
|
||||
type: Model
|
||||
backbone:
|
||||
type: deformable_resnet18
|
||||
pretrained: true
|
||||
neck:
|
||||
type: FPN
|
||||
inner_channels: 256
|
||||
head:
|
||||
type: DBHead
|
||||
out_channels: 2
|
||||
k: 50
|
||||
post_processing:
|
||||
type: SegDetectorRepresenter
|
||||
args:
|
||||
thresh: 0.3
|
||||
box_thresh: 0.7
|
||||
max_candidates: 1000
|
||||
unclip_ratio: 1.5 # from paper
|
||||
metric:
|
||||
type: QuadMetric
|
||||
args:
|
||||
is_output_polygon: false
|
||||
loss:
|
||||
type: DBLoss
|
||||
alpha: 1
|
||||
beta: 10
|
||||
ohem_ratio: 3
|
||||
optimizer:
|
||||
type: Adam
|
||||
args:
|
||||
lr: 0.001
|
||||
weight_decay: 0
|
||||
amsgrad: true
|
||||
lr_scheduler:
|
||||
type: WarmupPolyLR
|
||||
args:
|
||||
warmup_epoch: 3
|
||||
trainer:
|
||||
seed: 2
|
||||
epochs: 1200
|
||||
log_iter: 1
|
||||
show_images_iter: 1
|
||||
resume_checkpoint: ''
|
||||
finetune_checkpoint: ''
|
||||
output_dir: output
|
||||
visual_dl: false
|
||||
amp:
|
||||
scale_loss: 1024
|
||||
amp_level: O2
|
||||
custom_white_list: []
|
||||
custom_black_list: ['exp', 'sigmoid', 'concat']
|
||||
dataset:
|
||||
train:
|
||||
dataset:
|
||||
args:
|
||||
data_path:
|
||||
- ./datasets/train.json
|
||||
img_mode: RGB
|
||||
load_char_annotation: false
|
||||
expand_one_char: false
|
||||
loader:
|
||||
batch_size: 2
|
||||
shuffle: true
|
||||
num_workers: 6
|
||||
collate_fn: ''
|
||||
validate:
|
||||
dataset:
|
||||
args:
|
||||
data_path:
|
||||
- ./datasets/test.json
|
||||
pre_processes:
|
||||
- type: ResizeShortSize
|
||||
args:
|
||||
short_size: 736
|
||||
resize_text_polys: false
|
||||
img_mode: RGB
|
||||
load_char_annotation: false
|
||||
expand_one_char: false
|
||||
loader:
|
||||
batch_size: 1
|
||||
shuffle: true
|
||||
num_workers: 6
|
||||
collate_fn: ICDARCollectFN
|
@ -0,0 +1,86 @@
|
||||
name: DBNet
|
||||
base: ['config/open_dataset.yaml']
|
||||
arch:
|
||||
type: Model
|
||||
backbone:
|
||||
type: resnest50
|
||||
pretrained: true
|
||||
neck:
|
||||
type: FPN
|
||||
inner_channels: 256
|
||||
head:
|
||||
type: DBHead
|
||||
out_channels: 2
|
||||
k: 50
|
||||
post_processing:
|
||||
type: SegDetectorRepresenter
|
||||
args:
|
||||
thresh: 0.3
|
||||
box_thresh: 0.7
|
||||
max_candidates: 1000
|
||||
unclip_ratio: 1.5 # from paper
|
||||
metric:
|
||||
type: QuadMetric
|
||||
args:
|
||||
is_output_polygon: false
|
||||
loss:
|
||||
type: DBLoss
|
||||
alpha: 1
|
||||
beta: 10
|
||||
ohem_ratio: 3
|
||||
optimizer:
|
||||
type: Adam
|
||||
args:
|
||||
lr: 0.001
|
||||
weight_decay: 0
|
||||
amsgrad: true
|
||||
lr_scheduler:
|
||||
type: WarmupPolyLR
|
||||
args:
|
||||
warmup_epoch: 3
|
||||
trainer:
|
||||
seed: 2
|
||||
epochs: 1200
|
||||
log_iter: 1
|
||||
show_images_iter: 1
|
||||
resume_checkpoint: ''
|
||||
finetune_checkpoint: ''
|
||||
output_dir: output
|
||||
visual_dl: false
|
||||
amp:
|
||||
scale_loss: 1024
|
||||
amp_level: O2
|
||||
custom_white_list: []
|
||||
custom_black_list: ['exp', 'sigmoid', 'concat']
|
||||
dataset:
|
||||
train:
|
||||
dataset:
|
||||
args:
|
||||
data_path:
|
||||
- ./datasets/train.json
|
||||
img_mode: RGB
|
||||
load_char_annotation: false
|
||||
expand_one_char: false
|
||||
loader:
|
||||
batch_size: 2
|
||||
shuffle: true
|
||||
num_workers: 6
|
||||
collate_fn: ''
|
||||
validate:
|
||||
dataset:
|
||||
args:
|
||||
data_path:
|
||||
- ./datasets/test.json
|
||||
pre_processes:
|
||||
- type: ResizeShortSize
|
||||
args:
|
||||
short_size: 736
|
||||
resize_text_polys: false
|
||||
img_mode: RGB
|
||||
load_char_annotation: false
|
||||
expand_one_char: false
|
||||
loader:
|
||||
batch_size: 1
|
||||
shuffle: true
|
||||
num_workers: 6
|
||||
collate_fn: ICDARCollectFN
|
@ -0,0 +1,93 @@
|
||||
name: DBNet
|
||||
base: ['config/open_dataset.yaml']
|
||||
arch:
|
||||
type: Model
|
||||
backbone:
|
||||
type: resnet18
|
||||
pretrained: true
|
||||
neck:
|
||||
type: FPN
|
||||
inner_channels: 256
|
||||
head:
|
||||
type: DBHead
|
||||
out_channels: 2
|
||||
k: 50
|
||||
post_processing:
|
||||
type: SegDetectorRepresenter
|
||||
args:
|
||||
thresh: 0.3
|
||||
box_thresh: 0.7
|
||||
max_candidates: 1000
|
||||
unclip_ratio: 1.5 # from paper
|
||||
metric:
|
||||
type: QuadMetric
|
||||
args:
|
||||
is_output_polygon: false
|
||||
loss:
|
||||
type: DBLoss
|
||||
alpha: 1
|
||||
beta: 10
|
||||
ohem_ratio: 3
|
||||
optimizer:
|
||||
type: Adam
|
||||
args:
|
||||
lr: 0.001
|
||||
weight_decay: 0
|
||||
amsgrad: true
|
||||
lr_scheduler:
|
||||
type: WarmupPolyLR
|
||||
args:
|
||||
warmup_epoch: 3
|
||||
trainer:
|
||||
seed: 2
|
||||
epochs: 1200
|
||||
log_iter: 1
|
||||
show_images_iter: 1
|
||||
resume_checkpoint: ''
|
||||
finetune_checkpoint: ''
|
||||
output_dir: output
|
||||
visual_dl: false
|
||||
amp:
|
||||
scale_loss: 1024
|
||||
amp_level: O2
|
||||
custom_white_list: []
|
||||
custom_black_list: ['exp', 'sigmoid', 'concat']
|
||||
dataset:
|
||||
train:
|
||||
dataset:
|
||||
args:
|
||||
data_path:
|
||||
- ./datasets/train.json
|
||||
transforms: # 对图片进行的变换方式
|
||||
- type: ToTensor
|
||||
args: {}
|
||||
- type: Normalize
|
||||
args:
|
||||
mean: [0.485, 0.456, 0.406]
|
||||
std: [0.229, 0.224, 0.225]
|
||||
img_mode: RGB
|
||||
load_char_annotation: false
|
||||
expand_one_char: false
|
||||
loader:
|
||||
batch_size: 2
|
||||
shuffle: true
|
||||
num_workers: 6
|
||||
collate_fn: ''
|
||||
validate:
|
||||
dataset:
|
||||
args:
|
||||
data_path:
|
||||
- ./datasets/test.json
|
||||
pre_processes:
|
||||
- type: ResizeShortSize
|
||||
args:
|
||||
short_size: 736
|
||||
resize_text_polys: false
|
||||
img_mode: RGB
|
||||
load_char_annotation: false
|
||||
expand_one_char: false
|
||||
loader:
|
||||
batch_size: 1
|
||||
shuffle: true
|
||||
num_workers: 6
|
||||
collate_fn: ICDARCollectFN
|
@ -0,0 +1,8 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2019/12/4 10:53
|
||||
# @Author : zhoujun
|
||||
from .iaa_augment import IaaAugment
|
||||
from .augment import *
|
||||
from .random_crop_data import EastRandomCropData, PSERandomCrop
|
||||
from .make_border_map import MakeBorderMap
|
||||
from .make_shrink_map import MakeShrinkMap
|
@ -0,0 +1,68 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2019/12/4 18:06
|
||||
# @Author : zhoujun
|
||||
import numpy as np
|
||||
import imgaug
|
||||
import imgaug.augmenters as iaa
|
||||
|
||||
|
||||
class AugmenterBuilder(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def build(self, args, root=True):
|
||||
if args is None or len(args) == 0:
|
||||
return None
|
||||
elif isinstance(args, list):
|
||||
if root:
|
||||
sequence = [self.build(value, root=False) for value in args]
|
||||
return iaa.Sequential(sequence)
|
||||
else:
|
||||
return getattr(iaa, args[0])(
|
||||
*[self.to_tuple_if_list(a) for a in args[1:]]
|
||||
)
|
||||
elif isinstance(args, dict):
|
||||
cls = getattr(iaa, args["type"])
|
||||
return cls(**{k: self.to_tuple_if_list(v) for k, v in args["args"].items()})
|
||||
else:
|
||||
raise RuntimeError("unknown augmenter arg: " + str(args))
|
||||
|
||||
def to_tuple_if_list(self, obj):
|
||||
if isinstance(obj, list):
|
||||
return tuple(obj)
|
||||
return obj
|
||||
|
||||
|
||||
class IaaAugment:
|
||||
def __init__(self, augmenter_args):
|
||||
self.augmenter_args = augmenter_args
|
||||
self.augmenter = AugmenterBuilder().build(self.augmenter_args)
|
||||
|
||||
def __call__(self, data):
|
||||
image = data["img"]
|
||||
shape = image.shape
|
||||
|
||||
if self.augmenter:
|
||||
aug = self.augmenter.to_deterministic()
|
||||
data["img"] = aug.augment_image(image)
|
||||
data = self.may_augment_annotation(aug, data, shape)
|
||||
return data
|
||||
|
||||
def may_augment_annotation(self, aug, data, shape):
|
||||
if aug is None:
|
||||
return data
|
||||
|
||||
line_polys = []
|
||||
for poly in data["text_polys"]:
|
||||
new_poly = self.may_augment_poly(aug, shape, poly)
|
||||
line_polys.append(new_poly)
|
||||
data["text_polys"] = np.array(line_polys)
|
||||
return data
|
||||
|
||||
def may_augment_poly(self, aug, img_shape, poly):
|
||||
keypoints = [imgaug.Keypoint(p[0], p[1]) for p in poly]
|
||||
keypoints = aug.augment_keypoints(
|
||||
[imgaug.KeypointsOnImage(keypoints, shape=img_shape)]
|
||||
)[0].keypoints
|
||||
poly = [(p.x, p.y) for p in keypoints]
|
||||
return poly
|
@ -0,0 +1,21 @@
|
||||
name: dbnet
|
||||
channels:
|
||||
- conda-forge
|
||||
- defaults
|
||||
dependencies:
|
||||
- anyconfig==0.9.10
|
||||
- future==0.18.2
|
||||
- imgaug==0.4.0
|
||||
- matplotlib==3.1.2
|
||||
- numpy==1.17.4
|
||||
- opencv
|
||||
- pyclipper
|
||||
- PyYAML==5.2
|
||||
- scikit-image==0.16.2
|
||||
- Shapely==1.6.4
|
||||
- tensorboard=2
|
||||
- tqdm==4.40.1
|
||||
- ipython
|
||||
- pip
|
||||
- pip:
|
||||
- polygon3
|
@ -0,0 +1 @@
|
||||
CUDA_VISIBLE_DEVICES=0 python3 tools/eval.py --model_path ''
|
@ -0,0 +1,17 @@
|
||||
#Only use if your file names of the images and txts are identical
|
||||
rm ./datasets/train_img.txt
|
||||
rm ./datasets/train_gt.txt
|
||||
rm ./datasets/test_img.txt
|
||||
rm ./datasets/test_gt.txt
|
||||
rm ./datasets/train.txt
|
||||
rm ./datasets/test.txt
|
||||
ls ./datasets/train/img/*.jpg > ./datasets/train_img.txt
|
||||
ls ./datasets/train/gt/*.txt > ./datasets/train_gt.txt
|
||||
ls ./datasets/test/img/*.jpg > ./datasets/test_img.txt
|
||||
ls ./datasets/test/gt/*.txt > ./datasets/test_gt.txt
|
||||
paste ./datasets/train_img.txt ./datasets/train_gt.txt > ./datasets/train.txt
|
||||
paste ./datasets/test_img.txt ./datasets/test_gt.txt > ./datasets/test.txt
|
||||
rm ./datasets/train_img.txt
|
||||
rm ./datasets/train_gt.txt
|
||||
rm ./datasets/test_img.txt
|
||||
rm ./datasets/test_gt.txt
|
After Width: | Height: | Size: 190 KiB |
@ -0,0 +1,22 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2019/8/23 21:55
|
||||
# @Author : zhoujun
|
||||
import copy
|
||||
from .model import Model
|
||||
from .losses import build_loss
|
||||
|
||||
__all__ = ["build_loss", "build_model"]
|
||||
support_model = ["Model"]
|
||||
|
||||
|
||||
def build_model(config):
|
||||
"""
|
||||
get architecture model class
|
||||
"""
|
||||
copy_config = copy.deepcopy(config)
|
||||
arch_type = copy_config.pop("type")
|
||||
assert (
|
||||
arch_type in support_model
|
||||
), f"{arch_type} is not developed yet!, only {support_model} are support now"
|
||||
arch_model = eval(arch_type)(copy_config)
|
||||
return arch_model
|
@ -0,0 +1,25 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2019/8/23 21:54
|
||||
# @Author : zhoujun
|
||||
|
||||
from .resnet import *
|
||||
|
||||
__all__ = ["build_backbone"]
|
||||
|
||||
support_backbone = [
|
||||
"resnet18",
|
||||
"deformable_resnet18",
|
||||
"deformable_resnet50",
|
||||
"resnet50",
|
||||
"resnet34",
|
||||
"resnet101",
|
||||
"resnet152",
|
||||
]
|
||||
|
||||
|
||||
def build_backbone(backbone_name, **kwargs):
|
||||
assert (
|
||||
backbone_name in support_backbone
|
||||
), f"all support backbone is {support_backbone}"
|
||||
backbone = eval(backbone_name)(**kwargs)
|
||||
return backbone
|
@ -0,0 +1,366 @@
|
||||
import math
|
||||
import paddle
|
||||
from paddle import nn
|
||||
|
||||
BatchNorm2d = nn.BatchNorm2D
|
||||
|
||||
__all__ = [
|
||||
"ResNet",
|
||||
"resnet18",
|
||||
"resnet34",
|
||||
"resnet50",
|
||||
"resnet101",
|
||||
"deformable_resnet18",
|
||||
"deformable_resnet50",
|
||||
"resnet152",
|
||||
]
|
||||
|
||||
model_urls = {
|
||||
"resnet18": "https://download.pytorch.org/models/resnet18-5c106cde.pth",
|
||||
"resnet34": "https://download.pytorch.org/models/resnet34-333f7ec4.pth",
|
||||
"resnet50": "https://download.pytorch.org/models/resnet50-19c8e357.pth",
|
||||
"resnet101": "https://download.pytorch.org/models/resnet101-5d3b4d8f.pth",
|
||||
"resnet152": "https://download.pytorch.org/models/resnet152-b121ed2d.pth",
|
||||
}
|
||||
|
||||
|
||||
def constant_init(module, constant, bias=0):
|
||||
module.weight = paddle.create_parameter(
|
||||
shape=module.weight.shape,
|
||||
dtype="float32",
|
||||
default_initializer=paddle.nn.initializer.Constant(constant),
|
||||
)
|
||||
if hasattr(module, "bias"):
|
||||
module.bias = paddle.create_parameter(
|
||||
shape=module.bias.shape,
|
||||
dtype="float32",
|
||||
default_initializer=paddle.nn.initializer.Constant(bias),
|
||||
)
|
||||
|
||||
|
||||
def conv3x3(in_planes, out_planes, stride=1):
|
||||
"""3x3 convolution with padding"""
|
||||
return nn.Conv2D(
|
||||
in_planes, out_planes, kernel_size=3, stride=stride, padding=1, bias_attr=False
|
||||
)
|
||||
|
||||
|
||||
class BasicBlock(nn.Layer):
|
||||
expansion = 1
|
||||
|
||||
def __init__(self, inplanes, planes, stride=1, downsample=None, dcn=None):
|
||||
super(BasicBlock, self).__init__()
|
||||
self.with_dcn = dcn is not None
|
||||
self.conv1 = conv3x3(inplanes, planes, stride)
|
||||
self.bn1 = BatchNorm2d(planes, momentum=0.1)
|
||||
self.relu = nn.ReLU()
|
||||
self.with_modulated_dcn = False
|
||||
if not self.with_dcn:
|
||||
self.conv2 = nn.Conv2D(
|
||||
planes, planes, kernel_size=3, padding=1, bias_attr=False
|
||||
)
|
||||
else:
|
||||
from paddle.vision.ops import DeformConv2D
|
||||
|
||||
deformable_groups = dcn.get("deformable_groups", 1)
|
||||
offset_channels = 18
|
||||
self.conv2_offset = nn.Conv2D(
|
||||
planes, deformable_groups * offset_channels, kernel_size=3, padding=1
|
||||
)
|
||||
self.conv2 = DeformConv2D(
|
||||
planes, planes, kernel_size=3, padding=1, bias_attr=False
|
||||
)
|
||||
self.bn2 = BatchNorm2d(planes, momentum=0.1)
|
||||
self.downsample = downsample
|
||||
self.stride = stride
|
||||
|
||||
def forward(self, x):
|
||||
residual = x
|
||||
|
||||
out = self.conv1(x)
|
||||
out = self.bn1(out)
|
||||
out = self.relu(out)
|
||||
|
||||
# out = self.conv2(out)
|
||||
if not self.with_dcn:
|
||||
out = self.conv2(out)
|
||||
else:
|
||||
offset = self.conv2_offset(out)
|
||||
out = self.conv2(out, offset)
|
||||
out = self.bn2(out)
|
||||
|
||||
if self.downsample is not None:
|
||||
residual = self.downsample(x)
|
||||
|
||||
out += residual
|
||||
out = self.relu(out)
|
||||
|
||||
return out
|
||||
|
||||
|
||||
class Bottleneck(nn.Layer):
|
||||
expansion = 4
|
||||
|
||||
def __init__(self, inplanes, planes, stride=1, downsample=None, dcn=None):
|
||||
super(Bottleneck, self).__init__()
|
||||
self.with_dcn = dcn is not None
|
||||
self.conv1 = nn.Conv2D(inplanes, planes, kernel_size=1, bias_attr=False)
|
||||
self.bn1 = BatchNorm2d(planes, momentum=0.1)
|
||||
self.with_modulated_dcn = False
|
||||
if not self.with_dcn:
|
||||
self.conv2 = nn.Conv2D(
|
||||
planes, planes, kernel_size=3, stride=stride, padding=1, bias_attr=False
|
||||
)
|
||||
else:
|
||||
deformable_groups = dcn.get("deformable_groups", 1)
|
||||
from paddle.vision.ops import DeformConv2D
|
||||
|
||||
offset_channels = 18
|
||||
self.conv2_offset = nn.Conv2D(
|
||||
planes,
|
||||
deformable_groups * offset_channels,
|
||||
stride=stride,
|
||||
kernel_size=3,
|
||||
padding=1,
|
||||
)
|
||||
self.conv2 = DeformConv2D(
|
||||
planes, planes, kernel_size=3, padding=1, stride=stride, bias_attr=False
|
||||
)
|
||||
self.bn2 = BatchNorm2d(planes, momentum=0.1)
|
||||
self.conv3 = nn.Conv2D(planes, planes * 4, kernel_size=1, bias_attr=False)
|
||||
self.bn3 = BatchNorm2d(planes * 4, momentum=0.1)
|
||||
self.relu = nn.ReLU()
|
||||
self.downsample = downsample
|
||||
self.stride = stride
|
||||
self.dcn = dcn
|
||||
self.with_dcn = dcn is not None
|
||||
|
||||
def forward(self, x):
|
||||
residual = x
|
||||
|
||||
out = self.conv1(x)
|
||||
out = self.bn1(out)
|
||||
out = self.relu(out)
|
||||
|
||||
# out = self.conv2(out)
|
||||
if not self.with_dcn:
|
||||
out = self.conv2(out)
|
||||
else:
|
||||
offset = self.conv2_offset(out)
|
||||
out = self.conv2(out, offset)
|
||||
out = self.bn2(out)
|
||||
out = self.relu(out)
|
||||
|
||||
out = self.conv3(out)
|
||||
out = self.bn3(out)
|
||||
|
||||
if self.downsample is not None:
|
||||
residual = self.downsample(x)
|
||||
|
||||
out += residual
|
||||
out = self.relu(out)
|
||||
|
||||
return out
|
||||
|
||||
|
||||
class ResNet(nn.Layer):
|
||||
def __init__(self, block, layers, in_channels=3, dcn=None):
|
||||
self.dcn = dcn
|
||||
self.inplanes = 64
|
||||
super(ResNet, self).__init__()
|
||||
self.out_channels = []
|
||||
self.conv1 = nn.Conv2D(
|
||||
in_channels, 64, kernel_size=7, stride=2, padding=3, bias_attr=False
|
||||
)
|
||||
self.bn1 = BatchNorm2d(64, momentum=0.1)
|
||||
self.relu = nn.ReLU()
|
||||
self.maxpool = nn.MaxPool2D(kernel_size=3, stride=2, padding=1)
|
||||
self.layer1 = self._make_layer(block, 64, layers[0])
|
||||
self.layer2 = self._make_layer(block, 128, layers[1], stride=2, dcn=dcn)
|
||||
self.layer3 = self._make_layer(block, 256, layers[2], stride=2, dcn=dcn)
|
||||
self.layer4 = self._make_layer(block, 512, layers[3], stride=2, dcn=dcn)
|
||||
|
||||
if self.dcn is not None:
|
||||
for m in self.modules():
|
||||
if isinstance(m, Bottleneck) or isinstance(m, BasicBlock):
|
||||
if hasattr(m, "conv2_offset"):
|
||||
constant_init(m.conv2_offset, 0)
|
||||
|
||||
def _make_layer(self, block, planes, blocks, stride=1, dcn=None):
|
||||
downsample = None
|
||||
if stride != 1 or self.inplanes != planes * block.expansion:
|
||||
downsample = nn.Sequential(
|
||||
nn.Conv2D(
|
||||
self.inplanes,
|
||||
planes * block.expansion,
|
||||
kernel_size=1,
|
||||
stride=stride,
|
||||
bias_attr=False,
|
||||
),
|
||||
BatchNorm2d(planes * block.expansion, momentum=0.1),
|
||||
)
|
||||
|
||||
layers = []
|
||||
layers.append(block(self.inplanes, planes, stride, downsample, dcn=dcn))
|
||||
self.inplanes = planes * block.expansion
|
||||
for i in range(1, blocks):
|
||||
layers.append(block(self.inplanes, planes, dcn=dcn))
|
||||
self.out_channels.append(planes * block.expansion)
|
||||
return nn.Sequential(*layers)
|
||||
|
||||
def forward(self, x):
|
||||
x = self.conv1(x)
|
||||
x = self.bn1(x)
|
||||
x = self.relu(x)
|
||||
x = self.maxpool(x)
|
||||
|
||||
x2 = self.layer1(x)
|
||||
x3 = self.layer2(x2)
|
||||
x4 = self.layer3(x3)
|
||||
x5 = self.layer4(x4)
|
||||
|
||||
return x2, x3, x4, x5
|
||||
|
||||
|
||||
def load_torch_params(paddle_model, torch_patams):
|
||||
paddle_params = paddle_model.state_dict()
|
||||
|
||||
fc_names = ["classifier"]
|
||||
for key, torch_value in torch_patams.items():
|
||||
if "num_batches_tracked" in key:
|
||||
continue
|
||||
key = (
|
||||
key.replace("running_var", "_variance")
|
||||
.replace("running_mean", "_mean")
|
||||
.replace("module.", "")
|
||||
)
|
||||
torch_value = torch_value.detach().cpu().numpy()
|
||||
if key in paddle_params:
|
||||
flag = [i in key for i in fc_names]
|
||||
if any(flag) and "weight" in key: # ignore bias
|
||||
new_shape = [1, 0] + list(range(2, torch_value.ndim))
|
||||
print(
|
||||
f"name: {key}, ori shape: {torch_value.shape}, new shape: {torch_value.transpose(new_shape).shape}"
|
||||
)
|
||||
torch_value = torch_value.transpose(new_shape)
|
||||
paddle_params[key] = torch_value
|
||||
else:
|
||||
print(f"{key} not in paddle")
|
||||
paddle_model.set_state_dict(paddle_params)
|
||||
|
||||
|
||||
def load_models(model, model_name):
|
||||
import torch.utils.model_zoo as model_zoo
|
||||
|
||||
torch_patams = model_zoo.load_url(model_urls[model_name])
|
||||
load_torch_params(model, torch_patams)
|
||||
|
||||
|
||||
def resnet18(pretrained=True, **kwargs):
|
||||
"""Constructs a ResNet-18 model.
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
"""
|
||||
model = ResNet(BasicBlock, [2, 2, 2, 2], **kwargs)
|
||||
if pretrained:
|
||||
assert (
|
||||
kwargs.get("in_channels", 3) == 3
|
||||
), "in_channels must be 3 when pretrained is True"
|
||||
print("load from imagenet")
|
||||
load_models(model, "resnet18")
|
||||
return model
|
||||
|
||||
|
||||
def deformable_resnet18(pretrained=True, **kwargs):
|
||||
"""Constructs a ResNet-18 model.
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
"""
|
||||
model = ResNet(BasicBlock, [2, 2, 2, 2], dcn=dict(deformable_groups=1), **kwargs)
|
||||
if pretrained:
|
||||
assert (
|
||||
kwargs.get("in_channels", 3) == 3
|
||||
), "in_channels must be 3 when pretrained is True"
|
||||
print("load from imagenet")
|
||||
model.load_state_dict(model_zoo.load_url(model_urls["resnet18"]), strict=False)
|
||||
return model
|
||||
|
||||
|
||||
def resnet34(pretrained=True, **kwargs):
|
||||
"""Constructs a ResNet-34 model.
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
"""
|
||||
model = ResNet(BasicBlock, [3, 4, 6, 3], **kwargs)
|
||||
if pretrained:
|
||||
assert (
|
||||
kwargs.get("in_channels", 3) == 3
|
||||
), "in_channels must be 3 when pretrained is True"
|
||||
model.load_state_dict(model_zoo.load_url(model_urls["resnet34"]), strict=False)
|
||||
return model
|
||||
|
||||
|
||||
def resnet50(pretrained=True, **kwargs):
|
||||
"""Constructs a ResNet-50 model.
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
"""
|
||||
model = ResNet(Bottleneck, [3, 4, 6, 3], **kwargs)
|
||||
if pretrained:
|
||||
assert (
|
||||
kwargs.get("in_channels", 3) == 3
|
||||
), "in_channels must be 3 when pretrained is True"
|
||||
load_models(model, "resnet50")
|
||||
return model
|
||||
|
||||
|
||||
def deformable_resnet50(pretrained=True, **kwargs):
|
||||
"""Constructs a ResNet-50 model with deformable conv.
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
"""
|
||||
model = ResNet(Bottleneck, [3, 4, 6, 3], dcn=dict(deformable_groups=1), **kwargs)
|
||||
if pretrained:
|
||||
assert (
|
||||
kwargs.get("in_channels", 3) == 3
|
||||
), "in_channels must be 3 when pretrained is True"
|
||||
model.load_state_dict(model_zoo.load_url(model_urls["resnet50"]), strict=False)
|
||||
return model
|
||||
|
||||
|
||||
def resnet101(pretrained=True, **kwargs):
|
||||
"""Constructs a ResNet-101 model.
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
"""
|
||||
model = ResNet(Bottleneck, [3, 4, 23, 3], **kwargs)
|
||||
if pretrained:
|
||||
assert (
|
||||
kwargs.get("in_channels", 3) == 3
|
||||
), "in_channels must be 3 when pretrained is True"
|
||||
model.load_state_dict(model_zoo.load_url(model_urls["resnet101"]), strict=False)
|
||||
return model
|
||||
|
||||
|
||||
def resnet152(pretrained=True, **kwargs):
|
||||
"""Constructs a ResNet-152 model.
|
||||
Args:
|
||||
pretrained (bool): If True, returns a model pre-trained on ImageNet
|
||||
"""
|
||||
model = ResNet(Bottleneck, [3, 8, 36, 3], **kwargs)
|
||||
if pretrained:
|
||||
assert (
|
||||
kwargs.get("in_channels", 3) == 3
|
||||
), "in_channels must be 3 when pretrained is True"
|
||||
model.load_state_dict(model_zoo.load_url(model_urls["resnet152"]), strict=False)
|
||||
return model
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
x = paddle.zeros([2, 3, 640, 640])
|
||||
net = resnet50(pretrained=True)
|
||||
y = net(x)
|
||||
for u in y:
|
||||
print(u.shape)
|
||||
|
||||
print(net.out_channels)
|
@ -0,0 +1,40 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2019/12/6 11:19
|
||||
# @Author : zhoujun
|
||||
from paddle import nn
|
||||
|
||||
|
||||
class ConvBnRelu(nn.Layer):
|
||||
def __init__(
|
||||
self,
|
||||
in_channels,
|
||||
out_channels,
|
||||
kernel_size,
|
||||
stride=1,
|
||||
padding=0,
|
||||
dilation=1,
|
||||
groups=1,
|
||||
bias=True,
|
||||
padding_mode="zeros",
|
||||
inplace=True,
|
||||
):
|
||||
super().__init__()
|
||||
self.conv = nn.Conv2D(
|
||||
in_channels=in_channels,
|
||||
out_channels=out_channels,
|
||||
kernel_size=kernel_size,
|
||||
stride=stride,
|
||||
padding=padding,
|
||||
dilation=dilation,
|
||||
groups=groups,
|
||||
bias_attr=bias,
|
||||
padding_mode=padding_mode,
|
||||
)
|
||||
self.bn = nn.BatchNorm2D(out_channels)
|
||||
self.relu = nn.ReLU()
|
||||
|
||||
def forward(self, x):
|
||||
x = self.conv(x)
|
||||
x = self.bn(x)
|
||||
x = self.relu(x)
|
||||
return x
|
@ -0,0 +1,132 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2019/12/4 14:54
|
||||
# @Author : zhoujun
|
||||
import paddle
|
||||
from paddle import nn, ParamAttr
|
||||
|
||||
|
||||
class DBHead(nn.Layer):
|
||||
def __init__(self, in_channels, out_channels, k=50):
|
||||
super().__init__()
|
||||
self.k = k
|
||||
self.binarize = nn.Sequential(
|
||||
nn.Conv2D(
|
||||
in_channels,
|
||||
in_channels // 4,
|
||||
3,
|
||||
padding=1,
|
||||
weight_attr=ParamAttr(initializer=nn.initializer.KaimingNormal()),
|
||||
),
|
||||
nn.BatchNorm2D(
|
||||
in_channels // 4,
|
||||
weight_attr=ParamAttr(initializer=nn.initializer.Constant(1)),
|
||||
bias_attr=ParamAttr(initializer=nn.initializer.Constant(1e-4)),
|
||||
),
|
||||
nn.ReLU(),
|
||||
nn.Conv2DTranspose(
|
||||
in_channels // 4,
|
||||
in_channels // 4,
|
||||
2,
|
||||
2,
|
||||
weight_attr=ParamAttr(initializer=nn.initializer.KaimingNormal()),
|
||||
),
|
||||
nn.BatchNorm2D(
|
||||
in_channels // 4,
|
||||
weight_attr=ParamAttr(initializer=nn.initializer.Constant(1)),
|
||||
bias_attr=ParamAttr(initializer=nn.initializer.Constant(1e-4)),
|
||||
),
|
||||
nn.ReLU(),
|
||||
nn.Conv2DTranspose(
|
||||
in_channels // 4, 1, 2, 2, weight_attr=nn.initializer.KaimingNormal()
|
||||
),
|
||||
nn.Sigmoid(),
|
||||
)
|
||||
|
||||
self.thresh = self._init_thresh(in_channels)
|
||||
|
||||
def forward(self, x):
|
||||
shrink_maps = self.binarize(x)
|
||||
threshold_maps = self.thresh(x)
|
||||
if self.training:
|
||||
binary_maps = self.step_function(shrink_maps, threshold_maps)
|
||||
y = paddle.concat((shrink_maps, threshold_maps, binary_maps), axis=1)
|
||||
else:
|
||||
y = paddle.concat((shrink_maps, threshold_maps), axis=1)
|
||||
return y
|
||||
|
||||
def _init_thresh(self, inner_channels, serial=False, smooth=False, bias=False):
|
||||
in_channels = inner_channels
|
||||
if serial:
|
||||
in_channels += 1
|
||||
self.thresh = nn.Sequential(
|
||||
nn.Conv2D(
|
||||
in_channels,
|
||||
inner_channels // 4,
|
||||
3,
|
||||
padding=1,
|
||||
bias_attr=bias,
|
||||
weight_attr=ParamAttr(initializer=nn.initializer.KaimingNormal()),
|
||||
),
|
||||
nn.BatchNorm2D(
|
||||
inner_channels // 4,
|
||||
weight_attr=ParamAttr(initializer=nn.initializer.Constant(1)),
|
||||
bias_attr=ParamAttr(initializer=nn.initializer.Constant(1e-4)),
|
||||
),
|
||||
nn.ReLU(),
|
||||
self._init_upsample(
|
||||
inner_channels // 4, inner_channels // 4, smooth=smooth, bias=bias
|
||||
),
|
||||
nn.BatchNorm2D(
|
||||
inner_channels // 4,
|
||||
weight_attr=ParamAttr(initializer=nn.initializer.Constant(1)),
|
||||
bias_attr=ParamAttr(initializer=nn.initializer.Constant(1e-4)),
|
||||
),
|
||||
nn.ReLU(),
|
||||
self._init_upsample(inner_channels // 4, 1, smooth=smooth, bias=bias),
|
||||
nn.Sigmoid(),
|
||||
)
|
||||
return self.thresh
|
||||
|
||||
def _init_upsample(self, in_channels, out_channels, smooth=False, bias=False):
|
||||
if smooth:
|
||||
inter_out_channels = out_channels
|
||||
if out_channels == 1:
|
||||
inter_out_channels = in_channels
|
||||
module_list = [
|
||||
nn.Upsample(scale_factor=2, mode="nearest"),
|
||||
nn.Conv2D(
|
||||
in_channels,
|
||||
inter_out_channels,
|
||||
3,
|
||||
1,
|
||||
1,
|
||||
bias_attr=bias,
|
||||
weight_attr=ParamAttr(initializer=nn.initializer.KaimingNormal()),
|
||||
),
|
||||
]
|
||||
if out_channels == 1:
|
||||
module_list.append(
|
||||
nn.Conv2D(
|
||||
in_channels,
|
||||
out_channels,
|
||||
kernel_size=1,
|
||||
stride=1,
|
||||
padding=1,
|
||||
bias_attr=True,
|
||||
weight_attr=ParamAttr(
|
||||
initializer=nn.initializer.KaimingNormal()
|
||||
),
|
||||
)
|
||||
)
|
||||
return nn.Sequential(module_list)
|
||||
else:
|
||||
return nn.Conv2DTranspose(
|
||||
in_channels,
|
||||
out_channels,
|
||||
2,
|
||||
2,
|
||||
weight_attr=ParamAttr(initializer=nn.initializer.KaimingNormal()),
|
||||
)
|
||||
|
||||
def step_function(self, x, y):
|
||||
return paddle.reciprocal(1 + paddle.exp(-self.k * (x - y)))
|
@ -0,0 +1,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2020/6/5 11:35
|
||||
# @Author : zhoujun
|
||||
from .DBHead import DBHead
|
||||
|
||||
__all__ = ["build_head"]
|
||||
support_head = ["DBHead"]
|
||||
|
||||
|
||||
def build_head(head_name, **kwargs):
|
||||
assert head_name in support_head, f"all support head is {support_head}"
|
||||
head = eval(head_name)(**kwargs)
|
||||
return head
|
@ -0,0 +1,50 @@
|
||||
import paddle
|
||||
from models.losses.basic_loss import BalanceCrossEntropyLoss, MaskL1Loss, DiceLoss
|
||||
|
||||
|
||||
class DBLoss(paddle.nn.Layer):
|
||||
def __init__(self, alpha=1.0, beta=10, ohem_ratio=3, reduction="mean", eps=1e-06):
|
||||
"""
|
||||
Implement PSE Loss.
|
||||
:param alpha: binary_map loss 前面的系数
|
||||
:param beta: threshold_map loss 前面的系数
|
||||
:param ohem_ratio: OHEM的比例
|
||||
:param reduction: 'mean' or 'sum'对 batch里的loss 算均值或求和
|
||||
"""
|
||||
super().__init__()
|
||||
assert reduction in ["mean", "sum"], " reduction must in ['mean','sum']"
|
||||
self.alpha = alpha
|
||||
self.beta = beta
|
||||
self.bce_loss = BalanceCrossEntropyLoss(negative_ratio=ohem_ratio)
|
||||
self.dice_loss = DiceLoss(eps=eps)
|
||||
self.l1_loss = MaskL1Loss(eps=eps)
|
||||
self.ohem_ratio = ohem_ratio
|
||||
self.reduction = reduction
|
||||
|
||||
def forward(self, pred, batch):
|
||||
shrink_maps = pred[:, 0, :, :]
|
||||
threshold_maps = pred[:, 1, :, :]
|
||||
binary_maps = pred[:, 2, :, :]
|
||||
loss_shrink_maps = self.bce_loss(
|
||||
shrink_maps, batch["shrink_map"], batch["shrink_mask"]
|
||||
)
|
||||
loss_threshold_maps = self.l1_loss(
|
||||
threshold_maps, batch["threshold_map"], batch["threshold_mask"]
|
||||
)
|
||||
metrics = dict(
|
||||
loss_shrink_maps=loss_shrink_maps, loss_threshold_maps=loss_threshold_maps
|
||||
)
|
||||
if pred.shape[1] > 2:
|
||||
loss_binary_maps = self.dice_loss(
|
||||
binary_maps, batch["shrink_map"], batch["shrink_mask"]
|
||||
)
|
||||
metrics["loss_binary_maps"] = loss_binary_maps
|
||||
loss_all = (
|
||||
self.alpha * loss_shrink_maps
|
||||
+ self.beta * loss_threshold_maps
|
||||
+ loss_binary_maps
|
||||
)
|
||||
metrics["loss"] = loss_all
|
||||
else:
|
||||
metrics["loss"] = loss_shrink_maps
|
||||
return metrics
|
@ -0,0 +1,16 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2020/6/5 11:36
|
||||
# @Author : zhoujun
|
||||
import copy
|
||||
from .DB_loss import DBLoss
|
||||
|
||||
__all__ = ["build_loss"]
|
||||
support_loss = ["DBLoss"]
|
||||
|
||||
|
||||
def build_loss(config):
|
||||
copy_config = copy.deepcopy(config)
|
||||
loss_type = copy_config.pop("type")
|
||||
assert loss_type in support_loss, f"all support loss is {support_loss}"
|
||||
criterion = eval(loss_type)(**copy_config)
|
||||
return criterion
|
@ -0,0 +1,101 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2019/12/4 14:39
|
||||
# @Author : zhoujun
|
||||
import paddle
|
||||
import paddle.nn as nn
|
||||
|
||||
|
||||
class BalanceCrossEntropyLoss(nn.Layer):
|
||||
"""
|
||||
Balanced cross entropy loss.
|
||||
Shape:
|
||||
- Input: :math:`(N, 1, H, W)`
|
||||
- GT: :math:`(N, 1, H, W)`, same shape as the input
|
||||
- Mask: :math:`(N, H, W)`, same spatial shape as the input
|
||||
- Output: scalar.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, negative_ratio=3.0, eps=1e-6):
|
||||
super(BalanceCrossEntropyLoss, self).__init__()
|
||||
self.negative_ratio = negative_ratio
|
||||
self.eps = eps
|
||||
|
||||
def forward(
|
||||
self,
|
||||
pred: paddle.Tensor,
|
||||
gt: paddle.Tensor,
|
||||
mask: paddle.Tensor,
|
||||
return_origin=False,
|
||||
):
|
||||
"""
|
||||
Args:
|
||||
pred: shape :math:`(N, 1, H, W)`, the prediction of network
|
||||
gt: shape :math:`(N, 1, H, W)`, the target
|
||||
mask: shape :math:`(N, H, W)`, the mask indicates positive regions
|
||||
"""
|
||||
positive = gt * mask
|
||||
negative = (1 - gt) * mask
|
||||
positive_count = int(positive.sum())
|
||||
negative_count = min(
|
||||
int(negative.sum()), int(positive_count * self.negative_ratio)
|
||||
)
|
||||
loss = nn.functional.binary_cross_entropy(pred, gt, reduction="none")
|
||||
positive_loss = loss * positive
|
||||
negative_loss = loss * negative
|
||||
negative_loss, _ = negative_loss.reshape([-1]).topk(negative_count)
|
||||
|
||||
balance_loss = (positive_loss.sum() + negative_loss.sum()) / (
|
||||
positive_count + negative_count + self.eps
|
||||
)
|
||||
|
||||
if return_origin:
|
||||
return balance_loss, loss
|
||||
return balance_loss
|
||||
|
||||
|
||||
class DiceLoss(nn.Layer):
|
||||
"""
|
||||
Loss function from https://arxiv.org/abs/1707.03237,
|
||||
where iou computation is introduced heatmap manner to measure the
|
||||
diversity between tow heatmaps.
|
||||
"""
|
||||
|
||||
def __init__(self, eps=1e-6):
|
||||
super(DiceLoss, self).__init__()
|
||||
self.eps = eps
|
||||
|
||||
def forward(self, pred: paddle.Tensor, gt, mask, weights=None):
|
||||
"""
|
||||
pred: one or two heatmaps of shape (N, 1, H, W),
|
||||
the losses of tow heatmaps are added together.
|
||||
gt: (N, 1, H, W)
|
||||
mask: (N, H, W)
|
||||
"""
|
||||
return self._compute(pred, gt, mask, weights)
|
||||
|
||||
def _compute(self, pred, gt, mask, weights):
|
||||
if len(pred.shape) == 4:
|
||||
pred = pred[:, 0, :, :]
|
||||
gt = gt[:, 0, :, :]
|
||||
assert pred.shape == gt.shape
|
||||
assert pred.shape == mask.shape
|
||||
if weights is not None:
|
||||
assert weights.shape == mask.shape
|
||||
mask = weights * mask
|
||||
intersection = (pred * gt * mask).sum()
|
||||
|
||||
union = (pred * mask).sum() + (gt * mask).sum() + self.eps
|
||||
loss = 1 - 2.0 * intersection / union
|
||||
assert loss <= 1
|
||||
return loss
|
||||
|
||||
|
||||
class MaskL1Loss(nn.Layer):
|
||||
def __init__(self, eps=1e-6):
|
||||
super(MaskL1Loss, self).__init__()
|
||||
self.eps = eps
|
||||
|
||||
def forward(self, pred: paddle.Tensor, gt, mask):
|
||||
loss = (paddle.abs(pred - gt) * mask).sum() / (mask.sum() + self.eps)
|
||||
return loss
|
@ -0,0 +1,39 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2019/8/23 21:57
|
||||
# @Author : zhoujun
|
||||
from addict import Dict
|
||||
from paddle import nn
|
||||
import paddle.nn.functional as F
|
||||
|
||||
from models.backbone import build_backbone
|
||||
from models.neck import build_neck
|
||||
from models.head import build_head
|
||||
|
||||
|
||||
class Model(nn.Layer):
|
||||
def __init__(self, model_config: dict):
|
||||
"""
|
||||
PANnet
|
||||
:param model_config: 模型配置
|
||||
"""
|
||||
super().__init__()
|
||||
model_config = Dict(model_config)
|
||||
backbone_type = model_config.backbone.pop("type")
|
||||
neck_type = model_config.neck.pop("type")
|
||||
head_type = model_config.head.pop("type")
|
||||
self.backbone = build_backbone(backbone_type, **model_config.backbone)
|
||||
self.neck = build_neck(
|
||||
neck_type, in_channels=self.backbone.out_channels, **model_config.neck
|
||||
)
|
||||
self.head = build_head(
|
||||
head_type, in_channels=self.neck.out_channels, **model_config.head
|
||||
)
|
||||
self.name = f"{backbone_type}_{neck_type}_{head_type}"
|
||||
|
||||
def forward(self, x):
|
||||
_, _, H, W = x.shape
|
||||
backbone_out = self.backbone(x)
|
||||
neck_out = self.neck(backbone_out)
|
||||
y = self.head(neck_out)
|
||||
y = F.interpolate(y, size=(H, W), mode="bilinear", align_corners=True)
|
||||
return y
|
@ -0,0 +1,75 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2019/9/13 10:29
|
||||
# @Author : zhoujun
|
||||
import paddle
|
||||
import paddle.nn.functional as F
|
||||
from paddle import nn
|
||||
|
||||
from models.basic import ConvBnRelu
|
||||
|
||||
|
||||
class FPN(nn.Layer):
|
||||
def __init__(self, in_channels, inner_channels=256, **kwargs):
|
||||
"""
|
||||
:param in_channels: 基础网络输出的维度
|
||||
:param kwargs:
|
||||
"""
|
||||
super().__init__()
|
||||
inplace = True
|
||||
self.conv_out = inner_channels
|
||||
inner_channels = inner_channels // 4
|
||||
# reduce layers
|
||||
self.reduce_conv_c2 = ConvBnRelu(
|
||||
in_channels[0], inner_channels, kernel_size=1, inplace=inplace
|
||||
)
|
||||
self.reduce_conv_c3 = ConvBnRelu(
|
||||
in_channels[1], inner_channels, kernel_size=1, inplace=inplace
|
||||
)
|
||||
self.reduce_conv_c4 = ConvBnRelu(
|
||||
in_channels[2], inner_channels, kernel_size=1, inplace=inplace
|
||||
)
|
||||
self.reduce_conv_c5 = ConvBnRelu(
|
||||
in_channels[3], inner_channels, kernel_size=1, inplace=inplace
|
||||
)
|
||||
# Smooth layers
|
||||
self.smooth_p4 = ConvBnRelu(
|
||||
inner_channels, inner_channels, kernel_size=3, padding=1, inplace=inplace
|
||||
)
|
||||
self.smooth_p3 = ConvBnRelu(
|
||||
inner_channels, inner_channels, kernel_size=3, padding=1, inplace=inplace
|
||||
)
|
||||
self.smooth_p2 = ConvBnRelu(
|
||||
inner_channels, inner_channels, kernel_size=3, padding=1, inplace=inplace
|
||||
)
|
||||
|
||||
self.conv = nn.Sequential(
|
||||
nn.Conv2D(self.conv_out, self.conv_out, kernel_size=3, padding=1, stride=1),
|
||||
nn.BatchNorm2D(self.conv_out),
|
||||
nn.ReLU(),
|
||||
)
|
||||
self.out_channels = self.conv_out
|
||||
|
||||
def forward(self, x):
|
||||
c2, c3, c4, c5 = x
|
||||
# Top-down
|
||||
p5 = self.reduce_conv_c5(c5)
|
||||
p4 = self._upsample_add(p5, self.reduce_conv_c4(c4))
|
||||
p4 = self.smooth_p4(p4)
|
||||
p3 = self._upsample_add(p4, self.reduce_conv_c3(c3))
|
||||
p3 = self.smooth_p3(p3)
|
||||
p2 = self._upsample_add(p3, self.reduce_conv_c2(c2))
|
||||
p2 = self.smooth_p2(p2)
|
||||
|
||||
x = self._upsample_cat(p2, p3, p4, p5)
|
||||
x = self.conv(x)
|
||||
return x
|
||||
|
||||
def _upsample_add(self, x, y):
|
||||
return F.interpolate(x, size=y.shape[2:]) + y
|
||||
|
||||
def _upsample_cat(self, p2, p3, p4, p5):
|
||||
h, w = p2.shape[2:]
|
||||
p3 = F.interpolate(p3, size=(h, w))
|
||||
p4 = F.interpolate(p4, size=(h, w))
|
||||
p5 = F.interpolate(p5, size=(h, w))
|
||||
return paddle.concat([p2, p3, p4, p5], axis=1)
|
@ -0,0 +1,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# @Time : 2020/6/5 11:34
|
||||
# @Author : zhoujun
|
||||
from .FPN import FPN
|
||||
|
||||
__all__ = ["build_neck"]
|
||||
support_neck = ["FPN"]
|
||||
|
||||
|
||||
def build_neck(neck_name, **kwargs):
|
||||
assert neck_name in support_neck, f"all support neck is {support_neck}"
|
||||
neck = eval(neck_name)(**kwargs)
|
||||
return neck
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue