徐勤民 11 시간 전
부모
커밋
741771b365
44개의 변경된 파일34397개의 추가작업 그리고 1436개의 파일을 삭제
  1. BIN
      models/ocr/Cls/原始分类器模型.onnx
  2. BIN
      models/ocr/Det/中文_OCRv2.onnx
  3. BIN
      models/ocr/Det/中文_OCRv3.onnx
  4. BIN
      models/ocr/Det/多语言.onnx
  5. BIN
      models/ocr/Det/英文检测.onnx
  6. 6623 0
      models/ocr/Keys/中文简体_OCRv2.txt
  7. 6623 0
      models/ocr/Keys/中文简体_OCRv3.txt
  8. 8421 0
      models/ocr/Keys/中文繁体.txt
  9. 153 0
      models/ocr/Keys/卡纳达文.txt
  10. 163 0
      models/ocr/Keys/斯拉夫字母.txt
  11. 4399 0
      models/ocr/Keys/日文.txt
  12. 151 0
      models/ocr/Keys/泰卢固文.txt
  13. 95 0
      models/ocr/Keys/英文.txt
  14. 3688 0
      models/ocr/Keys/韩文.txt
  15. BIN
      models/ocr/Rec/中文简体_OCRv2.onnx
  16. BIN
      models/ocr/Rec/中文简体_OCRv3.onnx
  17. BIN
      models/ocr/Rec/中文繁体.onnx
  18. BIN
      models/ocr/Rec/卡纳达文.onnx
  19. BIN
      models/ocr/Rec/斯拉夫字母.onnx
  20. BIN
      models/ocr/Rec/日文.onnx
  21. BIN
      models/ocr/Rec/泰卢固文.onnx
  22. BIN
      models/ocr/Rec/英文.onnx
  23. BIN
      models/ocr/Rec/韩文.onnx
  24. 9 0
      package.json
  25. 197 0
      scripts/download-ppocrv5.js
  26. 115 0
      scripts/validate-models.js
  27. 0 468
      server/server.js
  28. 487 0
      server/server.ts
  29. 271 0
      server/utils/detectionProcessor.js
  30. 104 0
      server/utils/imagePreprocessor.js
  31. 201 0
      server/utils/onnxOcrManager.js
  32. 131 0
      server/utils/recognitionProcessor.js
  33. 85 0
      server/utils/textDirectionClassifier.js
  34. 163 0
      server/utils/textPostProcessor.js
  35. 370 0
      server/utils/textRecognizer.js
  36. 127 0
      server/utils/textRegionCropper.js
  37. 13 13
      src/main/main.js
  38. 97 953
      src/renderer/components/OCRPage.vue
  39. 223 0
      src/renderer/components/ocr/FilePanel.vue
  40. 303 0
      src/renderer/components/ocr/ImagePanel.vue
  41. 256 0
      src/renderer/components/ocr/ResultPanel.vue
  42. 215 0
      src/renderer/components/ocr/TextBlock.vue
  43. 60 0
      src/renderer/types/ocr.ts
  44. 654 2
      yarn.lock

BIN
models/ocr/Cls/原始分类器模型.onnx


BIN
models/ocr/Det/中文_OCRv2.onnx


BIN
models/ocr/Det/中文_OCRv3.onnx


BIN
models/ocr/Det/多语言.onnx


BIN
models/ocr/Det/英文检测.onnx


+ 6623 - 0
models/ocr/Keys/中文简体_OCRv2.txt

@@ -0,0 +1,6623 @@
+'
+疗
+绚
+诚
+娇
+溜
+题
+贿
+者
+廖
+更
+纳
+加
+奉
+公
+一
+就
+汴
+计
+与
+路
+房
+原
+妇
+2
+0
+8
+-
+7
+其
+>
+:
+]
+,
+,
+骑
+刈
+全
+消
+昏
+傈
+安
+久
+钟
+嗅
+不
+影
+处
+驽
+蜿
+资
+关
+椤
+地
+瘸
+专
+问
+忖
+票
+嫉
+炎
+韵
+要
+月
+田
+节
+陂
+鄙
+捌
+备
+拳
+伺
+眼
+网
+盎
+大
+傍
+心
+东
+愉
+汇
+蹿
+科
+每
+业
+里
+航
+晏
+字
+平
+录
+先
+1
+3
+彤
+鲶
+产
+稍
+督
+腴
+有
+象
+岳
+注
+绍
+在
+泺
+文
+定
+核
+名
+水
+过
+理
+让
+偷
+率
+等
+这
+发
+”
+为
+含
+肥
+酉
+相
+鄱
+七
+编
+猥
+锛
+日
+镀
+蒂
+掰
+倒
+辆
+栾
+栗
+综
+涩
+州
+雌
+滑
+馀
+了
+机
+块
+司
+宰
+甙
+兴
+矽
+抚
+保
+用
+沧
+秩
+如
+收
+息
+滥
+页
+疑
+埠
+!
+!
+姥
+异
+橹
+钇
+向
+下
+跄
+的
+椴
+沫
+国
+绥
+獠
+报
+开
+民
+蜇
+何
+分
+凇
+长
+讥
+藏
+掏
+施
+羽
+中
+讲
+派
+嘟
+人
+提
+浼
+间
+世
+而
+古
+多
+倪
+唇
+饯
+控
+庚
+首
+赛
+蜓
+味
+断
+制
+觉
+技
+替
+艰
+溢
+潮
+夕
+钺
+外
+摘
+枋
+动
+双
+单
+啮
+户
+枇
+确
+锦
+曜
+杜
+或
+能
+效
+霜
+盒
+然
+侗
+电
+晁
+放
+步
+鹃
+新
+杖
+蜂
+吒
+濂
+瞬
+评
+总
+隍
+对
+独
+合
+也
+是
+府
+青
+天
+诲
+墙
+组
+滴
+级
+邀
+帘
+示
+已
+时
+骸
+仄
+泅
+和
+遨
+店
+雇
+疫
+持
+巍
+踮
+境
+只
+亨
+目
+鉴
+崤
+闲
+体
+泄
+杂
+作
+般
+轰
+化
+解
+迂
+诿
+蛭
+璀
+腾
+告
+版
+服
+省
+师
+小
+规
+程
+线
+海
+办
+引
+二
+桧
+牌
+砺
+洄
+裴
+修
+图
+痫
+胡
+许
+犊
+事
+郛
+基
+柴
+呼
+食
+研
+奶
+律
+蛋
+因
+葆
+察
+戏
+褒
+戒
+再
+李
+骁
+工
+貂
+油
+鹅
+章
+啄
+休
+场
+给
+睡
+纷
+豆
+器
+捎
+说
+敏
+学
+会
+浒
+设
+诊
+格
+廓
+查
+来
+霓
+室
+溆
+¢
+诡
+寥
+焕
+舜
+柒
+狐
+回
+戟
+砾
+厄
+实
+翩
+尿
+五
+入
+径
+惭
+喹
+股
+宇
+篝
+|
+;
+美
+期
+云
+九
+祺
+扮
+靠
+锝
+槌
+系
+企
+酰
+阊
+暂
+蚕
+忻
+豁
+本
+羹
+执
+条
+钦
+H
+獒
+限
+进
+季
+楦
+于
+芘
+玖
+铋
+茯
+未
+答
+粘
+括
+样
+精
+欠
+矢
+甥
+帷
+嵩
+扣
+令
+仔
+风
+皈
+行
+支
+部
+蓉
+刮
+站
+蜡
+救
+钊
+汗
+松
+嫌
+成
+可
+.
+鹤
+院
+从
+交
+政
+怕
+活
+调
+球
+局
+验
+髌
+第
+韫
+谗
+串
+到
+圆
+年
+米
+/
+*
+友
+忿
+检
+区
+看
+自
+敢
+刃
+个
+兹
+弄
+流
+留
+同
+没
+齿
+星
+聆
+轼
+湖
+什
+三
+建
+蛔
+儿
+椋
+汕
+震
+颧
+鲤
+跟
+力
+情
+璺
+铨
+陪
+务
+指
+族
+训
+滦
+鄣
+濮
+扒
+商
+箱
+十
+召
+慷
+辗
+所
+莞
+管
+护
+臭
+横
+硒
+嗓
+接
+侦
+六
+露
+党
+馋
+驾
+剖
+高
+侬
+妪
+幂
+猗
+绺
+骐
+央
+酐
+孝
+筝
+课
+徇
+缰
+门
+男
+西
+项
+句
+谙
+瞒
+秃
+篇
+教
+碲
+罚
+声
+呐
+景
+前
+富
+嘴
+鳌
+稀
+免
+朋
+啬
+睐
+去
+赈
+鱼
+住
+肩
+愕
+速
+旁
+波
+厅
+健
+茼
+厥
+鲟
+谅
+投
+攸
+炔
+数
+方
+击
+呋
+谈
+绩
+别
+愫
+僚
+躬
+鹧
+胪
+炳
+招
+喇
+膨
+泵
+蹦
+毛
+结
+5
+4
+谱
+识
+陕
+粽
+婚
+拟
+构
+且
+搜
+任
+潘
+比
+郢
+妨
+醪
+陀
+桔
+碘
+扎
+选
+哈
+骷
+楷
+亿
+明
+缆
+脯
+监
+睫
+逻
+婵
+共
+赴
+淝
+凡
+惦
+及
+达
+揖
+谩
+澹
+减
+焰
+蛹
+番
+祁
+柏
+员
+禄
+怡
+峤
+龙
+白
+叽
+生
+闯
+起
+细
+装
+谕
+竟
+聚
+钙
+上
+导
+渊
+按
+艾
+辘
+挡
+耒
+盹
+饪
+臀
+记
+邮
+蕙
+受
+各
+医
+搂
+普
+滇
+朗
+茸
+带
+翻
+酚
+(
+光
+堤
+墟
+蔷
+万
+幻
+〓
+瑙
+辈
+昧
+盏
+亘
+蛀
+吉
+铰
+请
+子
+假
+闻
+税
+井
+诩
+哨
+嫂
+好
+面
+琐
+校
+馊
+鬣
+缂
+营
+访
+炖
+占
+农
+缀
+否
+经
+钚
+棵
+趟
+张
+亟
+吏
+茶
+谨
+捻
+论
+迸
+堂
+玉
+信
+吧
+瞠
+乡
+姬
+寺
+咬
+溏
+苄
+皿
+意
+赉
+宝
+尔
+钰
+艺
+特
+唳
+踉
+都
+荣
+倚
+登
+荐
+丧
+奇
+涵
+批
+炭
+近
+符
+傩
+感
+道
+着
+菊
+虹
+仲
+众
+懈
+濯
+颞
+眺
+南
+释
+北
+缝
+标
+既
+茗
+整
+撼
+迤
+贲
+挎
+耱
+拒
+某
+妍
+卫
+哇
+英
+矶
+藩
+治
+他
+元
+领
+膜
+遮
+穗
+蛾
+飞
+荒
+棺
+劫
+么
+市
+火
+温
+拈
+棚
+洼
+转
+果
+奕
+卸
+迪
+伸
+泳
+斗
+邡
+侄
+涨
+屯
+萋
+胭
+氡
+崮
+枞
+惧
+冒
+彩
+斜
+手
+豚
+随
+旭
+淑
+妞
+形
+菌
+吲
+沱
+争
+驯
+歹
+挟
+兆
+柱
+传
+至
+包
+内
+响
+临
+红
+功
+弩
+衡
+寂
+禁
+老
+棍
+耆
+渍
+织
+害
+氵
+渑
+布
+载
+靥
+嗬
+虽
+苹
+咨
+娄
+库
+雉
+榜
+帜
+嘲
+套
+瑚
+亲
+簸
+欧
+边
+6
+腿
+旮
+抛
+吹
+瞳
+得
+镓
+梗
+厨
+继
+漾
+愣
+憨
+士
+策
+窑
+抑
+躯
+襟
+脏
+参
+贸
+言
+干
+绸
+鳄
+穷
+藜
+音
+折
+详
+)
+举
+悍
+甸
+癌
+黎
+谴
+死
+罩
+迁
+寒
+驷
+袖
+媒
+蒋
+掘
+模
+纠
+恣
+观
+祖
+蛆
+碍
+位
+稿
+主
+澧
+跌
+筏
+京
+锏
+帝
+贴
+证
+糠
+才
+黄
+鲸
+略
+炯
+饱
+四
+出
+园
+犀
+牧
+容
+汉
+杆
+浈
+汰
+瑷
+造
+虫
+瘩
+怪
+驴
+济
+应
+花
+沣
+谔
+夙
+旅
+价
+矿
+以
+考
+s
+u
+呦
+晒
+巡
+茅
+准
+肟
+瓴
+詹
+仟
+褂
+译
+桌
+混
+宁
+怦
+郑
+抿
+些
+余
+鄂
+饴
+攒
+珑
+群
+阖
+岔
+琨
+藓
+预
+环
+洮
+岌
+宀
+杲
+瀵
+最
+常
+囡
+周
+踊
+女
+鼓
+袭
+喉
+简
+范
+薯
+遐
+疏
+粱
+黜
+禧
+法
+箔
+斤
+遥
+汝
+奥
+直
+贞
+撑
+置
+绱
+集
+她
+馅
+逗
+钧
+橱
+魉
+[
+恙
+躁
+唤
+9
+旺
+膘
+待
+脾
+惫
+购
+吗
+依
+盲
+度
+瘿
+蠖
+俾
+之
+镗
+拇
+鲵
+厝
+簧
+续
+款
+展
+啃
+表
+剔
+品
+钻
+腭
+损
+清
+锶
+统
+涌
+寸
+滨
+贪
+链
+吠
+冈
+伎
+迥
+咏
+吁
+览
+防
+迅
+失
+汾
+阔
+逵
+绀
+蔑
+列
+川
+凭
+努
+熨
+揪
+利
+俱
+绉
+抢
+鸨
+我
+即
+责
+膦
+易
+毓
+鹊
+刹
+玷
+岿
+空
+嘞
+绊
+排
+术
+估
+锷
+违
+们
+苟
+铜
+播
+肘
+件
+烫
+审
+鲂
+广
+像
+铌
+惰
+铟
+巳
+胍
+鲍
+康
+憧
+色
+恢
+想
+拷
+尤
+疳
+知
+S
+Y
+F
+D
+A
+峄
+裕
+帮
+握
+搔
+氐
+氘
+难
+墒
+沮
+雨
+叁
+缥
+悴
+藐
+湫
+娟
+苑
+稠
+颛
+簇
+后
+阕
+闭
+蕤
+缚
+怎
+佞
+码
+嘤
+蔡
+痊
+舱
+螯
+帕
+赫
+昵
+升
+烬
+岫
+、
+疵
+蜻
+髁
+蕨
+隶
+烛
+械
+丑
+盂
+梁
+强
+鲛
+由
+拘
+揉
+劭
+龟
+撤
+钩
+呕
+孛
+费
+妻
+漂
+求
+阑
+崖
+秤
+甘
+通
+深
+补
+赃
+坎
+床
+啪
+承
+吼
+量
+暇
+钼
+烨
+阂
+擎
+脱
+逮
+称
+P
+神
+属
+矗
+华
+届
+狍
+葑
+汹
+育
+患
+窒
+蛰
+佼
+静
+槎
+运
+鳗
+庆
+逝
+曼
+疱
+克
+代
+官
+此
+麸
+耧
+蚌
+晟
+例
+础
+榛
+副
+测
+唰
+缢
+迹
+灬
+霁
+身
+岁
+赭
+扛
+又
+菡
+乜
+雾
+板
+读
+陷
+徉
+贯
+郁
+虑
+变
+钓
+菜
+圾
+现
+琢
+式
+乐
+维
+渔
+浜
+左
+吾
+脑
+钡
+警
+T
+啵
+拴
+偌
+漱
+湿
+硕
+止
+骼
+魄
+积
+燥
+联
+踢
+玛
+则
+窿
+见
+振
+畿
+送
+班
+钽
+您
+赵
+刨
+印
+讨
+踝
+籍
+谡
+舌
+崧
+汽
+蔽
+沪
+酥
+绒
+怖
+财
+帖
+肱
+私
+莎
+勋
+羔
+霸
+励
+哼
+帐
+将
+帅
+渠
+纪
+婴
+娩
+岭
+厘
+滕
+吻
+伤
+坝
+冠
+戊
+隆
+瘁
+介
+涧
+物
+黍
+并
+姗
+奢
+蹑
+掣
+垸
+锴
+命
+箍
+捉
+病
+辖
+琰
+眭
+迩
+艘
+绌
+繁
+寅
+若
+毋
+思
+诉
+类
+诈
+燮
+轲
+酮
+狂
+重
+反
+职
+筱
+县
+委
+磕
+绣
+奖
+晋
+濉
+志
+徽
+肠
+呈
+獐
+坻
+口
+片
+碰
+几
+村
+柿
+劳
+料
+获
+亩
+惕
+晕
+厌
+号
+罢
+池
+正
+鏖
+煨
+家
+棕
+复
+尝
+懋
+蜥
+锅
+岛
+扰
+队
+坠
+瘾
+钬
+@
+卧
+疣
+镇
+譬
+冰
+彷
+频
+黯
+据
+垄
+采
+八
+缪
+瘫
+型
+熹
+砰
+楠
+襁
+箐
+但
+嘶
+绳
+啤
+拍
+盥
+穆
+傲
+洗
+盯
+塘
+怔
+筛
+丿
+台
+恒
+喂
+葛
+永
+¥
+烟
+酒
+桦
+书
+砂
+蚝
+缉
+态
+瀚
+袄
+圳
+轻
+蛛
+超
+榧
+遛
+姒
+奘
+铮
+右
+荽
+望
+偻
+卡
+丶
+氰
+附
+做
+革
+索
+戚
+坨
+桷
+唁
+垅
+榻
+岐
+偎
+坛
+莨
+山
+殊
+微
+骇
+陈
+爨
+推
+嗝
+驹
+澡
+藁
+呤
+卤
+嘻
+糅
+逛
+侵
+郓
+酌
+德
+摇
+※
+鬃
+被
+慨
+殡
+羸
+昌
+泡
+戛
+鞋
+河
+宪
+沿
+玲
+鲨
+翅
+哽
+源
+铅
+语
+照
+邯
+址
+荃
+佬
+顺
+鸳
+町
+霭
+睾
+瓢
+夸
+椁
+晓
+酿
+痈
+咔
+侏
+券
+噎
+湍
+签
+嚷
+离
+午
+尚
+社
+锤
+背
+孟
+使
+浪
+缦
+潍
+鞅
+军
+姹
+驶
+笑
+鳟
+鲁
+》
+孽
+钜
+绿
+洱
+礴
+焯
+椰
+颖
+囔
+乌
+孔
+巴
+互
+性
+椽
+哞
+聘
+昨
+早
+暮
+胶
+炀
+隧
+低
+彗
+昝
+铁
+呓
+氽
+藉
+喔
+癖
+瑗
+姨
+权
+胱
+韦
+堑
+蜜
+酋
+楝
+砝
+毁
+靓
+歙
+锲
+究
+屋
+喳
+骨
+辨
+碑
+武
+鸠
+宫
+辜
+烊
+适
+坡
+殃
+培
+佩
+供
+走
+蜈
+迟
+翼
+况
+姣
+凛
+浔
+吃
+飘
+债
+犟
+金
+促
+苛
+崇
+坂
+莳
+畔
+绂
+兵
+蠕
+斋
+根
+砍
+亢
+欢
+恬
+崔
+剁
+餐
+榫
+快
+扶
+‖
+濒
+缠
+鳜
+当
+彭
+驭
+浦
+篮
+昀
+锆
+秸
+钳
+弋
+娣
+瞑
+夷
+龛
+苫
+拱
+致
+%
+嵊
+障
+隐
+弑
+初
+娓
+抉
+汩
+累
+蓖
+"
+唬
+助
+苓
+昙
+押
+毙
+破
+城
+郧
+逢
+嚏
+獭
+瞻
+溱
+婿
+赊
+跨
+恼
+璧
+萃
+姻
+貉
+灵
+炉
+密
+氛
+陶
+砸
+谬
+衔
+点
+琛
+沛
+枳
+层
+岱
+诺
+脍
+榈
+埂
+征
+冷
+裁
+打
+蹴
+素
+瘘
+逞
+蛐
+聊
+激
+腱
+萘
+踵
+飒
+蓟
+吆
+取
+咙
+簋
+涓
+矩
+曝
+挺
+揣
+座
+你
+史
+舵
+焱
+尘
+苏
+笈
+脚
+溉
+榨
+诵
+樊
+邓
+焊
+义
+庶
+儋
+蟋
+蒲
+赦
+呷
+杞
+诠
+豪
+还
+试
+颓
+茉
+太
+除
+紫
+逃
+痴
+草
+充
+鳕
+珉
+祗
+墨
+渭
+烩
+蘸
+慕
+璇
+镶
+穴
+嵘
+恶
+骂
+险
+绋
+幕
+碉
+肺
+戳
+刘
+潞
+秣
+纾
+潜
+銮
+洛
+须
+罘
+销
+瘪
+汞
+兮
+屉
+r
+林
+厕
+质
+探
+划
+狸
+殚
+善
+煊
+烹
+〒
+锈
+逯
+宸
+辍
+泱
+柚
+袍
+远
+蹋
+嶙
+绝
+峥
+娥
+缍
+雀
+徵
+认
+镱
+谷
+=
+贩
+勉
+撩
+鄯
+斐
+洋
+非
+祚
+泾
+诒
+饿
+撬
+威
+晷
+搭
+芍
+锥
+笺
+蓦
+候
+琊
+档
+礁
+沼
+卵
+荠
+忑
+朝
+凹
+瑞
+头
+仪
+弧
+孵
+畏
+铆
+突
+衲
+车
+浩
+气
+茂
+悖
+厢
+枕
+酝
+戴
+湾
+邹
+飚
+攘
+锂
+写
+宵
+翁
+岷
+无
+喜
+丈
+挑
+嗟
+绛
+殉
+议
+槽
+具
+醇
+淞
+笃
+郴
+阅
+饼
+底
+壕
+砚
+弈
+询
+缕
+庹
+翟
+零
+筷
+暨
+舟
+闺
+甯
+撞
+麂
+茌
+蔼
+很
+珲
+捕
+棠
+角
+阉
+媛
+娲
+诽
+剿
+尉
+爵
+睬
+韩
+诰
+匣
+危
+糍
+镯
+立
+浏
+阳
+少
+盆
+舔
+擘
+匪
+申
+尬
+铣
+旯
+抖
+赘
+瓯
+居
+哮
+游
+锭
+茏
+歌
+坏
+甚
+秒
+舞
+沙
+仗
+劲
+潺
+阿
+燧
+郭
+嗖
+霏
+忠
+材
+奂
+耐
+跺
+砀
+输
+岖
+媳
+氟
+极
+摆
+灿
+今
+扔
+腻
+枝
+奎
+药
+熄
+吨
+话
+q
+额
+慑
+嘌
+协
+喀
+壳
+埭
+视
+著
+於
+愧
+陲
+翌
+峁
+颅
+佛
+腹
+聋
+侯
+咎
+叟
+秀
+颇
+存
+较
+罪
+哄
+岗
+扫
+栏
+钾
+羌
+己
+璨
+枭
+霉
+煌
+涸
+衿
+键
+镝
+益
+岢
+奏
+连
+夯
+睿
+冥
+均
+糖
+狞
+蹊
+稻
+爸
+刿
+胥
+煜
+丽
+肿
+璃
+掸
+跚
+灾
+垂
+樾
+濑
+乎
+莲
+窄
+犹
+撮
+战
+馄
+软
+络
+显
+鸢
+胸
+宾
+妲
+恕
+埔
+蝌
+份
+遇
+巧
+瞟
+粒
+恰
+剥
+桡
+博
+讯
+凯
+堇
+阶
+滤
+卖
+斌
+骚
+彬
+兑
+磺
+樱
+舷
+两
+娱
+福
+仃
+差
+找
+桁
+净
+把
+阴
+污
+戬
+雷
+碓
+蕲
+楚
+罡
+焖
+抽
+妫
+咒
+仑
+闱
+尽
+邑
+菁
+爱
+贷
+沥
+鞑
+牡
+嗉
+崴
+骤
+塌
+嗦
+订
+拮
+滓
+捡
+锻
+次
+坪
+杩
+臃
+箬
+融
+珂
+鹗
+宗
+枚
+降
+鸬
+妯
+阄
+堰
+盐
+毅
+必
+杨
+崃
+俺
+甬
+状
+莘
+货
+耸
+菱
+腼
+铸
+唏
+痤
+孚
+澳
+懒
+溅
+翘
+疙
+杷
+淼
+缙
+骰
+喊
+悉
+砻
+坷
+艇
+赁
+界
+谤
+纣
+宴
+晃
+茹
+归
+饭
+梢
+铡
+街
+抄
+肼
+鬟
+苯
+颂
+撷
+戈
+炒
+咆
+茭
+瘙
+负
+仰
+客
+琉
+铢
+封
+卑
+珥
+椿
+镧
+窨
+鬲
+寿
+御
+袤
+铃
+萎
+砖
+餮
+脒
+裳
+肪
+孕
+嫣
+馗
+嵇
+恳
+氯
+江
+石
+褶
+冢
+祸
+阻
+狈
+羞
+银
+靳
+透
+咳
+叼
+敷
+芷
+啥
+它
+瓤
+兰
+痘
+懊
+逑
+肌
+往
+捺
+坊
+甩
+呻
+〃
+沦
+忘
+膻
+祟
+菅
+剧
+崆
+智
+坯
+臧
+霍
+墅
+攻
+眯
+倘
+拢
+骠
+铐
+庭
+岙
+瓠
+′
+缺
+泥
+迢
+捶
+?
+?
+郏
+喙
+掷
+沌
+纯
+秘
+种
+听
+绘
+固
+螨
+团
+香
+盗
+妒
+埚
+蓝
+拖
+旱
+荞
+铀
+血
+遏
+汲
+辰
+叩
+拽
+幅
+硬
+惶
+桀
+漠
+措
+泼
+唑
+齐
+肾
+念
+酱
+虚
+屁
+耶
+旗
+砦
+闵
+婉
+馆
+拭
+绅
+韧
+忏
+窝
+醋
+葺
+顾
+辞
+倜
+堆
+辋
+逆
+玟
+贱
+疾
+董
+惘
+倌
+锕
+淘
+嘀
+莽
+俭
+笏
+绑
+鲷
+杈
+择
+蟀
+粥
+嗯
+驰
+逾
+案
+谪
+褓
+胫
+哩
+昕
+颚
+鲢
+绠
+躺
+鹄
+崂
+儒
+俨
+丝
+尕
+泌
+啊
+萸
+彰
+幺
+吟
+骄
+苣
+弦
+脊
+瑰
+〈
+诛
+镁
+析
+闪
+剪
+侧
+哟
+框
+螃
+守
+嬗
+燕
+狭
+铈
+缮
+概
+迳
+痧
+鲲
+俯
+售
+笼
+痣
+扉
+挖
+满
+咋
+援
+邱
+扇
+歪
+便
+玑
+绦
+峡
+蛇
+叨
+〖
+泽
+胃
+斓
+喋
+怂
+坟
+猪
+该
+蚬
+炕
+弥
+赞
+棣
+晔
+娠
+挲
+狡
+创
+疖
+铕
+镭
+稷
+挫
+弭
+啾
+翔
+粉
+履
+苘
+哦
+楼
+秕
+铂
+土
+锣
+瘟
+挣
+栉
+习
+享
+桢
+袅
+磨
+桂
+谦
+延
+坚
+蔚
+噗
+署
+谟
+猬
+钎
+恐
+嬉
+雒
+倦
+衅
+亏
+璩
+睹
+刻
+殿
+王
+算
+雕
+麻
+丘
+柯
+骆
+丸
+塍
+谚
+添
+鲈
+垓
+桎
+蚯
+芥
+予
+飕
+镦
+谌
+窗
+醚
+菀
+亮
+搪
+莺
+蒿
+羁
+足
+J
+真
+轶
+悬
+衷
+靛
+翊
+掩
+哒
+炅
+掐
+冼
+妮
+l
+谐
+稚
+荆
+擒
+犯
+陵
+虏
+浓
+崽
+刍
+陌
+傻
+孜
+千
+靖
+演
+矜
+钕
+煽
+杰
+酗
+渗
+伞
+栋
+俗
+泫
+戍
+罕
+沾
+疽
+灏
+煦
+芬
+磴
+叱
+阱
+榉
+湃
+蜀
+叉
+醒
+彪
+租
+郡
+篷
+屎
+良
+垢
+隗
+弱
+陨
+峪
+砷
+掴
+颁
+胎
+雯
+绵
+贬
+沐
+撵
+隘
+篙
+暖
+曹
+陡
+栓
+填
+臼
+彦
+瓶
+琪
+潼
+哪
+鸡
+摩
+啦
+俟
+锋
+域
+耻
+蔫
+疯
+纹
+撇
+毒
+绶
+痛
+酯
+忍
+爪
+赳
+歆
+嘹
+辕
+烈
+册
+朴
+钱
+吮
+毯
+癜
+娃
+谀
+邵
+厮
+炽
+璞
+邃
+丐
+追
+词
+瓒
+忆
+轧
+芫
+谯
+喷
+弟
+半
+冕
+裙
+掖
+墉
+绮
+寝
+苔
+势
+顷
+褥
+切
+衮
+君
+佳
+嫒
+蚩
+霞
+佚
+洙
+逊
+镖
+暹
+唛
+&
+殒
+顶
+碗
+獗
+轭
+铺
+蛊
+废
+恹
+汨
+崩
+珍
+那
+杵
+曲
+纺
+夏
+薰
+傀
+闳
+淬
+姘
+舀
+拧
+卷
+楂
+恍
+讪
+厩
+寮
+篪
+赓
+乘
+灭
+盅
+鞣
+沟
+慎
+挂
+饺
+鼾
+杳
+树
+缨
+丛
+絮
+娌
+臻
+嗳
+篡
+侩
+述
+衰
+矛
+圈
+蚜
+匕
+筹
+匿
+濞
+晨
+叶
+骋
+郝
+挚
+蚴
+滞
+增
+侍
+描
+瓣
+吖
+嫦
+蟒
+匾
+圣
+赌
+毡
+癞
+恺
+百
+曳
+需
+篓
+肮
+庖
+帏
+卿
+驿
+遗
+蹬
+鬓
+骡
+歉
+芎
+胳
+屐
+禽
+烦
+晌
+寄
+媾
+狄
+翡
+苒
+船
+廉
+终
+痞
+殇
+々
+畦
+饶
+改
+拆
+悻
+萄
+£
+瓿
+乃
+訾
+桅
+匮
+溧
+拥
+纱
+铍
+骗
+蕃
+龋
+缬
+父
+佐
+疚
+栎
+醍
+掳
+蓄
+x
+惆
+颜
+鲆
+榆
+〔
+猎
+敌
+暴
+谥
+鲫
+贾
+罗
+玻
+缄
+扦
+芪
+癣
+落
+徒
+臾
+恿
+猩
+托
+邴
+肄
+牵
+春
+陛
+耀
+刊
+拓
+蓓
+邳
+堕
+寇
+枉
+淌
+啡
+湄
+兽
+酷
+萼
+碚
+濠
+萤
+夹
+旬
+戮
+梭
+琥
+椭
+昔
+勺
+蜊
+绐
+晚
+孺
+僵
+宣
+摄
+冽
+旨
+萌
+忙
+蚤
+眉
+噼
+蟑
+付
+契
+瓜
+悼
+颡
+壁
+曾
+窕
+颢
+澎
+仿
+俑
+浑
+嵌
+浣
+乍
+碌
+褪
+乱
+蔟
+隙
+玩
+剐
+葫
+箫
+纲
+围
+伐
+决
+伙
+漩
+瑟
+刑
+肓
+镳
+缓
+蹭
+氨
+皓
+典
+畲
+坍
+铑
+檐
+塑
+洞
+倬
+储
+胴
+淳
+戾
+吐
+灼
+惺
+妙
+毕
+珐
+缈
+虱
+盖
+羰
+鸿
+磅
+谓
+髅
+娴
+苴
+唷
+蚣
+霹
+抨
+贤
+唠
+犬
+誓
+逍
+庠
+逼
+麓
+籼
+釉
+呜
+碧
+秧
+氩
+摔
+霄
+穸
+纨
+辟
+妈
+映
+完
+牛
+缴
+嗷
+炊
+恩
+荔
+茆
+掉
+紊
+慌
+莓
+羟
+阙
+萁
+磐
+另
+蕹
+辱
+鳐
+湮
+吡
+吩
+唐
+睦
+垠
+舒
+圜
+冗
+瞿
+溺
+芾
+囱
+匠
+僳
+汐
+菩
+饬
+漓
+黑
+霰
+浸
+濡
+窥
+毂
+蒡
+兢
+驻
+鹉
+芮
+诙
+迫
+雳
+厂
+忐
+臆
+猴
+鸣
+蚪
+栈
+箕
+羡
+渐
+莆
+捍
+眈
+哓
+趴
+蹼
+埕
+嚣
+骛
+宏
+淄
+斑
+噜
+严
+瑛
+垃
+椎
+诱
+压
+庾
+绞
+焘
+廿
+抡
+迄
+棘
+夫
+纬
+锹
+眨
+瞌
+侠
+脐
+竞
+瀑
+孳
+骧
+遁
+姜
+颦
+荪
+滚
+萦
+伪
+逸
+粳
+爬
+锁
+矣
+役
+趣
+洒
+颔
+诏
+逐
+奸
+甭
+惠
+攀
+蹄
+泛
+尼
+拼
+阮
+鹰
+亚
+颈
+惑
+勒
+〉
+际
+肛
+爷
+刚
+钨
+丰
+养
+冶
+鲽
+辉
+蔻
+画
+覆
+皴
+妊
+麦
+返
+醉
+皂
+擀
+〗
+酶
+凑
+粹
+悟
+诀
+硖
+港
+卜
+z
+杀
+涕
+舍
+铠
+抵
+弛
+段
+敝
+镐
+奠
+拂
+轴
+跛
+袱
+e
+t
+沉
+菇
+俎
+薪
+峦
+秭
+蟹
+历
+盟
+菠
+寡
+液
+肢
+喻
+染
+裱
+悱
+抱
+氙
+赤
+捅
+猛
+跑
+氮
+谣
+仁
+尺
+辊
+窍
+烙
+衍
+架
+擦
+倏
+璐
+瑁
+币
+楞
+胖
+夔
+趸
+邛
+惴
+饕
+虔
+蝎
+哉
+贝
+宽
+辫
+炮
+扩
+饲
+籽
+魏
+菟
+锰
+伍
+猝
+末
+琳
+哚
+蛎
+邂
+呀
+姿
+鄞
+却
+歧
+仙
+恸
+椐
+森
+牒
+寤
+袒
+婆
+虢
+雅
+钉
+朵
+贼
+欲
+苞
+寰
+故
+龚
+坭
+嘘
+咫
+礼
+硷
+兀
+睢
+汶
+’
+铲
+烧
+绕
+诃
+浃
+钿
+哺
+柜
+讼
+颊
+璁
+腔
+洽
+咐
+脲
+簌
+筠
+镣
+玮
+鞠
+谁
+兼
+姆
+挥
+梯
+蝴
+谘
+漕
+刷
+躏
+宦
+弼
+b
+垌
+劈
+麟
+莉
+揭
+笙
+渎
+仕
+嗤
+仓
+配
+怏
+抬
+错
+泯
+镊
+孰
+猿
+邪
+仍
+秋
+鼬
+壹
+歇
+吵
+炼
+<
+尧
+射
+柬
+廷
+胧
+霾
+凳
+隋
+肚
+浮
+梦
+祥
+株
+堵
+退
+L
+鹫
+跎
+凶
+毽
+荟
+炫
+栩
+玳
+甜
+沂
+鹿
+顽
+伯
+爹
+赔
+蛴
+徐
+匡
+欣
+狰
+缸
+雹
+蟆
+疤
+默
+沤
+啜
+痂
+衣
+禅
+w
+i
+h
+辽
+葳
+黝
+钗
+停
+沽
+棒
+馨
+颌
+肉
+吴
+硫
+悯
+劾
+娈
+马
+啧
+吊
+悌
+镑
+峭
+帆
+瀣
+涉
+咸
+疸
+滋
+泣
+翦
+拙
+癸
+钥
+蜒
++
+尾
+庄
+凝
+泉
+婢
+渴
+谊
+乞
+陆
+锉
+糊
+鸦
+淮
+I
+B
+N
+晦
+弗
+乔
+庥
+葡
+尻
+席
+橡
+傣
+渣
+拿
+惩
+麋
+斛
+缃
+矮
+蛏
+岘
+鸽
+姐
+膏
+催
+奔
+镒
+喱
+蠡
+摧
+钯
+胤
+柠
+拐
+璋
+鸥
+卢
+荡
+倾
+^
+_
+珀
+逄
+萧
+塾
+掇
+贮
+笆
+聂
+圃
+冲
+嵬
+M
+滔
+笕
+值
+炙
+偶
+蜱
+搐
+梆
+汪
+蔬
+腑
+鸯
+蹇
+敞
+绯
+仨
+祯
+谆
+梧
+糗
+鑫
+啸
+豺
+囹
+猾
+巢
+柄
+瀛
+筑
+踌
+沭
+暗
+苁
+鱿
+蹉
+脂
+蘖
+牢
+热
+木
+吸
+溃
+宠
+序
+泞
+偿
+拜
+檩
+厚
+朐
+毗
+螳
+吞
+媚
+朽
+担
+蝗
+橘
+畴
+祈
+糟
+盱
+隼
+郜
+惜
+珠
+裨
+铵
+焙
+琚
+唯
+咚
+噪
+骊
+丫
+滢
+勤
+棉
+呸
+咣
+淀
+隔
+蕾
+窈
+饨
+挨
+煅
+短
+匙
+粕
+镜
+赣
+撕
+墩
+酬
+馁
+豌
+颐
+抗
+酣
+氓
+佑
+搁
+哭
+递
+耷
+涡
+桃
+贻
+碣
+截
+瘦
+昭
+镌
+蔓
+氚
+甲
+猕
+蕴
+蓬
+散
+拾
+纛
+狼
+猷
+铎
+埋
+旖
+矾
+讳
+囊
+糜
+迈
+粟
+蚂
+紧
+鲳
+瘢
+栽
+稼
+羊
+锄
+斟
+睁
+桥
+瓮
+蹙
+祉
+醺
+鼻
+昱
+剃
+跳
+篱
+跷
+蒜
+翎
+宅
+晖
+嗑
+壑
+峻
+癫
+屏
+狠
+陋
+袜
+途
+憎
+祀
+莹
+滟
+佶
+溥
+臣
+约
+盛
+峰
+磁
+慵
+婪
+拦
+莅
+朕
+鹦
+粲
+裤
+哎
+疡
+嫖
+琵
+窟
+堪
+谛
+嘉
+儡
+鳝
+斩
+郾
+驸
+酊
+妄
+胜
+贺
+徙
+傅
+噌
+钢
+栅
+庇
+恋
+匝
+巯
+邈
+尸
+锚
+粗
+佟
+蛟
+薹
+纵
+蚊
+郅
+绢
+锐
+苗
+俞
+篆
+淆
+膀
+鲜
+煎
+诶
+秽
+寻
+涮
+刺
+怀
+噶
+巨
+褰
+魅
+灶
+灌
+桉
+藕
+谜
+舸
+薄
+搀
+恽
+借
+牯
+痉
+渥
+愿
+亓
+耘
+杠
+柩
+锔
+蚶
+钣
+珈
+喘
+蹒
+幽
+赐
+稗
+晤
+莱
+泔
+扯
+肯
+菪
+裆
+腩
+豉
+疆
+骜
+腐
+倭
+珏
+唔
+粮
+亡
+润
+慰
+伽
+橄
+玄
+誉
+醐
+胆
+龊
+粼
+塬
+陇
+彼
+削
+嗣
+绾
+芽
+妗
+垭
+瘴
+爽
+薏
+寨
+龈
+泠
+弹
+赢
+漪
+猫
+嘧
+涂
+恤
+圭
+茧
+烽
+屑
+痕
+巾
+赖
+荸
+凰
+腮
+畈
+亵
+蹲
+偃
+苇
+澜
+艮
+换
+骺
+烘
+苕
+梓
+颉
+肇
+哗
+悄
+氤
+涠
+葬
+屠
+鹭
+植
+竺
+佯
+诣
+鲇
+瘀
+鲅
+邦
+移
+滁
+冯
+耕
+癔
+戌
+茬
+沁
+巩
+悠
+湘
+洪
+痹
+锟
+循
+谋
+腕
+鳃
+钠
+捞
+焉
+迎
+碱
+伫
+急
+榷
+奈
+邝
+卯
+辄
+皲
+卟
+醛
+畹
+忧
+稳
+雄
+昼
+缩
+阈
+睑
+扌
+耗
+曦
+涅
+捏
+瞧
+邕
+淖
+漉
+铝
+耦
+禹
+湛
+喽
+莼
+琅
+诸
+苎
+纂
+硅
+始
+嗨
+傥
+燃
+臂
+赅
+嘈
+呆
+贵
+屹
+壮
+肋
+亍
+蚀
+卅
+豹
+腆
+邬
+迭
+浊
+}
+童
+螂
+捐
+圩
+勐
+触
+寞
+汊
+壤
+荫
+膺
+渌
+芳
+懿
+遴
+螈
+泰
+蓼
+蛤
+茜
+舅
+枫
+朔
+膝
+眙
+避
+梅
+判
+鹜
+璜
+牍
+缅
+垫
+藻
+黔
+侥
+惚
+懂
+踩
+腰
+腈
+札
+丞
+唾
+慈
+顿
+摹
+荻
+琬
+~
+斧
+沈
+滂
+胁
+胀
+幄
+莜
+Z
+匀
+鄄
+掌
+绰
+茎
+焚
+赋
+萱
+谑
+汁
+铒
+瞎
+夺
+蜗
+野
+娆
+冀
+弯
+篁
+懵
+灞
+隽
+芡
+脘
+俐
+辩
+芯
+掺
+喏
+膈
+蝈
+觐
+悚
+踹
+蔗
+熠
+鼠
+呵
+抓
+橼
+峨
+畜
+缔
+禾
+崭
+弃
+熊
+摒
+凸
+拗
+穹
+蒙
+抒
+祛
+劝
+闫
+扳
+阵
+醌
+踪
+喵
+侣
+搬
+仅
+荧
+赎
+蝾
+琦
+买
+婧
+瞄
+寓
+皎
+冻
+赝
+箩
+莫
+瞰
+郊
+笫
+姝
+筒
+枪
+遣
+煸
+袋
+舆
+痱
+涛
+母
+〇
+启
+践
+耙
+绲
+盘
+遂
+昊
+搞
+槿
+诬
+纰
+泓
+惨
+檬
+亻
+越
+C
+o
+憩
+熵
+祷
+钒
+暧
+塔
+阗
+胰
+咄
+娶
+魔
+琶
+钞
+邻
+扬
+杉
+殴
+咽
+弓
+〆
+髻
+】
+吭
+揽
+霆
+拄
+殖
+脆
+彻
+岩
+芝
+勃
+辣
+剌
+钝
+嘎
+甄
+佘
+皖
+伦
+授
+徕
+憔
+挪
+皇
+庞
+稔
+芜
+踏
+溴
+兖
+卒
+擢
+饥
+鳞
+煲
+‰
+账
+颗
+叻
+斯
+捧
+鳍
+琮
+讹
+蛙
+纽
+谭
+酸
+兔
+莒
+睇
+伟
+觑
+羲
+嗜
+宜
+褐
+旎
+辛
+卦
+诘
+筋
+鎏
+溪
+挛
+熔
+阜
+晰
+鳅
+丢
+奚
+灸
+呱
+献
+陉
+黛
+鸪
+甾
+萨
+疮
+拯
+洲
+疹
+辑
+叙
+恻
+谒
+允
+柔
+烂
+氏
+逅
+漆
+拎
+惋
+扈
+湟
+纭
+啕
+掬
+擞
+哥
+忽
+涤
+鸵
+靡
+郗
+瓷
+扁
+廊
+怨
+雏
+钮
+敦
+E
+懦
+憋
+汀
+拚
+啉
+腌
+岸
+f
+痼
+瞅
+尊
+咀
+眩
+飙
+忌
+仝
+迦
+熬
+毫
+胯
+篑
+茄
+腺
+凄
+舛
+碴
+锵
+诧
+羯
+後
+漏
+汤
+宓
+仞
+蚁
+壶
+谰
+皑
+铄
+棰
+罔
+辅
+晶
+苦
+牟
+闽
+\
+烃
+饮
+聿
+丙
+蛳
+朱
+煤
+涔
+鳖
+犁
+罐
+荼
+砒
+淦
+妤
+黏
+戎
+孑
+婕
+瑾
+戢
+钵
+枣
+捋
+砥
+衩
+狙
+桠
+稣
+阎
+肃
+梏
+诫
+孪
+昶
+婊
+衫
+嗔
+侃
+塞
+蜃
+樵
+峒
+貌
+屿
+欺
+缫
+阐
+栖
+诟
+珞
+荭
+吝
+萍
+嗽
+恂
+啻
+蜴
+磬
+峋
+俸
+豫
+谎
+徊
+镍
+韬
+魇
+晴
+U
+囟
+猜
+蛮
+坐
+囿
+伴
+亭
+肝
+佗
+蝠
+妃
+胞
+滩
+榴
+氖
+垩
+苋
+砣
+扪
+馏
+姓
+轩
+厉
+夥
+侈
+禀
+垒
+岑
+赏
+钛
+辐
+痔
+披
+纸
+碳
+“
+坞
+蠓
+挤
+荥
+沅
+悔
+铧
+帼
+蒌
+蝇
+a
+p
+y
+n
+g
+哀
+浆
+瑶
+凿
+桶
+馈
+皮
+奴
+苜
+佤
+伶
+晗
+铱
+炬
+优
+弊
+氢
+恃
+甫
+攥
+端
+锌
+灰
+稹
+炝
+曙
+邋
+亥
+眶
+碾
+拉
+萝
+绔
+捷
+浍
+腋
+姑
+菖
+凌
+涞
+麽
+锢
+桨
+潢
+绎
+镰
+殆
+锑
+渝
+铬
+困
+绽
+觎
+匈
+糙
+暑
+裹
+鸟
+盔
+肽
+迷
+綦
+『
+亳
+佝
+俘
+钴
+觇
+骥
+仆
+疝
+跪
+婶
+郯
+瀹
+唉
+脖
+踞
+针
+晾
+忒
+扼
+瞩
+叛
+椒
+疟
+嗡
+邗
+肆
+跆
+玫
+忡
+捣
+咧
+唆
+艄
+蘑
+潦
+笛
+阚
+沸
+泻
+掊
+菽
+贫
+斥
+髂
+孢
+镂
+赂
+麝
+鸾
+屡
+衬
+苷
+恪
+叠
+希
+粤
+爻
+喝
+茫
+惬
+郸
+绻
+庸
+撅
+碟
+宄
+妹
+膛
+叮
+饵
+崛
+嗲
+椅
+冤
+搅
+咕
+敛
+尹
+垦
+闷
+蝉
+霎
+勰
+败
+蓑
+泸
+肤
+鹌
+幌
+焦
+浠
+鞍
+刁
+舰
+乙
+竿
+裔
+。
+茵
+函
+伊
+兄
+丨
+娜
+匍
+謇
+莪
+宥
+似
+蝽
+翳
+酪
+翠
+粑
+薇
+祢
+骏
+赠
+叫
+Q
+噤
+噻
+竖
+芗
+莠
+潭
+俊
+羿
+耜
+O
+郫
+趁
+嗪
+囚
+蹶
+芒
+洁
+笋
+鹑
+敲
+硝
+啶
+堡
+渲
+揩
+』
+携
+宿
+遒
+颍
+扭
+棱
+割
+萜
+蔸
+葵
+琴
+捂
+饰
+衙
+耿
+掠
+募
+岂
+窖
+涟
+蔺
+瘤
+柞
+瞪
+怜
+匹
+距
+楔
+炜
+哆
+秦
+缎
+幼
+茁
+绪
+痨
+恨
+楸
+娅
+瓦
+桩
+雪
+嬴
+伏
+榔
+妥
+铿
+拌
+眠
+雍
+缇
+‘
+卓
+搓
+哌
+觞
+噩
+屈
+哧
+髓
+咦
+巅
+娑
+侑
+淫
+膳
+祝
+勾
+姊
+莴
+胄
+疃
+薛
+蜷
+胛
+巷
+芙
+芋
+熙
+闰
+勿
+窃
+狱
+剩
+钏
+幢
+陟
+铛
+慧
+靴
+耍
+k
+浙
+浇
+飨
+惟
+绗
+祜
+澈
+啼
+咪
+磷
+摞
+诅
+郦
+抹
+跃
+壬
+吕
+肖
+琏
+颤
+尴
+剡
+抠
+凋
+赚
+泊
+津
+宕
+殷
+倔
+氲
+漫
+邺
+涎
+怠
+$
+垮
+荬
+遵
+俏
+叹
+噢
+饽
+蜘
+孙
+筵
+疼
+鞭
+羧
+牦
+箭
+潴
+c
+眸
+祭
+髯
+啖
+坳
+愁
+芩
+驮
+倡
+巽
+穰
+沃
+胚
+怒
+凤
+槛
+剂
+趵
+嫁
+v
+邢
+灯
+鄢
+桐
+睽
+檗
+锯
+槟
+婷
+嵋
+圻
+诗
+蕈
+颠
+遭
+痢
+芸
+怯
+馥
+竭
+锗
+徜
+恭
+遍
+籁
+剑
+嘱
+苡
+龄
+僧
+桑
+潸
+弘
+澶
+楹
+悲
+讫
+愤
+腥
+悸
+谍
+椹
+呢
+桓
+葭
+攫
+阀
+翰
+躲
+敖
+柑
+郎
+笨
+橇
+呃
+魁
+燎
+脓
+葩
+磋
+垛
+玺
+狮
+沓
+砜
+蕊
+锺
+罹
+蕉
+翱
+虐
+闾
+巫
+旦
+茱
+嬷
+枯
+鹏
+贡
+芹
+汛
+矫
+绁
+拣
+禺
+佃
+讣
+舫
+惯
+乳
+趋
+疲
+挽
+岚
+虾
+衾
+蠹
+蹂
+飓
+氦
+铖
+孩
+稞
+瑜
+壅
+掀
+勘
+妓
+畅
+髋
+W
+庐
+牲
+蓿
+榕
+练
+垣
+唱
+邸
+菲
+昆
+婺
+穿
+绡
+麒
+蚱
+掂
+愚
+泷
+涪
+漳
+妩
+娉
+榄
+讷
+觅
+旧
+藤
+煮
+呛
+柳
+腓
+叭
+庵
+烷
+阡
+罂
+蜕
+擂
+猖
+咿
+媲
+脉
+【
+沏
+貅
+黠
+熏
+哲
+烁
+坦
+酵
+兜
+潇
+撒
+剽
+珩
+圹
+乾
+摸
+樟
+帽
+嗒
+襄
+魂
+轿
+憬
+锡
+〕
+喃
+皆
+咖
+隅
+脸
+残
+泮
+袂
+鹂
+珊
+囤
+捆
+咤
+误
+徨
+闹
+淙
+芊
+淋
+怆
+囗
+拨
+梳
+渤
+R
+G
+绨
+蚓
+婀
+幡
+狩
+麾
+谢
+唢
+裸
+旌
+伉
+纶
+裂
+驳
+砼
+咛
+澄
+樨
+蹈
+宙
+澍
+倍
+貔
+操
+勇
+蟠
+摈
+砧
+虬
+够
+缁
+悦
+藿
+撸
+艹
+摁
+淹
+豇
+虎
+榭
+吱
+d
+喧
+荀
+踱
+侮
+奋
+偕
+饷
+犍
+惮
+坑
+璎
+徘
+宛
+妆
+袈
+倩
+窦
+昂
+荏
+乖
+K
+怅
+撰
+鳙
+牙
+袁
+酞
+X
+痿
+琼
+闸
+雁
+趾
+荚
+虻
+涝
+《
+杏
+韭
+偈
+烤
+绫
+鞘
+卉
+症
+遢
+蓥
+诋
+杭
+荨
+匆
+竣
+簪
+辙
+敕
+虞
+丹
+缭
+咩
+黟
+m
+淤
+瑕
+咂
+铉
+硼
+茨
+嶂
+痒
+畸
+敬
+涿
+粪
+窘
+熟
+叔
+嫔
+盾
+忱
+裘
+憾
+梵
+赡
+珙
+咯
+娘
+庙
+溯
+胺
+葱
+痪
+摊
+荷
+卞
+乒
+髦
+寐
+铭
+坩
+胗
+枷
+爆
+溟
+嚼
+羚
+砬
+轨
+惊
+挠
+罄
+竽
+菏
+氧
+浅
+楣
+盼
+枢
+炸
+阆
+杯
+谏
+噬
+淇
+渺
+俪
+秆
+墓
+泪
+跻
+砌
+痰
+垡
+渡
+耽
+釜
+讶
+鳎
+煞
+呗
+韶
+舶
+绷
+鹳
+缜
+旷
+铊
+皱
+龌
+檀
+霖
+奄
+槐
+艳
+蝶
+旋
+哝
+赶
+骞
+蚧
+腊
+盈
+丁
+`
+蜚
+矸
+蝙
+睨
+嚓
+僻
+鬼
+醴
+夜
+彝
+磊
+笔
+拔
+栀
+糕
+厦
+邰
+纫
+逭
+纤
+眦
+膊
+馍
+躇
+烯
+蘼
+冬
+诤
+暄
+骶
+哑
+瘠
+」
+臊
+丕
+愈
+咱
+螺
+擅
+跋
+搏
+硪
+谄
+笠
+淡
+嘿
+骅
+谧
+鼎
+皋
+姚
+歼
+蠢
+驼
+耳
+胬
+挝
+涯
+狗
+蒽
+孓
+犷
+凉
+芦
+箴
+铤
+孤
+嘛
+坤
+V
+茴
+朦
+挞
+尖
+橙
+诞
+搴
+碇
+洵
+浚
+帚
+蜍
+漯
+柘
+嚎
+讽
+芭
+荤
+咻
+祠
+秉
+跖
+埃
+吓
+糯
+眷
+馒
+惹
+娼
+鲑
+嫩
+讴
+轮
+瞥
+靶
+褚
+乏
+缤
+宋
+帧
+删
+驱
+碎
+扑
+俩
+俄
+偏
+涣
+竹
+噱
+皙
+佰
+渚
+唧
+斡
+#
+镉
+刀
+崎
+筐
+佣
+夭
+贰
+肴
+峙
+哔
+艿
+匐
+牺
+镛
+缘
+仡
+嫡
+劣
+枸
+堀
+梨
+簿
+鸭
+蒸
+亦
+稽
+浴
+{
+衢
+束
+槲
+j
+阁
+揍
+疥
+棋
+潋
+聪
+窜
+乓
+睛
+插
+冉
+阪
+苍
+搽
+「
+蟾
+螟
+幸
+仇
+樽
+撂
+慢
+跤
+幔
+俚
+淅
+覃
+觊
+溶
+妖
+帛
+侨
+曰
+妾
+泗
+:
+瀘
+風
+(
+)
+∶
+紅
+紗
+瑭
+雲
+頭
+鶏
+財
+許
+•
+樂
+焗
+麗
+—
+;
+滙
+東
+榮
+繪
+興
+…
+門
+業
+楊
+國
+顧
+盤
+寳
+龍
+鳳
+島
+誌
+緣
+結
+銭
+萬
+勝
+祎
+璟
+優
+歡
+臨
+時
+購
+=
+★
+藍
+昇
+鐵
+觀
+勅
+農
+聲
+畫
+兿
+術
+發
+劉
+記
+專
+耑
+園
+書
+壴
+種
+●
+褀
+號
+銀
+匯
+敟
+锘
+葉
+橪
+廣
+進
+蒄
+鑽
+阝
+祙
+貢
+鍋
+豊
+夬
+喆
+團
+閣
+開
+燁
+賓
+館
+酡
+沔
+順
++
+硚
+劵
+饸
+陽
+車
+湓
+復
+萊
+氣
+軒
+華
+堃
+迮
+纟
+戶
+馬
+學
+裡
+電
+嶽
+獨
+マ
+シ
+サ
+ジ
+燘
+袪
+環
+❤
+臺
+灣
+専
+賣
+孖
+聖
+攝
+線
+▪
+傢
+俬
+夢
+達
+莊
+喬
+貝
+薩
+劍
+羅
+壓
+棛
+饦
+尃
+璈
+囍
+醫
+G
+I
+A
+#
+N
+鷄
+髙
+嬰
+啓
+約
+隹
+潔
+賴
+藝
+~
+寶
+籣
+麺
+ 
+嶺
+√
+義
+網
+峩
+長
+∧
+魚
+機
+構
+②
+鳯
+偉
+L
+B
+㙟
+畵
+鴿
+'
+詩
+溝
+嚞
+屌
+藔
+佧
+玥
+蘭
+織
+1
+3
+9
+0
+7
+點
+砭
+鴨
+鋪
+銘
+廳
+弍
+‧
+創
+湯
+坶
+℃
+卩
+骝
+&
+烜
+荘
+當
+潤
+扞
+係
+懷
+碶
+钅
+蚨
+讠
+☆
+叢
+爲
+埗
+涫
+塗
+→
+楽
+現
+鯨
+愛
+瑪
+鈺
+忄
+悶
+藥
+飾
+樓
+視
+孬
+ㆍ
+燚
+苪
+師
+①
+丼
+锽
+│
+韓
+標
+兒
+閏
+匋
+張
+漢
+髪
+會
+閑
+檔
+習
+裝
+の
+峯
+菘
+輝
+雞
+釣
+億
+浐
+K
+O
+R
+8
+H
+E
+P
+T
+W
+D
+S
+C
+M
+F
+姌
+饹
+晞
+廰
+嵯
+鷹
+負
+飲
+絲
+冚
+楗
+澤
+綫
+區
+❋
+←
+質
+靑
+揚
+③
+滬
+統
+産
+協
+﹑
+乸
+畐
+經
+運
+際
+洺
+岽
+為
+粵
+諾
+崋
+豐
+碁
+V
+2
+6
+齋
+誠
+訂
+勑
+雙
+陳
+無
+泩
+媄
+夌
+刂
+i
+c
+t
+o
+r
+a
+嘢
+耄
+燴
+暃
+壽
+媽
+靈
+抻
+體
+唻
+冮
+甹
+鎮
+錦
+蜛
+蠄
+尓
+駕
+戀
+飬
+逹
+倫
+貴
+極
+寬
+磚
+嶪
+郎
+職
+|
+間
+n
+d
+剎
+伈
+課
+飛
+橋
+瘊
+№
+譜
+骓
+圗
+滘
+縣
+粿
+咅
+養
+濤
+彳
+%
+Ⅱ
+啰
+㴪
+見
+矞
+薬
+糁
+邨
+鲮
+顔
+罱
+選
+話
+贏
+氪
+俵
+競
+瑩
+繡
+枱
+綉
+獅
+爾
+™
+麵
+戋
+淩
+徳
+個
+劇
+場
+務
+簡
+寵
+h
+實
+膠
+轱
+圖
+築
+嘣
+樹
+㸃
+營
+耵
+孫
+饃
+鄺
+飯
+麯
+遠
+輸
+坫
+孃
+乚
+閃
+鏢
+㎡
+題
+廠
+關
+↑
+爺
+將
+軍
+連
+篦
+覌
+參
+箸
+-
+窠
+棽
+寕
+夀
+爰
+歐
+呙
+閥
+頡
+熱
+雎
+垟
+裟
+凬
+勁
+帑
+馕
+夆
+疌
+枼
+馮
+貨
+蒤
+樸
+彧
+旸
+靜
+龢
+暢
+㐱
+鳥
+珺
+鏡
+灡
+爭
+堷
+廚
+騰
+診
+┅
+蘇
+褔
+凱
+頂
+豕
+亞
+帥
+嘬
+⊥
+仺
+桖
+複
+饣
+絡
+穂
+顏
+棟
+納
+▏
+濟
+親
+設
+計
+攵
+埌
+烺
+頤
+燦
+蓮
+撻
+節
+講
+濱
+濃
+娽
+洳
+朿
+燈
+鈴
+護
+膚
+铔
+過
+補
+Z
+U
+5
+4
+坋
+闿
+䖝
+餘
+缐
+铞
+貿
+铪
+桼
+趙
+鍊
+[
+㐂
+垚
+菓
+揸
+捲
+鐘
+滏
+𣇉
+爍
+輪
+燜
+鴻
+鮮
+動
+鹞
+鷗
+丄
+慶
+鉌
+翥
+飮
+腸
+⇋
+漁
+覺
+來
+熘
+昴
+翏
+鲱
+圧
+鄉
+萭
+頔
+爐
+嫚
+貭
+類
+聯
+幛
+輕
+訓
+鑒
+夋
+锨
+芃
+珣
+䝉
+扙
+嵐
+銷
+處
+ㄱ
+語
+誘
+苝
+歸
+儀
+燒
+楿
+內
+粢
+葒
+奧
+麥
+礻
+滿
+蠔
+穵
+瞭
+態
+鱬
+榞
+硂
+鄭
+黃
+煙
+祐
+奓
+逺
+*
+瑄
+獲
+聞
+薦
+讀
+這
+樣
+決
+問
+啟
+們
+執
+説
+轉
+單
+隨
+唘
+帶
+倉
+庫
+還
+贈
+尙
+皺
+■
+餅
+產
+○
+∈
+報
+狀
+楓
+賠
+琯
+嗮
+禮
+`
+傳
+>
+≤
+嗞
+≥
+換
+咭
+∣
+↓
+曬
+応
+寫
+″
+終
+様
+純
+費
+療
+聨
+凍
+壐
+郵
+黒
+∫
+製
+塊
+調
+軽
+確
+撃
+級
+馴
+Ⅲ
+涇
+繹
+數
+碼
+證
+狒
+処
+劑
+<
+晧
+賀
+衆
+]
+櫥
+兩
+陰
+絶
+對
+鯉
+憶
+◎
+p
+e
+Y
+蕒
+煖
+頓
+測
+試
+鼽
+僑
+碩
+妝
+帯
+≈
+鐡
+舖
+權
+喫
+倆
+該
+悅
+俫
+.
+f
+s
+b
+m
+k
+g
+u
+j
+貼
+淨
+濕
+針
+適
+備
+l
+/
+給
+謢
+強
+觸
+衛
+與
+⊙
+$
+緯
+變
+⑴
+⑵
+⑶
+㎏
+殺
+∩
+幚
+─
+價
+▲
+離
+飄
+烏
+関
+閟
+﹝
+﹞
+邏
+輯
+鍵
+驗
+訣
+導
+歷
+屆
+層
+▼
+儱
+錄
+熳
+艦
+吋
+錶
+辧
+飼
+顯
+④
+禦
+販
+気
+対
+枰
+閩
+紀
+幹
+瞓
+貊
+淚
+△
+眞
+墊
+獻
+褲
+縫
+緑
+亜
+鉅
+餠
+{
+}
+◆
+蘆
+薈
+█
+◇
+溫
+彈
+晳
+粧
+犸
+穩
+訊
+崬
+凖
+熥
+舊
+條
+紋
+圍
+Ⅳ
+筆
+尷
+難
+雜
+錯
+綁
+識
+頰
+鎖
+艶
+□
+殁
+殼
+⑧
+├
+▕
+鵬
+糝
+綱
+▎
+盜
+饅
+醬
+籤
+蓋
+釀
+鹽
+據
+辦
+◥
+彐
+┌
+婦
+獸
+鲩
+伱
+蒟
+蒻
+齊
+袆
+腦
+寧
+凈
+妳
+煥
+詢
+偽
+謹
+啫
+鯽
+騷
+鱸
+損
+傷
+鎻
+髮
+買
+冏
+儥
+両
+﹢
+∞
+載
+喰
+z
+羙
+悵
+燙
+曉
+員
+組
+徹
+艷
+痠
+鋼
+鼙
+縮
+細
+嚒
+爯
+≠
+維
+"
+鱻
+壇
+厍
+帰
+浥
+犇
+薡
+軎
+應
+醜
+刪
+緻
+鶴
+賜
+噁
+軌
+尨
+镔
+鷺
+槗
+彌
+葚
+濛
+請
+溇
+緹
+賢
+訪
+獴
+瑅
+資
+縤
+陣
+蕟
+栢
+韻
+祼
+恁
+伢
+謝
+劃
+涑
+總
+衖
+踺
+砋
+凉
+籃
+駿
+苼
+瘋
+昽
+紡
+驊
+腎
+﹗
+響
+杋
+剛
+嚴
+禪
+歓
+槍
+傘
+檸
+檫
+炣
+勢
+鏜
+鎢
+銑
+尐
+減
+奪
+惡
+僮
+婭
+臘
+殻
+鉄
+∑
+蛲
+焼
+緖
+續
+紹
+懮

+ 6623 - 0
models/ocr/Keys/中文简体_OCRv3.txt

@@ -0,0 +1,6623 @@
+'
+疗
+绚
+诚
+娇
+溜
+题
+贿
+者
+廖
+更
+纳
+加
+奉
+公
+一
+就
+汴
+计
+与
+路
+房
+原
+妇
+2
+0
+8
+-
+7
+其
+>
+:
+]
+,
+,
+骑
+刈
+全
+消
+昏
+傈
+安
+久
+钟
+嗅
+不
+影
+处
+驽
+蜿
+资
+关
+椤
+地
+瘸
+专
+问
+忖
+票
+嫉
+炎
+韵
+要
+月
+田
+节
+陂
+鄙
+捌
+备
+拳
+伺
+眼
+网
+盎
+大
+傍
+心
+东
+愉
+汇
+蹿
+科
+每
+业
+里
+航
+晏
+字
+平
+录
+先
+1
+3
+彤
+鲶
+产
+稍
+督
+腴
+有
+象
+岳
+注
+绍
+在
+泺
+文
+定
+核
+名
+水
+过
+理
+让
+偷
+率
+等
+这
+发
+”
+为
+含
+肥
+酉
+相
+鄱
+七
+编
+猥
+锛
+日
+镀
+蒂
+掰
+倒
+辆
+栾
+栗
+综
+涩
+州
+雌
+滑
+馀
+了
+机
+块
+司
+宰
+甙
+兴
+矽
+抚
+保
+用
+沧
+秩
+如
+收
+息
+滥
+页
+疑
+埠
+!
+!
+姥
+异
+橹
+钇
+向
+下
+跄
+的
+椴
+沫
+国
+绥
+獠
+报
+开
+民
+蜇
+何
+分
+凇
+长
+讥
+藏
+掏
+施
+羽
+中
+讲
+派
+嘟
+人
+提
+浼
+间
+世
+而
+古
+多
+倪
+唇
+饯
+控
+庚
+首
+赛
+蜓
+味
+断
+制
+觉
+技
+替
+艰
+溢
+潮
+夕
+钺
+外
+摘
+枋
+动
+双
+单
+啮
+户
+枇
+确
+锦
+曜
+杜
+或
+能
+效
+霜
+盒
+然
+侗
+电
+晁
+放
+步
+鹃
+新
+杖
+蜂
+吒
+濂
+瞬
+评
+总
+隍
+对
+独
+合
+也
+是
+府
+青
+天
+诲
+墙
+组
+滴
+级
+邀
+帘
+示
+已
+时
+骸
+仄
+泅
+和
+遨
+店
+雇
+疫
+持
+巍
+踮
+境
+只
+亨
+目
+鉴
+崤
+闲
+体
+泄
+杂
+作
+般
+轰
+化
+解
+迂
+诿
+蛭
+璀
+腾
+告
+版
+服
+省
+师
+小
+规
+程
+线
+海
+办
+引
+二
+桧
+牌
+砺
+洄
+裴
+修
+图
+痫
+胡
+许
+犊
+事
+郛
+基
+柴
+呼
+食
+研
+奶
+律
+蛋
+因
+葆
+察
+戏
+褒
+戒
+再
+李
+骁
+工
+貂
+油
+鹅
+章
+啄
+休
+场
+给
+睡
+纷
+豆
+器
+捎
+说
+敏
+学
+会
+浒
+设
+诊
+格
+廓
+查
+来
+霓
+室
+溆
+¢
+诡
+寥
+焕
+舜
+柒
+狐
+回
+戟
+砾
+厄
+实
+翩
+尿
+五
+入
+径
+惭
+喹
+股
+宇
+篝
+|
+;
+美
+期
+云
+九
+祺
+扮
+靠
+锝
+槌
+系
+企
+酰
+阊
+暂
+蚕
+忻
+豁
+本
+羹
+执
+条
+钦
+H
+獒
+限
+进
+季
+楦
+于
+芘
+玖
+铋
+茯
+未
+答
+粘
+括
+样
+精
+欠
+矢
+甥
+帷
+嵩
+扣
+令
+仔
+风
+皈
+行
+支
+部
+蓉
+刮
+站
+蜡
+救
+钊
+汗
+松
+嫌
+成
+可
+.
+鹤
+院
+从
+交
+政
+怕
+活
+调
+球
+局
+验
+髌
+第
+韫
+谗
+串
+到
+圆
+年
+米
+/
+*
+友
+忿
+检
+区
+看
+自
+敢
+刃
+个
+兹
+弄
+流
+留
+同
+没
+齿
+星
+聆
+轼
+湖
+什
+三
+建
+蛔
+儿
+椋
+汕
+震
+颧
+鲤
+跟
+力
+情
+璺
+铨
+陪
+务
+指
+族
+训
+滦
+鄣
+濮
+扒
+商
+箱
+十
+召
+慷
+辗
+所
+莞
+管
+护
+臭
+横
+硒
+嗓
+接
+侦
+六
+露
+党
+馋
+驾
+剖
+高
+侬
+妪
+幂
+猗
+绺
+骐
+央
+酐
+孝
+筝
+课
+徇
+缰
+门
+男
+西
+项
+句
+谙
+瞒
+秃
+篇
+教
+碲
+罚
+声
+呐
+景
+前
+富
+嘴
+鳌
+稀
+免
+朋
+啬
+睐
+去
+赈
+鱼
+住
+肩
+愕
+速
+旁
+波
+厅
+健
+茼
+厥
+鲟
+谅
+投
+攸
+炔
+数
+方
+击
+呋
+谈
+绩
+别
+愫
+僚
+躬
+鹧
+胪
+炳
+招
+喇
+膨
+泵
+蹦
+毛
+结
+5
+4
+谱
+识
+陕
+粽
+婚
+拟
+构
+且
+搜
+任
+潘
+比
+郢
+妨
+醪
+陀
+桔
+碘
+扎
+选
+哈
+骷
+楷
+亿
+明
+缆
+脯
+监
+睫
+逻
+婵
+共
+赴
+淝
+凡
+惦
+及
+达
+揖
+谩
+澹
+减
+焰
+蛹
+番
+祁
+柏
+员
+禄
+怡
+峤
+龙
+白
+叽
+生
+闯
+起
+细
+装
+谕
+竟
+聚
+钙
+上
+导
+渊
+按
+艾
+辘
+挡
+耒
+盹
+饪
+臀
+记
+邮
+蕙
+受
+各
+医
+搂
+普
+滇
+朗
+茸
+带
+翻
+酚
+(
+光
+堤
+墟
+蔷
+万
+幻
+〓
+瑙
+辈
+昧
+盏
+亘
+蛀
+吉
+铰
+请
+子
+假
+闻
+税
+井
+诩
+哨
+嫂
+好
+面
+琐
+校
+馊
+鬣
+缂
+营
+访
+炖
+占
+农
+缀
+否
+经
+钚
+棵
+趟
+张
+亟
+吏
+茶
+谨
+捻
+论
+迸
+堂
+玉
+信
+吧
+瞠
+乡
+姬
+寺
+咬
+溏
+苄
+皿
+意
+赉
+宝
+尔
+钰
+艺
+特
+唳
+踉
+都
+荣
+倚
+登
+荐
+丧
+奇
+涵
+批
+炭
+近
+符
+傩
+感
+道
+着
+菊
+虹
+仲
+众
+懈
+濯
+颞
+眺
+南
+释
+北
+缝
+标
+既
+茗
+整
+撼
+迤
+贲
+挎
+耱
+拒
+某
+妍
+卫
+哇
+英
+矶
+藩
+治
+他
+元
+领
+膜
+遮
+穗
+蛾
+飞
+荒
+棺
+劫
+么
+市
+火
+温
+拈
+棚
+洼
+转
+果
+奕
+卸
+迪
+伸
+泳
+斗
+邡
+侄
+涨
+屯
+萋
+胭
+氡
+崮
+枞
+惧
+冒
+彩
+斜
+手
+豚
+随
+旭
+淑
+妞
+形
+菌
+吲
+沱
+争
+驯
+歹
+挟
+兆
+柱
+传
+至
+包
+内
+响
+临
+红
+功
+弩
+衡
+寂
+禁
+老
+棍
+耆
+渍
+织
+害
+氵
+渑
+布
+载
+靥
+嗬
+虽
+苹
+咨
+娄
+库
+雉
+榜
+帜
+嘲
+套
+瑚
+亲
+簸
+欧
+边
+6
+腿
+旮
+抛
+吹
+瞳
+得
+镓
+梗
+厨
+继
+漾
+愣
+憨
+士
+策
+窑
+抑
+躯
+襟
+脏
+参
+贸
+言
+干
+绸
+鳄
+穷
+藜
+音
+折
+详
+)
+举
+悍
+甸
+癌
+黎
+谴
+死
+罩
+迁
+寒
+驷
+袖
+媒
+蒋
+掘
+模
+纠
+恣
+观
+祖
+蛆
+碍
+位
+稿
+主
+澧
+跌
+筏
+京
+锏
+帝
+贴
+证
+糠
+才
+黄
+鲸
+略
+炯
+饱
+四
+出
+园
+犀
+牧
+容
+汉
+杆
+浈
+汰
+瑷
+造
+虫
+瘩
+怪
+驴
+济
+应
+花
+沣
+谔
+夙
+旅
+价
+矿
+以
+考
+s
+u
+呦
+晒
+巡
+茅
+准
+肟
+瓴
+詹
+仟
+褂
+译
+桌
+混
+宁
+怦
+郑
+抿
+些
+余
+鄂
+饴
+攒
+珑
+群
+阖
+岔
+琨
+藓
+预
+环
+洮
+岌
+宀
+杲
+瀵
+最
+常
+囡
+周
+踊
+女
+鼓
+袭
+喉
+简
+范
+薯
+遐
+疏
+粱
+黜
+禧
+法
+箔
+斤
+遥
+汝
+奥
+直
+贞
+撑
+置
+绱
+集
+她
+馅
+逗
+钧
+橱
+魉
+[
+恙
+躁
+唤
+9
+旺
+膘
+待
+脾
+惫
+购
+吗
+依
+盲
+度
+瘿
+蠖
+俾
+之
+镗
+拇
+鲵
+厝
+簧
+续
+款
+展
+啃
+表
+剔
+品
+钻
+腭
+损
+清
+锶
+统
+涌
+寸
+滨
+贪
+链
+吠
+冈
+伎
+迥
+咏
+吁
+览
+防
+迅
+失
+汾
+阔
+逵
+绀
+蔑
+列
+川
+凭
+努
+熨
+揪
+利
+俱
+绉
+抢
+鸨
+我
+即
+责
+膦
+易
+毓
+鹊
+刹
+玷
+岿
+空
+嘞
+绊
+排
+术
+估
+锷
+违
+们
+苟
+铜
+播
+肘
+件
+烫
+审
+鲂
+广
+像
+铌
+惰
+铟
+巳
+胍
+鲍
+康
+憧
+色
+恢
+想
+拷
+尤
+疳
+知
+S
+Y
+F
+D
+A
+峄
+裕
+帮
+握
+搔
+氐
+氘
+难
+墒
+沮
+雨
+叁
+缥
+悴
+藐
+湫
+娟
+苑
+稠
+颛
+簇
+后
+阕
+闭
+蕤
+缚
+怎
+佞
+码
+嘤
+蔡
+痊
+舱
+螯
+帕
+赫
+昵
+升
+烬
+岫
+、
+疵
+蜻
+髁
+蕨
+隶
+烛
+械
+丑
+盂
+梁
+强
+鲛
+由
+拘
+揉
+劭
+龟
+撤
+钩
+呕
+孛
+费
+妻
+漂
+求
+阑
+崖
+秤
+甘
+通
+深
+补
+赃
+坎
+床
+啪
+承
+吼
+量
+暇
+钼
+烨
+阂
+擎
+脱
+逮
+称
+P
+神
+属
+矗
+华
+届
+狍
+葑
+汹
+育
+患
+窒
+蛰
+佼
+静
+槎
+运
+鳗
+庆
+逝
+曼
+疱
+克
+代
+官
+此
+麸
+耧
+蚌
+晟
+例
+础
+榛
+副
+测
+唰
+缢
+迹
+灬
+霁
+身
+岁
+赭
+扛
+又
+菡
+乜
+雾
+板
+读
+陷
+徉
+贯
+郁
+虑
+变
+钓
+菜
+圾
+现
+琢
+式
+乐
+维
+渔
+浜
+左
+吾
+脑
+钡
+警
+T
+啵
+拴
+偌
+漱
+湿
+硕
+止
+骼
+魄
+积
+燥
+联
+踢
+玛
+则
+窿
+见
+振
+畿
+送
+班
+钽
+您
+赵
+刨
+印
+讨
+踝
+籍
+谡
+舌
+崧
+汽
+蔽
+沪
+酥
+绒
+怖
+财
+帖
+肱
+私
+莎
+勋
+羔
+霸
+励
+哼
+帐
+将
+帅
+渠
+纪
+婴
+娩
+岭
+厘
+滕
+吻
+伤
+坝
+冠
+戊
+隆
+瘁
+介
+涧
+物
+黍
+并
+姗
+奢
+蹑
+掣
+垸
+锴
+命
+箍
+捉
+病
+辖
+琰
+眭
+迩
+艘
+绌
+繁
+寅
+若
+毋
+思
+诉
+类
+诈
+燮
+轲
+酮
+狂
+重
+反
+职
+筱
+县
+委
+磕
+绣
+奖
+晋
+濉
+志
+徽
+肠
+呈
+獐
+坻
+口
+片
+碰
+几
+村
+柿
+劳
+料
+获
+亩
+惕
+晕
+厌
+号
+罢
+池
+正
+鏖
+煨
+家
+棕
+复
+尝
+懋
+蜥
+锅
+岛
+扰
+队
+坠
+瘾
+钬
+@
+卧
+疣
+镇
+譬
+冰
+彷
+频
+黯
+据
+垄
+采
+八
+缪
+瘫
+型
+熹
+砰
+楠
+襁
+箐
+但
+嘶
+绳
+啤
+拍
+盥
+穆
+傲
+洗
+盯
+塘
+怔
+筛
+丿
+台
+恒
+喂
+葛
+永
+¥
+烟
+酒
+桦
+书
+砂
+蚝
+缉
+态
+瀚
+袄
+圳
+轻
+蛛
+超
+榧
+遛
+姒
+奘
+铮
+右
+荽
+望
+偻
+卡
+丶
+氰
+附
+做
+革
+索
+戚
+坨
+桷
+唁
+垅
+榻
+岐
+偎
+坛
+莨
+山
+殊
+微
+骇
+陈
+爨
+推
+嗝
+驹
+澡
+藁
+呤
+卤
+嘻
+糅
+逛
+侵
+郓
+酌
+德
+摇
+※
+鬃
+被
+慨
+殡
+羸
+昌
+泡
+戛
+鞋
+河
+宪
+沿
+玲
+鲨
+翅
+哽
+源
+铅
+语
+照
+邯
+址
+荃
+佬
+顺
+鸳
+町
+霭
+睾
+瓢
+夸
+椁
+晓
+酿
+痈
+咔
+侏
+券
+噎
+湍
+签
+嚷
+离
+午
+尚
+社
+锤
+背
+孟
+使
+浪
+缦
+潍
+鞅
+军
+姹
+驶
+笑
+鳟
+鲁
+》
+孽
+钜
+绿
+洱
+礴
+焯
+椰
+颖
+囔
+乌
+孔
+巴
+互
+性
+椽
+哞
+聘
+昨
+早
+暮
+胶
+炀
+隧
+低
+彗
+昝
+铁
+呓
+氽
+藉
+喔
+癖
+瑗
+姨
+权
+胱
+韦
+堑
+蜜
+酋
+楝
+砝
+毁
+靓
+歙
+锲
+究
+屋
+喳
+骨
+辨
+碑
+武
+鸠
+宫
+辜
+烊
+适
+坡
+殃
+培
+佩
+供
+走
+蜈
+迟
+翼
+况
+姣
+凛
+浔
+吃
+飘
+债
+犟
+金
+促
+苛
+崇
+坂
+莳
+畔
+绂
+兵
+蠕
+斋
+根
+砍
+亢
+欢
+恬
+崔
+剁
+餐
+榫
+快
+扶
+‖
+濒
+缠
+鳜
+当
+彭
+驭
+浦
+篮
+昀
+锆
+秸
+钳
+弋
+娣
+瞑
+夷
+龛
+苫
+拱
+致
+%
+嵊
+障
+隐
+弑
+初
+娓
+抉
+汩
+累
+蓖
+"
+唬
+助
+苓
+昙
+押
+毙
+破
+城
+郧
+逢
+嚏
+獭
+瞻
+溱
+婿
+赊
+跨
+恼
+璧
+萃
+姻
+貉
+灵
+炉
+密
+氛
+陶
+砸
+谬
+衔
+点
+琛
+沛
+枳
+层
+岱
+诺
+脍
+榈
+埂
+征
+冷
+裁
+打
+蹴
+素
+瘘
+逞
+蛐
+聊
+激
+腱
+萘
+踵
+飒
+蓟
+吆
+取
+咙
+簋
+涓
+矩
+曝
+挺
+揣
+座
+你
+史
+舵
+焱
+尘
+苏
+笈
+脚
+溉
+榨
+诵
+樊
+邓
+焊
+义
+庶
+儋
+蟋
+蒲
+赦
+呷
+杞
+诠
+豪
+还
+试
+颓
+茉
+太
+除
+紫
+逃
+痴
+草
+充
+鳕
+珉
+祗
+墨
+渭
+烩
+蘸
+慕
+璇
+镶
+穴
+嵘
+恶
+骂
+险
+绋
+幕
+碉
+肺
+戳
+刘
+潞
+秣
+纾
+潜
+銮
+洛
+须
+罘
+销
+瘪
+汞
+兮
+屉
+r
+林
+厕
+质
+探
+划
+狸
+殚
+善
+煊
+烹
+〒
+锈
+逯
+宸
+辍
+泱
+柚
+袍
+远
+蹋
+嶙
+绝
+峥
+娥
+缍
+雀
+徵
+认
+镱
+谷
+=
+贩
+勉
+撩
+鄯
+斐
+洋
+非
+祚
+泾
+诒
+饿
+撬
+威
+晷
+搭
+芍
+锥
+笺
+蓦
+候
+琊
+档
+礁
+沼
+卵
+荠
+忑
+朝
+凹
+瑞
+头
+仪
+弧
+孵
+畏
+铆
+突
+衲
+车
+浩
+气
+茂
+悖
+厢
+枕
+酝
+戴
+湾
+邹
+飚
+攘
+锂
+写
+宵
+翁
+岷
+无
+喜
+丈
+挑
+嗟
+绛
+殉
+议
+槽
+具
+醇
+淞
+笃
+郴
+阅
+饼
+底
+壕
+砚
+弈
+询
+缕
+庹
+翟
+零
+筷
+暨
+舟
+闺
+甯
+撞
+麂
+茌
+蔼
+很
+珲
+捕
+棠
+角
+阉
+媛
+娲
+诽
+剿
+尉
+爵
+睬
+韩
+诰
+匣
+危
+糍
+镯
+立
+浏
+阳
+少
+盆
+舔
+擘
+匪
+申
+尬
+铣
+旯
+抖
+赘
+瓯
+居
+哮
+游
+锭
+茏
+歌
+坏
+甚
+秒
+舞
+沙
+仗
+劲
+潺
+阿
+燧
+郭
+嗖
+霏
+忠
+材
+奂
+耐
+跺
+砀
+输
+岖
+媳
+氟
+极
+摆
+灿
+今
+扔
+腻
+枝
+奎
+药
+熄
+吨
+话
+q
+额
+慑
+嘌
+协
+喀
+壳
+埭
+视
+著
+於
+愧
+陲
+翌
+峁
+颅
+佛
+腹
+聋
+侯
+咎
+叟
+秀
+颇
+存
+较
+罪
+哄
+岗
+扫
+栏
+钾
+羌
+己
+璨
+枭
+霉
+煌
+涸
+衿
+键
+镝
+益
+岢
+奏
+连
+夯
+睿
+冥
+均
+糖
+狞
+蹊
+稻
+爸
+刿
+胥
+煜
+丽
+肿
+璃
+掸
+跚
+灾
+垂
+樾
+濑
+乎
+莲
+窄
+犹
+撮
+战
+馄
+软
+络
+显
+鸢
+胸
+宾
+妲
+恕
+埔
+蝌
+份
+遇
+巧
+瞟
+粒
+恰
+剥
+桡
+博
+讯
+凯
+堇
+阶
+滤
+卖
+斌
+骚
+彬
+兑
+磺
+樱
+舷
+两
+娱
+福
+仃
+差
+找
+桁
+净
+把
+阴
+污
+戬
+雷
+碓
+蕲
+楚
+罡
+焖
+抽
+妫
+咒
+仑
+闱
+尽
+邑
+菁
+爱
+贷
+沥
+鞑
+牡
+嗉
+崴
+骤
+塌
+嗦
+订
+拮
+滓
+捡
+锻
+次
+坪
+杩
+臃
+箬
+融
+珂
+鹗
+宗
+枚
+降
+鸬
+妯
+阄
+堰
+盐
+毅
+必
+杨
+崃
+俺
+甬
+状
+莘
+货
+耸
+菱
+腼
+铸
+唏
+痤
+孚
+澳
+懒
+溅
+翘
+疙
+杷
+淼
+缙
+骰
+喊
+悉
+砻
+坷
+艇
+赁
+界
+谤
+纣
+宴
+晃
+茹
+归
+饭
+梢
+铡
+街
+抄
+肼
+鬟
+苯
+颂
+撷
+戈
+炒
+咆
+茭
+瘙
+负
+仰
+客
+琉
+铢
+封
+卑
+珥
+椿
+镧
+窨
+鬲
+寿
+御
+袤
+铃
+萎
+砖
+餮
+脒
+裳
+肪
+孕
+嫣
+馗
+嵇
+恳
+氯
+江
+石
+褶
+冢
+祸
+阻
+狈
+羞
+银
+靳
+透
+咳
+叼
+敷
+芷
+啥
+它
+瓤
+兰
+痘
+懊
+逑
+肌
+往
+捺
+坊
+甩
+呻
+〃
+沦
+忘
+膻
+祟
+菅
+剧
+崆
+智
+坯
+臧
+霍
+墅
+攻
+眯
+倘
+拢
+骠
+铐
+庭
+岙
+瓠
+′
+缺
+泥
+迢
+捶
+?
+?
+郏
+喙
+掷
+沌
+纯
+秘
+种
+听
+绘
+固
+螨
+团
+香
+盗
+妒
+埚
+蓝
+拖
+旱
+荞
+铀
+血
+遏
+汲
+辰
+叩
+拽
+幅
+硬
+惶
+桀
+漠
+措
+泼
+唑
+齐
+肾
+念
+酱
+虚
+屁
+耶
+旗
+砦
+闵
+婉
+馆
+拭
+绅
+韧
+忏
+窝
+醋
+葺
+顾
+辞
+倜
+堆
+辋
+逆
+玟
+贱
+疾
+董
+惘
+倌
+锕
+淘
+嘀
+莽
+俭
+笏
+绑
+鲷
+杈
+择
+蟀
+粥
+嗯
+驰
+逾
+案
+谪
+褓
+胫
+哩
+昕
+颚
+鲢
+绠
+躺
+鹄
+崂
+儒
+俨
+丝
+尕
+泌
+啊
+萸
+彰
+幺
+吟
+骄
+苣
+弦
+脊
+瑰
+〈
+诛
+镁
+析
+闪
+剪
+侧
+哟
+框
+螃
+守
+嬗
+燕
+狭
+铈
+缮
+概
+迳
+痧
+鲲
+俯
+售
+笼
+痣
+扉
+挖
+满
+咋
+援
+邱
+扇
+歪
+便
+玑
+绦
+峡
+蛇
+叨
+〖
+泽
+胃
+斓
+喋
+怂
+坟
+猪
+该
+蚬
+炕
+弥
+赞
+棣
+晔
+娠
+挲
+狡
+创
+疖
+铕
+镭
+稷
+挫
+弭
+啾
+翔
+粉
+履
+苘
+哦
+楼
+秕
+铂
+土
+锣
+瘟
+挣
+栉
+习
+享
+桢
+袅
+磨
+桂
+谦
+延
+坚
+蔚
+噗
+署
+谟
+猬
+钎
+恐
+嬉
+雒
+倦
+衅
+亏
+璩
+睹
+刻
+殿
+王
+算
+雕
+麻
+丘
+柯
+骆
+丸
+塍
+谚
+添
+鲈
+垓
+桎
+蚯
+芥
+予
+飕
+镦
+谌
+窗
+醚
+菀
+亮
+搪
+莺
+蒿
+羁
+足
+J
+真
+轶
+悬
+衷
+靛
+翊
+掩
+哒
+炅
+掐
+冼
+妮
+l
+谐
+稚
+荆
+擒
+犯
+陵
+虏
+浓
+崽
+刍
+陌
+傻
+孜
+千
+靖
+演
+矜
+钕
+煽
+杰
+酗
+渗
+伞
+栋
+俗
+泫
+戍
+罕
+沾
+疽
+灏
+煦
+芬
+磴
+叱
+阱
+榉
+湃
+蜀
+叉
+醒
+彪
+租
+郡
+篷
+屎
+良
+垢
+隗
+弱
+陨
+峪
+砷
+掴
+颁
+胎
+雯
+绵
+贬
+沐
+撵
+隘
+篙
+暖
+曹
+陡
+栓
+填
+臼
+彦
+瓶
+琪
+潼
+哪
+鸡
+摩
+啦
+俟
+锋
+域
+耻
+蔫
+疯
+纹
+撇
+毒
+绶
+痛
+酯
+忍
+爪
+赳
+歆
+嘹
+辕
+烈
+册
+朴
+钱
+吮
+毯
+癜
+娃
+谀
+邵
+厮
+炽
+璞
+邃
+丐
+追
+词
+瓒
+忆
+轧
+芫
+谯
+喷
+弟
+半
+冕
+裙
+掖
+墉
+绮
+寝
+苔
+势
+顷
+褥
+切
+衮
+君
+佳
+嫒
+蚩
+霞
+佚
+洙
+逊
+镖
+暹
+唛
+&
+殒
+顶
+碗
+獗
+轭
+铺
+蛊
+废
+恹
+汨
+崩
+珍
+那
+杵
+曲
+纺
+夏
+薰
+傀
+闳
+淬
+姘
+舀
+拧
+卷
+楂
+恍
+讪
+厩
+寮
+篪
+赓
+乘
+灭
+盅
+鞣
+沟
+慎
+挂
+饺
+鼾
+杳
+树
+缨
+丛
+絮
+娌
+臻
+嗳
+篡
+侩
+述
+衰
+矛
+圈
+蚜
+匕
+筹
+匿
+濞
+晨
+叶
+骋
+郝
+挚
+蚴
+滞
+增
+侍
+描
+瓣
+吖
+嫦
+蟒
+匾
+圣
+赌
+毡
+癞
+恺
+百
+曳
+需
+篓
+肮
+庖
+帏
+卿
+驿
+遗
+蹬
+鬓
+骡
+歉
+芎
+胳
+屐
+禽
+烦
+晌
+寄
+媾
+狄
+翡
+苒
+船
+廉
+终
+痞
+殇
+々
+畦
+饶
+改
+拆
+悻
+萄
+£
+瓿
+乃
+訾
+桅
+匮
+溧
+拥
+纱
+铍
+骗
+蕃
+龋
+缬
+父
+佐
+疚
+栎
+醍
+掳
+蓄
+x
+惆
+颜
+鲆
+榆
+〔
+猎
+敌
+暴
+谥
+鲫
+贾
+罗
+玻
+缄
+扦
+芪
+癣
+落
+徒
+臾
+恿
+猩
+托
+邴
+肄
+牵
+春
+陛
+耀
+刊
+拓
+蓓
+邳
+堕
+寇
+枉
+淌
+啡
+湄
+兽
+酷
+萼
+碚
+濠
+萤
+夹
+旬
+戮
+梭
+琥
+椭
+昔
+勺
+蜊
+绐
+晚
+孺
+僵
+宣
+摄
+冽
+旨
+萌
+忙
+蚤
+眉
+噼
+蟑
+付
+契
+瓜
+悼
+颡
+壁
+曾
+窕
+颢
+澎
+仿
+俑
+浑
+嵌
+浣
+乍
+碌
+褪
+乱
+蔟
+隙
+玩
+剐
+葫
+箫
+纲
+围
+伐
+决
+伙
+漩
+瑟
+刑
+肓
+镳
+缓
+蹭
+氨
+皓
+典
+畲
+坍
+铑
+檐
+塑
+洞
+倬
+储
+胴
+淳
+戾
+吐
+灼
+惺
+妙
+毕
+珐
+缈
+虱
+盖
+羰
+鸿
+磅
+谓
+髅
+娴
+苴
+唷
+蚣
+霹
+抨
+贤
+唠
+犬
+誓
+逍
+庠
+逼
+麓
+籼
+釉
+呜
+碧
+秧
+氩
+摔
+霄
+穸
+纨
+辟
+妈
+映
+完
+牛
+缴
+嗷
+炊
+恩
+荔
+茆
+掉
+紊
+慌
+莓
+羟
+阙
+萁
+磐
+另
+蕹
+辱
+鳐
+湮
+吡
+吩
+唐
+睦
+垠
+舒
+圜
+冗
+瞿
+溺
+芾
+囱
+匠
+僳
+汐
+菩
+饬
+漓
+黑
+霰
+浸
+濡
+窥
+毂
+蒡
+兢
+驻
+鹉
+芮
+诙
+迫
+雳
+厂
+忐
+臆
+猴
+鸣
+蚪
+栈
+箕
+羡
+渐
+莆
+捍
+眈
+哓
+趴
+蹼
+埕
+嚣
+骛
+宏
+淄
+斑
+噜
+严
+瑛
+垃
+椎
+诱
+压
+庾
+绞
+焘
+廿
+抡
+迄
+棘
+夫
+纬
+锹
+眨
+瞌
+侠
+脐
+竞
+瀑
+孳
+骧
+遁
+姜
+颦
+荪
+滚
+萦
+伪
+逸
+粳
+爬
+锁
+矣
+役
+趣
+洒
+颔
+诏
+逐
+奸
+甭
+惠
+攀
+蹄
+泛
+尼
+拼
+阮
+鹰
+亚
+颈
+惑
+勒
+〉
+际
+肛
+爷
+刚
+钨
+丰
+养
+冶
+鲽
+辉
+蔻
+画
+覆
+皴
+妊
+麦
+返
+醉
+皂
+擀
+〗
+酶
+凑
+粹
+悟
+诀
+硖
+港
+卜
+z
+杀
+涕
+舍
+铠
+抵
+弛
+段
+敝
+镐
+奠
+拂
+轴
+跛
+袱
+e
+t
+沉
+菇
+俎
+薪
+峦
+秭
+蟹
+历
+盟
+菠
+寡
+液
+肢
+喻
+染
+裱
+悱
+抱
+氙
+赤
+捅
+猛
+跑
+氮
+谣
+仁
+尺
+辊
+窍
+烙
+衍
+架
+擦
+倏
+璐
+瑁
+币
+楞
+胖
+夔
+趸
+邛
+惴
+饕
+虔
+蝎
+哉
+贝
+宽
+辫
+炮
+扩
+饲
+籽
+魏
+菟
+锰
+伍
+猝
+末
+琳
+哚
+蛎
+邂
+呀
+姿
+鄞
+却
+歧
+仙
+恸
+椐
+森
+牒
+寤
+袒
+婆
+虢
+雅
+钉
+朵
+贼
+欲
+苞
+寰
+故
+龚
+坭
+嘘
+咫
+礼
+硷
+兀
+睢
+汶
+’
+铲
+烧
+绕
+诃
+浃
+钿
+哺
+柜
+讼
+颊
+璁
+腔
+洽
+咐
+脲
+簌
+筠
+镣
+玮
+鞠
+谁
+兼
+姆
+挥
+梯
+蝴
+谘
+漕
+刷
+躏
+宦
+弼
+b
+垌
+劈
+麟
+莉
+揭
+笙
+渎
+仕
+嗤
+仓
+配
+怏
+抬
+错
+泯
+镊
+孰
+猿
+邪
+仍
+秋
+鼬
+壹
+歇
+吵
+炼
+<
+尧
+射
+柬
+廷
+胧
+霾
+凳
+隋
+肚
+浮
+梦
+祥
+株
+堵
+退
+L
+鹫
+跎
+凶
+毽
+荟
+炫
+栩
+玳
+甜
+沂
+鹿
+顽
+伯
+爹
+赔
+蛴
+徐
+匡
+欣
+狰
+缸
+雹
+蟆
+疤
+默
+沤
+啜
+痂
+衣
+禅
+w
+i
+h
+辽
+葳
+黝
+钗
+停
+沽
+棒
+馨
+颌
+肉
+吴
+硫
+悯
+劾
+娈
+马
+啧
+吊
+悌
+镑
+峭
+帆
+瀣
+涉
+咸
+疸
+滋
+泣
+翦
+拙
+癸
+钥
+蜒
++
+尾
+庄
+凝
+泉
+婢
+渴
+谊
+乞
+陆
+锉
+糊
+鸦
+淮
+I
+B
+N
+晦
+弗
+乔
+庥
+葡
+尻
+席
+橡
+傣
+渣
+拿
+惩
+麋
+斛
+缃
+矮
+蛏
+岘
+鸽
+姐
+膏
+催
+奔
+镒
+喱
+蠡
+摧
+钯
+胤
+柠
+拐
+璋
+鸥
+卢
+荡
+倾
+^
+_
+珀
+逄
+萧
+塾
+掇
+贮
+笆
+聂
+圃
+冲
+嵬
+M
+滔
+笕
+值
+炙
+偶
+蜱
+搐
+梆
+汪
+蔬
+腑
+鸯
+蹇
+敞
+绯
+仨
+祯
+谆
+梧
+糗
+鑫
+啸
+豺
+囹
+猾
+巢
+柄
+瀛
+筑
+踌
+沭
+暗
+苁
+鱿
+蹉
+脂
+蘖
+牢
+热
+木
+吸
+溃
+宠
+序
+泞
+偿
+拜
+檩
+厚
+朐
+毗
+螳
+吞
+媚
+朽
+担
+蝗
+橘
+畴
+祈
+糟
+盱
+隼
+郜
+惜
+珠
+裨
+铵
+焙
+琚
+唯
+咚
+噪
+骊
+丫
+滢
+勤
+棉
+呸
+咣
+淀
+隔
+蕾
+窈
+饨
+挨
+煅
+短
+匙
+粕
+镜
+赣
+撕
+墩
+酬
+馁
+豌
+颐
+抗
+酣
+氓
+佑
+搁
+哭
+递
+耷
+涡
+桃
+贻
+碣
+截
+瘦
+昭
+镌
+蔓
+氚
+甲
+猕
+蕴
+蓬
+散
+拾
+纛
+狼
+猷
+铎
+埋
+旖
+矾
+讳
+囊
+糜
+迈
+粟
+蚂
+紧
+鲳
+瘢
+栽
+稼
+羊
+锄
+斟
+睁
+桥
+瓮
+蹙
+祉
+醺
+鼻
+昱
+剃
+跳
+篱
+跷
+蒜
+翎
+宅
+晖
+嗑
+壑
+峻
+癫
+屏
+狠
+陋
+袜
+途
+憎
+祀
+莹
+滟
+佶
+溥
+臣
+约
+盛
+峰
+磁
+慵
+婪
+拦
+莅
+朕
+鹦
+粲
+裤
+哎
+疡
+嫖
+琵
+窟
+堪
+谛
+嘉
+儡
+鳝
+斩
+郾
+驸
+酊
+妄
+胜
+贺
+徙
+傅
+噌
+钢
+栅
+庇
+恋
+匝
+巯
+邈
+尸
+锚
+粗
+佟
+蛟
+薹
+纵
+蚊
+郅
+绢
+锐
+苗
+俞
+篆
+淆
+膀
+鲜
+煎
+诶
+秽
+寻
+涮
+刺
+怀
+噶
+巨
+褰
+魅
+灶
+灌
+桉
+藕
+谜
+舸
+薄
+搀
+恽
+借
+牯
+痉
+渥
+愿
+亓
+耘
+杠
+柩
+锔
+蚶
+钣
+珈
+喘
+蹒
+幽
+赐
+稗
+晤
+莱
+泔
+扯
+肯
+菪
+裆
+腩
+豉
+疆
+骜
+腐
+倭
+珏
+唔
+粮
+亡
+润
+慰
+伽
+橄
+玄
+誉
+醐
+胆
+龊
+粼
+塬
+陇
+彼
+削
+嗣
+绾
+芽
+妗
+垭
+瘴
+爽
+薏
+寨
+龈
+泠
+弹
+赢
+漪
+猫
+嘧
+涂
+恤
+圭
+茧
+烽
+屑
+痕
+巾
+赖
+荸
+凰
+腮
+畈
+亵
+蹲
+偃
+苇
+澜
+艮
+换
+骺
+烘
+苕
+梓
+颉
+肇
+哗
+悄
+氤
+涠
+葬
+屠
+鹭
+植
+竺
+佯
+诣
+鲇
+瘀
+鲅
+邦
+移
+滁
+冯
+耕
+癔
+戌
+茬
+沁
+巩
+悠
+湘
+洪
+痹
+锟
+循
+谋
+腕
+鳃
+钠
+捞
+焉
+迎
+碱
+伫
+急
+榷
+奈
+邝
+卯
+辄
+皲
+卟
+醛
+畹
+忧
+稳
+雄
+昼
+缩
+阈
+睑
+扌
+耗
+曦
+涅
+捏
+瞧
+邕
+淖
+漉
+铝
+耦
+禹
+湛
+喽
+莼
+琅
+诸
+苎
+纂
+硅
+始
+嗨
+傥
+燃
+臂
+赅
+嘈
+呆
+贵
+屹
+壮
+肋
+亍
+蚀
+卅
+豹
+腆
+邬
+迭
+浊
+}
+童
+螂
+捐
+圩
+勐
+触
+寞
+汊
+壤
+荫
+膺
+渌
+芳
+懿
+遴
+螈
+泰
+蓼
+蛤
+茜
+舅
+枫
+朔
+膝
+眙
+避
+梅
+判
+鹜
+璜
+牍
+缅
+垫
+藻
+黔
+侥
+惚
+懂
+踩
+腰
+腈
+札
+丞
+唾
+慈
+顿
+摹
+荻
+琬
+~
+斧
+沈
+滂
+胁
+胀
+幄
+莜
+Z
+匀
+鄄
+掌
+绰
+茎
+焚
+赋
+萱
+谑
+汁
+铒
+瞎
+夺
+蜗
+野
+娆
+冀
+弯
+篁
+懵
+灞
+隽
+芡
+脘
+俐
+辩
+芯
+掺
+喏
+膈
+蝈
+觐
+悚
+踹
+蔗
+熠
+鼠
+呵
+抓
+橼
+峨
+畜
+缔
+禾
+崭
+弃
+熊
+摒
+凸
+拗
+穹
+蒙
+抒
+祛
+劝
+闫
+扳
+阵
+醌
+踪
+喵
+侣
+搬
+仅
+荧
+赎
+蝾
+琦
+买
+婧
+瞄
+寓
+皎
+冻
+赝
+箩
+莫
+瞰
+郊
+笫
+姝
+筒
+枪
+遣
+煸
+袋
+舆
+痱
+涛
+母
+〇
+启
+践
+耙
+绲
+盘
+遂
+昊
+搞
+槿
+诬
+纰
+泓
+惨
+檬
+亻
+越
+C
+o
+憩
+熵
+祷
+钒
+暧
+塔
+阗
+胰
+咄
+娶
+魔
+琶
+钞
+邻
+扬
+杉
+殴
+咽
+弓
+〆
+髻
+】
+吭
+揽
+霆
+拄
+殖
+脆
+彻
+岩
+芝
+勃
+辣
+剌
+钝
+嘎
+甄
+佘
+皖
+伦
+授
+徕
+憔
+挪
+皇
+庞
+稔
+芜
+踏
+溴
+兖
+卒
+擢
+饥
+鳞
+煲
+‰
+账
+颗
+叻
+斯
+捧
+鳍
+琮
+讹
+蛙
+纽
+谭
+酸
+兔
+莒
+睇
+伟
+觑
+羲
+嗜
+宜
+褐
+旎
+辛
+卦
+诘
+筋
+鎏
+溪
+挛
+熔
+阜
+晰
+鳅
+丢
+奚
+灸
+呱
+献
+陉
+黛
+鸪
+甾
+萨
+疮
+拯
+洲
+疹
+辑
+叙
+恻
+谒
+允
+柔
+烂
+氏
+逅
+漆
+拎
+惋
+扈
+湟
+纭
+啕
+掬
+擞
+哥
+忽
+涤
+鸵
+靡
+郗
+瓷
+扁
+廊
+怨
+雏
+钮
+敦
+E
+懦
+憋
+汀
+拚
+啉
+腌
+岸
+f
+痼
+瞅
+尊
+咀
+眩
+飙
+忌
+仝
+迦
+熬
+毫
+胯
+篑
+茄
+腺
+凄
+舛
+碴
+锵
+诧
+羯
+後
+漏
+汤
+宓
+仞
+蚁
+壶
+谰
+皑
+铄
+棰
+罔
+辅
+晶
+苦
+牟
+闽
+\
+烃
+饮
+聿
+丙
+蛳
+朱
+煤
+涔
+鳖
+犁
+罐
+荼
+砒
+淦
+妤
+黏
+戎
+孑
+婕
+瑾
+戢
+钵
+枣
+捋
+砥
+衩
+狙
+桠
+稣
+阎
+肃
+梏
+诫
+孪
+昶
+婊
+衫
+嗔
+侃
+塞
+蜃
+樵
+峒
+貌
+屿
+欺
+缫
+阐
+栖
+诟
+珞
+荭
+吝
+萍
+嗽
+恂
+啻
+蜴
+磬
+峋
+俸
+豫
+谎
+徊
+镍
+韬
+魇
+晴
+U
+囟
+猜
+蛮
+坐
+囿
+伴
+亭
+肝
+佗
+蝠
+妃
+胞
+滩
+榴
+氖
+垩
+苋
+砣
+扪
+馏
+姓
+轩
+厉
+夥
+侈
+禀
+垒
+岑
+赏
+钛
+辐
+痔
+披
+纸
+碳
+“
+坞
+蠓
+挤
+荥
+沅
+悔
+铧
+帼
+蒌
+蝇
+a
+p
+y
+n
+g
+哀
+浆
+瑶
+凿
+桶
+馈
+皮
+奴
+苜
+佤
+伶
+晗
+铱
+炬
+优
+弊
+氢
+恃
+甫
+攥
+端
+锌
+灰
+稹
+炝
+曙
+邋
+亥
+眶
+碾
+拉
+萝
+绔
+捷
+浍
+腋
+姑
+菖
+凌
+涞
+麽
+锢
+桨
+潢
+绎
+镰
+殆
+锑
+渝
+铬
+困
+绽
+觎
+匈
+糙
+暑
+裹
+鸟
+盔
+肽
+迷
+綦
+『
+亳
+佝
+俘
+钴
+觇
+骥
+仆
+疝
+跪
+婶
+郯
+瀹
+唉
+脖
+踞
+针
+晾
+忒
+扼
+瞩
+叛
+椒
+疟
+嗡
+邗
+肆
+跆
+玫
+忡
+捣
+咧
+唆
+艄
+蘑
+潦
+笛
+阚
+沸
+泻
+掊
+菽
+贫
+斥
+髂
+孢
+镂
+赂
+麝
+鸾
+屡
+衬
+苷
+恪
+叠
+希
+粤
+爻
+喝
+茫
+惬
+郸
+绻
+庸
+撅
+碟
+宄
+妹
+膛
+叮
+饵
+崛
+嗲
+椅
+冤
+搅
+咕
+敛
+尹
+垦
+闷
+蝉
+霎
+勰
+败
+蓑
+泸
+肤
+鹌
+幌
+焦
+浠
+鞍
+刁
+舰
+乙
+竿
+裔
+。
+茵
+函
+伊
+兄
+丨
+娜
+匍
+謇
+莪
+宥
+似
+蝽
+翳
+酪
+翠
+粑
+薇
+祢
+骏
+赠
+叫
+Q
+噤
+噻
+竖
+芗
+莠
+潭
+俊
+羿
+耜
+O
+郫
+趁
+嗪
+囚
+蹶
+芒
+洁
+笋
+鹑
+敲
+硝
+啶
+堡
+渲
+揩
+』
+携
+宿
+遒
+颍
+扭
+棱
+割
+萜
+蔸
+葵
+琴
+捂
+饰
+衙
+耿
+掠
+募
+岂
+窖
+涟
+蔺
+瘤
+柞
+瞪
+怜
+匹
+距
+楔
+炜
+哆
+秦
+缎
+幼
+茁
+绪
+痨
+恨
+楸
+娅
+瓦
+桩
+雪
+嬴
+伏
+榔
+妥
+铿
+拌
+眠
+雍
+缇
+‘
+卓
+搓
+哌
+觞
+噩
+屈
+哧
+髓
+咦
+巅
+娑
+侑
+淫
+膳
+祝
+勾
+姊
+莴
+胄
+疃
+薛
+蜷
+胛
+巷
+芙
+芋
+熙
+闰
+勿
+窃
+狱
+剩
+钏
+幢
+陟
+铛
+慧
+靴
+耍
+k
+浙
+浇
+飨
+惟
+绗
+祜
+澈
+啼
+咪
+磷
+摞
+诅
+郦
+抹
+跃
+壬
+吕
+肖
+琏
+颤
+尴
+剡
+抠
+凋
+赚
+泊
+津
+宕
+殷
+倔
+氲
+漫
+邺
+涎
+怠
+$
+垮
+荬
+遵
+俏
+叹
+噢
+饽
+蜘
+孙
+筵
+疼
+鞭
+羧
+牦
+箭
+潴
+c
+眸
+祭
+髯
+啖
+坳
+愁
+芩
+驮
+倡
+巽
+穰
+沃
+胚
+怒
+凤
+槛
+剂
+趵
+嫁
+v
+邢
+灯
+鄢
+桐
+睽
+檗
+锯
+槟
+婷
+嵋
+圻
+诗
+蕈
+颠
+遭
+痢
+芸
+怯
+馥
+竭
+锗
+徜
+恭
+遍
+籁
+剑
+嘱
+苡
+龄
+僧
+桑
+潸
+弘
+澶
+楹
+悲
+讫
+愤
+腥
+悸
+谍
+椹
+呢
+桓
+葭
+攫
+阀
+翰
+躲
+敖
+柑
+郎
+笨
+橇
+呃
+魁
+燎
+脓
+葩
+磋
+垛
+玺
+狮
+沓
+砜
+蕊
+锺
+罹
+蕉
+翱
+虐
+闾
+巫
+旦
+茱
+嬷
+枯
+鹏
+贡
+芹
+汛
+矫
+绁
+拣
+禺
+佃
+讣
+舫
+惯
+乳
+趋
+疲
+挽
+岚
+虾
+衾
+蠹
+蹂
+飓
+氦
+铖
+孩
+稞
+瑜
+壅
+掀
+勘
+妓
+畅
+髋
+W
+庐
+牲
+蓿
+榕
+练
+垣
+唱
+邸
+菲
+昆
+婺
+穿
+绡
+麒
+蚱
+掂
+愚
+泷
+涪
+漳
+妩
+娉
+榄
+讷
+觅
+旧
+藤
+煮
+呛
+柳
+腓
+叭
+庵
+烷
+阡
+罂
+蜕
+擂
+猖
+咿
+媲
+脉
+【
+沏
+貅
+黠
+熏
+哲
+烁
+坦
+酵
+兜
+潇
+撒
+剽
+珩
+圹
+乾
+摸
+樟
+帽
+嗒
+襄
+魂
+轿
+憬
+锡
+〕
+喃
+皆
+咖
+隅
+脸
+残
+泮
+袂
+鹂
+珊
+囤
+捆
+咤
+误
+徨
+闹
+淙
+芊
+淋
+怆
+囗
+拨
+梳
+渤
+R
+G
+绨
+蚓
+婀
+幡
+狩
+麾
+谢
+唢
+裸
+旌
+伉
+纶
+裂
+驳
+砼
+咛
+澄
+樨
+蹈
+宙
+澍
+倍
+貔
+操
+勇
+蟠
+摈
+砧
+虬
+够
+缁
+悦
+藿
+撸
+艹
+摁
+淹
+豇
+虎
+榭
+吱
+d
+喧
+荀
+踱
+侮
+奋
+偕
+饷
+犍
+惮
+坑
+璎
+徘
+宛
+妆
+袈
+倩
+窦
+昂
+荏
+乖
+K
+怅
+撰
+鳙
+牙
+袁
+酞
+X
+痿
+琼
+闸
+雁
+趾
+荚
+虻
+涝
+《
+杏
+韭
+偈
+烤
+绫
+鞘
+卉
+症
+遢
+蓥
+诋
+杭
+荨
+匆
+竣
+簪
+辙
+敕
+虞
+丹
+缭
+咩
+黟
+m
+淤
+瑕
+咂
+铉
+硼
+茨
+嶂
+痒
+畸
+敬
+涿
+粪
+窘
+熟
+叔
+嫔
+盾
+忱
+裘
+憾
+梵
+赡
+珙
+咯
+娘
+庙
+溯
+胺
+葱
+痪
+摊
+荷
+卞
+乒
+髦
+寐
+铭
+坩
+胗
+枷
+爆
+溟
+嚼
+羚
+砬
+轨
+惊
+挠
+罄
+竽
+菏
+氧
+浅
+楣
+盼
+枢
+炸
+阆
+杯
+谏
+噬
+淇
+渺
+俪
+秆
+墓
+泪
+跻
+砌
+痰
+垡
+渡
+耽
+釜
+讶
+鳎
+煞
+呗
+韶
+舶
+绷
+鹳
+缜
+旷
+铊
+皱
+龌
+檀
+霖
+奄
+槐
+艳
+蝶
+旋
+哝
+赶
+骞
+蚧
+腊
+盈
+丁
+`
+蜚
+矸
+蝙
+睨
+嚓
+僻
+鬼
+醴
+夜
+彝
+磊
+笔
+拔
+栀
+糕
+厦
+邰
+纫
+逭
+纤
+眦
+膊
+馍
+躇
+烯
+蘼
+冬
+诤
+暄
+骶
+哑
+瘠
+」
+臊
+丕
+愈
+咱
+螺
+擅
+跋
+搏
+硪
+谄
+笠
+淡
+嘿
+骅
+谧
+鼎
+皋
+姚
+歼
+蠢
+驼
+耳
+胬
+挝
+涯
+狗
+蒽
+孓
+犷
+凉
+芦
+箴
+铤
+孤
+嘛
+坤
+V
+茴
+朦
+挞
+尖
+橙
+诞
+搴
+碇
+洵
+浚
+帚
+蜍
+漯
+柘
+嚎
+讽
+芭
+荤
+咻
+祠
+秉
+跖
+埃
+吓
+糯
+眷
+馒
+惹
+娼
+鲑
+嫩
+讴
+轮
+瞥
+靶
+褚
+乏
+缤
+宋
+帧
+删
+驱
+碎
+扑
+俩
+俄
+偏
+涣
+竹
+噱
+皙
+佰
+渚
+唧
+斡
+#
+镉
+刀
+崎
+筐
+佣
+夭
+贰
+肴
+峙
+哔
+艿
+匐
+牺
+镛
+缘
+仡
+嫡
+劣
+枸
+堀
+梨
+簿
+鸭
+蒸
+亦
+稽
+浴
+{
+衢
+束
+槲
+j
+阁
+揍
+疥
+棋
+潋
+聪
+窜
+乓
+睛
+插
+冉
+阪
+苍
+搽
+「
+蟾
+螟
+幸
+仇
+樽
+撂
+慢
+跤
+幔
+俚
+淅
+覃
+觊
+溶
+妖
+帛
+侨
+曰
+妾
+泗
+:
+瀘
+風
+(
+)
+∶
+紅
+紗
+瑭
+雲
+頭
+鶏
+財
+許
+•
+樂
+焗
+麗
+—
+;
+滙
+東
+榮
+繪
+興
+…
+門
+業
+楊
+國
+顧
+盤
+寳
+龍
+鳳
+島
+誌
+緣
+結
+銭
+萬
+勝
+祎
+璟
+優
+歡
+臨
+時
+購
+=
+★
+藍
+昇
+鐵
+觀
+勅
+農
+聲
+畫
+兿
+術
+發
+劉
+記
+專
+耑
+園
+書
+壴
+種
+●
+褀
+號
+銀
+匯
+敟
+锘
+葉
+橪
+廣
+進
+蒄
+鑽
+阝
+祙
+貢
+鍋
+豊
+夬
+喆
+團
+閣
+開
+燁
+賓
+館
+酡
+沔
+順
++
+硚
+劵
+饸
+陽
+車
+湓
+復
+萊
+氣
+軒
+華
+堃
+迮
+纟
+戶
+馬
+學
+裡
+電
+嶽
+獨
+マ
+シ
+サ
+ジ
+燘
+袪
+環
+❤
+臺
+灣
+専
+賣
+孖
+聖
+攝
+線
+▪
+傢
+俬
+夢
+達
+莊
+喬
+貝
+薩
+劍
+羅
+壓
+棛
+饦
+尃
+璈
+囍
+醫
+G
+I
+A
+#
+N
+鷄
+髙
+嬰
+啓
+約
+隹
+潔
+賴
+藝
+~
+寶
+籣
+麺
+ 
+嶺
+√
+義
+網
+峩
+長
+∧
+魚
+機
+構
+②
+鳯
+偉
+L
+B
+㙟
+畵
+鴿
+'
+詩
+溝
+嚞
+屌
+藔
+佧
+玥
+蘭
+織
+1
+3
+9
+0
+7
+點
+砭
+鴨
+鋪
+銘
+廳
+弍
+‧
+創
+湯
+坶
+℃
+卩
+骝
+&
+烜
+荘
+當
+潤
+扞
+係
+懷
+碶
+钅
+蚨
+讠
+☆
+叢
+爲
+埗
+涫
+塗
+→
+楽
+現
+鯨
+愛
+瑪
+鈺
+忄
+悶
+藥
+飾
+樓
+視
+孬
+ㆍ
+燚
+苪
+師
+①
+丼
+锽
+│
+韓
+標
+兒
+閏
+匋
+張
+漢
+髪
+會
+閑
+檔
+習
+裝
+の
+峯
+菘
+輝
+雞
+釣
+億
+浐
+K
+O
+R
+8
+H
+E
+P
+T
+W
+D
+S
+C
+M
+F
+姌
+饹
+晞
+廰
+嵯
+鷹
+負
+飲
+絲
+冚
+楗
+澤
+綫
+區
+❋
+←
+質
+靑
+揚
+③
+滬
+統
+産
+協
+﹑
+乸
+畐
+經
+運
+際
+洺
+岽
+為
+粵
+諾
+崋
+豐
+碁
+V
+2
+6
+齋
+誠
+訂
+勑
+雙
+陳
+無
+泩
+媄
+夌
+刂
+i
+c
+t
+o
+r
+a
+嘢
+耄
+燴
+暃
+壽
+媽
+靈
+抻
+體
+唻
+冮
+甹
+鎮
+錦
+蜛
+蠄
+尓
+駕
+戀
+飬
+逹
+倫
+貴
+極
+寬
+磚
+嶪
+郎
+職
+|
+間
+n
+d
+剎
+伈
+課
+飛
+橋
+瘊
+№
+譜
+骓
+圗
+滘
+縣
+粿
+咅
+養
+濤
+彳
+%
+Ⅱ
+啰
+㴪
+見
+矞
+薬
+糁
+邨
+鲮
+顔
+罱
+選
+話
+贏
+氪
+俵
+競
+瑩
+繡
+枱
+綉
+獅
+爾
+™
+麵
+戋
+淩
+徳
+個
+劇
+場
+務
+簡
+寵
+h
+實
+膠
+轱
+圖
+築
+嘣
+樹
+㸃
+營
+耵
+孫
+饃
+鄺
+飯
+麯
+遠
+輸
+坫
+孃
+乚
+閃
+鏢
+㎡
+題
+廠
+關
+↑
+爺
+將
+軍
+連
+篦
+覌
+參
+箸
+-
+窠
+棽
+寕
+夀
+爰
+歐
+呙
+閥
+頡
+熱
+雎
+垟
+裟
+凬
+勁
+帑
+馕
+夆
+疌
+枼
+馮
+貨
+蒤
+樸
+彧
+旸
+靜
+龢
+暢
+㐱
+鳥
+珺
+鏡
+灡
+爭
+堷
+廚
+騰
+診
+┅
+蘇
+褔
+凱
+頂
+豕
+亞
+帥
+嘬
+⊥
+仺
+桖
+複
+饣
+絡
+穂
+顏
+棟
+納
+▏
+濟
+親
+設
+計
+攵
+埌
+烺
+頤
+燦
+蓮
+撻
+節
+講
+濱
+濃
+娽
+洳
+朿
+燈
+鈴
+護
+膚
+铔
+過
+補
+Z
+U
+5
+4
+坋
+闿
+䖝
+餘
+缐
+铞
+貿
+铪
+桼
+趙
+鍊
+[
+㐂
+垚
+菓
+揸
+捲
+鐘
+滏
+𣇉
+爍
+輪
+燜
+鴻
+鮮
+動
+鹞
+鷗
+丄
+慶
+鉌
+翥
+飮
+腸
+⇋
+漁
+覺
+來
+熘
+昴
+翏
+鲱
+圧
+鄉
+萭
+頔
+爐
+嫚
+貭
+類
+聯
+幛
+輕
+訓
+鑒
+夋
+锨
+芃
+珣
+䝉
+扙
+嵐
+銷
+處
+ㄱ
+語
+誘
+苝
+歸
+儀
+燒
+楿
+內
+粢
+葒
+奧
+麥
+礻
+滿
+蠔
+穵
+瞭
+態
+鱬
+榞
+硂
+鄭
+黃
+煙
+祐
+奓
+逺
+*
+瑄
+獲
+聞
+薦
+讀
+這
+樣
+決
+問
+啟
+們
+執
+説
+轉
+單
+隨
+唘
+帶
+倉
+庫
+還
+贈
+尙
+皺
+■
+餅
+產
+○
+∈
+報
+狀
+楓
+賠
+琯
+嗮
+禮
+`
+傳
+>
+≤
+嗞
+≥
+換
+咭
+∣
+↓
+曬
+応
+寫
+″
+終
+様
+純
+費
+療
+聨
+凍
+壐
+郵
+黒
+∫
+製
+塊
+調
+軽
+確
+撃
+級
+馴
+Ⅲ
+涇
+繹
+數
+碼
+證
+狒
+処
+劑
+<
+晧
+賀
+衆
+]
+櫥
+兩
+陰
+絶
+對
+鯉
+憶
+◎
+p
+e
+Y
+蕒
+煖
+頓
+測
+試
+鼽
+僑
+碩
+妝
+帯
+≈
+鐡
+舖
+權
+喫
+倆
+該
+悅
+俫
+.
+f
+s
+b
+m
+k
+g
+u
+j
+貼
+淨
+濕
+針
+適
+備
+l
+/
+給
+謢
+強
+觸
+衛
+與
+⊙
+$
+緯
+變
+⑴
+⑵
+⑶
+㎏
+殺
+∩
+幚
+─
+價
+▲
+離
+飄
+烏
+関
+閟
+﹝
+﹞
+邏
+輯
+鍵
+驗
+訣
+導
+歷
+屆
+層
+▼
+儱
+錄
+熳
+艦
+吋
+錶
+辧
+飼
+顯
+④
+禦
+販
+気
+対
+枰
+閩
+紀
+幹
+瞓
+貊
+淚
+△
+眞
+墊
+獻
+褲
+縫
+緑
+亜
+鉅
+餠
+{
+}
+◆
+蘆
+薈
+█
+◇
+溫
+彈
+晳
+粧
+犸
+穩
+訊
+崬
+凖
+熥
+舊
+條
+紋
+圍
+Ⅳ
+筆
+尷
+難
+雜
+錯
+綁
+識
+頰
+鎖
+艶
+□
+殁
+殼
+⑧
+├
+▕
+鵬
+糝
+綱
+▎
+盜
+饅
+醬
+籤
+蓋
+釀
+鹽
+據
+辦
+◥
+彐
+┌
+婦
+獸
+鲩
+伱
+蒟
+蒻
+齊
+袆
+腦
+寧
+凈
+妳
+煥
+詢
+偽
+謹
+啫
+鯽
+騷
+鱸
+損
+傷
+鎻
+髮
+買
+冏
+儥
+両
+﹢
+∞
+載
+喰
+z
+羙
+悵
+燙
+曉
+員
+組
+徹
+艷
+痠
+鋼
+鼙
+縮
+細
+嚒
+爯
+≠
+維
+"
+鱻
+壇
+厍
+帰
+浥
+犇
+薡
+軎
+應
+醜
+刪
+緻
+鶴
+賜
+噁
+軌
+尨
+镔
+鷺
+槗
+彌
+葚
+濛
+請
+溇
+緹
+賢
+訪
+獴
+瑅
+資
+縤
+陣
+蕟
+栢
+韻
+祼
+恁
+伢
+謝
+劃
+涑
+總
+衖
+踺
+砋
+凉
+籃
+駿
+苼
+瘋
+昽
+紡
+驊
+腎
+﹗
+響
+杋
+剛
+嚴
+禪
+歓
+槍
+傘
+檸
+檫
+炣
+勢
+鏜
+鎢
+銑
+尐
+減
+奪
+惡
+僮
+婭
+臘
+殻
+鉄
+∑
+蛲
+焼
+緖
+續
+紹
+懮

+ 8421 - 0
models/ocr/Keys/中文繁体.txt

@@ -0,0 +1,8421 @@
+!
+"
+#
+$
+%
+&
+'
+(
+)
+*
++
+,
+-
+.
+/
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+:
+;
+<
+=
+>
+?
+@
+A
+B
+C
+D
+E
+F
+G
+H
+I
+J
+K
+L
+M
+N
+O
+P
+Q
+R
+S
+T
+U
+V
+W
+X
+Y
+Z
+[
+\
+]
+^
+_
+`
+a
+b
+c
+d
+e
+f
+g
+h
+i
+j
+k
+l
+m
+n
+o
+p
+q
+r
+s
+t
+u
+v
+w
+x
+y
+z
+{
+|
+}
+~
+—
+‖
+‘
+’
+“
+”
+•
+…
+‧
+′
+″
+※
+℃
+№
+™
+Ⅱ
+Ⅲ
+Ⅳ
+←
+↑
+→
+↓
+⇋
+∈
+∑
+√
+∞
+∣
+∧
+∩
+∫
+∶
+≈
+≠
+≤
+≥
+⊙
+⊥
+①
+②
+③
+④
+⑧
+⑴
+⑵
+⑶
+─
+│
+┅
+┌
+├
+█
+▎
+▏
+▕
+■
+□
+▪
+▲
+△
+▼
+◆
+◇
+○
+◎
+●
+◥
+★
+☆
+❋
+❤
+ 
+、
+。
+〇
+〉
+《
+》
+「
+」
+『
+』
+【
+】
+〔
+〕
+〖
+〗
+の
+サ
+シ
+ジ
+マ
+ㄱ
+ㆍ
+㎏
+㎡
+㐂
+㐱
+㙟
+㴪
+㸃
+䖝
+䝉
+䰾
+䲁
+一
+丁
+七
+丄
+丈
+三
+上
+下
+丌
+不
+与
+丏
+丐
+丑
+且
+丕
+世
+丘
+丙
+丞
+丟
+両
+並
+丨
+丫
+中
+丰
+串
+丶
+丸
+丹
+主
+丼
+丿
+乂
+乃
+久
+么
+之
+乍
+乎
+乏
+乒
+乓
+乖
+乗
+乘
+乙
+乚
+乜
+九
+乞
+也
+乩
+乭
+乳
+乸
+乹
+乾
+亀
+亂
+亅
+了
+予
+亊
+事
+二
+亍
+云
+互
+亓
+五
+井
+亘
+些
+亜
+亞
+亟
+亠
+亡
+亢
+交
+亥
+亦
+亨
+享
+京
+亭
+亮
+亰
+亳
+亶
+亹
+人
+亻
+什
+仁
+仂
+仃
+仄
+仇
+仉
+今
+介
+仍
+仏
+仔
+仕
+他
+仗
+付
+仙
+仛
+仝
+仞
+仟
+仡
+代
+令
+以
+仨
+仫
+仮
+仰
+仲
+仳
+仵
+件
+仺
+任
+仼
+份
+仿
+企
+伃
+伈
+伉
+伊
+伋
+伍
+伎
+伏
+伐
+休
+伕
+伙
+伝
+伢
+伯
+估
+伱
+伴
+伶
+伷
+伸
+伺
+似
+伽
+伾
+佀
+佁
+佃
+但
+佇
+佈
+佉
+佋
+位
+低
+住
+佐
+佑
+体
+佔
+何
+佗
+佘
+余
+佚
+佛
+作
+佝
+佞
+佟
+你
+佣
+佤
+佧
+佩
+佬
+佯
+佰
+佳
+併
+佶
+佹
+佺
+佼
+佾
+使
+侁
+侃
+侄
+侅
+來
+侈
+侊
+例
+侍
+侏
+侑
+侖
+侗
+侘
+侚
+供
+依
+侞
+価
+侮
+侯
+侵
+侶
+侷
+侹
+便
+俁
+係
+促
+俄
+俅
+俊
+俋
+俌
+俍
+俎
+俏
+俐
+俑
+俗
+俘
+俚
+俛
+保
+俞
+俟
+俠
+信
+俬
+修
+俯
+俱
+俳
+俴
+俵
+俶
+俸
+俺
+俽
+俾
+倆
+倈
+倉
+個
+倌
+倍
+們
+倒
+倓
+倔
+倖
+倗
+倘
+候
+倚
+倜
+倞
+借
+倡
+倢
+倣
+値
+倦
+倧
+倩
+倪
+倫
+倬
+倭
+倮
+倻
+值
+偁
+偃
+假
+偈
+偉
+偊
+偌
+偍
+偎
+偏
+偓
+偕
+做
+停
+健
+偪
+偲
+側
+偵
+偶
+偷
+偸
+偽
+傀
+傃
+傅
+傈
+傉
+傍
+傑
+傒
+傕
+傖
+傘
+備
+傜
+傢
+傣
+催
+傭
+傲
+傳
+債
+傷
+傻
+傾
+僅
+僉
+僊
+働
+像
+僑
+僔
+僕
+僖
+僙
+僚
+僜
+僡
+僧
+僩
+僭
+僮
+僰
+僱
+僳
+僴
+僵
+價
+僻
+儀
+儁
+儂
+億
+儆
+儇
+儈
+儉
+儋
+儐
+儒
+儔
+儕
+儘
+儚
+儞
+償
+儡
+儥
+儦
+優
+儫
+儱
+儲
+儷
+儺
+儻
+儼
+兀
+允
+元
+兄
+充
+兆
+先
+光
+克
+兌
+免
+児
+兒
+兔
+兕
+兗
+兜
+入
+內
+全
+兩
+兪
+八
+公
+六
+兮
+共
+兵
+其
+具
+典
+兼
+兿
+冀
+冂
+円
+冇
+冉
+冊
+再
+冏
+冑
+冒
+冕
+冖
+冗
+冚
+冠
+冢
+冤
+冥
+冧
+冨
+冪
+冫
+冬
+冮
+冰
+冴
+冶
+冷
+冼
+冽
+凃
+凄
+准
+凈
+凋
+凌
+凍
+凖
+凜
+凝
+凞
+几
+凡
+処
+凪
+凬
+凰
+凱
+凳
+凵
+凶
+凸
+凹
+出
+函
+刀
+刁
+刂
+刃
+刄
+分
+切
+刈
+刊
+刎
+刑
+划
+列
+初
+判
+別
+刦
+刧
+刨
+利
+刪
+刮
+到
+制
+刷
+券
+刺
+刻
+刼
+剁
+剃
+則
+削
+剋
+剌
+前
+剎
+剏
+剔
+剖
+剛
+剝
+剡
+剣
+剩
+剪
+剮
+副
+割
+創
+剿
+劃
+劄
+劇
+劈
+劉
+劊
+劌
+劍
+劑
+劔
+力
+功
+加
+劣
+助
+努
+劫
+劬
+劭
+劵
+効
+劼
+劾
+勁
+勃
+勅
+勇
+勉
+勐
+勑
+勒
+勔
+動
+勖
+勗
+勘
+務
+勛
+勝
+勞
+募
+勢
+勣
+勤
+勦
+勰
+勱
+勲
+勳
+勵
+勷
+勸
+勺
+勻
+勾
+勿
+匂
+匄
+包
+匆
+匈
+匋
+匍
+匏
+匐
+匕
+化
+北
+匙
+匚
+匝
+匠
+匡
+匣
+匪
+匯
+匱
+匸
+匹
+匾
+匿
+區
+十
+千
+卅
+升
+午
+卉
+半
+卋
+卍
+卐
+卑
+卒
+卓
+協
+南
+博
+卜
+卞
+卟
+占
+卡
+卣
+卦
+卧
+卩
+卬
+卮
+卯
+印
+危
+卲
+即
+卵
+卷
+卸
+卹
+卺
+卻
+卽
+卿
+厄
+厓
+厔
+厙
+厚
+厝
+原
+厥
+厭
+厰
+厲
+厴
+厶
+去
+參
+叄
+又
+叉
+及
+友
+反
+収
+叔
+叕
+取
+受
+叛
+叟
+叡
+叢
+口
+古
+句
+另
+叨
+叩
+只
+叫
+召
+叭
+叮
+可
+台
+叱
+史
+右
+叵
+司
+叻
+叼
+吁
+吃
+各
+吆
+合
+吉
+吊
+吋
+同
+名
+后
+吏
+吐
+向
+吒
+吔
+吖
+君
+吝
+吞
+吟
+吠
+吡
+吥
+否
+吧
+吩
+含
+吮
+吱
+吲
+吳
+吵
+吶
+吸
+吹
+吻
+吼
+吾
+呀
+呂
+呃
+呈
+呉
+告
+呋
+呎
+呢
+呤
+呦
+周
+呱
+味
+呵
+呷
+呸
+呼
+命
+呾
+咀
+咁
+咂
+咄
+咅
+咆
+咋
+和
+咎
+咑
+咒
+咔
+咕
+咖
+咗
+咘
+咚
+咟
+咤
+咥
+咧
+咨
+咩
+咪
+咫
+咬
+咭
+咯
+咱
+咲
+咳
+咸
+咻
+咼
+咽
+咾
+咿
+哀
+品
+哂
+哄
+哆
+哇
+哈
+哉
+哌
+哎
+哏
+哐
+哖
+哚
+哞
+員
+哥
+哦
+哨
+哩
+哪
+哭
+哮
+哱
+哲
+哺
+哼
+唃
+唄
+唆
+唇
+唉
+唏
+唐
+唑
+唔
+唘
+唧
+唫
+唬
+唭
+售
+唯
+唱
+唳
+唵
+唷
+唸
+唻
+唾
+啁
+啃
+啄
+商
+啉
+啊
+啍
+問
+啓
+啖
+啚
+啜
+啞
+啟
+啡
+啣
+啤
+啥
+啦
+啪
+啫
+啯
+啰
+啱
+啲
+啵
+啶
+啷
+啻
+啼
+啾
+喀
+喂
+喃
+善
+喆
+喇
+喈
+喉
+喊
+喋
+喏
+喔
+喘
+喙
+喚
+喜
+喝
+喢
+喦
+喧
+喪
+喫
+喬
+單
+喰
+喱
+喲
+喳
+喵
+喹
+喻
+喼
+嗄
+嗅
+嗆
+嗇
+嗊
+嗎
+嗑
+嗒
+嗓
+嗔
+嗖
+嗚
+嗜
+嗝
+嗞
+嗡
+嗢
+嗣
+嗦
+嗨
+嗩
+嗪
+嗮
+嗯
+嗲
+嗶
+嗹
+嗽
+嘀
+嘅
+嘆
+嘉
+嘌
+嘍
+嘎
+嘏
+嘔
+嘗
+嘚
+嘛
+嘜
+嘞
+嘟
+嘢
+嘣
+嘥
+嘧
+嘩
+嘬
+嘮
+嘯
+嘰
+嘲
+嘴
+嘶
+嘸
+嘹
+嘻
+嘿
+噁
+噌
+噍
+噏
+噓
+噗
+噝
+噠
+噢
+噤
+噥
+噦
+器
+噩
+噪
+噬
+噯
+噰
+噲
+噴
+噶
+噸
+噹
+噻
+嚇
+嚈
+嚎
+嚏
+嚐
+嚒
+嚓
+嚕
+嚗
+嚙
+嚞
+嚟
+嚤
+嚦
+嚧
+嚨
+嚩
+嚮
+嚳
+嚴
+嚶
+嚷
+嚼
+嚿
+囀
+囂
+囃
+囉
+囊
+囍
+囑
+囒
+囓
+囗
+囚
+四
+囝
+回
+因
+囡
+団
+囤
+囧
+囪
+囮
+囯
+困
+囲
+図
+囶
+囷
+囹
+固
+囿
+圂
+圃
+圄
+圈
+圉
+國
+圍
+圏
+園
+圓
+圖
+圗
+團
+圜
+土
+圧
+在
+圩
+圪
+圭
+圯
+地
+圳
+圻
+圾
+址
+均
+坊
+坋
+坌
+坍
+坎
+坐
+坑
+坖
+坡
+坣
+坤
+坦
+坨
+坩
+坪
+坫
+坬
+坭
+坮
+坯
+坳
+坵
+坶
+坷
+坻
+垂
+垃
+垈
+型
+垍
+垓
+垕
+垚
+垛
+垞
+垟
+垠
+垢
+垣
+垮
+垯
+垰
+垵
+垸
+垻
+垿
+埃
+埅
+埇
+埈
+埋
+埌
+城
+埏
+埒
+埔
+埕
+埗
+埜
+域
+埠
+埡
+埤
+埧
+埨
+埪
+埭
+埮
+埴
+埵
+執
+培
+基
+埻
+埼
+堀
+堂
+堃
+堅
+堆
+堇
+堈
+堉
+堊
+堍
+堖
+堝
+堡
+堤
+堦
+堪
+堮
+堯
+堰
+報
+場
+堵
+堷
+堺
+塀
+塅
+塆
+塊
+塋
+塌
+塍
+塏
+塑
+塔
+塗
+塘
+塙
+塜
+塞
+塡
+塢
+塤
+塨
+塩
+填
+塬
+塭
+塰
+塱
+塲
+塵
+塹
+塽
+塾
+墀
+境
+墅
+墉
+墊
+墎
+墓
+増
+墘
+墜
+增
+墟
+墡
+墣
+墨
+墩
+墫
+墬
+墮
+墱
+墳
+墺
+墼
+墾
+壁
+壄
+壆
+壇
+壋
+壌
+壎
+壐
+壑
+壓
+壔
+壕
+壘
+壙
+壞
+壟
+壠
+壢
+壤
+壩
+士
+壬
+壯
+壱
+壴
+壹
+壺
+壽
+夀
+夆
+変
+夊
+夋
+夌
+夏
+夔
+夕
+外
+夙
+多
+夜
+夠
+夢
+夤
+夥
+大
+天
+太
+夫
+夬
+夭
+央
+夯
+失
+夷
+夾
+奀
+奄
+奇
+奈
+奉
+奎
+奏
+奐
+契
+奓
+奔
+奕
+套
+奘
+奚
+奠
+奢
+奣
+奧
+奩
+奪
+奫
+奭
+奮
+女
+奴
+奶
+她
+好
+妀
+妁
+如
+妃
+妄
+妊
+妍
+妏
+妑
+妒
+妓
+妖
+妙
+妝
+妞
+妠
+妤
+妥
+妧
+妨
+妭
+妮
+妯
+妲
+妳
+妸
+妹
+妺
+妻
+妾
+姀
+姁
+姃
+姆
+姈
+姉
+姊
+始
+姌
+姍
+姐
+姑
+姒
+姓
+委
+姚
+姜
+姝
+姣
+姥
+姦
+姨
+姪
+姫
+姬
+姮
+姵
+姶
+姸
+姻
+姿
+威
+娃
+娉
+娋
+娌
+娍
+娎
+娑
+娖
+娘
+娛
+娜
+娟
+娠
+娣
+娥
+娩
+娫
+娳
+娶
+娸
+娼
+娽
+婀
+婁
+婆
+婉
+婊
+婑
+婕
+婚
+婢
+婦
+婧
+婪
+婭
+婯
+婷
+婺
+婻
+婼
+婿
+媃
+媄
+媊
+媐
+媒
+媓
+媖
+媗
+媚
+媛
+媜
+媞
+媧
+媭
+媯
+媲
+媳
+媺
+媼
+媽
+媾
+媿
+嫁
+嫂
+嫄
+嫈
+嫉
+嫌
+嫖
+嫘
+嫚
+嫡
+嫣
+嫦
+嫩
+嫪
+嫲
+嫳
+嫵
+嫺
+嫻
+嬅
+嬈
+嬉
+嬋
+嬌
+嬗
+嬛
+嬝
+嬡
+嬤
+嬨
+嬪
+嬬
+嬭
+嬰
+嬴
+嬸
+嬾
+嬿
+孀
+孃
+孆
+孋
+孌
+子
+孑
+孔
+孕
+孖
+字
+存
+孚
+孛
+孜
+孝
+孟
+孢
+季
+孤
+孩
+孫
+孬
+孮
+孰
+孳
+孵
+學
+孺
+孻
+孽
+孿
+宀
+它
+宅
+宇
+守
+安
+宋
+完
+宍
+宏
+宓
+宕
+宗
+官
+宙
+定
+宛
+宜
+実
+客
+宣
+室
+宥
+宦
+宧
+宮
+宰
+害
+宴
+宵
+家
+宸
+容
+宿
+寀
+寁
+寂
+寄
+寅
+密
+寇
+寈
+寊
+富
+寐
+寒
+寓
+寔
+寕
+寖
+寗
+寘
+寛
+寜
+寞
+察
+寡
+寢
+寤
+寥
+實
+寧
+寨
+審
+寫
+寬
+寮
+寯
+寰
+寳
+寵
+寶
+寸
+寺
+対
+封
+専
+尃
+射
+將
+專
+尉
+尊
+尋
+對
+導
+小
+尐
+少
+尓
+尕
+尖
+尗
+尙
+尚
+尢
+尤
+尨
+尪
+尬
+就
+尷
+尹
+尺
+尻
+尼
+尾
+尿
+局
+屁
+屄
+居
+屆
+屇
+屈
+屋
+屌
+屍
+屎
+屏
+屐
+屑
+屓
+展
+屚
+屜
+屠
+屢
+層
+履
+屬
+屭
+屯
+山
+屹
+屺
+屻
+岀
+岈
+岌
+岐
+岑
+岔
+岡
+岢
+岣
+岧
+岩
+岪
+岫
+岬
+岰
+岱
+岳
+岵
+岷
+岸
+岻
+峁
+峅
+峇
+峋
+峍
+峒
+峘
+峙
+峚
+峠
+峨
+峩
+峪
+峭
+峯
+峰
+峴
+島
+峻
+峼
+峽
+崁
+崆
+崇
+崈
+崋
+崍
+崎
+崐
+崑
+崒
+崔
+崖
+崗
+崘
+崙
+崚
+崛
+崞
+崟
+崠
+崢
+崤
+崧
+崩
+崬
+崮
+崱
+崴
+崵
+崶
+崽
+嵇
+嵊
+嵋
+嵌
+嵎
+嵐
+嵒
+嵕
+嵖
+嵗
+嵙
+嵛
+嵜
+嵨
+嵩
+嵬
+嵮
+嵯
+嵰
+嵴
+嵻
+嵿
+嶁
+嶂
+嶃
+嶄
+嶇
+嶋
+嶌
+嶍
+嶒
+嶔
+嶗
+嶝
+嶠
+嶢
+嶦
+嶧
+嶪
+嶬
+嶰
+嶲
+嶴
+嶷
+嶸
+嶺
+嶼
+嶽
+巂
+巄
+巆
+巋
+巌
+巍
+巎
+巑
+巒
+巔
+巖
+巘
+巛
+川
+州
+巡
+巢
+工
+左
+巧
+巨
+巫
+差
+巰
+己
+已
+巳
+巴
+巶
+巷
+巻
+巽
+巾
+巿
+市
+布
+帆
+希
+帑
+帔
+帕
+帖
+帘
+帙
+帚
+帛
+帝
+帡
+帢
+帥
+師
+席
+帯
+帰
+帳
+帶
+帷
+常
+帽
+幀
+幃
+幄
+幅
+幌
+幔
+幕
+幗
+幚
+幛
+幟
+幡
+幢
+幣
+幪
+幫
+干
+平
+年
+幵
+幷
+幸
+幹
+幺
+幻
+幼
+幽
+幾
+庀
+庁
+広
+庇
+床
+序
+底
+庖
+店
+庚
+府
+庠
+庢
+庥
+度
+座
+庫
+庭
+庲
+庵
+庶
+康
+庸
+庹
+庼
+庾
+廁
+廂
+廄
+廆
+廈
+廉
+廊
+廋
+廌
+廍
+廑
+廓
+廔
+廕
+廖
+廙
+廚
+廝
+廞
+廟
+廠
+廡
+廢
+廣
+廧
+廨
+廩
+廬
+廰
+廱
+廳
+延
+廷
+廸
+建
+廻
+廼
+廿
+弁
+弄
+弅
+弇
+弈
+弉
+弊
+弋
+弍
+式
+弐
+弒
+弓
+弔
+引
+弖
+弗
+弘
+弛
+弟
+弢
+弦
+弧
+弨
+弩
+弭
+弱
+張
+強
+弸
+弼
+弾
+彀
+彄
+彅
+彆
+彈
+彊
+彌
+彎
+彐
+彔
+彖
+彗
+彘
+彙
+彜
+彞
+彠
+彡
+形
+彣
+彤
+彥
+彧
+彩
+彪
+彫
+彬
+彭
+彰
+影
+彳
+彷
+役
+彼
+彿
+往
+征
+徂
+待
+徇
+很
+徉
+徊
+律
+後
+徐
+徑
+徒
+得
+徘
+徙
+徜
+從
+徠
+御
+徧
+徨
+復
+循
+徫
+徬
+徭
+微
+徳
+徴
+徵
+德
+徸
+徹
+徽
+心
+忄
+必
+忉
+忌
+忍
+忐
+忑
+忒
+志
+忘
+忙
+応
+忝
+忞
+忠
+快
+忬
+忯
+忱
+忳
+念
+忻
+忽
+忿
+怍
+怎
+怒
+怕
+怖
+怙
+怛
+思
+怠
+怡
+急
+怦
+性
+怨
+怪
+怯
+怵
+恁
+恂
+恃
+恆
+恊
+恍
+恐
+恕
+恙
+恢
+恣
+恤
+恥
+恨
+恩
+恪
+恬
+恭
+息
+恰
+恵
+恿
+悄
+悅
+悆
+悉
+悌
+悍
+悔
+悖
+悚
+悛
+悝
+悞
+悟
+悠
+患
+悧
+您
+悪
+悰
+悲
+悳
+悵
+悶
+悸
+悼
+情
+惆
+惇
+惑
+惔
+惕
+惘
+惚
+惜
+惟
+惠
+惡
+惣
+惦
+惰
+惱
+惲
+想
+惶
+惹
+惺
+愁
+愃
+愆
+愈
+愉
+愍
+意
+愐
+愒
+愔
+愕
+愚
+愛
+愜
+感
+愣
+愧
+愨
+愫
+愭
+愴
+愷
+愼
+愾
+愿
+慄
+慈
+態
+慌
+慎
+慕
+慘
+慚
+慜
+慟
+慢
+慣
+慥
+慧
+慨
+慮
+慰
+慳
+慵
+慶
+慷
+慾
+憂
+憊
+憋
+憍
+憎
+憐
+憑
+憓
+憕
+憙
+憚
+憤
+憧
+憨
+憩
+憫
+憬
+憲
+憶
+憺
+憻
+憾
+懂
+懃
+懇
+懈
+應
+懋
+懌
+懍
+懐
+懣
+懦
+懮
+懲
+懵
+懶
+懷
+懸
+懺
+懼
+懽
+懾
+懿
+戀
+戇
+戈
+戊
+戌
+戍
+戎
+成
+我
+戒
+戔
+戕
+或
+戙
+戚
+戛
+戟
+戡
+戢
+戥
+戦
+戩
+截
+戮
+戰
+戱
+戲
+戳
+戴
+戶
+戸
+戻
+戽
+戾
+房
+所
+扁
+扆
+扇
+扈
+扉
+手
+扌
+才
+扎
+扒
+打
+扔
+托
+扙
+扛
+扞
+扣
+扥
+扦
+扭
+扮
+扯
+扳
+扶
+批
+扼
+找
+承
+技
+抃
+抄
+抇
+抉
+把
+抑
+抒
+抓
+投
+抖
+抗
+折
+抦
+披
+抬
+抱
+抵
+抹
+抻
+押
+抽
+抿
+拂
+拆
+拇
+拈
+拉
+拋
+拌
+拍
+拎
+拏
+拐
+拒
+拓
+拔
+拖
+拗
+拘
+拙
+拚
+招
+拜
+拝
+拡
+括
+拭
+拮
+拯
+拱
+拳
+拴
+拷
+拺
+拼
+拽
+拾
+拿
+持
+指
+按
+挎
+挑
+挖
+挙
+挨
+挪
+挫
+振
+挲
+挵
+挹
+挺
+挻
+挾
+捂
+捆
+捉
+捌
+捍
+捎
+捏
+捐
+捒
+捕
+捜
+捦
+捧
+捨
+捩
+捫
+捭
+捱
+捲
+捶
+捷
+捺
+捻
+掀
+掂
+掃
+掄
+掇
+授
+掉
+掌
+掏
+掐
+排
+掖
+掘
+掙
+掛
+掞
+掟
+掠
+採
+探
+掣
+接
+控
+推
+掩
+措
+掬
+掰
+掾
+揀
+揄
+揆
+揉
+揍
+描
+提
+插
+揔
+揖
+揚
+換
+握
+揪
+揭
+揮
+援
+揸
+揺
+損
+搏
+搐
+搓
+搔
+搖
+搗
+搜
+搞
+搠
+搢
+搪
+搬
+搭
+搳
+搴
+搵
+搶
+搽
+搾
+摂
+摒
+摔
+摘
+摜
+摞
+摟
+摠
+摧
+摩
+摭
+摯
+摳
+摴
+摵
+摶
+摸
+摹
+摺
+摻
+摽
+撃
+撇
+撈
+撐
+撒
+撓
+撕
+撖
+撙
+撚
+撞
+撣
+撤
+撥
+撩
+撫
+撬
+播
+撮
+撰
+撲
+撳
+撻
+撼
+撾
+撿
+擀
+擁
+擂
+擅
+擇
+擊
+擋
+操
+擎
+擒
+擔
+擘
+據
+擠
+擢
+擥
+擦
+擬
+擯
+擰
+擱
+擲
+擴
+擷
+擺
+擼
+擾
+攀
+攏
+攔
+攖
+攘
+攜
+攝
+攞
+攢
+攣
+攤
+攪
+攫
+攬
+支
+攴
+攵
+收
+攷
+攸
+改
+攻
+攽
+放
+政
+故
+效
+敍
+敎
+敏
+救
+敔
+敕
+敖
+敗
+敘
+教
+敝
+敞
+敟
+敢
+散
+敦
+敫
+敬
+敭
+敲
+整
+敵
+敷
+數
+敻
+敾
+斂
+斃
+文
+斌
+斎
+斐
+斑
+斕
+斖
+斗
+料
+斛
+斜
+斝
+斟
+斡
+斤
+斥
+斧
+斬
+斯
+新
+斷
+方
+於
+施
+斿
+旁
+旂
+旃
+旄
+旅
+旉
+旋
+旌
+旎
+族
+旖
+旗
+旙
+旛
+旡
+既
+日
+旦
+旨
+早
+旬
+旭
+旱
+旲
+旳
+旺
+旻
+旼
+旽
+旾
+旿
+昀
+昂
+昃
+昆
+昇
+昉
+昊
+昌
+昍
+明
+昏
+昐
+易
+昔
+昕
+昚
+昛
+昜
+昝
+昞
+星
+映
+昡
+昣
+昤
+春
+昧
+昨
+昪
+昫
+昭
+是
+昰
+昱
+昴
+昵
+昶
+昺
+晁
+時
+晃
+晈
+晉
+晊
+晏
+晗
+晙
+晚
+晛
+晝
+晞
+晟
+晤
+晦
+晧
+晨
+晩
+晪
+晫
+晭
+普
+景
+晰
+晳
+晴
+晶
+晷
+晸
+智
+晾
+暃
+暄
+暅
+暇
+暈
+暉
+暊
+暌
+暎
+暏
+暐
+暑
+暕
+暖
+暗
+暘
+暝
+暟
+暠
+暢
+暦
+暨
+暫
+暮
+暱
+暲
+暴
+暸
+暹
+暻
+暾
+曄
+曅
+曆
+曇
+曉
+曌
+曔
+曖
+曙
+曜
+曝
+曠
+曦
+曧
+曨
+曩
+曬
+曮
+曰
+曲
+曳
+更
+曶
+曷
+書
+曹
+曺
+曼
+曽
+曾
+替
+最
+會
+月
+有
+朊
+朋
+服
+朏
+朐
+朓
+朔
+朕
+朖
+朗
+望
+朝
+期
+朦
+朧
+木
+未
+末
+本
+札
+朱
+朴
+朵
+朶
+朽
+朿
+杁
+杉
+杋
+杌
+李
+杏
+材
+村
+杓
+杖
+杙
+杜
+杞
+束
+杠
+杣
+杤
+杧
+杬
+杭
+杯
+東
+杲
+杳
+杴
+杵
+杷
+杻
+杼
+松
+板
+极
+枇
+枉
+枋
+枏
+析
+枕
+枖
+林
+枚
+枛
+果
+枝
+枠
+枡
+枯
+枰
+枱
+枲
+枳
+架
+枷
+枸
+枹
+枼
+柁
+柃
+柄
+柉
+柊
+柎
+柏
+某
+柑
+柒
+染
+柔
+柘
+柚
+柜
+柝
+柞
+柟
+查
+柩
+柬
+柯
+柰
+柱
+柳
+柴
+柵
+柶
+柷
+査
+柾
+柿
+栃
+栄
+栐
+栒
+栓
+栜
+栝
+栞
+校
+栢
+栨
+栩
+株
+栲
+栴
+核
+根
+栻
+格
+栽
+桀
+桁
+桂
+桃
+桄
+桅
+框
+案
+桉
+桌
+桎
+桐
+桑
+桓
+桔
+桕
+桖
+桙
+桜
+桝
+桫
+桱
+桲
+桴
+桶
+桷
+桼
+桿
+梀
+梁
+梂
+梃
+梅
+梆
+梉
+梏
+梓
+梔
+梗
+梘
+條
+梟
+梠
+梢
+梣
+梧
+梨
+梫
+梭
+梯
+械
+梱
+梳
+梵
+梶
+梽
+棄
+棆
+棉
+棋
+棍
+棐
+棒
+棓
+棕
+棖
+棗
+棘
+棚
+棛
+棟
+棠
+棡
+棣
+棧
+棨
+棩
+棪
+棫
+森
+棱
+棲
+棵
+棶
+棹
+棺
+棻
+棼
+棽
+椅
+椆
+椇
+椋
+植
+椎
+椏
+椒
+椙
+椥
+椪
+椰
+椲
+椴
+椵
+椹
+椽
+椿
+楂
+楊
+楓
+楔
+楗
+楙
+楚
+楝
+楞
+楠
+楡
+楢
+楣
+楤
+楦
+楧
+楨
+楫
+業
+楮
+楯
+楳
+極
+楷
+楸
+楹
+楽
+楿
+概
+榆
+榊
+榍
+榎
+榑
+榔
+榕
+榖
+榗
+榘
+榛
+榜
+榞
+榢
+榣
+榤
+榦
+榧
+榨
+榫
+榭
+榮
+榲
+榴
+榷
+榻
+榿
+槀
+槁
+槃
+槊
+構
+槌
+槍
+槎
+槐
+槓
+槔
+槗
+様
+槙
+槤
+槩
+槭
+槰
+槱
+槲
+槳
+槺
+槻
+槼
+槽
+槿
+樀
+樁
+樂
+樅
+樆
+樊
+樋
+樑
+樓
+樗
+樘
+標
+樞
+樟
+模
+樣
+樨
+権
+樫
+樵
+樸
+樹
+樺
+樻
+樽
+樾
+橄
+橇
+橈
+橋
+橐
+橒
+橓
+橘
+橙
+橚
+機
+橡
+橢
+橪
+橫
+橿
+檀
+檄
+檇
+檉
+檊
+檎
+檐
+檔
+檗
+檜
+檞
+檠
+檡
+檢
+檣
+檦
+檨
+檫
+檬
+檯
+檳
+檵
+檸
+檻
+檽
+櫂
+櫃
+櫆
+櫈
+櫓
+櫚
+櫛
+櫞
+櫟
+櫥
+櫨
+櫪
+櫱
+櫸
+櫻
+櫾
+櫿
+欄
+欉
+權
+欏
+欒
+欖
+欞
+欠
+次
+欣
+欥
+欲
+欸
+欹
+欺
+欽
+款
+歆
+歇
+歉
+歊
+歌
+歎
+歐
+歓
+歙
+歛
+歡
+止
+正
+此
+步
+武
+歧
+歩
+歪
+歲
+歳
+歴
+歷
+歸
+歹
+死
+歿
+殂
+殃
+殄
+殆
+殉
+殊
+殑
+殖
+殘
+殛
+殞
+殟
+殤
+殭
+殮
+殯
+殲
+殳
+段
+殷
+殺
+殻
+殼
+殿
+毀
+毅
+毆
+毉
+毋
+毌
+母
+毎
+每
+毐
+毒
+毓
+比
+毖
+毗
+毘
+毛
+毫
+毬
+毯
+毴
+毸
+毽
+毿
+氂
+氈
+氍
+氏
+氐
+民
+氓
+氖
+気
+氘
+氙
+氚
+氛
+氟
+氣
+氦
+氧
+氨
+氪
+氫
+氬
+氮
+氯
+氰
+水
+氵
+氷
+永
+氹
+氻
+氽
+氾
+汀
+汁
+求
+汊
+汎
+汐
+汕
+汗
+汛
+汜
+汝
+汞
+江
+池
+污
+汧
+汨
+汩
+汪
+汭
+汰
+汲
+汴
+汶
+決
+汽
+汾
+沁
+沂
+沃
+沄
+沅
+沆
+沇
+沈
+沉
+沌
+沍
+沏
+沐
+沒
+沓
+沔
+沖
+沘
+沙
+沚
+沛
+沜
+沢
+沨
+沫
+沭
+沮
+沯
+沱
+河
+沸
+油
+沺
+治
+沼
+沽
+沾
+沿
+況
+泂
+泄
+泆
+泇
+泉
+泊
+泌
+泐
+泓
+泔
+法
+泖
+泗
+泚
+泛
+泠
+泡
+波
+泣
+泥
+泩
+泫
+泮
+泯
+泰
+泱
+泳
+泵
+洄
+洋
+洌
+洎
+洗
+洙
+洛
+洞
+洢
+洣
+洤
+津
+洨
+洩
+洪
+洮
+洱
+洲
+洳
+洵
+洸
+洹
+洺
+活
+洽
+派
+流
+浄
+浙
+浚
+浛
+浜
+浞
+浟
+浠
+浡
+浣
+浤
+浥
+浦
+浩
+浪
+浮
+浯
+浴
+浵
+海
+浸
+浹
+涅
+涇
+消
+涉
+涌
+涎
+涑
+涓
+涔
+涕
+涙
+涪
+涫
+涮
+涯
+液
+涵
+涸
+涼
+涿
+淄
+淅
+淆
+淇
+淋
+淌
+淍
+淎
+淏
+淑
+淓
+淖
+淘
+淙
+淚
+淛
+淝
+淞
+淠
+淡
+淤
+淥
+淦
+淨
+淩
+淪
+淫
+淬
+淮
+淯
+淰
+深
+淳
+淵
+淶
+混
+淸
+淹
+淺
+添
+淼
+淽
+渃
+清
+済
+渉
+渋
+渕
+渙
+渚
+減
+渝
+渟
+渠
+渡
+渣
+渤
+渥
+渦
+渫
+測
+渭
+港
+渲
+渴
+游
+渺
+渼
+渽
+渾
+湃
+湄
+湉
+湊
+湍
+湓
+湔
+湖
+湘
+湛
+湜
+湞
+湟
+湣
+湥
+湧
+湫
+湮
+湯
+湳
+湴
+湼
+満
+溁
+溇
+溈
+溉
+溋
+溎
+溏
+源
+準
+溙
+溜
+溝
+溟
+溢
+溥
+溦
+溧
+溪
+溫
+溯
+溱
+溲
+溴
+溵
+溶
+溺
+溼
+滀
+滁
+滂
+滄
+滅
+滇
+滈
+滉
+滋
+滌
+滎
+滏
+滑
+滓
+滔
+滕
+滘
+滙
+滝
+滬
+滯
+滲
+滴
+滷
+滸
+滹
+滻
+滽
+滾
+滿
+漁
+漂
+漆
+漇
+漈
+漎
+漏
+漓
+演
+漕
+漚
+漠
+漢
+漣
+漩
+漪
+漫
+漬
+漯
+漱
+漲
+漳
+漴
+漵
+漷
+漸
+漼
+漾
+漿
+潁
+潑
+潔
+潘
+潛
+潞
+潟
+潢
+潤
+潭
+潮
+潯
+潰
+潲
+潺
+潼
+潽
+潾
+潿
+澀
+澁
+澂
+澄
+澆
+澇
+澈
+澉
+澋
+澌
+澍
+澎
+澔
+澗
+澠
+澡
+澣
+澤
+澥
+澧
+澪
+澮
+澯
+澱
+澳
+澶
+澹
+澻
+激
+濁
+濂
+濃
+濉
+濊
+濋
+濕
+濘
+濙
+濛
+濞
+濟
+濠
+濡
+濤
+濫
+濬
+濮
+濯
+濰
+濱
+濲
+濶
+濺
+濼
+濾
+瀁
+瀅
+瀆
+瀉
+瀍
+瀏
+瀑
+瀔
+瀕
+瀘
+瀚
+瀛
+瀝
+瀞
+瀟
+瀠
+瀣
+瀦
+瀧
+瀨
+瀬
+瀰
+瀲
+瀴
+瀶
+瀹
+瀾
+灃
+灊
+灌
+灑
+灘
+灝
+灞
+灡
+灣
+灤
+灧
+火
+灰
+灴
+灸
+灼
+災
+炁
+炅
+炆
+炊
+炎
+炒
+炔
+炕
+炘
+炙
+炟
+炣
+炤
+炫
+炬
+炭
+炮
+炯
+炱
+炲
+炳
+炷
+炸
+為
+炻
+烈
+烉
+烊
+烋
+烏
+烒
+烔
+烘
+烙
+烜
+烝
+烤
+烯
+烱
+烴
+烷
+烹
+烺
+烽
+焃
+焄
+焉
+焊
+焌
+焓
+焗
+焙
+焚
+焜
+焞
+無
+焦
+焯
+焰
+焱
+焴
+然
+焻
+焼
+焿
+煇
+煉
+煊
+煌
+煎
+煐
+煒
+煔
+煕
+煖
+煙
+煚
+煜
+煞
+煠
+煤
+煥
+煦
+照
+煨
+煩
+煬
+煮
+煲
+煳
+煵
+煶
+煸
+煽
+熄
+熅
+熇
+熈
+熊
+熏
+熒
+熔
+熖
+熗
+熘
+熙
+熜
+熟
+熠
+熤
+熥
+熨
+熬
+熯
+熱
+熲
+熳
+熵
+熹
+熺
+熼
+熾
+熿
+燁
+燃
+燄
+燈
+燉
+燊
+燎
+燏
+燐
+燒
+燔
+燕
+燘
+燙
+燚
+燜
+燝
+營
+燥
+燦
+燧
+燫
+燬
+燭
+燮
+燴
+燹
+燻
+燼
+燾
+燿
+爀
+爆
+爌
+爍
+爐
+爔
+爚
+爛
+爝
+爨
+爪
+爬
+爭
+爯
+爰
+爲
+爵
+父
+爸
+爹
+爺
+爻
+爽
+爾
+爿
+牁
+牂
+牆
+片
+版
+牌
+牒
+牕
+牖
+牘
+牙
+牛
+牝
+牟
+牠
+牡
+牢
+牧
+物
+牯
+牲
+特
+牻
+牼
+牽
+犀
+犁
+犂
+犇
+犍
+犎
+犖
+犛
+犢
+犧
+犨
+犬
+犯
+犰
+犴
+犽
+狀
+狂
+狄
+狍
+狎
+狐
+狒
+狓
+狗
+狙
+狛
+狟
+狠
+狡
+狦
+狨
+狩
+狳
+狶
+狷
+狸
+狹
+狻
+狼
+猁
+猄
+猇
+猊
+猗
+猙
+猛
+猜
+猝
+猞
+猢
+猥
+猨
+猩
+猳
+猴
+猶
+猷
+猺
+猻
+猾
+猿
+獁
+獃
+獄
+獅
+獇
+獎
+獏
+獐
+獒
+獠
+獢
+獣
+獨
+獬
+獮
+獯
+獰
+獲
+獴
+獵
+獷
+獸
+獺
+獻
+獼
+獾
+玀
+玄
+玆
+率
+玉
+王
+玎
+玏
+玓
+玕
+玖
+玗
+玘
+玙
+玟
+玠
+玡
+玢
+玥
+玧
+玨
+玩
+玫
+玭
+玲
+玳
+玶
+玷
+玹
+玻
+玾
+珀
+珂
+珅
+珈
+珉
+珊
+珌
+珍
+珎
+珏
+珖
+珙
+珝
+珞
+珠
+珡
+珣
+珤
+珥
+珦
+珧
+珩
+珪
+班
+珮
+珵
+珹
+珺
+珽
+現
+琁
+球
+琄
+琅
+理
+琇
+琉
+琊
+琍
+琎
+琚
+琛
+琡
+琢
+琤
+琥
+琦
+琨
+琪
+琬
+琮
+琯
+琰
+琱
+琳
+琴
+琵
+琶
+琹
+琺
+琿
+瑀
+瑁
+瑂
+瑄
+瑅
+瑆
+瑈
+瑊
+瑋
+瑑
+瑒
+瑕
+瑗
+瑙
+瑚
+瑛
+瑜
+瑝
+瑞
+瑟
+瑠
+瑢
+瑣
+瑤
+瑥
+瑧
+瑨
+瑩
+瑪
+瑭
+瑯
+瑰
+瑱
+瑳
+瑴
+瑺
+瑾
+璀
+璁
+璃
+璄
+璆
+璇
+璈
+璉
+璋
+璌
+璐
+璕
+璘
+璙
+璚
+璜
+璞
+璟
+璠
+璡
+璣
+璥
+璦
+璧
+璨
+璩
+璪
+璫
+璬
+璮
+環
+璱
+璵
+璸
+璹
+璽
+璿
+瓈
+瓊
+瓌
+瓏
+瓑
+瓔
+瓖
+瓘
+瓚
+瓛
+瓜
+瓞
+瓠
+瓢
+瓣
+瓤
+瓦
+瓮
+瓴
+瓶
+瓷
+瓿
+甂
+甄
+甌
+甍
+甑
+甕
+甘
+甙
+甚
+甜
+生
+甡
+產
+産
+甥
+甦
+用
+甩
+甪
+甫
+甬
+甯
+田
+由
+甲
+申
+男
+甸
+甹
+町
+甾
+畀
+畇
+畈
+畊
+畋
+界
+畎
+畏
+畐
+畑
+畔
+留
+畜
+畝
+畠
+畢
+略
+畦
+畧
+番
+畫
+畬
+畯
+異
+畲
+畳
+畵
+當
+畷
+畸
+畹
+畿
+疃
+疆
+疇
+疊
+疋
+疌
+疍
+疏
+疑
+疒
+疕
+疙
+疚
+疝
+疣
+疤
+疥
+疫
+疲
+疳
+疵
+疸
+疹
+疼
+疽
+疾
+痂
+病
+症
+痊
+痍
+痔
+痕
+痘
+痙
+痛
+痞
+痟
+痠
+痢
+痣
+痤
+痧
+痩
+痰
+痱
+痲
+痴
+痹
+痺
+痿
+瘀
+瘁
+瘊
+瘋
+瘍
+瘓
+瘙
+瘜
+瘞
+瘟
+瘠
+瘡
+瘢
+瘤
+瘦
+瘧
+瘩
+瘰
+瘴
+瘺
+癀
+療
+癆
+癇
+癌
+癒
+癖
+癘
+癜
+癟
+癡
+癢
+癤
+癥
+癩
+癬
+癭
+癮
+癯
+癰
+癱
+癲
+癸
+発
+登
+發
+白
+百
+皂
+的
+皆
+皇
+皈
+皋
+皎
+皐
+皓
+皖
+皙
+皚
+皛
+皝
+皞
+皮
+皰
+皴
+皷
+皸
+皺
+皿
+盂
+盃
+盅
+盆
+盈
+益
+盋
+盌
+盎
+盒
+盔
+盛
+盜
+盞
+盟
+盡
+監
+盤
+盥
+盦
+盧
+盨
+盩
+盪
+盫
+目
+盯
+盱
+盲
+直
+盷
+相
+盹
+盺
+盼
+盾
+眀
+省
+眉
+看
+県
+眙
+眛
+眜
+眞
+真
+眠
+眥
+眨
+眩
+眭
+眯
+眵
+眶
+眷
+眸
+眺
+眼
+眾
+着
+睇
+睛
+睜
+睞
+睡
+睢
+督
+睥
+睦
+睨
+睪
+睫
+睭
+睹
+睺
+睽
+睾
+睿
+瞄
+瞅
+瞋
+瞌
+瞎
+瞑
+瞓
+瞞
+瞢
+瞥
+瞧
+瞪
+瞫
+瞬
+瞭
+瞰
+瞳
+瞻
+瞼
+瞽
+瞿
+矇
+矍
+矗
+矚
+矛
+矜
+矞
+矢
+矣
+知
+矧
+矩
+短
+矮
+矯
+石
+矸
+矽
+砂
+砋
+砌
+砍
+砒
+研
+砝
+砢
+砥
+砦
+砧
+砩
+砫
+砭
+砮
+砯
+砰
+砲
+砳
+破
+砵
+砷
+砸
+砼
+硂
+硃
+硅
+硇
+硏
+硐
+硒
+硓
+硚
+硜
+硝
+硤
+硨
+硫
+硬
+硭
+硯
+硼
+碁
+碇
+碉
+碌
+碎
+碑
+碓
+碕
+碗
+碘
+碚
+碟
+碡
+碣
+碧
+碩
+碪
+碭
+碰
+碲
+碳
+碴
+碶
+碸
+確
+碻
+碼
+碽
+碾
+磁
+磅
+磊
+磋
+磐
+磔
+磕
+磘
+磙
+磚
+磜
+磡
+磨
+磪
+磬
+磯
+磱
+磲
+磵
+磷
+磺
+磻
+磾
+礁
+礄
+礎
+礐
+礑
+礒
+礙
+礠
+礦
+礪
+礫
+礬
+礮
+礱
+礴
+示
+礻
+礽
+社
+祀
+祁
+祂
+祆
+祇
+祈
+祉
+祋
+祏
+祐
+祓
+祕
+祖
+祗
+祙
+祚
+祛
+祜
+祝
+神
+祟
+祠
+祥
+祧
+票
+祭
+祹
+祺
+祼
+祿
+禁
+禃
+禇
+禍
+禎
+福
+禑
+禓
+禔
+禕
+禘
+禛
+禟
+禠
+禤
+禦
+禧
+禨
+禩
+禪
+禮
+禰
+禱
+禵
+禹
+禺
+禼
+禽
+禾
+禿
+秀
+私
+秈
+秉
+秋
+科
+秒
+秕
+秘
+租
+秠
+秣
+秤
+秦
+秧
+秩
+秭
+秳
+秸
+移
+稀
+稅
+稈
+稉
+程
+稍
+稑
+稔
+稗
+稘
+稙
+稚
+稜
+稞
+稟
+稠
+種
+稱
+稲
+稷
+稹
+稺
+稻
+稼
+稽
+稾
+稿
+穀
+穂
+穆
+穈
+穉
+穌
+積
+穎
+穗
+穟
+穠
+穡
+穢
+穣
+穩
+穫
+穰
+穴
+穵
+究
+穹
+空
+穿
+突
+窄
+窅
+窈
+窋
+窒
+窕
+窖
+窗
+窘
+窟
+窠
+窣
+窨
+窩
+窪
+窮
+窯
+窰
+窶
+窺
+窿
+竄
+竅
+竇
+竈
+竊
+立
+竑
+站
+竜
+竟
+章
+竣
+童
+竦
+竩
+竭
+端
+競
+竹
+竺
+竻
+竿
+笄
+笆
+笈
+笏
+笑
+笘
+笙
+笛
+笞
+笠
+笥
+符
+笨
+笩
+笪
+第
+笭
+笮
+笯
+笱
+笳
+笹
+筅
+筆
+等
+筊
+筋
+筌
+筍
+筏
+筐
+筒
+答
+策
+筘
+筠
+筥
+筦
+筧
+筬
+筭
+筱
+筲
+筳
+筵
+筶
+筷
+筻
+箆
+箇
+箋
+箍
+箏
+箐
+箑
+箒
+箔
+箕
+算
+箜
+管
+箬
+箭
+箱
+箴
+箸
+節
+篁
+範
+篆
+篇
+築
+篊
+篋
+篌
+篔
+篙
+篝
+篠
+篡
+篤
+篥
+篦
+篩
+篪
+篭
+篯
+篳
+篷
+簀
+簃
+簇
+簉
+簋
+簍
+簑
+簕
+簗
+簞
+簠
+簡
+簧
+簪
+簫
+簷
+簸
+簹
+簺
+簽
+簾
+簿
+籀
+籃
+籌
+籍
+籐
+籙
+籛
+籜
+籝
+籟
+籠
+籣
+籤
+籥
+籪
+籬
+籮
+籲
+米
+籽
+籾
+粄
+粉
+粍
+粑
+粒
+粕
+粗
+粘
+粟
+粢
+粥
+粦
+粧
+粩
+粱
+粲
+粳
+粵
+粹
+粼
+粽
+精
+粿
+糀
+糅
+糊
+糌
+糍
+糎
+糕
+糖
+糙
+糜
+糝
+糞
+糟
+糠
+糢
+糧
+糬
+糯
+糰
+糴
+糶
+糸
+糹
+糺
+系
+糾
+紀
+紂
+約
+紅
+紆
+紇
+紈
+紉
+紊
+紋
+納
+紐
+紑
+紓
+純
+紕
+紗
+紘
+紙
+級
+紛
+紜
+紝
+紞
+素
+紡
+索
+紫
+紮
+累
+細
+紱
+紲
+紳
+紵
+紹
+紺
+紿
+終
+絃
+組
+絆
+経
+絎
+結
+絕
+絛
+絜
+絞
+絡
+絢
+給
+絨
+絪
+絮
+統
+絲
+絳
+絵
+絶
+絹
+絺
+綁
+綃
+綈
+綉
+綎
+綏
+經
+綖
+継
+続
+綜
+綝
+綞
+綠
+綢
+綣
+綦
+綧
+綫
+綬
+維
+綮
+綰
+綱
+網
+綳
+綴
+綸
+綺
+綻
+綽
+綾
+綿
+緁
+緃
+緄
+緈
+緊
+緋
+総
+緑
+緒
+緖
+緘
+線
+緜
+緝
+緞
+締
+緡
+緣
+緤
+編
+緩
+緬
+緯
+緱
+緲
+練
+緹
+緻
+縂
+縄
+縈
+縉
+縊
+縕
+縛
+縝
+縞
+縠
+縡
+縣
+縤
+縫
+縮
+縯
+縱
+縴
+縵
+縷
+縹
+縻
+總
+績
+繁
+繃
+繆
+繇
+繒
+織
+繕
+繖
+繙
+繚
+繞
+繡
+繩
+繪
+繫
+繭
+繰
+繳
+繹
+繻
+繼
+繽
+繾
+纁
+纂
+纈
+續
+纍
+纏
+纓
+纔
+纕
+纖
+纘
+纛
+纜
+缐
+缶
+缸
+缺
+缽
+罃
+罄
+罅
+罈
+罉
+罌
+罍
+罐
+罔
+罕
+罘
+罟
+罡
+罨
+罩
+罪
+置
+罰
+罱
+署
+罳
+罵
+罶
+罷
+罹
+罽
+羂
+羅
+羆
+羈
+羊
+羋
+羌
+美
+羔
+羕
+羗
+羙
+羚
+羞
+羡
+羣
+群
+羥
+羧
+羨
+義
+羯
+羰
+羱
+羲
+羸
+羹
+羽
+羿
+翀
+翁
+翂
+翃
+翅
+翊
+翌
+翎
+翏
+習
+翔
+翕
+翙
+翜
+翟
+翠
+翡
+翥
+翦
+翩
+翬
+翮
+翰
+翱
+翳
+翹
+翻
+翼
+耀
+老
+考
+耄
+者
+耆
+而
+耍
+耎
+耐
+耑
+耒
+耔
+耕
+耗
+耘
+耙
+耜
+耦
+耨
+耬
+耳
+耵
+耶
+耷
+耽
+耿
+聃
+聆
+聊
+聒
+聖
+聘
+聚
+聞
+聟
+聨
+聯
+聰
+聱
+聲
+聳
+聴
+聶
+職
+聽
+聾
+聿
+肄
+肅
+肆
+肇
+肉
+肋
+肌
+肏
+肖
+肘
+肚
+肛
+肜
+肝
+肟
+股
+肢
+肥
+肩
+肪
+肫
+肯
+肱
+育
+肸
+肹
+肺
+肼
+肽
+胂
+胃
+胄
+胅
+胇
+胊
+背
+胍
+胎
+胖
+胗
+胙
+胚
+胛
+胝
+胞
+胡
+胤
+胥
+胬
+胭
+胰
+胱
+胳
+胴
+胸
+胺
+胼
+能
+脂
+脅
+脆
+脇
+脈
+脊
+脒
+脖
+脘
+脛
+脣
+脩
+脫
+脬
+脭
+脯
+脲
+脳
+脷
+脹
+脾
+腆
+腈
+腊
+腋
+腌
+腎
+腐
+腑
+腓
+腔
+腕
+腥
+腦
+腧
+腩
+腫
+腮
+腰
+腱
+腳
+腴
+腸
+腹
+腺
+腿
+膀
+膂
+膈
+膊
+膏
+膚
+膛
+膜
+膝
+膠
+膣
+膥
+膦
+膨
+膩
+膮
+膳
+膺
+膽
+膾
+膿
+臀
+臂
+臃
+臆
+臉
+臊
+臍
+臏
+臘
+臚
+臞
+臟
+臠
+臣
+臧
+臨
+自
+臭
+臯
+至
+致
+臺
+臻
+臼
+臾
+舂
+舅
+與
+興
+舉
+舊
+舌
+舍
+舎
+舒
+舔
+舖
+舘
+舛
+舜
+舞
+舟
+舢
+舥
+舨
+舩
+航
+舫
+般
+舲
+舵
+舶
+舷
+舸
+船
+舺
+艅
+艇
+艉
+艋
+艎
+艏
+艔
+艘
+艙
+艚
+艦
+艮
+良
+艱
+色
+艶
+艷
+艸
+艽
+艾
+艿
+芃
+芊
+芋
+芍
+芎
+芑
+芒
+芘
+芙
+芛
+芝
+芡
+芥
+芨
+芩
+芪
+芫
+芬
+芭
+芮
+芯
+花
+芳
+芴
+芷
+芸
+芹
+芻
+芽
+芾
+苄
+苅
+苑
+苒
+苓
+苔
+苕
+苗
+苛
+苜
+苝
+苞
+苟
+苡
+苣
+苤
+若
+苦
+苧
+苪
+苫
+苯
+英
+苳
+苴
+苷
+苺
+苻
+苼
+苾
+茀
+茁
+茂
+范
+茄
+茅
+茆
+茇
+茈
+茉
+茌
+茗
+茘
+茚
+茛
+茜
+茝
+茨
+茫
+茬
+茭
+茮
+茯
+茱
+茲
+茴
+茵
+茶
+茷
+茸
+茹
+茺
+茼
+荀
+荃
+荅
+荇
+草
+荊
+荎
+荏
+荒
+荔
+荖
+荘
+荳
+荷
+荸
+荻
+荼
+荽
+莆
+莉
+莊
+莎
+莒
+莓
+莕
+莖
+莘
+莙
+莛
+莜
+莞
+莠
+莢
+莧
+莨
+莩
+莪
+莫
+莽
+莿
+菀
+菁
+菅
+菇
+菈
+菉
+菊
+菌
+菍
+菏
+菑
+菓
+菔
+菖
+菘
+菜
+菝
+菟
+菠
+菡
+菥
+菩
+菪
+菫
+華
+菰
+菱
+菲
+菴
+菶
+菸
+菹
+菺
+菼
+菽
+菾
+萁
+萃
+萄
+萇
+萊
+萌
+萍
+萎
+萐
+萘
+萜
+萠
+萡
+萣
+萩
+萬
+萭
+萱
+萵
+萸
+萹
+萼
+落
+葃
+葆
+葉
+葊
+葎
+葑
+葒
+著
+葙
+葚
+葛
+葜
+葝
+葡
+董
+葦
+葩
+葫
+葬
+葭
+葯
+葰
+葳
+葵
+葶
+葷
+葺
+蒂
+蒄
+蒍
+蒎
+蒐
+蒓
+蒔
+蒗
+蒙
+蒜
+蒞
+蒟
+蒡
+蒢
+蒤
+蒧
+蒨
+蒭
+蒯
+蒲
+蒴
+蒸
+蒹
+蒺
+蒻
+蒼
+蒽
+蒾
+蒿
+蓀
+蓁
+蓂
+蓄
+蓆
+蓉
+蓋
+蓍
+蓑
+蓓
+蓖
+蓘
+蓚
+蓧
+蓨
+蓪
+蓬
+蓭
+蓮
+蓯
+蓳
+蓼
+蓽
+蓿
+蔆
+蔎
+蔑
+蔓
+蔔
+蔕
+蔗
+蔘
+蔚
+蔝
+蔞
+蔡
+蔣
+蔥
+蔦
+蔬
+蔭
+蔴
+蔵
+蔻
+蔽
+蕁
+蕃
+蕅
+蕈
+蕉
+蕊
+蕎
+蕑
+蕒
+蕖
+蕘
+蕙
+蕚
+蕟
+蕡
+蕢
+蕤
+蕨
+蕩
+蕪
+蕭
+蕷
+蕹
+蕺
+蕻
+蕾
+薀
+薄
+薆
+薇
+薈
+薊
+薌
+薏
+薐
+薑
+薔
+薗
+薘
+薙
+薛
+薜
+薞
+薟
+薡
+薦
+薨
+薩
+薪
+薫
+薬
+薯
+薰
+薲
+薷
+薸
+薹
+薺
+薾
+薿
+藁
+藉
+藍
+藎
+藏
+藐
+藔
+藕
+藜
+藝
+藟
+藤
+藥
+藦
+藨
+藩
+藪
+藶
+藸
+藹
+藺
+藻
+藿
+蘂
+蘄
+蘅
+蘆
+蘇
+蘊
+蘋
+蘐
+蘑
+蘓
+蘗
+蘘
+蘚
+蘞
+蘢
+蘧
+蘩
+蘭
+蘵
+蘶
+蘸
+蘼
+蘿
+虉
+虎
+虐
+虓
+虔
+處
+虖
+虛
+虜
+虞
+號
+虢
+虧
+虨
+虯
+虱
+虵
+虹
+虺
+虻
+蚆
+蚊
+蚋
+蚌
+蚍
+蚓
+蚖
+蚜
+蚝
+蚡
+蚢
+蚣
+蚤
+蚧
+蚨
+蚩
+蚪
+蚯
+蚱
+蚴
+蚵
+蚶
+蚺
+蚼
+蛀
+蛄
+蛇
+蛉
+蛋
+蛍
+蛐
+蛑
+蛔
+蛙
+蛛
+蛞
+蛟
+蛤
+蛭
+蛯
+蛸
+蛹
+蛺
+蛻
+蛾
+蜀
+蜂
+蜃
+蜆
+蜇
+蜈
+蜉
+蜊
+蜍
+蜑
+蜒
+蜓
+蜘
+蜚
+蜛
+蜜
+蜞
+蜢
+蜣
+蜥
+蜨
+蜮
+蜯
+蜱
+蜴
+蜷
+蜻
+蜾
+蜿
+蝀
+蝌
+蝍
+蝎
+蝓
+蝕
+蝗
+蝘
+蝙
+蝚
+蝟
+蝠
+蝣
+蝤
+蝦
+蝨
+蝮
+蝯
+蝰
+蝲
+蝴
+蝶
+蝸
+蝽
+螂
+螃
+螄
+螅
+螈
+螋
+融
+螐
+螔
+螞
+螟
+螠
+螢
+螣
+螥
+螫
+螭
+螯
+螳
+螶
+螺
+螻
+螽
+螾
+蟀
+蟄
+蟅
+蟆
+蟊
+蟋
+蟌
+蟎
+蟑
+蟒
+蟜
+蟠
+蟥
+蟪
+蟫
+蟬
+蟯
+蟲
+蟳
+蟴
+蟶
+蟹
+蟻
+蟾
+蠂
+蠃
+蠄
+蠅
+蠆
+蠊
+蠋
+蠍
+蠐
+蠑
+蠓
+蠔
+蠕
+蠖
+蠘
+蠙
+蠟
+蠡
+蠢
+蠣
+蠱
+蠲
+蠵
+蠶
+蠷
+蠹
+蠻
+血
+衂
+衆
+行
+衍
+衎
+術
+衕
+衖
+街
+衙
+衚
+衛
+衜
+衝
+衞
+衡
+衢
+衣
+表
+衩
+衫
+衰
+衲
+衷
+衽
+衾
+衿
+袁
+袂
+袈
+袋
+袍
+袓
+袖
+袛
+袞
+袤
+袪
+被
+袱
+袴
+袾
+裁
+裂
+裊
+裎
+裒
+裔
+裕
+裖
+裘
+裙
+補
+裝
+裟
+裡
+裨
+裬
+裱
+裳
+裴
+裵
+裸
+裹
+製
+裾
+裿
+褀
+褂
+複
+褌
+褍
+褎
+褐
+褒
+褓
+褔
+褘
+褙
+褚
+褞
+褥
+褧
+褪
+褫
+褭
+褲
+褶
+褸
+褻
+襄
+襌
+襖
+襞
+襟
+襠
+襤
+襦
+襪
+襯
+襲
+襴
+襶
+襻
+襾
+西
+要
+覃
+覆
+覇
+覈
+見
+覌
+規
+覓
+視
+覚
+覡
+覦
+覧
+親
+覬
+覲
+観
+覺
+覽
+覿
+觀
+角
+觔
+觙
+觚
+觜
+解
+觭
+觱
+觴
+觶
+觸
+觿
+言
+訁
+訂
+訃
+訇
+計
+訊
+訌
+討
+訏
+訐
+訒
+訓
+訔
+訕
+訖
+託
+記
+訛
+訝
+訟
+訣
+訥
+訪
+設
+許
+訴
+訶
+診
+註
+証
+訾
+詁
+詆
+詈
+詐
+詒
+詔
+評
+詛
+詞
+詠
+詡
+詢
+詣
+詥
+試
+詧
+詩
+詫
+詭
+詮
+詰
+話
+該
+詳
+詵
+詹
+詼
+誄
+誅
+誇
+誌
+認
+誒
+誓
+誕
+誘
+語
+誠
+誡
+誣
+誤
+誥
+誦
+誨
+說
+説
+読
+誰
+課
+誴
+誹
+誼
+誾
+調
+談
+請
+諍
+諏
+諒
+論
+諗
+諜
+諟
+諠
+諡
+諤
+諦
+諧
+諪
+諫
+諭
+諮
+諱
+諲
+諳
+諴
+諶
+諷
+諸
+諺
+諼
+諾
+謀
+謁
+謂
+謄
+謇
+謊
+謌
+謎
+謏
+謐
+謔
+謖
+謗
+謙
+謚
+講
+謜
+謝
+謠
+謢
+謤
+謨
+謩
+謫
+謬
+謳
+謹
+謾
+證
+譏
+譓
+譔
+識
+譙
+譚
+譜
+譞
+警
+譫
+譬
+譭
+譯
+議
+譲
+譳
+譴
+護
+譽
+譿
+讀
+讃
+變
+讌
+讎
+讓
+讖
+讙
+讚
+讜
+讞
+谷
+谿
+豁
+豆
+豇
+豈
+豉
+豊
+豌
+豎
+豐
+豔
+豕
+豚
+象
+豢
+豨
+豪
+豫
+豬
+豳
+豸
+豹
+豺
+豿
+貂
+貅
+貉
+貊
+貌
+貐
+貒
+貓
+貔
+貘
+貝
+貞
+負
+財
+貢
+貤
+貧
+貨
+販
+貪
+貫
+責
+貭
+貮
+貯
+貲
+貳
+貴
+貶
+買
+貸
+貺
+費
+貼
+貽
+貿
+賀
+賁
+賂
+賃
+賄
+資
+賈
+賊
+賑
+賒
+賓
+賔
+賕
+賚
+賜
+賞
+賠
+賡
+賢
+賣
+賤
+賦
+賨
+質
+賬
+賭
+賴
+賹
+賺
+賻
+購
+賽
+賾
+贄
+贅
+贇
+贈
+贊
+贌
+贍
+贏
+贓
+贔
+贖
+贛
+赤
+赦
+赧
+赫
+赬
+赭
+走
+赳
+赴
+起
+趁
+超
+越
+趐
+趕
+趖
+趙
+趟
+趣
+趨
+足
+趴
+趵
+趺
+趼
+趾
+跅
+跆
+跋
+跌
+跏
+跑
+跖
+跗
+跛
+距
+跟
+跡
+跣
+跤
+跨
+跩
+跪
+路
+跳
+踎
+踏
+踐
+踝
+踞
+踢
+踩
+踰
+踴
+踹
+踺
+蹂
+蹄
+蹇
+蹈
+蹉
+蹊
+蹋
+蹕
+蹙
+蹟
+蹠
+蹤
+蹦
+蹬
+蹭
+蹯
+蹲
+蹴
+蹶
+蹺
+蹻
+蹼
+躁
+躂
+躄
+躉
+躋
+躍
+躑
+躒
+躔
+躝
+躪
+身
+躬
+躰
+躲
+躺
+軀
+車
+軋
+軌
+軍
+軎
+軒
+軔
+軛
+軟
+転
+軫
+軲
+軸
+軹
+軺
+軻
+軼
+軽
+軾
+較
+輄
+輅
+載
+輋
+輒
+輓
+輔
+輕
+輛
+輝
+輞
+輟
+輥
+輦
+輩
+輪
+輬
+輭
+輯
+輶
+輸
+輻
+輾
+輿
+轀
+轂
+轄
+轅
+轆
+轉
+轍
+轎
+轘
+轝
+轟
+轤
+辛
+辜
+辟
+辣
+辦
+辧
+辨
+辭
+辮
+辯
+辰
+辱
+農
+辵
+辺
+辻
+込
+迂
+迄
+迅
+迎
+近
+返
+迢
+迤
+迥
+迦
+迪
+迫
+迭
+迮
+述
+迴
+迵
+迷
+迸
+迺
+追
+退
+送
+逃
+逄
+逅
+逆
+逈
+逋
+逌
+逍
+逎
+透
+逐
+逑
+途
+逕
+逖
+逗
+這
+通
+逛
+逝
+逞
+速
+造
+逢
+連
+逤
+逨
+逮
+逯
+進
+逴
+逵
+逸
+逹
+逺
+逼
+逾
+遁
+遂
+遄
+遇
+遊
+運
+遍
+過
+遏
+遐
+遒
+道
+達
+違
+遘
+遙
+遛
+遜
+遞
+遠
+遢
+遣
+遨
+適
+遭
+遮
+遯
+遲
+遴
+遵
+遶
+遷
+選
+遹
+遺
+遼
+避
+邀
+邁
+邂
+邃
+還
+邇
+邈
+邉
+邊
+邋
+邏
+邑
+邕
+邗
+邙
+邛
+邠
+邡
+邢
+那
+邦
+邨
+邪
+邯
+邰
+邱
+邲
+邳
+邴
+邵
+邸
+邽
+邾
+郁
+郃
+郄
+郅
+郇
+郊
+郋
+郎
+郗
+郛
+郜
+郝
+郞
+郟
+郡
+郢
+郤
+部
+郪
+郫
+郭
+郯
+郳
+郴
+郵
+郷
+都
+郾
+郿
+鄂
+鄃
+鄄
+鄆
+鄉
+鄋
+鄑
+鄒
+鄔
+鄖
+鄗
+鄘
+鄙
+鄚
+鄜
+鄞
+鄠
+鄢
+鄣
+鄤
+鄧
+鄩
+鄫
+鄭
+鄯
+鄰
+鄱
+鄲
+鄳
+鄴
+鄺
+酃
+酆
+酈
+酉
+酊
+酋
+酌
+配
+酎
+酏
+酐
+酒
+酔
+酗
+酚
+酞
+酡
+酢
+酣
+酥
+酩
+酪
+酬
+酮
+酯
+酰
+酴
+酵
+酶
+酷
+酸
+酺
+酼
+醁
+醂
+醃
+醅
+醇
+醉
+醋
+醌
+醍
+醐
+醒
+醚
+醛
+醜
+醞
+醢
+醣
+醪
+醫
+醬
+醮
+醯
+醴
+醺
+醾
+醿
+釀
+釁
+釆
+采
+釉
+釋
+里
+重
+野
+量
+釐
+金
+釒
+釓
+釔
+釕
+釗
+釘
+釙
+釚
+釜
+針
+釣
+釤
+釦
+釧
+釩
+釪
+釭
+釴
+釵
+釷
+釹
+釺
+鈀
+鈁
+鈄
+鈇
+鈈
+鈉
+鈊
+鈍
+鈏
+鈐
+鈑
+鈔
+鈕
+鈖
+鈞
+鈢
+鈣
+鈥
+鈦
+鈫
+鈮
+鈰
+鈳
+鈴
+鈷
+鈸
+鈹
+鈺
+鈾
+鈿
+鉀
+鉄
+鉅
+鉆
+鉈
+鉉
+鉋
+鉌
+鉍
+鉏
+鉑
+鉓
+鉗
+鉚
+鉛
+鉞
+鉟
+鉤
+鉦
+鉬
+鉭
+鉲
+鉶
+鉷
+鉸
+鉻
+鉾
+鉿
+銀
+銂
+銃
+銅
+銋
+銍
+銑
+銓
+銕
+銖
+銘
+銚
+銜
+銠
+銣
+銥
+銦
+銨
+銩
+銪
+銫
+銬
+銭
+銱
+銲
+銳
+銶
+銷
+銹
+銻
+銼
+銾
+鋁
+鋅
+鋆
+鋇
+鋌
+鋏
+鋐
+鋒
+鋕
+鋗
+鋙
+鋡
+鋤
+鋥
+鋦
+鋨
+鋪
+鋮
+鋯
+鋰
+鋱
+鋳
+鋶
+鋸
+鋹
+鋼
+錀
+錄
+錏
+錐
+錒
+錕
+錘
+錚
+錞
+錟
+錠
+錡
+錢
+錦
+錨
+錫
+錬
+錮
+錯
+錳
+錶
+錸
+錻
+鍀
+鍇
+鍈
+鍉
+鍊
+鍋
+鍍
+鍏
+鍔
+鍘
+鍛
+鍝
+鍟
+鍠
+鍥
+鍩
+鍬
+鍱
+鍳
+鍵
+鍶
+鍷
+鍺
+鍼
+鍾
+鎂
+鎅
+鎊
+鎌
+鎏
+鎓
+鎔
+鎖
+鎗
+鎘
+鎚
+鎛
+鎢
+鎣
+鎦
+鎧
+鎪
+鎬
+鎭
+鎮
+鎰
+鎳
+鎵
+鎻
+鏃
+鏇
+鏈
+鏊
+鏌
+鏐
+鏑
+鏓
+鏖
+鏗
+鏘
+鏜
+鏝
+鏞
+鏟
+鏡
+鏢
+鏤
+鏦
+鏳
+鏴
+鏵
+鏷
+鏻
+鏽
+鐃
+鐇
+鐈
+鐓
+鐔
+鐘
+鐙
+鐠
+鐡
+鐤
+鐦
+鐧
+鐫
+鐬
+鐭
+鐮
+鐲
+鐳
+鐵
+鐸
+鐺
+鐽
+鐿
+鑀
+鑁
+鑂
+鑄
+鑅
+鑊
+鑌
+鑑
+鑒
+鑛
+鑠
+鑣
+鑨
+鑪
+鑫
+鑭
+鑰
+鑲
+鑴
+鑷
+鑼
+鑽
+鑾
+鑿
+長
+門
+閂
+閃
+閆
+閉
+開
+閎
+閏
+閑
+閒
+間
+閔
+閘
+閜
+閞
+閟
+関
+閣
+閥
+閦
+閨
+閩
+閬
+閭
+閰
+閱
+閶
+閹
+閻
+閼
+閾
+閿
+闆
+闇
+闈
+闊
+闋
+闌
+闍
+闐
+闓
+闔
+闕
+闖
+闘
+關
+闞
+闡
+闢
+闥
+阜
+阝
+阡
+阪
+阭
+阮
+阯
+阱
+防
+阻
+阿
+陀
+陁
+陂
+附
+陋
+陌
+降
+限
+陔
+陘
+陛
+陜
+陝
+陞
+陟
+陡
+院
+陣
+除
+陪
+陬
+陰
+陲
+陳
+陵
+陶
+陷
+陸
+険
+陽
+隄
+隅
+隆
+隈
+隊
+隋
+隍
+階
+隔
+隕
+隗
+隘
+隙
+際
+障
+隣
+隧
+隨
+險
+隰
+隱
+隲
+隳
+隴
+隷
+隸
+隹
+隻
+隼
+雀
+雁
+雄
+雅
+集
+雇
+雉
+雋
+雌
+雍
+雎
+雑
+雒
+雕
+雖
+雙
+雛
+雜
+雝
+雞
+離
+難
+雨
+雩
+雪
+雫
+雯
+雱
+雲
+零
+雷
+雹
+電
+需
+霄
+霅
+霆
+震
+霈
+霉
+霊
+霍
+霎
+霏
+霑
+霓
+霖
+霙
+霜
+霞
+霤
+霧
+霨
+霰
+露
+霶
+霸
+霹
+霽
+霾
+靁
+靂
+靄
+靈
+靉
+靑
+青
+靖
+靚
+靛
+靜
+非
+靠
+靡
+面
+革
+靫
+靬
+靭
+靳
+靴
+靶
+靺
+靼
+鞅
+鞆
+鞋
+鞍
+鞏
+鞘
+鞞
+鞠
+鞣
+鞥
+鞦
+鞨
+鞭
+鞮
+鞴
+韁
+韃
+韆
+韋
+韌
+韑
+韓
+韙
+韜
+韞
+韠
+韡
+韭
+韮
+音
+韶
+韺
+韻
+韾
+響
+頁
+頂
+頃
+項
+順
+須
+頊
+頌
+頍
+頎
+頏
+預
+頑
+頒
+頓
+頔
+頗
+領
+頜
+頠
+頡
+頤
+頦
+頫
+頭
+頰
+頴
+頵
+頷
+頸
+頹
+頻
+頼
+顆
+題
+額
+顎
+顏
+顒
+顓
+顔
+顕
+顗
+願
+顙
+顛
+類
+顥
+顧
+顫
+顯
+顰
+顱
+顳
+顴
+風
+颮
+颯
+颱
+颶
+颺
+颼
+飄
+飆
+飈
+飛
+食
+飠
+飡
+飢
+飥
+飩
+飪
+飫
+飬
+飭
+飮
+飯
+飲
+飴
+飼
+飽
+飾
+餃
+餄
+餅
+餉
+養
+餌
+餎
+餐
+餒
+餓
+餗
+餘
+餚
+餛
+餞
+餠
+餡
+館
+餮
+餵
+餺
+餾
+餿
+饃
+饅
+饋
+饌
+饑
+饒
+饕
+饗
+饞
+饟
+饢
+首
+馗
+馘
+香
+馛
+馥
+馦
+馨
+馬
+馭
+馮
+馯
+馱
+馳
+馴
+馼
+駁
+駄
+駅
+駆
+駐
+駑
+駒
+駔
+駕
+駘
+駙
+駛
+駝
+駟
+駢
+駭
+駰
+駱
+駿
+騁
+騂
+騄
+騅
+騋
+騎
+騏
+験
+騖
+騙
+騤
+騨
+騫
+騭
+騮
+騰
+騶
+騷
+騾
+驁
+驃
+驄
+驅
+驊
+驌
+驍
+驎
+驒
+驕
+驗
+驚
+驛
+驟
+驢
+驤
+驥
+驩
+驪
+骨
+骯
+骰
+骶
+骷
+骸
+骼
+髀
+髂
+髎
+髏
+髑
+髒
+髓
+體
+高
+髙
+髡
+髦
+髪
+髭
+髮
+髯
+髲
+髷
+髹
+髻
+鬃
+鬄
+鬅
+鬆
+鬍
+鬚
+鬟
+鬢
+鬣
+鬥
+鬧
+鬨
+鬩
+鬪
+鬬
+鬮
+鬯
+鬱
+鬲
+鬹
+鬻
+鬼
+魁
+魂
+魃
+魄
+魅
+魈
+魋
+魍
+魎
+魏
+魔
+魕
+魘
+魚
+魛
+魞
+魟
+魣
+魨
+魩
+魮
+魯
+魴
+魷
+鮀
+鮁
+鮃
+鮄
+鮊
+鮋
+鮍
+鮐
+鮑
+鮒
+鮓
+鮗
+鮜
+鮟
+鮠
+鮡
+鮣
+鮨
+鮪
+鮫
+鮭
+鮮
+鮰
+鮸
+鮹
+鮻
+鯀
+鯁
+鯃
+鯇
+鯉
+鯊
+鯏
+鯒
+鯓
+鯔
+鯕
+鯖
+鯗
+鯙
+鯛
+鯡
+鯢
+鯤
+鯧
+鯨
+鯪
+鯭
+鯮
+鯰
+鯶
+鯷
+鯻
+鯽
+鯿
+鰂
+鰃
+鰆
+鰈
+鰉
+鰍
+鰏
+鰒
+鰓
+鰕
+鰗
+鰛
+鰜
+鰟
+鰣
+鰤
+鰧
+鰨
+鰩
+鰭
+鰮
+鰱
+鰲
+鰳
+鰶
+鰷
+鰹
+鰺
+鰻
+鰼
+鰾
+鱀
+鱂
+鱅
+鱇
+鱈
+鱉
+鱊
+鱒
+鱓
+鱔
+鱖
+鱗
+鱘
+鱚
+鱝
+鱟
+鱠
+鱣
+鱥
+鱧
+鱨
+鱬
+鱮
+鱰
+鱲
+鱵
+鱷
+鱸
+鱺
+鱻
+鳥
+鳧
+鳩
+鳯
+鳰
+鳳
+鳴
+鳶
+鳽
+鴆
+鴇
+鴉
+鴒
+鴓
+鴕
+鴗
+鴛
+鴝
+鴞
+鴟
+鴡
+鴣
+鴦
+鴨
+鴫
+鴯
+鴰
+鴴
+鴻
+鴿
+鵂
+鵄
+鵎
+鵐
+鵑
+鵒
+鵓
+鵙
+鵜
+鵝
+鵞
+鵟
+鵠
+鵡
+鵪
+鵬
+鵯
+鵰
+鵲
+鵵
+鵼
+鵾
+鶆
+鶇
+鶉
+鶏
+鶒
+鶓
+鶘
+鶚
+鶡
+鶥
+鶩
+鶬
+鶯
+鶲
+鶴
+鶹
+鶺
+鶻
+鶼
+鶿
+鷂
+鷄
+鷉
+鷎
+鷓
+鷗
+鷙
+鷚
+鷟
+鷥
+鷦
+鷫
+鷯
+鷲
+鷳
+鷸
+鷹
+鷺
+鸊
+鸌
+鸐
+鸑
+鸕
+鸘
+鸚
+鸛
+鸜
+鸝
+鸞
+鹮
+鹵
+鹹
+鹼
+鹽
+鹿
+麂
+麅
+麇
+麈
+麊
+麋
+麐
+麒
+麓
+麗
+麝
+麞
+麟
+麥
+麩
+麪
+麯
+麴
+麵
+麹
+麺
+麻
+麼
+麽
+麾
+麿
+黁
+黃
+黇
+黌
+黍
+黎
+黏
+黐
+黑
+黒
+黔
+默
+黙
+黛
+黜
+黝
+點
+黟
+黥
+黧
+黨
+黯
+黴
+黶
+黻
+黼
+黽
+黿
+鼂
+鼇
+鼈
+鼉
+鼎
+鼐
+鼒
+鼓
+鼕
+鼙
+鼠
+鼢
+鼩
+鼬
+鼯
+鼱
+鼴
+鼷
+鼻
+鼽
+鼾
+齊
+齋
+齒
+齕
+齡
+齣
+齦
+齧
+齲
+齶
+龍
+龎
+龐
+龑
+龔
+龕
+龜
+龝
+龠
+龢
+郎
+凉
+﹑
+﹗
+﹝
+﹞
+﹢
+!
+"
+#
+$
+%
+&
+'
+(
+)
+*
++
+,
+-
+.
+/
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+:
+;
+<
+=
+>
+?
+A
+B
+C
+D
+E
+F
+G
+H
+I
+K
+L
+M
+N
+O
+P
+R
+S
+T
+U
+V
+W
+Y
+Z
+[
+]
+`
+a
+b
+c
+d
+e
+f
+g
+h
+i
+j
+k
+l
+m
+n
+o
+p
+r
+s
+t
+u
+z
+{
+|
+}
+~
+¥
+𣇉
+ 

+ 153 - 0
models/ocr/Keys/卡纳达文.txt

@@ -0,0 +1,153 @@
+k
+a
+_
+i
+m
+g
+/
+1
+2
+I
+L
+S
+V
+R
+C
+0
+v
+l
+6
+4
+8
+.
+j
+p
+ಗ
+ು
+ಣ
+ಪ
+ಡ
+ಿ
+ಸ
+ಲ
+ಾ
+ದ
+್
+7
+5
+3
+ವ
+ಷ
+ಬ
+ಹ
+ೆ
+9
+ಅ
+ಳ
+ನ
+ರ
+ಉ
+ಕ
+ಎ
+ೇ
+ಂ
+ೈ
+ೊ
+ೀ
+ಯ
+ೋ
+ತ
+ಶ
+ಭ
+ಧ
+ಚ
+ಜ
+ೂ
+ಮ
+ಒ
+ೃ
+ಥ
+ಇ
+ಟ
+ಖ
+ಆ
+ಞ
+ಫ
+-
+ಢ
+ಊ
+ಓ
+ಐ
+ಃ
+ಘ
+ಝ
+ೌ
+ಠ
+ಛ
+ಔ
+ಏ
+ಈ
+ಋ
+೨
+೦
+೧
+೮
+೯
+೪
+,
+೫
+೭
+೩
+೬
+ಙ
+s
+c
+e
+n
+w
+o
+u
+t
+d
+E
+A
+T
+B
+Z
+N
+G
+O
+q
+z
+r
+x
+P
+K
+M
+J
+U
+D
+f
+F
+h
+b
+W
+Y
+y
+H
+X
+Q
+'
+#
+&
+!
+@
+$
+:
+%
+(
+?
++
+ 

+ 163 - 0
models/ocr/Keys/斯拉夫字母.txt

@@ -0,0 +1,163 @@
+ 
+!
+#
+$
+%
+&
+'
+(
++
+,
+-
+.
+/
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+:
+?
+@
+A
+B
+C
+D
+E
+F
+G
+H
+I
+J
+K
+L
+M
+N
+O
+P
+Q
+R
+S
+T
+U
+V
+W
+X
+Y
+Z
+_
+a
+b
+c
+d
+e
+f
+g
+h
+i
+j
+k
+l
+m
+n
+o
+p
+q
+r
+s
+t
+u
+v
+w
+x
+y
+z
+п

+ 4399 - 0
models/ocr/Keys/日文.txt

@@ -0,0 +1,4399 @@
+!
+"
+#
+$
+%
+&
+'
+(
+)
+*
++
+,
+-
+.
+/
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+:
+;
+<
+=
+>
+?
+A
+B
+C
+D
+E
+F
+G
+H
+I
+J
+K
+L
+M
+N
+O
+P
+Q
+R
+S
+T
+U
+V
+W
+X
+Y
+Z
+[
+]
+_
+`
+a
+b
+c
+d
+e
+f
+g
+h
+i
+j
+k
+l
+m
+n
+o
+p
+q
+r
+s
+t
+u
+v
+w
+x
+y
+z
+ồ
+​
+—
+―
+’
+“
+”
+…
+℃
+→
+∇
+−
+■
+☆
+ 
+、
+。
+々
+〆
+〈
+〉
+「
+」
+『
+』
+〔
+〕
+〜
+ぁ
+あ
+ぃ
+い
+う
+ぇ
+え
+ぉ
+お
+か
+が
+き
+ぎ
+く
+ぐ
+け
+げ
+こ
+ご
+さ
+ざ
+し
+じ
+す
+ず
+せ
+ぜ
+そ
+ぞ
+た
+だ
+ち
+ぢ
+っ
+つ
+づ
+て
+で
+と
+ど
+な
+に
+ぬ
+ね
+の
+は
+ば
+ぱ
+ひ
+び
+ぴ
+ふ
+ぶ
+ぷ
+へ
+べ
+ぺ
+ほ
+ぼ
+ぽ
+ま
+み
+む
+め
+も
+ゃ
+や
+ゅ
+ゆ
+ょ
+よ
+ら
+り
+る
+れ
+ろ
+わ
+ゑ
+を
+ん
+ゝ
+ゞ
+ァ
+ア
+ィ
+イ
+ゥ
+ウ
+ェ
+エ
+ォ
+オ
+カ
+ガ
+キ
+ギ
+ク
+グ
+ケ
+ゲ
+コ
+ゴ
+サ
+ザ
+シ
+ジ
+ス
+ズ
+セ
+ゼ
+ソ
+ゾ
+タ
+ダ
+チ
+ヂ
+ッ
+ツ
+ヅ
+テ
+デ
+ト
+ド
+ナ
+ニ
+ヌ
+ネ
+ノ
+ハ
+バ
+パ
+ヒ
+ビ
+ピ
+フ
+ブ
+プ
+ヘ
+ベ
+ペ
+ホ
+ボ
+ポ
+マ
+ミ
+ム
+メ
+モ
+ャ
+ヤ
+ュ
+ユ
+ョ
+ヨ
+ラ
+リ
+ル
+レ
+ロ
+ワ
+ヰ
+ン
+ヴ
+ヵ
+ヶ
+・
+ー
+㈱
+一
+丁
+七
+万
+丈
+三
+上
+下
+不
+与
+丑
+且
+世
+丘
+丙
+丞
+両
+並
+中
+串
+丸
+丹
+主
+丼
+丿
+乃
+久
+之
+乎
+乏
+乗
+乘
+乙
+九
+乞
+也
+乱
+乳
+乾
+亀
+了
+予
+争
+事
+二
+于
+互
+五
+井
+亘
+亙
+些
+亜
+亟
+亡
+交
+亥
+亦
+亨
+享
+京
+亭
+亮
+人
+什
+仁
+仇
+今
+介
+仍
+仏
+仔
+仕
+他
+仗
+付
+仙
+代
+令
+以
+仮
+仰
+仲
+件
+任
+企
+伊
+伍
+伎
+伏
+伐
+休
+会
+伝
+伯
+估
+伴
+伶
+伸
+伺
+似
+伽
+佃
+但
+位
+低
+住
+佐
+佑
+体
+何
+余
+佚
+佛
+作
+佩
+佳
+併
+佶
+使
+侈
+例
+侍
+侏
+侑
+侘
+供
+依
+侠
+価
+侮
+侯
+侵
+侶
+便
+係
+促
+俄
+俊
+俔
+俗
+俘
+保
+信
+俣
+俤
+修
+俯
+俳
+俵
+俸
+俺
+倉
+個
+倍
+倒
+候
+借
+倣
+値
+倫
+倭
+倶
+倹
+偃
+假
+偈
+偉
+偏
+偐
+偕
+停
+健
+側
+偵
+偶
+偽
+傀
+傅
+傍
+傑
+傘
+備
+催
+傭
+傲
+傳
+債
+傷
+傾
+僊
+働
+像
+僑
+僕
+僚
+僧
+僭
+僮
+儀
+億
+儇
+儒
+儛
+償
+儡
+優
+儲
+儺
+儼
+兀
+允
+元
+兄
+充
+兆
+先
+光
+克
+兌
+免
+兎
+児
+党
+兜
+入
+全
+八
+公
+六
+共
+兵
+其
+具
+典
+兼
+内
+円
+冊
+再
+冑
+冒
+冗
+写
+冠
+冤
+冥
+冨
+冬
+冲
+决
+冶
+冷
+准
+凉
+凋
+凌
+凍
+凛
+凝
+凞
+几
+凡
+処
+凪
+凰
+凱
+凶
+凸
+凹
+出
+函
+刀
+刃
+分
+切
+刈
+刊
+刎
+刑
+列
+初
+判
+別
+利
+刪
+到
+制
+刷
+券
+刹
+刺
+刻
+剃
+則
+削
+剋
+前
+剖
+剛
+剣
+剤
+剥
+剪
+副
+剰
+割
+創
+剽
+劇
+劉
+劔
+力
+功
+加
+劣
+助
+努
+劫
+劭
+励
+労
+効
+劾
+勃
+勅
+勇
+勉
+勒
+動
+勘
+務
+勝
+募
+勢
+勤
+勧
+勲
+勺
+勾
+勿
+匁
+匂
+包
+匏
+化
+北
+匙
+匝
+匠
+匡
+匣
+匯
+匲
+匹
+区
+医
+匿
+十
+千
+升
+午
+卉
+半
+卍
+卑
+卒
+卓
+協
+南
+単
+博
+卜
+占
+卦
+卯
+印
+危
+即
+却
+卵
+卸
+卿
+厄
+厚
+原
+厠
+厨
+厩
+厭
+厳
+去
+参
+又
+叉
+及
+友
+双
+反
+収
+叔
+取
+受
+叙
+叛
+叟
+叡
+叢
+口
+古
+句
+叩
+只
+叫
+召
+可
+台
+叱
+史
+右
+叶
+号
+司
+吃
+各
+合
+吉
+吊
+同
+名
+后
+吏
+吐
+向
+君
+吝
+吟
+吠
+否
+含
+吸
+吹
+吻
+吽
+吾
+呂
+呆
+呈
+呉
+告
+呑
+周
+呪
+呰
+味
+呼
+命
+咀
+咄
+咋
+和
+咒
+咫
+咲
+咳
+咸
+哀
+品
+哇
+哉
+員
+哨
+哩
+哭
+哲
+哺
+唄
+唆
+唇
+唐
+唖
+唯
+唱
+唳
+唸
+唾
+啄
+商
+問
+啓
+啼
+善
+喋
+喚
+喜
+喝
+喧
+喩
+喪
+喫
+喬
+單
+喰
+営
+嗅
+嗇
+嗔
+嗚
+嗜
+嗣
+嘆
+嘉
+嘗
+嘘
+嘩
+嘯
+嘱
+嘲
+嘴
+噂
+噌
+噛
+器
+噴
+噺
+嚆
+嚢
+囀
+囃
+囉
+囚
+四
+回
+因
+団
+困
+囲
+図
+固
+国
+圀
+圃
+國
+圏
+園
+圓
+團
+圜
+土
+圧
+在
+圭
+地
+址
+坂
+均
+坊
+坐
+坑
+坡
+坤
+坦
+坪
+垂
+型
+垢
+垣
+埃
+埋
+城
+埒
+埔
+域
+埠
+埴
+埵
+執
+培
+基
+埼
+堀
+堂
+堅
+堆
+堕
+堤
+堪
+堯
+堰
+報
+場
+堵
+堺
+塀
+塁
+塊
+塑
+塔
+塗
+塘
+塙
+塚
+塞
+塩
+填
+塵
+塾
+境
+墉
+墓
+増
+墜
+墟
+墨
+墳
+墺
+墻
+墾
+壁
+壇
+壊
+壌
+壕
+士
+壬
+壮
+声
+壱
+売
+壷
+壹
+壺
+壽
+変
+夏
+夕
+外
+夙
+多
+夜
+夢
+夥
+大
+天
+太
+夫
+夬
+夭
+央
+失
+夷
+夾
+奄
+奇
+奈
+奉
+奎
+奏
+契
+奔
+奕
+套
+奘
+奠
+奢
+奥
+奨
+奪
+奮
+女
+奴
+奸
+好
+如
+妃
+妄
+妊
+妍
+妓
+妖
+妙
+妥
+妨
+妬
+妲
+妹
+妻
+妾
+姉
+始
+姐
+姓
+委
+姚
+姜
+姞
+姥
+姦
+姨
+姪
+姫
+姶
+姻
+姿
+威
+娑
+娘
+娟
+娠
+娩
+娯
+娼
+婆
+婉
+婚
+婢
+婦
+婬
+婿
+媄
+媒
+媓
+媚
+媛
+媞
+媽
+嫁
+嫄
+嫉
+嫌
+嫐
+嫗
+嫡
+嬉
+嬌
+嬢
+嬪
+嬬
+嬾
+孁
+子
+孔
+字
+存
+孚
+孝
+孟
+季
+孤
+学
+孫
+孵
+學
+宅
+宇
+守
+安
+宋
+完
+宍
+宏
+宕
+宗
+官
+宙
+定
+宛
+宜
+宝
+実
+客
+宣
+室
+宥
+宮
+宰
+害
+宴
+宵
+家
+宸
+容
+宿
+寂
+寄
+寅
+密
+寇
+富
+寒
+寓
+寔
+寛
+寝
+察
+寡
+實
+寧
+審
+寮
+寵
+寶
+寸
+寺
+対
+寿
+封
+専
+射
+将
+尉
+尊
+尋
+對
+導
+小
+少
+尖
+尚
+尤
+尪
+尭
+就
+尹
+尺
+尻
+尼
+尽
+尾
+尿
+局
+居
+屈
+届
+屋
+屍
+屎
+屏
+屑
+屓
+展
+属
+屠
+層
+履
+屯
+山
+岐
+岑
+岡
+岩
+岫
+岬
+岳
+岷
+岸
+峠
+峡
+峨
+峯
+峰
+島
+峻
+崇
+崋
+崎
+崑
+崖
+崗
+崛
+崩
+嵌
+嵐
+嵩
+嵯
+嶂
+嶋
+嶠
+嶺
+嶼
+嶽
+巀
+巌
+巒
+巖
+川
+州
+巡
+巣
+工
+左
+巧
+巨
+巫
+差
+己
+巳
+巴
+巷
+巻
+巽
+巾
+市
+布
+帆
+希
+帖
+帚
+帛
+帝
+帥
+師
+席
+帯
+帰
+帳
+帷
+常
+帽
+幄
+幅
+幇
+幌
+幔
+幕
+幟
+幡
+幢
+幣
+干
+平
+年
+并
+幸
+幹
+幻
+幼
+幽
+幾
+庁
+広
+庄
+庇
+床
+序
+底
+庖
+店
+庚
+府
+度
+座
+庫
+庭
+庵
+庶
+康
+庸
+廂
+廃
+廉
+廊
+廓
+廟
+廠
+廣
+廬
+延
+廷
+建
+廻
+廼
+廿
+弁
+弄
+弉
+弊
+弌
+式
+弐
+弓
+弔
+引
+弖
+弗
+弘
+弛
+弟
+弥
+弦
+弧
+弱
+張
+強
+弼
+弾
+彈
+彊
+彌
+彎
+当
+彗
+彙
+彝
+形
+彦
+彩
+彫
+彬
+彭
+彰
+影
+彷
+役
+彼
+往
+征
+徂
+径
+待
+律
+後
+徐
+徑
+徒
+従
+得
+徠
+御
+徧
+徨
+復
+循
+徭
+微
+徳
+徴
+德
+徹
+徽
+心
+必
+忉
+忌
+忍
+志
+忘
+忙
+応
+忠
+快
+忯
+念
+忻
+忽
+忿
+怒
+怖
+思
+怠
+怡
+急
+性
+怨
+怪
+怯
+恂
+恋
+恐
+恒
+恕
+恣
+恤
+恥
+恨
+恩
+恬
+恭
+息
+恵
+悉
+悌
+悍
+悔
+悟
+悠
+患
+悦
+悩
+悪
+悲
+悼
+情
+惇
+惑
+惚
+惜
+惟
+惠
+惣
+惧
+惨
+惰
+想
+惹
+惺
+愈
+愉
+愍
+意
+愔
+愚
+愛
+感
+愷
+愿
+慈
+態
+慌
+慎
+慕
+慢
+慣
+慧
+慨
+慮
+慰
+慶
+憂
+憎
+憐
+憑
+憙
+憤
+憧
+憩
+憬
+憲
+憶
+憾
+懇
+應
+懌
+懐
+懲
+懸
+懺
+懽
+懿
+戈
+戊
+戌
+戎
+成
+我
+戒
+戔
+或
+戚
+戟
+戦
+截
+戮
+戯
+戴
+戸
+戻
+房
+所
+扁
+扇
+扈
+扉
+手
+才
+打
+払
+托
+扮
+扱
+扶
+批
+承
+技
+抄
+把
+抑
+抓
+投
+抗
+折
+抜
+択
+披
+抱
+抵
+抹
+押
+抽
+担
+拇
+拈
+拉
+拍
+拏
+拐
+拒
+拓
+拘
+拙
+招
+拝
+拠
+拡
+括
+拭
+拳
+拵
+拶
+拾
+拿
+持
+挂
+指
+按
+挑
+挙
+挟
+挨
+振
+挺
+挽
+挿
+捉
+捕
+捗
+捜
+捧
+捨
+据
+捺
+捻
+掃
+掄
+授
+掌
+排
+掖
+掘
+掛
+掟
+採
+探
+掣
+接
+控
+推
+掩
+措
+掬
+掲
+掴
+掻
+掾
+揃
+揄
+揆
+揉
+描
+提
+揖
+揚
+換
+握
+揮
+援
+揶
+揺
+損
+搦
+搬
+搭
+携
+搾
+摂
+摘
+摩
+摸
+摺
+撃
+撒
+撞
+撤
+撥
+撫
+播
+撮
+撰
+撲
+撹
+擁
+操
+擔
+擦
+擬
+擾
+攘
+攝
+攣
+支
+收
+改
+攻
+放
+政
+故
+敏
+救
+敗
+教
+敢
+散
+敦
+敬
+数
+整
+敵
+敷
+斂
+文
+斉
+斎
+斐
+斑
+斗
+料
+斜
+斟
+斤
+斥
+斧
+斬
+断
+斯
+新
+方
+於
+施
+旁
+旅
+旋
+旌
+族
+旗
+旛
+无
+旡
+既
+日
+旦
+旧
+旨
+早
+旬
+旭
+旺
+旻
+昂
+昆
+昇
+昉
+昌
+明
+昏
+易
+昔
+星
+映
+春
+昧
+昨
+昪
+昭
+是
+昵
+昼
+晁
+時
+晃
+晋
+晏
+晒
+晟
+晦
+晧
+晩
+普
+景
+晴
+晶
+智
+暁
+暇
+暈
+暉
+暑
+暖
+暗
+暘
+暢
+暦
+暫
+暮
+暲
+暴
+暹
+暾
+曄
+曇
+曉
+曖
+曙
+曜
+曝
+曠
+曰
+曲
+曳
+更
+書
+曹
+曼
+曽
+曾
+替
+最
+會
+月
+有
+朋
+服
+朏
+朔
+朕
+朗
+望
+朝
+期
+朧
+木
+未
+末
+本
+札
+朱
+朴
+机
+朽
+杁
+杉
+李
+杏
+材
+村
+杓
+杖
+杜
+杞
+束
+条
+杢
+杣
+来
+杭
+杮
+杯
+東
+杲
+杵
+杷
+杼
+松
+板
+枅
+枇
+析
+枓
+枕
+林
+枚
+果
+枝
+枠
+枡
+枢
+枯
+枳
+架
+柄
+柊
+柏
+某
+柑
+染
+柔
+柘
+柚
+柯
+柱
+柳
+柴
+柵
+査
+柾
+柿
+栂
+栃
+栄
+栖
+栗
+校
+株
+栲
+栴
+核
+根
+栻
+格
+栽
+桁
+桂
+桃
+框
+案
+桐
+桑
+桓
+桔
+桜
+桝
+桟
+桧
+桴
+桶
+桾
+梁
+梅
+梆
+梓
+梔
+梗
+梛
+條
+梟
+梢
+梧
+梨
+械
+梱
+梲
+梵
+梶
+棄
+棋
+棒
+棗
+棘
+棚
+棟
+棠
+森
+棲
+棹
+棺
+椀
+椅
+椋
+植
+椎
+椏
+椒
+椙
+検
+椥
+椹
+椿
+楊
+楓
+楕
+楚
+楞
+楠
+楡
+楢
+楨
+楪
+楫
+業
+楮
+楯
+楳
+極
+楷
+楼
+楽
+概
+榊
+榎
+榕
+榛
+榜
+榮
+榱
+榴
+槃
+槇
+槊
+構
+槌
+槍
+槐
+様
+槙
+槻
+槽
+槿
+樂
+樋
+樓
+樗
+標
+樟
+模
+権
+横
+樫
+樵
+樹
+樺
+樽
+橇
+橋
+橘
+機
+橿
+檀
+檄
+檎
+檐
+檗
+檜
+檣
+檥
+檬
+檮
+檸
+檻
+櫃
+櫓
+櫛
+櫟
+櫨
+櫻
+欄
+欅
+欠
+次
+欣
+欧
+欲
+欺
+欽
+款
+歌
+歎
+歓
+止
+正
+此
+武
+歩
+歪
+歯
+歳
+歴
+死
+殆
+殉
+殊
+残
+殖
+殯
+殴
+段
+殷
+殺
+殻
+殿
+毀
+毅
+母
+毎
+毒
+比
+毘
+毛
+毫
+毬
+氈
+氏
+民
+気
+水
+氷
+永
+氾
+汀
+汁
+求
+汎
+汐
+汗
+汚
+汝
+江
+池
+汪
+汰
+汲
+決
+汽
+沂
+沃
+沅
+沆
+沈
+沌
+沐
+沓
+沖
+沙
+没
+沢
+沱
+河
+沸
+油
+治
+沼
+沽
+沿
+況
+泉
+泊
+泌
+法
+泗
+泡
+波
+泣
+泥
+注
+泯
+泰
+泳
+洋
+洒
+洗
+洛
+洞
+津
+洩
+洪
+洲
+洸
+洹
+活
+洽
+派
+流
+浄
+浅
+浙
+浚
+浜
+浣
+浦
+浩
+浪
+浮
+浴
+海
+浸
+涅
+消
+涌
+涙
+涛
+涯
+液
+涵
+涼
+淀
+淄
+淆
+淇
+淋
+淑
+淘
+淡
+淤
+淨
+淫
+深
+淳
+淵
+混
+淹
+添
+清
+済
+渉
+渋
+渓
+渕
+渚
+減
+渟
+渠
+渡
+渤
+渥
+渦
+温
+渫
+測
+港
+游
+渾
+湊
+湖
+湘
+湛
+湧
+湫
+湯
+湾
+湿
+満
+源
+準
+溜
+溝
+溢
+溥
+溪
+溶
+溺
+滄
+滅
+滋
+滌
+滑
+滕
+滝
+滞
+滴
+滸
+滹
+滿
+漁
+漂
+漆
+漉
+漏
+漑
+演
+漕
+漠
+漢
+漣
+漫
+漬
+漱
+漸
+漿
+潅
+潔
+潙
+潜
+潟
+潤
+潭
+潮
+潰
+潴
+澁
+澂
+澄
+澎
+澗
+澤
+澪
+澱
+澳
+激
+濁
+濃
+濟
+濠
+濡
+濤
+濫
+濯
+濱
+濾
+瀉
+瀋
+瀑
+瀕
+瀞
+瀟
+瀧
+瀬
+瀾
+灌
+灑
+灘
+火
+灯
+灰
+灸
+災
+炉
+炊
+炎
+炒
+炭
+炮
+炷
+点
+為
+烈
+烏
+烙
+烝
+烹
+焔
+焙
+焚
+無
+焦
+然
+焼
+煇
+煉
+煌
+煎
+煕
+煙
+煤
+煥
+照
+煩
+煬
+煮
+煽
+熈
+熊
+熙
+熟
+熨
+熱
+熹
+熾
+燃
+燈
+燎
+燔
+燕
+燗
+燥
+燭
+燻
+爆
+爐
+爪
+爬
+爲
+爵
+父
+爺
+爼
+爽
+爾
+片
+版
+牌
+牒
+牘
+牙
+牛
+牝
+牟
+牡
+牢
+牧
+物
+牲
+特
+牽
+犂
+犠
+犬
+犯
+状
+狂
+狄
+狐
+狗
+狙
+狛
+狡
+狩
+独
+狭
+狷
+狸
+狼
+猊
+猛
+猟
+猥
+猨
+猩
+猪
+猫
+献
+猴
+猶
+猷
+猾
+猿
+獄
+獅
+獏
+獣
+獲
+玄
+玅
+率
+玉
+王
+玖
+玩
+玲
+珀
+珂
+珈
+珉
+珊
+珍
+珎
+珞
+珠
+珣
+珥
+珪
+班
+現
+球
+理
+琉
+琢
+琥
+琦
+琮
+琲
+琳
+琴
+琵
+琶
+瑁
+瑋
+瑙
+瑚
+瑛
+瑜
+瑞
+瑠
+瑤
+瑩
+瑪
+瑳
+瑾
+璃
+璋
+璜
+璞
+璧
+璨
+環
+璵
+璽
+璿
+瓊
+瓔
+瓜
+瓢
+瓦
+瓶
+甍
+甑
+甕
+甘
+甚
+甞
+生
+産
+甥
+用
+甫
+田
+由
+甲
+申
+男
+町
+画
+界
+畏
+畑
+畔
+留
+畜
+畝
+畠
+畢
+略
+番
+異
+畳
+當
+畷
+畸
+畺
+畿
+疆
+疇
+疋
+疎
+疏
+疑
+疫
+疱
+疲
+疹
+疼
+疾
+病
+症
+痒
+痔
+痕
+痘
+痙
+痛
+痢
+痩
+痴
+痺
+瘍
+瘡
+瘧
+療
+癇
+癌
+癒
+癖
+癡
+癪
+発
+登
+白
+百
+的
+皆
+皇
+皋
+皐
+皓
+皮
+皺
+皿
+盂
+盃
+盆
+盈
+益
+盒
+盗
+盛
+盞
+盟
+盡
+監
+盤
+盥
+盧
+目
+盲
+直
+相
+盾
+省
+眉
+看
+県
+眞
+真
+眠
+眷
+眺
+眼
+着
+睡
+督
+睦
+睨
+睿
+瞋
+瞑
+瞞
+瞬
+瞭
+瞰
+瞳
+瞻
+瞼
+瞿
+矍
+矛
+矜
+矢
+知
+矧
+矩
+短
+矮
+矯
+石
+砂
+砌
+研
+砕
+砥
+砦
+砧
+砲
+破
+砺
+硝
+硫
+硬
+硯
+碁
+碇
+碌
+碑
+碓
+碕
+碗
+碣
+碧
+碩
+確
+碾
+磁
+磐
+磔
+磧
+磨
+磬
+磯
+礁
+礎
+礒
+礙
+礫
+礬
+示
+礼
+社
+祀
+祁
+祇
+祈
+祉
+祐
+祓
+祕
+祖
+祗
+祚
+祝
+神
+祟
+祠
+祢
+祥
+票
+祭
+祷
+祺
+禁
+禄
+禅
+禊
+禍
+禎
+福
+禔
+禖
+禛
+禦
+禧
+禮
+禰
+禹
+禽
+禿
+秀
+私
+秋
+科
+秒
+秘
+租
+秤
+秦
+秩
+称
+移
+稀
+程
+税
+稔
+稗
+稙
+稚
+稜
+稠
+種
+稱
+稲
+稷
+稻
+稼
+稽
+稿
+穀
+穂
+穆
+積
+穎
+穏
+穗
+穜
+穢
+穣
+穫
+穴
+究
+空
+突
+窃
+窄
+窒
+窓
+窟
+窠
+窩
+窪
+窮
+窯
+竃
+竄
+竈
+立
+站
+竜
+竝
+竟
+章
+童
+竪
+竭
+端
+竴
+競
+竹
+竺
+竽
+竿
+笄
+笈
+笏
+笑
+笙
+笛
+笞
+笠
+笥
+符
+第
+笹
+筅
+筆
+筇
+筈
+等
+筋
+筌
+筍
+筏
+筐
+筑
+筒
+答
+策
+筝
+筥
+筧
+筬
+筮
+筯
+筰
+筵
+箆
+箇
+箋
+箏
+箒
+箔
+箕
+算
+箙
+箜
+管
+箪
+箭
+箱
+箸
+節
+篁
+範
+篆
+篇
+築
+篋
+篌
+篝
+篠
+篤
+篥
+篦
+篩
+篭
+篳
+篷
+簀
+簒
+簡
+簧
+簪
+簫
+簺
+簾
+簿
+籀
+籃
+籌
+籍
+籐
+籟
+籠
+籤
+籬
+米
+籾
+粂
+粉
+粋
+粒
+粕
+粗
+粘
+粛
+粟
+粥
+粧
+粮
+粳
+精
+糊
+糖
+糜
+糞
+糟
+糠
+糧
+糯
+糸
+糺
+系
+糾
+紀
+約
+紅
+紋
+納
+紐
+純
+紗
+紘
+紙
+級
+紛
+素
+紡
+索
+紫
+紬
+累
+細
+紳
+紵
+紹
+紺
+絁
+終
+絃
+組
+絅
+経
+結
+絖
+絞
+絡
+絣
+給
+統
+絲
+絵
+絶
+絹
+絽
+綏
+經
+継
+続
+綜
+綟
+綬
+維
+綱
+網
+綴
+綸
+綺
+綽
+綾
+綿
+緊
+緋
+総
+緑
+緒
+線
+締
+緥
+編
+緩
+緬
+緯
+練
+緻
+縁
+縄
+縅
+縒
+縛
+縞
+縢
+縣
+縦
+縫
+縮
+縹
+總
+績
+繁
+繊
+繋
+繍
+織
+繕
+繝
+繦
+繧
+繰
+繹
+繼
+纂
+纈
+纏
+纐
+纒
+纛
+缶
+罔
+罠
+罧
+罪
+置
+罰
+署
+罵
+罷
+罹
+羂
+羅
+羆
+羇
+羈
+羊
+羌
+美
+群
+羨
+義
+羯
+羲
+羹
+羽
+翁
+翅
+翌
+習
+翔
+翛
+翠
+翡
+翫
+翰
+翺
+翻
+翼
+耀
+老
+考
+者
+耆
+而
+耐
+耕
+耗
+耨
+耳
+耶
+耽
+聊
+聖
+聘
+聚
+聞
+聟
+聡
+聨
+聯
+聰
+聲
+聴
+職
+聾
+肄
+肆
+肇
+肉
+肋
+肌
+肖
+肘
+肛
+肝
+股
+肢
+肥
+肩
+肪
+肯
+肱
+育
+肴
+肺
+胃
+胆
+背
+胎
+胖
+胚
+胝
+胞
+胡
+胤
+胱
+胴
+胸
+能
+脂
+脅
+脆
+脇
+脈
+脊
+脚
+脛
+脩
+脱
+脳
+腋
+腎
+腐
+腑
+腔
+腕
+腫
+腰
+腱
+腸
+腹
+腺
+腿
+膀
+膏
+膚
+膜
+膝
+膠
+膣
+膨
+膩
+膳
+膵
+膾
+膿
+臂
+臆
+臈
+臍
+臓
+臘
+臚
+臣
+臥
+臨
+自
+臭
+至
+致
+臺
+臼
+舂
+舅
+與
+興
+舌
+舍
+舎
+舒
+舖
+舗
+舘
+舜
+舞
+舟
+舩
+航
+般
+舳
+舶
+船
+艇
+艘
+艦
+艮
+良
+色
+艶
+芋
+芒
+芙
+芝
+芥
+芦
+芬
+芭
+芯
+花
+芳
+芸
+芹
+芻
+芽
+芿
+苅
+苑
+苔
+苗
+苛
+苞
+苡
+若
+苦
+苧
+苫
+英
+苴
+苻
+茂
+范
+茄
+茅
+茎
+茗
+茘
+茜
+茨
+茲
+茵
+茶
+茸
+茹
+草
+荊
+荏
+荒
+荘
+荷
+荻
+荼
+莞
+莪
+莫
+莬
+莱
+莵
+莽
+菅
+菊
+菌
+菓
+菖
+菘
+菜
+菟
+菩
+菫
+華
+菱
+菴
+萄
+萊
+萌
+萍
+萎
+萠
+萩
+萬
+萱
+落
+葉
+著
+葛
+葡
+董
+葦
+葩
+葬
+葭
+葱
+葵
+葺
+蒋
+蒐
+蒔
+蒙
+蒟
+蒡
+蒲
+蒸
+蒻
+蒼
+蒿
+蓄
+蓆
+蓉
+蓋
+蓑
+蓬
+蓮
+蓼
+蔀
+蔑
+蔓
+蔚
+蔡
+蔦
+蔬
+蔭
+蔵
+蔽
+蕃
+蕉
+蕊
+蕎
+蕨
+蕩
+蕪
+蕭
+蕾
+薄
+薇
+薊
+薔
+薗
+薙
+薛
+薦
+薨
+薩
+薪
+薫
+薬
+薭
+薮
+藁
+藉
+藍
+藏
+藐
+藝
+藤
+藩
+藪
+藷
+藹
+藺
+藻
+蘂
+蘆
+蘇
+蘊
+蘭
+虎
+虐
+虔
+虚
+虜
+虞
+號
+虫
+虹
+虻
+蚊
+蚕
+蛇
+蛉
+蛍
+蛎
+蛙
+蛛
+蛟
+蛤
+蛭
+蛮
+蛸
+蛹
+蛾
+蜀
+蜂
+蜃
+蜆
+蜊
+蜘
+蜜
+蜷
+蜻
+蝉
+蝋
+蝕
+蝙
+蝠
+蝦
+蝶
+蝿
+螂
+融
+螣
+螺
+蟄
+蟇
+蟠
+蟷
+蟹
+蟻
+蠢
+蠣
+血
+衆
+行
+衍
+衒
+術
+街
+衙
+衛
+衝
+衞
+衡
+衢
+衣
+表
+衫
+衰
+衵
+衷
+衽
+衾
+衿
+袁
+袈
+袋
+袍
+袒
+袖
+袙
+袞
+袢
+被
+袰
+袱
+袴
+袷
+袿
+裁
+裂
+裃
+装
+裏
+裔
+裕
+裘
+裙
+補
+裟
+裡
+裲
+裳
+裴
+裸
+裹
+製
+裾
+褂
+褄
+複
+褌
+褐
+褒
+褥
+褪
+褶
+褻
+襄
+襖
+襞
+襟
+襠
+襦
+襪
+襲
+襴
+襷
+西
+要
+覆
+覇
+覈
+見
+規
+視
+覗
+覚
+覧
+親
+覲
+観
+覺
+觀
+角
+解
+触
+言
+訂
+計
+討
+訓
+託
+記
+訛
+訟
+訢
+訥
+訪
+設
+許
+訳
+訴
+訶
+診
+註
+証
+詐
+詔
+評
+詛
+詞
+詠
+詢
+詣
+試
+詩
+詫
+詮
+詰
+話
+該
+詳
+誄
+誅
+誇
+誉
+誌
+認
+誓
+誕
+誘
+語
+誠
+誡
+誣
+誤
+誥
+誦
+説
+読
+誰
+課
+誼
+誾
+調
+談
+請
+諌
+諍
+諏
+諒
+論
+諚
+諜
+諟
+諡
+諦
+諧
+諫
+諭
+諮
+諱
+諶
+諷
+諸
+諺
+諾
+謀
+謄
+謌
+謎
+謗
+謙
+謚
+講
+謝
+謡
+謫
+謬
+謹
+證
+識
+譚
+譛
+譜
+警
+譬
+譯
+議
+譲
+譴
+護
+讀
+讃
+讐
+讒
+谷
+谿
+豅
+豆
+豊
+豎
+豐
+豚
+象
+豪
+豫
+豹
+貌
+貝
+貞
+負
+財
+貢
+貧
+貨
+販
+貪
+貫
+責
+貯
+貰
+貴
+買
+貸
+費
+貼
+貿
+賀
+賁
+賂
+賃
+賄
+資
+賈
+賊
+賎
+賑
+賓
+賛
+賜
+賞
+賠
+賢
+賣
+賤
+賦
+質
+賭
+購
+賽
+贄
+贅
+贈
+贋
+贔
+贖
+赤
+赦
+走
+赴
+起
+超
+越
+趙
+趣
+足
+趺
+趾
+跋
+跏
+距
+跡
+跨
+跪
+路
+跳
+践
+踊
+踏
+踐
+踞
+踪
+踵
+蹄
+蹉
+蹊
+蹟
+蹲
+蹴
+躅
+躇
+躊
+躍
+躑
+躙
+躪
+身
+躬
+躯
+躰
+車
+軋
+軌
+軍
+軒
+軟
+転
+軸
+軻
+軽
+軾
+較
+載
+輌
+輔
+輜
+輝
+輦
+輩
+輪
+輯
+輸
+輿
+轄
+轍
+轟
+轢
+辛
+辞
+辟
+辥
+辦
+辨
+辰
+辱
+農
+辺
+辻
+込
+迂
+迅
+迎
+近
+返
+迢
+迦
+迪
+迫
+迭
+述
+迷
+迹
+追
+退
+送
+逃
+逅
+逆
+逍
+透
+逐
+逓
+途
+逕
+逗
+這
+通
+逝
+逞
+速
+造
+逢
+連
+逮
+週
+進
+逸
+逼
+遁
+遂
+遅
+遇
+遊
+運
+遍
+過
+遐
+道
+達
+違
+遙
+遜
+遠
+遡
+遣
+遥
+適
+遭
+遮
+遯
+遵
+遷
+選
+遺
+遼
+避
+邀
+邁
+邂
+邃
+還
+邇
+邉
+邊
+邑
+那
+邦
+邨
+邪
+邯
+邵
+邸
+郁
+郊
+郎
+郡
+郢
+部
+郭
+郴
+郵
+郷
+都
+鄂
+鄙
+鄭
+鄰
+鄲
+酉
+酋
+酌
+配
+酎
+酒
+酔
+酢
+酥
+酪
+酬
+酵
+酷
+酸
+醍
+醐
+醒
+醗
+醜
+醤
+醪
+醵
+醸
+采
+釈
+釉
+釋
+里
+重
+野
+量
+釐
+金
+釘
+釜
+針
+釣
+釧
+釿
+鈍
+鈎
+鈐
+鈔
+鈞
+鈦
+鈴
+鈷
+鈸
+鈿
+鉄
+鉇
+鉉
+鉋
+鉛
+鉢
+鉤
+鉦
+鉱
+鉾
+銀
+銃
+銅
+銈
+銑
+銕
+銘
+銚
+銜
+銭
+鋏
+鋒
+鋤
+鋭
+鋲
+鋳
+鋸
+鋺
+鋼
+錆
+錍
+錐
+錘
+錠
+錣
+錦
+錫
+錬
+錯
+録
+錵
+鍋
+鍍
+鍑
+鍔
+鍛
+鍬
+鍮
+鍵
+鍼
+鍾
+鎌
+鎖
+鎗
+鎚
+鎧
+鎬
+鎮
+鎰
+鎹
+鏃
+鏑
+鏡
+鐃
+鐇
+鐐
+鐔
+鐘
+鐙
+鐚
+鐡
+鐵
+鐸
+鑁
+鑊
+鑑
+鑒
+鑚
+鑠
+鑢
+鑰
+鑵
+鑷
+鑼
+鑽
+鑿
+長
+門
+閃
+閇
+閉
+開
+閏
+閑
+間
+閔
+閘
+関
+閣
+閤
+閥
+閦
+閨
+閬
+閲
+閻
+閼
+閾
+闇
+闍
+闔
+闕
+闘
+關
+闡
+闢
+闥
+阜
+阪
+阮
+阯
+防
+阻
+阿
+陀
+陂
+附
+陌
+降
+限
+陛
+陞
+院
+陣
+除
+陥
+陪
+陬
+陰
+陳
+陵
+陶
+陸
+険
+陽
+隅
+隆
+隈
+隊
+隋
+階
+随
+隔
+際
+障
+隠
+隣
+隧
+隷
+隻
+隼
+雀
+雁
+雄
+雅
+集
+雇
+雉
+雊
+雋
+雌
+雍
+雑
+雖
+雙
+雛
+離
+難
+雨
+雪
+雫
+雰
+雲
+零
+雷
+雹
+電
+需
+震
+霊
+霍
+霖
+霜
+霞
+霧
+霰
+露
+靈
+青
+靖
+静
+靜
+非
+面
+革
+靫
+靭
+靱
+靴
+靺
+鞁
+鞄
+鞆
+鞋
+鞍
+鞏
+鞘
+鞠
+鞨
+鞭
+韋
+韓
+韜
+韮
+音
+韶
+韻
+響
+頁
+頂
+頃
+項
+順
+須
+頌
+預
+頑
+頒
+頓
+領
+頚
+頬
+頭
+頴
+頸
+頻
+頼
+顆
+題
+額
+顎
+顔
+顕
+顗
+願
+顛
+類
+顧
+顯
+風
+飛
+食
+飢
+飩
+飫
+飯
+飲
+飴
+飼
+飽
+飾
+餃
+餅
+餉
+養
+餌
+餐
+餓
+餘
+餝
+餡
+館
+饂
+饅
+饉
+饋
+饌
+饒
+饗
+首
+馗
+香
+馨
+馬
+馳
+馴
+駄
+駅
+駆
+駈
+駐
+駒
+駕
+駝
+駿
+騁
+騎
+騏
+騒
+験
+騙
+騨
+騰
+驕
+驚
+驛
+驢
+骨
+骸
+髄
+體
+高
+髙
+髢
+髪
+髭
+髮
+髷
+髻
+鬘
+鬚
+鬢
+鬨
+鬯
+鬱
+鬼
+魁
+魂
+魄
+魅
+魏
+魔
+魚
+魯
+鮎
+鮑
+鮒
+鮪
+鮫
+鮭
+鮮
+鯉
+鯔
+鯖
+鯛
+鯨
+鯰
+鯱
+鰐
+鰒
+鰭
+鰯
+鰰
+鰹
+鰻
+鱈
+鱒
+鱗
+鱧
+鳥
+鳩
+鳰
+鳳
+鳴
+鳶
+鴈
+鴉
+鴎
+鴛
+鴟
+鴦
+鴨
+鴫
+鴻
+鵄
+鵜
+鵞
+鵡
+鵬
+鵲
+鵺
+鶉
+鶏
+鶯
+鶴
+鷄
+鷙
+鷲
+鷹
+鷺
+鸚
+鸞
+鹸
+鹽
+鹿
+麁
+麒
+麓
+麗
+麝
+麞
+麟
+麦
+麩
+麹
+麺
+麻
+麾
+麿
+黄
+黌
+黍
+黒
+黙
+黛
+黠
+鼈
+鼉
+鼎
+鼓
+鼠
+鼻
+齊
+齋
+齟
+齢
+齬
+龍
+龕
+龗
+!
+#
+%
+&
+(
+)
++
+,
+-
+.
+/
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+:
+;
+=
+?
+@
+A
+B
+C
+D
+E
+F
+G
+H
+I
+J
+K
+L
+M
+N
+O
+P
+R
+S
+T
+U
+V
+W
+X
+Z
+a
+c
+d
+e
+f
+h
+i
+j
+k
+l
+m
+n
+o
+p
+r
+s
+t
+u
+y
+z
+~
+・
+ 

+ 151 - 0
models/ocr/Keys/泰卢固文.txt

@@ -0,0 +1,151 @@
+t
+e
+_
+i
+m
+g
+/
+5
+I
+L
+S
+V
+R
+C
+2
+0
+1
+v
+a
+l
+3
+4
+8
+9
+.
+j
+p
+త
+ె
+ర
+క
+్
+ి
+ం
+చ
+ే
+ద
+ు
+7
+6
+ఉ
+ా
+మ
+ట
+ో
+వ
+ప
+ల
+శ
+ఆ
+య
+ై
+భ
+'
+ీ
+గ
+ూ
+డ
+ధ
+హ
+న
+జ
+స
+[
+‌
+ష
+అ
+ణ
+ఫ
+బ
+ఎ
+;
+ళ
+థ
+ొ
+ఠ
+ృ
+ఒ
+ఇ
+ః
+ఊ
+ఖ
+-
+ఐ
+ఘ
+ౌ
+ఏ
+ఈ
+ఛ
+,
+ఓ
+ఞ
+|
+?
+:
+ఢ
+"
+(
+”
+!
++
+)
+*
+=
+&
+“
+€
+]
+$
+s
+c
+n
+w
+k
+J
+G
+u
+d
+r
+E
+o
+h
+y
+b
+f
+B
+M
+O
+T
+N
+D
+P
+A
+F
+x
+W
+Y
+U
+H
+K
+X
+z
+Z
+Q
+q
+%
+#
+@

+ 95 - 0
models/ocr/Keys/英文.txt

@@ -0,0 +1,95 @@
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+:
+;
+<
+=
+>
+?
+@
+A
+B
+C
+D
+E
+F
+G
+H
+I
+J
+K
+L
+M
+N
+O
+P
+Q
+R
+S
+T
+U
+V
+W
+X
+Y
+Z
+[
+\
+]
+^
+_
+`
+a
+b
+c
+d
+e
+f
+g
+h
+i
+j
+k
+l
+m
+n
+o
+p
+q
+r
+s
+t
+u
+v
+w
+x
+y
+z
+{
+|
+}
+~
+!
+"
+#
+$
+%
+&
+'
+(
+)
+*
++
+,
+-
+.
+/
+ 

+ 3688 - 0
models/ocr/Keys/韩文.txt

@@ -0,0 +1,3688 @@
+!
+"
+#
+$
+%
+&
+'
+*
++
+-
+/
+0
+1
+2
+3
+4
+5
+6
+7
+8
+9
+:
+;
+<
+=
+>
+?
+A
+B
+C
+D
+E
+F
+G
+H
+I
+J
+K
+L
+M
+N
+O
+P
+Q
+R
+S
+T
+U
+V
+W
+X
+Y
+Z
+[
+\
+]
+^
+_
+`
+a
+b
+c
+d
+e
+f
+g
+h
+i
+j
+k
+l
+m
+n
+o
+p
+q
+r
+s
+t
+u
+v
+w
+x
+y
+z
+{
+|
+}
+~
+​
+’
+“
+”
+→
+∇
+∼
+「
+」
+ア
+カ
+グ
+ニ
+ラ
+ン
+ㄱ
+ㄴ
+ㄷ
+ㄸ
+ㄹ
+ㅂ
+ㅅ
+ㅆ
+ㅇ
+ㅈ
+ㅊ
+ㅋ
+ㅌ
+ㅎ
+ㅓ
+ㅜ
+ㅣ
+一
+丁
+七
+三
+上
+下
+不
+丑
+世
+丘
+丞
+中
+丸
+丹
+主
+乃
+久
+之
+乎
+乘
+九
+也
+乳
+乾
+事
+二
+云
+互
+五
+井
+亞
+亡
+交
+亥
+亨
+享
+京
+亭
+人
+仁
+今
+他
+仙
+代
+令
+以
+仰
+仲
+件
+任
+企
+伊
+伍
+伎
+伏
+伐
+休
+伯
+伴
+伸
+佃
+佈
+位
+低
+住
+佐
+何
+佛
+作
+使
+來
+供
+依
+侯
+侵
+侶
+便
+俗
+保
+俠
+信
+修
+俱
+俳
+倉
+個
+倍
+倒
+候
+借
+値
+倫
+倭
+假
+偈
+偉
+偏
+停
+偶
+傅
+傑
+傳
+傷
+傾
+像
+僞
+僥
+僧
+價
+儀
+儉
+儒
+優
+儼
+兀
+允
+元
+兆
+先
+光
+克
+兒
+入
+內
+全
+八
+公
+六
+共
+兵
+其
+具
+典
+兼
+再
+冠
+冥
+冶
+准
+凞
+凡
+凱
+出
+函
+刀
+分
+刊
+刑
+列
+初
+判
+別
+利
+到
+制
+券
+刺
+刻
+則
+前
+剛
+副
+創
+劃
+劑
+力
+功
+加
+劣
+助
+劫
+勇
+動
+務
+勝
+勢
+勳
+勸
+匈
+化
+北
+匠
+區
+十
+千
+午
+半
+卍
+卑
+卒
+卓
+南
+博
+卜
+占
+卦
+印
+危
+卵
+卷
+卽
+卿
+厄
+原
+厦
+去
+參
+又
+叉
+友
+反
+叔
+受
+口
+古
+句
+可
+台
+史
+右
+司
+各
+合
+吉
+同
+名
+后
+吏
+吐
+君
+吠
+吳
+呂
+告
+周
+味
+呵
+命
+和
+咳
+咸
+咽
+哀
+品
+哨
+哮
+哲
+唐
+唯
+唱
+商
+問
+啼
+善
+喆
+喉
+喜
+喩
+喪
+嘗
+器
+嚴
+囊
+四
+回
+因
+困
+固
+圈
+國
+圍
+園
+圓
+圖
+團
+土
+在
+地
+均
+坊
+坐
+坑
+坵
+型
+垢
+城
+域
+埴
+執
+培
+基
+堂
+堅
+堆
+堤
+堯
+報
+場
+塔
+塚
+塞
+塵
+境
+墜
+墟
+墨
+墳
+墾
+壁
+壇
+壓
+壤
+士
+壬
+壯
+壺
+壽
+夏
+夕
+外
+多
+夜
+夢
+大
+天
+太
+夫
+央
+失
+夷
+奄
+奇
+奉
+奎
+奏
+契
+奔
+奮
+女
+奴
+好
+如
+妄
+妊
+妖
+妙
+始
+姑
+姓
+姚
+姜
+威
+婆
+婚
+婦
+媒
+媚
+子
+孔
+字
+存
+孝
+孟
+季
+孤
+孫
+學
+孺
+宇
+守
+安
+宋
+宗
+官
+宙
+定
+客
+宣
+室
+宮
+害
+家
+容
+寂
+寃
+寄
+寅
+密
+寇
+富
+寒
+寓
+實
+審
+寫
+寬
+寶
+寸
+寺
+封
+將
+專
+尊
+對
+小
+少
+尙
+尹
+尼
+尿
+局
+居
+屈
+屋
+屍
+屎
+屛
+層
+屬
+山
+岐
+岡
+岩
+岳
+岸
+峙
+峰
+島
+峻
+峽
+崇
+崔
+崖
+崩
+嶋
+巖
+川
+州
+巢
+工
+左
+巧
+巨
+巫
+差
+己
+巷
+市
+布
+帝
+師
+帶
+常
+帽
+幕
+干
+平
+年
+幹
+幻
+幼
+幽
+庇
+序
+店
+府
+度
+座
+庫
+庭
+康
+廟
+廣
+廳
+延
+廷
+建
+廻
+弁
+式
+弑
+弓
+引
+弘
+弟
+弱
+張
+强
+弼
+彌
+彛
+形
+彬
+影
+役
+彼
+彿
+往
+征
+待
+律
+後
+徐
+徑
+得
+從
+循
+微
+德
+徹
+心
+必
+忌
+忍
+志
+忠
+思
+怡
+急
+性
+恐
+恒
+恨
+恩
+悅
+悖
+患
+悲
+情
+惑
+惟
+惠
+惡
+想
+惺
+愁
+意
+愚
+愛
+感
+愼
+慈
+態
+慕
+慣
+慧
+慾
+憂
+憤
+憺
+應
+懸
+戎
+成
+我
+戟
+戮
+戰
+戴
+戶
+房
+所
+手
+才
+打
+批
+承
+技
+抄
+把
+抗
+抱
+抽
+拇
+拓
+拘
+拙
+拜
+拾
+持
+指
+捌
+捨
+捿
+授
+掌
+排
+接
+推
+提
+揚
+揭
+援
+損
+搗
+摩
+播
+操
+擒
+擔
+擘
+據
+擧
+攘
+攝
+攬
+支
+改
+攻
+放
+政
+故
+敍
+敎
+救
+敗
+散
+敬
+整
+數
+文
+斗
+料
+斛
+斜
+斧
+斯
+新
+斷
+方
+於
+施
+旋
+族
+旗
+日
+旨
+早
+旱
+昌
+明
+易
+昔
+星
+春
+昧
+昭
+是
+時
+晉
+晋
+晩
+普
+景
+晴
+晶
+智
+暈
+暑
+暗
+暘
+曉
+曜
+曠
+曦
+曰
+曲
+書
+曹
+曼
+曾
+最
+會
+月
+有
+朋
+服
+望
+朝
+期
+木
+未
+末
+本
+朱
+朴
+李
+材
+村
+杖
+杜
+杞
+杭
+杯
+東
+松
+板
+林
+果
+枝
+枯
+枰
+枾
+柏
+柑
+柱
+栗
+校
+栢
+核
+根
+格
+桀
+桂
+案
+桎
+桑
+桓
+桔
+梁
+梏
+梓
+梗
+條
+梨
+梵
+棗
+棟
+森
+植
+椒
+楊
+楓
+楚
+業
+楮
+極
+榮
+槃
+槍
+樂
+樓
+樗
+樣
+樸
+樹
+樺
+樽
+橄
+橋
+橘
+機
+橡
+檀
+檎
+權
+欌
+欖
+次
+欲
+歌
+歐
+止
+正
+此
+步
+武
+歲
+歸
+死
+殖
+段
+殷
+殺
+殿
+毅
+母
+毒
+比
+毛
+氏
+民
+氣
+水
+永
+求
+汎
+汗
+江
+池
+沅
+沒
+沖
+沙
+沛
+河
+油
+治
+沼
+沿
+泉
+泊
+法
+泗
+泡
+波
+注
+泰
+洋
+洙
+洛
+洞
+津
+洲
+活
+派
+流
+浅
+浦
+浮
+浴
+海
+涅
+涇
+消
+涌
+液
+淑
+淡
+淨
+淫
+深
+淳
+淵
+淸
+渠
+渡
+游
+渾
+湖
+湯
+源
+溪
+溫
+溶
+滄
+滅
+滋
+滯
+滿
+漁
+漆
+漢
+漫
+漸
+潑
+潤
+潭
+澄
+澎
+澤
+澳
+澹
+濁
+濕
+濟
+濤
+濯
+瀋
+瀝
+灣
+火
+灰
+灸
+災
+炎
+炭
+点
+烈
+烏
+烙
+焚
+無
+焦
+然
+煌
+煎
+照
+煬
+煮
+熟
+熱
+燁
+燈
+燔
+燕
+燥
+燧
+燮
+爲
+爵
+父
+片
+版
+牌
+牛
+牝
+牟
+牡
+物
+特
+犧
+犬
+狀
+狗
+猥
+猩
+猪
+獨
+獵
+獸
+獻
+玄
+玉
+王
+玲
+珍
+珠
+珪
+班
+現
+球
+理
+琴
+瑞
+瑟
+瑪
+璃
+璋
+璽
+瓜
+瓦
+甑
+甘
+生
+産
+用
+甫
+田
+由
+甲
+申
+男
+界
+畏
+留
+畜
+畢
+略
+番
+異
+畵
+當
+畸
+疏
+疑
+疫
+疹
+疼
+病
+症
+痔
+痛
+痺
+瘀
+瘍
+瘡
+療
+癌
+癖
+登
+發
+白
+百
+的
+皆
+皇
+皮
+盂
+盆
+益
+盛
+盜
+盟
+盡
+盤
+盧
+目
+直
+相
+省
+看
+眞
+眼
+睡
+督
+瞋
+矢
+矣
+知
+短
+石
+破
+碍
+碑
+磁
+磨
+磬
+示
+社
+祇
+祖
+祝
+神
+祥
+祭
+祺
+禁
+禅
+禍
+福
+禦
+禪
+禮
+禹
+禽
+禾
+秀
+私
+秉
+秋
+科
+秘
+秤
+秦
+秩
+移
+稀
+稗
+種
+稱
+稷
+稼
+稽
+穀
+穆
+積
+空
+窮
+竅
+立
+章
+童
+竭
+端
+竹
+笑
+符
+第
+筆
+等
+筍
+答
+策
+箋
+箕
+管
+箱
+節
+篇
+簡
+米
+粉
+粘
+粥
+精
+糖
+糞
+系
+紀
+紂
+約
+紅
+紋
+純
+紙
+級
+素
+索
+紫
+紬
+累
+細
+紳
+終
+組
+結
+絡
+統
+絲
+絶
+絹
+經
+綠
+維
+綱
+網
+綸
+綽
+緖
+線
+緣
+緯
+縣
+縱
+總
+織
+繡
+繩
+繪
+繭
+纂
+續
+罕
+置
+罰
+羅
+羊
+美
+群
+義
+羽
+翁
+習
+翟
+老
+考
+者
+而
+耐
+耕
+耳
+聃
+聖
+聞
+聰
+聲
+職
+肇
+肉
+肖
+肝
+股
+肥
+育
+肺
+胃
+胎
+胚
+胞
+胡
+胥
+能
+脂
+脈
+脚
+脛
+脣
+脩
+脫
+脯
+脾
+腋
+腎
+腫
+腸
+腹
+膜
+膠
+膨
+膽
+臆
+臟
+臣
+臥
+臨
+自
+至
+致
+臺
+臼
+臾
+與
+興
+舊
+舌
+舍
+舒
+舜
+舟
+般
+船
+艦
+良
+色
+芋
+花
+芳
+芽
+苑
+苔
+苕
+苛
+苞
+若
+苦
+英
+茂
+茵
+茶
+茹
+荀
+荇
+草
+荒
+荷
+莊
+莫
+菊
+菌
+菜
+菩
+菫
+華
+菴
+菽
+萊
+萍
+萬
+落
+葉
+著
+葛
+董
+葬
+蒙
+蒜
+蒲
+蒸
+蒿
+蓮
+蔓
+蔘
+蔡
+蔬
+蕃
+蕉
+蕓
+薄
+薑
+薛
+薩
+薪
+薺
+藏
+藝
+藤
+藥
+藩
+藻
+蘆
+蘇
+蘊
+蘚
+蘭
+虎
+處
+虛
+虞
+虹
+蜀
+蜂
+蜜
+蝕
+蝶
+融
+蟬
+蟲
+蠶
+蠻
+血
+衆
+行
+術
+衛
+衡
+衣
+表
+袁
+裔
+裕
+裙
+補
+製
+複
+襄
+西
+要
+見
+視
+親
+覺
+觀
+角
+解
+言
+訂
+訊
+訓
+託
+記
+訣
+設
+診
+註
+評
+詩
+話
+詵
+誅
+誌
+認
+誕
+語
+誠
+誤
+誥
+誦
+說
+調
+談
+諍
+論
+諡
+諫
+諭
+諸
+謙
+講
+謝
+謠
+證
+識
+譚
+譜
+譯
+議
+護
+讀
+變
+谷
+豆
+豊
+豚
+象
+豪
+豫
+貝
+貞
+財
+貧
+貨
+貪
+貫
+貴
+貸
+費
+資
+賊
+賓
+賞
+賢
+賣
+賦
+質
+贍
+赤
+赫
+走
+起
+超
+越
+趙
+趣
+趨
+足
+趾
+跋
+跡
+路
+踏
+蹟
+身
+躬
+車
+軍
+軒
+軟
+載
+輓
+輕
+輪
+輯
+輸
+輻
+輿
+轅
+轉
+辨
+辭
+辯
+辰
+農
+近
+迦
+述
+追
+逆
+透
+逐
+通
+逝
+造
+逢
+連
+進
+逵
+遂
+遊
+運
+遍
+過
+道
+達
+遠
+遡
+適
+遷
+選
+遺
+遽
+還
+邊
+邑
+那
+邪
+郞
+郡
+部
+都
+鄒
+鄕
+鄭
+鄲
+配
+酒
+酸
+醉
+醫
+醯
+釋
+里
+重
+野
+量
+釐
+金
+針
+鈍
+鈴
+鉞
+銀
+銅
+銘
+鋼
+錄
+錢
+錦
+鎭
+鏡
+鐘
+鐵
+鑑
+鑛
+長
+門
+閃
+開
+間
+閔
+閣
+閥
+閭
+閻
+闕
+關
+阪
+防
+阿
+陀
+降
+限
+陝
+院
+陰
+陳
+陵
+陶
+陸
+陽
+隆
+隊
+隋
+階
+際
+障
+隣
+隨
+隱
+隷
+雀
+雄
+雅
+集
+雇
+雌
+雖
+雙
+雜
+離
+難
+雨
+雪
+雲
+電
+霜
+露
+靈
+靑
+靖
+靜
+非
+面
+革
+靴
+鞏
+韓
+音
+韶
+韻
+順
+須
+頊
+頌
+領
+頭
+顔
+願
+顚
+類
+顯
+風
+飛
+食
+飢
+飮
+飯
+飾
+養
+餓
+餘
+首
+香
+馨
+馬
+駒
+騫
+騷
+驕
+骨
+骸
+髓
+體
+高
+髥
+髮
+鬪
+鬱
+鬼
+魏
+魔
+魚
+魯
+鮮
+鰍
+鰐
+鳥
+鳧
+鳳
+鴨
+鵲
+鶴
+鷄
+鷹
+鹽
+鹿
+麗
+麥
+麻
+黃
+黑
+默
+點
+黨
+鼎
+齊
+齋
+齒
+龍
+龜
+가
+각
+간
+갇
+갈
+갉
+감
+갑
+값
+갓
+갔
+강
+갖
+갗
+같
+갚
+갛
+개
+객
+갠
+갤
+갬
+갭
+갯
+갰
+갱
+갸
+걀
+걔
+걘
+거
+걱
+건
+걷
+걸
+검
+겁
+것
+겄
+겅
+겆
+겉
+겊
+겋
+게
+겐
+겔
+겟
+겠
+겡
+겨
+격
+겪
+견
+결
+겸
+겹
+겻
+겼
+경
+곁
+계
+곕
+곗
+고
+곡
+곤
+곧
+골
+곪
+곬
+곯
+곰
+곱
+곳
+공
+곶
+과
+곽
+관
+괄
+괌
+광
+괘
+괜
+괭
+괴
+괸
+굉
+교
+구
+국
+군
+굳
+굴
+굵
+굶
+굼
+굽
+굿
+궁
+궂
+궈
+권
+궐
+궜
+궝
+궤
+귀
+귄
+귈
+귓
+규
+균
+귤
+그
+극
+근
+글
+긁
+금
+급
+긋
+긍
+기
+긴
+길
+김
+깁
+깃
+깅
+깊
+까
+깍
+깎
+깐
+깔
+깜
+깝
+깟
+깡
+깥
+깨
+깬
+깰
+깻
+깼
+깽
+꺄
+꺼
+꺽
+꺾
+껀
+껄
+껌
+껍
+껏
+껐
+껑
+께
+껴
+꼈
+꼍
+꼐
+꼬
+꼭
+꼴
+꼼
+꼽
+꼿
+꽁
+꽂
+꽃
+꽉
+꽝
+꽤
+꽥
+꾀
+꾜
+꾸
+꾹
+꾼
+꿀
+꿇
+꿈
+꿉
+꿋
+꿍
+꿎
+꿔
+꿨
+꿩
+꿰
+꿴
+뀄
+뀌
+뀐
+뀔
+뀜
+뀝
+끄
+끈
+끊
+끌
+끓
+끔
+끕
+끗
+끙
+끝
+끼
+끽
+낀
+낄
+낌
+낍
+낏
+낑
+나
+낙
+낚
+난
+낟
+날
+낡
+남
+납
+낫
+났
+낭
+낮
+낯
+낱
+낳
+내
+낵
+낸
+낼
+냄
+냅
+냇
+냈
+냉
+냐
+냔
+냘
+냥
+너
+넉
+넋
+넌
+널
+넓
+넘
+넙
+넛
+넜
+넝
+넣
+네
+넥
+넨
+넬
+넴
+넵
+넷
+넸
+넹
+녀
+녁
+년
+념
+녔
+녕
+녘
+녜
+노
+녹
+논
+놀
+놈
+놋
+농
+높
+놓
+놔
+놨
+뇌
+뇨
+뇩
+뇽
+누
+눅
+눈
+눌
+눔
+눕
+눗
+눠
+눴
+뉘
+뉜
+뉩
+뉴
+늄
+늅
+늉
+느
+늑
+는
+늘
+늙
+늠
+늡
+능
+늦
+늪
+늬
+니
+닉
+닌
+닐
+님
+닙
+닛
+닝
+닢
+다
+닥
+닦
+단
+닫
+달
+닭
+닮
+닯
+닳
+담
+답
+닷
+당
+닻
+닿
+대
+댁
+댄
+댈
+댐
+댑
+댓
+댔
+댕
+댜
+더
+덕
+덖
+던
+덜
+덟
+덤
+덥
+덧
+덩
+덫
+덮
+데
+덱
+덴
+델
+뎀
+뎃
+뎅
+뎌
+뎠
+뎨
+도
+독
+돈
+돋
+돌
+돔
+돕
+돗
+동
+돛
+돝
+돼
+됐
+되
+된
+될
+됨
+됩
+됴
+두
+둑
+둔
+둘
+둠
+둡
+둣
+둥
+둬
+뒀
+뒤
+뒬
+뒷
+뒹
+듀
+듈
+듐
+드
+득
+든
+듣
+들
+듦
+듬
+듭
+듯
+등
+듸
+디
+딕
+딘
+딛
+딜
+딤
+딥
+딧
+딨
+딩
+딪
+따
+딱
+딴
+딸
+땀
+땄
+땅
+때
+땐
+땔
+땜
+땝
+땠
+땡
+떠
+떡
+떤
+떨
+떫
+떰
+떱
+떳
+떴
+떵
+떻
+떼
+떽
+뗀
+뗄
+뗍
+뗏
+뗐
+뗑
+또
+똑
+똘
+똥
+뙤
+뚜
+뚝
+뚤
+뚫
+뚱
+뛰
+뛴
+뛸
+뜀
+뜁
+뜨
+뜩
+뜬
+뜯
+뜰
+뜸
+뜻
+띄
+띈
+띌
+띔
+띕
+띠
+띤
+띨
+띱
+띵
+라
+락
+란
+랄
+람
+랍
+랏
+랐
+랑
+랒
+랗
+래
+랙
+랜
+랠
+램
+랩
+랫
+랬
+랭
+랴
+략
+량
+러
+럭
+런
+럴
+럼
+럽
+럿
+렀
+렁
+렇
+레
+렉
+렌
+렐
+렘
+렙
+렛
+렝
+려
+력
+련
+렬
+렴
+렵
+렷
+렸
+령
+례
+로
+록
+론
+롤
+롬
+롭
+롯
+롱
+롸
+롹
+뢰
+뢴
+뢸
+룃
+료
+룐
+룡
+루
+룩
+룬
+룰
+룸
+룹
+룻
+룽
+뤄
+뤘
+뤼
+류
+륙
+륜
+률
+륨
+륭
+르
+륵
+른
+를
+름
+릅
+릇
+릉
+릎
+리
+릭
+린
+릴
+림
+립
+릿
+링
+마
+막
+만
+많
+맏
+말
+맑
+맘
+맙
+맛
+망
+맞
+맡
+맣
+매
+맥
+맨
+맬
+맴
+맵
+맷
+맸
+맹
+맺
+먀
+먁
+머
+먹
+먼
+멀
+멈
+멋
+멍
+멎
+메
+멕
+멘
+멜
+멤
+멥
+멧
+멩
+며
+멱
+면
+멸
+몄
+명
+몇
+모
+목
+몫
+몬
+몰
+몸
+몹
+못
+몽
+뫼
+묘
+무
+묵
+묶
+문
+묻
+물
+묽
+뭄
+뭅
+뭇
+뭉
+뭍
+뭏
+뭐
+뭔
+뭘
+뭡
+뭣
+뮈
+뮌
+뮐
+뮤
+뮬
+므
+믈
+믐
+미
+믹
+민
+믿
+밀
+밈
+밉
+밋
+밌
+밍
+및
+밑
+바
+박
+밖
+반
+받
+발
+밝
+밟
+밤
+밥
+밧
+방
+밭
+배
+백
+밴
+밸
+뱀
+뱁
+뱃
+뱄
+뱅
+뱉
+뱍
+뱐
+버
+벅
+번
+벌
+범
+법
+벗
+벙
+벚
+베
+벡
+벤
+벨
+벰
+벱
+벳
+벵
+벼
+벽
+변
+별
+볍
+볏
+볐
+병
+볕
+보
+복
+볶
+본
+볼
+봄
+봅
+봇
+봉
+봐
+봤
+뵈
+뵐
+뵙
+부
+북
+분
+붇
+불
+붉
+붐
+붓
+붕
+붙
+뷔
+뷰
+뷴
+뷸
+브
+븐
+블
+비
+빅
+빈
+빌
+빔
+빕
+빗
+빙
+빚
+빛
+빠
+빡
+빤
+빨
+빳
+빴
+빵
+빻
+빼
+빽
+뺀
+뺄
+뺌
+뺏
+뺐
+뺑
+뺨
+뻐
+뻑
+뻔
+뻗
+뻘
+뻣
+뻤
+뻥
+뻬
+뼈
+뼉
+뼘
+뽀
+뽈
+뽐
+뽑
+뽕
+뾰
+뿌
+뿍
+뿐
+뿔
+뿜
+쁘
+쁜
+쁠
+쁨
+삐
+삔
+삘
+사
+삭
+삯
+산
+살
+삵
+삶
+삼
+삽
+삿
+샀
+상
+샅
+새
+색
+샌
+샐
+샘
+샙
+샛
+샜
+생
+샤
+샨
+샬
+샴
+샵
+샷
+샹
+서
+석
+섞
+선
+섣
+설
+섬
+섭
+섯
+섰
+성
+섶
+세
+섹
+센
+셀
+셈
+셉
+셋
+셌
+셍
+셔
+션
+셜
+셨
+셰
+셴
+셸
+소
+속
+손
+솔
+솜
+솝
+솟
+송
+솥
+쇄
+쇠
+쇤
+쇳
+쇼
+숀
+숄
+숍
+수
+숙
+순
+숟
+술
+숨
+숩
+숫
+숭
+숯
+숱
+숲
+숴
+쉐
+쉘
+쉬
+쉭
+쉰
+쉴
+쉼
+쉽
+슈
+슐
+슘
+슛
+슝
+스
+슥
+슨
+슬
+슭
+슴
+습
+슷
+승
+시
+식
+신
+싣
+실
+싫
+심
+십
+싯
+싱
+싶
+싸
+싹
+싼
+쌀
+쌈
+쌉
+쌌
+쌍
+쌓
+쌔
+쌘
+쌩
+써
+썩
+썬
+썰
+썸
+썹
+썼
+썽
+쎄
+쎈
+쏘
+쏙
+쏜
+쏟
+쏠
+쏭
+쏴
+쐈
+쐐
+쐬
+쑤
+쑥
+쑨
+쒀
+쒔
+쓰
+쓱
+쓴
+쓸
+씀
+씁
+씌
+씨
+씩
+씬
+씰
+씸
+씹
+씻
+씽
+아
+악
+안
+앉
+않
+알
+앎
+앓
+암
+압
+앗
+았
+앙
+앞
+애
+액
+앤
+앨
+앰
+앱
+앳
+앴
+앵
+야
+약
+얀
+얄
+얇
+얌
+얍
+얏
+양
+얕
+얗
+얘
+얜
+어
+억
+언
+얹
+얻
+얼
+얽
+엄
+업
+없
+엇
+었
+엉
+엊
+엌
+엎
+에
+엑
+엔
+엘
+엠
+엡
+엣
+엥
+여
+역
+엮
+연
+열
+엷
+염
+엽
+엾
+엿
+였
+영
+옅
+옆
+옇
+예
+옌
+옐
+옙
+옛
+오
+옥
+온
+올
+옭
+옮
+옳
+옴
+옵
+옷
+옹
+옻
+와
+왁
+완
+왈
+왑
+왓
+왔
+왕
+왜
+왠
+왱
+외
+왼
+요
+욕
+욘
+욜
+욤
+용
+우
+욱
+운
+울
+움
+웁
+웃
+웅
+워
+웍
+원
+월
+웜
+웠
+웡
+웨
+웬
+웰
+웸
+웹
+위
+윅
+윈
+윌
+윔
+윗
+윙
+유
+육
+윤
+율
+윱
+윳
+융
+으
+윽
+은
+을
+읊
+음
+읍
+응
+의
+읜
+읠
+이
+익
+인
+일
+읽
+잃
+임
+입
+잇
+있
+잉
+잊
+잎
+자
+작
+잔
+잖
+잘
+잠
+잡
+잣
+잤
+장
+잦
+재
+잭
+잰
+잴
+잽
+잿
+쟀
+쟁
+쟈
+쟉
+쟤
+저
+적
+전
+절
+젊
+점
+접
+젓
+정
+젖
+제
+젝
+젠
+젤
+젬
+젭
+젯
+져
+젼
+졀
+졌
+졍
+조
+족
+존
+졸
+좀
+좁
+종
+좇
+좋
+좌
+좍
+좽
+죄
+죠
+죤
+주
+죽
+준
+줄
+줌
+줍
+줏
+중
+줘
+줬
+쥐
+쥔
+쥘
+쥬
+쥴
+즈
+즉
+즌
+즐
+즘
+즙
+증
+지
+직
+진
+짇
+질
+짊
+짐
+집
+짓
+징
+짖
+짙
+짚
+짜
+짝
+짠
+짢
+짤
+짧
+짬
+짭
+짰
+짱
+째
+짹
+짼
+쨀
+쨉
+쨋
+쨌
+쨍
+쩄
+쩌
+쩍
+쩐
+쩔
+쩜
+쩝
+쩡
+쩨
+쪄
+쪘
+쪼
+쪽
+쪾
+쫀
+쫄
+쫑
+쫓
+쫙
+쬐
+쭈
+쭉
+쭐
+쭙
+쯔
+쯤
+쯧
+찌
+찍
+찐
+찔
+찜
+찝
+찡
+찢
+찧
+차
+착
+찬
+찮
+찰
+참
+찹
+찻
+찼
+창
+찾
+채
+책
+챈
+챌
+챔
+챕
+챗
+챘
+챙
+챠
+챤
+처
+척
+천
+철
+첨
+첩
+첫
+청
+체
+첵
+첸
+첼
+쳄
+쳇
+쳉
+쳐
+쳔
+쳤
+초
+촉
+촌
+촘
+촛
+총
+촨
+촬
+최
+쵸
+추
+축
+춘
+출
+춤
+춥
+춧
+충
+춰
+췄
+췌
+취
+췬
+츄
+츠
+측
+츨
+츰
+층
+치
+칙
+친
+칠
+칡
+침
+칩
+칫
+칭
+카
+칵
+칸
+칼
+캄
+캅
+캇
+캉
+캐
+캔
+캘
+캠
+캡
+캣
+캤
+캥
+캬
+커
+컥
+컨
+컫
+컬
+컴
+컵
+컷
+컸
+컹
+케
+켄
+켈
+켐
+켓
+켕
+켜
+켠
+켤
+켭
+켯
+켰
+코
+콕
+콘
+콜
+콤
+콥
+콧
+콩
+콰
+콱
+콴
+콸
+쾅
+쾌
+쾡
+쾨
+쾰
+쿄
+쿠
+쿡
+쿤
+쿨
+쿰
+쿵
+쿼
+퀀
+퀄
+퀘
+퀭
+퀴
+퀵
+퀸
+퀼
+큐
+큘
+크
+큰
+클
+큼
+큽
+키
+킥
+킨
+킬
+킴
+킵
+킷
+킹
+타
+탁
+탄
+탈
+탉
+탐
+탑
+탓
+탔
+탕
+태
+택
+탠
+탤
+탬
+탭
+탯
+탰
+탱
+터
+턱
+턴
+털
+텀
+텁
+텃
+텄
+텅
+테
+텍
+텐
+텔
+템
+텝
+텡
+텨
+톈
+토
+톡
+톤
+톨
+톰
+톱
+톳
+통
+퇴
+툇
+투
+툭
+툰
+툴
+툼
+퉁
+퉈
+퉜
+튀
+튄
+튈
+튕
+튜
+튠
+튤
+튬
+트
+특
+튼
+튿
+틀
+틈
+틉
+틋
+틔
+티
+틱
+틴
+틸
+팀
+팁
+팅
+파
+팍
+팎
+판
+팔
+팜
+팝
+팟
+팠
+팡
+팥
+패
+팩
+팬
+팰
+팸
+팻
+팼
+팽
+퍼
+퍽
+펀
+펄
+펌
+펍
+펐
+펑
+페
+펙
+펜
+펠
+펨
+펩
+펫
+펭
+펴
+편
+펼
+폄
+폈
+평
+폐
+포
+폭
+폰
+폴
+폼
+폿
+퐁
+표
+푭
+푸
+푹
+푼
+풀
+품
+풋
+풍
+퓨
+퓬
+퓰
+퓸
+프
+픈
+플
+픔
+픕
+피
+픽
+핀
+필
+핌
+핍
+핏
+핑
+하
+학
+한
+할
+핥
+함
+합
+핫
+항
+해
+핵
+핸
+핼
+햄
+햅
+햇
+했
+행
+햐
+향
+헀
+허
+헉
+헌
+헐
+험
+헙
+헛
+헝
+헤
+헥
+헨
+헬
+헴
+헵
+헷
+헹
+혀
+혁
+현
+혈
+혐
+협
+혓
+혔
+형
+혜
+호
+혹
+혼
+홀
+홈
+홉
+홋
+홍
+홑
+화
+확
+환
+활
+홧
+황
+홰
+홱
+횃
+회
+획
+횝
+횟
+횡
+효
+후
+훅
+훈
+훌
+훑
+훔
+훗
+훤
+훨
+훼
+휄
+휑
+휘
+휙
+휜
+휠
+휩
+휭
+휴
+휼
+흄
+흉
+흐
+흑
+흔
+흘
+흙
+흠
+흡
+흣
+흥
+흩
+희
+흰
+흽
+히
+힉
+힌
+힐
+힘
+힙
+힝
+車
+滑
+金
+奈
+羅
+洛
+卵
+欄
+蘭
+郎
+來
+盧
+老
+魯
+綠
+鹿
+論
+雷
+樓
+縷
+凌
+樂
+不
+參
+葉
+沈
+若
+兩
+凉
+梁
+呂
+女
+廬
+麗
+黎
+曆
+歷
+戀
+蓮
+連
+列
+烈
+裂
+念
+獵
+靈
+領
+例
+禮
+醴
+惡
+尿
+料
+遼
+龍
+暈
+柳
+流
+類
+六
+陸
+倫
+律
+栗
+利
+李
+梨
+理
+離
+燐
+林
+臨
+立
+茶
+切
+宅
+ 

BIN
models/ocr/Rec/中文简体_OCRv2.onnx


BIN
models/ocr/Rec/中文简体_OCRv3.onnx


BIN
models/ocr/Rec/中文繁体.onnx


BIN
models/ocr/Rec/卡纳达文.onnx


BIN
models/ocr/Rec/斯拉夫字母.onnx


BIN
models/ocr/Rec/日文.onnx


BIN
models/ocr/Rec/泰卢固文.onnx


BIN
models/ocr/Rec/英文.onnx


BIN
models/ocr/Rec/韩文.onnx


+ 9 - 0
package.json

@@ -4,6 +4,8 @@
   "version": "0.0.0",
   "main": "src/main/main.js",
   "scripts": {
+    "download-ppocrv5": "node scripts/download-ppocrv5.js",
+    "validate-models": "node scripts/validate-models.js",
     "dev": "concurrently \"yarn serve\" \"yarn electron-dev\"",
     "serve": "vite --host",
     "electron-dev": "wait-on tcp:5173 && cross-env NODE_ENV=development electron .",
@@ -11,16 +13,22 @@
     "preview": "vite preview"
   },
   "dependencies": {
+    "@techstark/opencv-js": "^4.12.0-release.1",
     "canvas": "^3.2.0",
     "cors": "^2.8.5",
     "crypto-ts": "^1.0.2",
     "express": "^5.1.0",
     "fs-extra": "^11.3.2",
+    "jimp": "^1.6.0",
     "multer": "^2.0.2",
+    "node-fetch": "^3.3.2",
     "node-tesseract-ocr": "^2.2.1",
+    "onnxruntime-node": "^1.23.2",
+    "opencv.js": "^1.2.1",
     "sharp": "^0.34.5",
     "sqlite": "^5.1.1",
     "sqlite3": "^5.1.7",
+    "tar": "^7.4.3",
     "tesseract.js": "^6.0.1",
     "vue": "^3.5.22",
     "vue-router": "^4.6.3"
@@ -28,6 +36,7 @@
   "devDependencies": {
     "@types/cors": "^2.8.19",
     "@types/express": "^5.0.5",
+    "@types/fs-extra": "^11.0.4",
     "@types/multer": "^2.0.0",
     "@types/node": "^24.6.0",
     "@vitejs/plugin-vue": "^6.0.1",

+ 197 - 0
scripts/download-ppocrv5.js

@@ -0,0 +1,197 @@
+// scripts/download-ppocrv5.js
+import fs from 'fs-extra';
+import path from 'path';
+import { fileURLToPath } from 'url';
+import { createRequire } from 'module';
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+const require = createRequire(import.meta.url);
+
+class PPOCRv5Downloader {
+    constructor() {
+        this.modelDir = path.join(process.cwd(), 'models', 'ppocrv5');
+        this.tempDir = path.join(process.cwd(), 'temp', 'downloads');
+
+        // PP-OCRv5 官方模型下载链接
+        this.modelUrls = {
+            detection: {
+                url: 'https://paddleocr.bj.bcebos.com/PP-OCRv5/chinese/ch_PP-OCRv5_det_infer.onnx',
+                filename: 'ch_PP-OCRv5_det_infer.onnx'
+            },
+            recognition: {
+                url: 'https://paddleocr.bj.bcebos.com/PP-OCRv5/chinese/ch_PP-OCRv5_rec_infer.onnx',
+                filename: 'ch_PP-OCRv5_rec_infer.onnx'
+            },
+            classification: {
+                url: 'https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.onnx',
+                filename: 'ch_ppocr_mobile_v2.0_cls_infer.onnx'
+            },
+            keys: {
+                url: 'https://raw.githubusercontent.com/PaddlePaddle/PaddleOCR/release/2.7/ppocr/utils/ppocr_keys_v1.txt',
+                filename: 'ppocr_keys_v1.txt'
+            }
+        };
+    }
+
+    async downloadModels() {
+        console.log('🚀 开始下载 PP-OCRv5 模型...');
+        console.log('📝 PP-OCRv5 特性:');
+        console.log('   - 更高的文本检测准确率');
+        console.log('   - 更好的小文本识别能力');
+        console.log('   - 优化的模型结构');
+        console.log('   - 完全离线运行\n');
+
+        try {
+            // 创建目录结构
+            await this.createDirectories();
+
+            let successCount = 0;
+            const totalCount = Object.keys(this.modelUrls).length;
+
+            // 并行下载所有模型
+            const downloadPromises = Object.entries(this.modelUrls).map(async ([type, info]) => {
+                try {
+                    await this.downloadFile(type, info);
+                    successCount++;
+                    console.log(`   ✅ ${this.getTypeName(type)} 下载完成 (${successCount}/${totalCount})`);
+                } catch (error) {
+                    console.log(`   ❌ ${this.getTypeName(type)} 下载失败: ${error.message}`);
+                    throw error;
+                }
+            });
+
+            await Promise.all(downloadPromises);
+
+            console.log('\n🎉 所有模型下载完成!');
+            this.displayModelInfo();
+
+        } catch (error) {
+            console.error('\n❌ 下载过程中出现错误:', error.message);
+            await this.provideAlternativeSources();
+        }
+    }
+
+    async createDirectories() {
+        const dirs = [
+            this.modelDir,
+            path.join(this.modelDir, 'det'),
+            path.join(this.modelDir, 'rec'),
+            path.join(this.modelDir, 'cls'),
+            path.join(this.modelDir, 'keys'),
+            this.tempDir
+        ];
+
+        for (const dir of dirs) {
+            await fs.ensureDir(dir);
+        }
+        console.log('📁 目录结构创建完成');
+    }
+
+    async downloadFile(type, info) {
+        const targetPath = this.getTargetPath(type, info.filename);
+
+        // 检查文件是否已存在
+        if (await fs.pathExists(targetPath)) {
+            const stats = await fs.stat(targetPath);
+            if (stats.size > this.getMinFileSize(type)) {
+                console.log(`   ⏭️ ${this.getTypeName(type)} 已存在,跳过下载`);
+                return;
+            }
+        }
+
+        console.log(`   📥 下载 ${this.getTypeName(type)}...`);
+
+        const fetch = await import('node-fetch');
+        const response = await fetch.default(info.url);
+
+        if (!response.ok) {
+            throw new Error(`HTTP ${response.status}: ${response.statusText}`);
+        }
+
+        const buffer = await response.buffer();
+
+        // 验证文件大小
+        if (buffer.length < this.getMinFileSize(type)) {
+            throw new Error(`文件大小异常: ${(buffer.length / 1024 / 1024).toFixed(2)} MB`);
+        }
+
+        await fs.writeFile(targetPath, buffer);
+
+        // 验证文件完整性
+        await this.validateFile(type, targetPath);
+    }
+
+    getTargetPath(type, filename) {
+        const dirs = {
+            detection: path.join(this.modelDir, 'det'),
+            recognition: path.join(this.modelDir, 'rec'),
+            classification: path.join(this.modelDir, 'cls'),
+            keys: path.join(this.modelDir, 'keys')
+        };
+        return path.join(dirs[type], filename);
+    }
+
+    getTypeName(type) {
+        const names = {
+            detection: '检测模型 (PP-OCRv5 Det)',
+            recognition: '识别模型 (PP-OCRv5 Rec)',
+            classification: '分类模型 (Cls)',
+            keys: '字符集文件'
+        };
+        return names[type];
+    }
+
+    getMinFileSize(type) {
+        const sizes = {
+            detection: 2000000,    // 2MB
+            recognition: 8000000,  // 8MB
+            classification: 1000000, // 1MB
+            keys: 50000           // 50KB
+        };
+        return sizes[type];
+    }
+
+    async validateFile(type, filePath) {
+        const stats = await fs.stat(filePath);
+
+        if (type === 'keys') {
+            const content = await fs.readFile(filePath, 'utf8');
+            const lines = content.split('\n').filter(line => line.trim());
+            if (lines.length < 5000) {
+                throw new Error('字符集文件不完整');
+            }
+        }
+
+        console.log(`      📊 文件大小: ${(stats.size / 1024 / 1024).toFixed(2)} MB`);
+    }
+
+    displayModelInfo() {
+        console.log('\n📂 模型文件位置:');
+        console.log(`   🎯 检测模型: ${path.join(this.modelDir, 'det', 'ch_PP-OCRv5_det_infer.onnx')}`);
+        console.log(`   🔤 识别模型: ${path.join(this.modelDir, 'rec', 'ch_PP-OCRv5_rec_infer.onnx')}`);
+        console.log(`   🧭 分类模型: ${path.join(this.modelDir, 'cls', 'ch_ppocr_mobile_v2.0_cls_infer.onnx')}`);
+        console.log(`   📝 字符集: ${path.join(this.modelDir, 'keys', 'ppocr_keys_v1.txt')}`);
+
+        console.log('\n🚀 使用命令:');
+        console.log('   yarn dev  # 启动应用');
+    }
+
+    async provideAlternativeSources() {
+        console.log('\n💡 备用下载方案:');
+        console.log('   1. 手动下载 PP-OCRv5 模型:');
+        console.log('      - 检测模型: https://paddleocr.bj.bcebos.com/PP-OCRv5/chinese/ch_PP-OCRv5_det_infer.onnx');
+        console.log('      - 识别模型: https://paddleocr.bj.bcebos.com/PP-OCRv5/chinese/ch_PP-OCRv5_rec_infer.onnx');
+        console.log('      - 分类模型: https://paddleocr.bj.bcebos.com/dygraph_v2.0/ch/ch_ppocr_mobile_v2.0_cls_infer.onnx');
+        console.log('      - 字符集: https://raw.githubusercontent.com/PaddlePaddle/PaddleOCR/release/2.7/ppocr/utils/ppocr_keys_v1.txt');
+        console.log('\n   2. 将文件放置到以下目录:');
+        console.log(`      ${this.modelDir}/`);
+        console.log('      ├── det/ch_PP-OCRv5_det_infer.onnx');
+        console.log('      ├── rec/ch_PP-OCRv5_rec_infer.onnx');
+        console.log('      ├── cls/ch_ppocr_mobile_v2.0_cls_infer.onnx');
+        console.log('      └── keys/ppocr_keys_v1.txt');
+    }
+}
+
+// 执行下载
+const downloader = new PPOCRv5Downloader();
+downloader.downloadModels().catch(console.error);

+ 115 - 0
scripts/validate-models.js

@@ -0,0 +1,115 @@
+// scripts/validate-models.js
+import fs from 'fs-extra';
+import path from 'path';
+import { fileURLToPath } from 'url';
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+
+class ModelValidator {
+    constructor() {
+        this.modelDir = path.join(process.cwd(), 'models', 'ocr');
+        this.requiredFiles = {
+            detection: path.join(this.modelDir, 'Det', '中文_OCRv3.onnx'),
+            recognition: path.join(this.modelDir, 'Rec', '中文简体_OCRv3.onnx'),
+            classification: path.join(this.modelDir, 'Cls', '原始分类器模型.onnx'),
+            keys: path.join(this.modelDir, 'Keys', '中文简体_OCRv3.txt')
+        };
+    }
+
+    async validateModels() {
+        console.log('🔍 验证模型文件...\n');
+
+        let allValid = true;
+        const results = [];
+
+        for (const [name, filePath] of Object.entries(this.requiredFiles)) {
+            const exists = await fs.pathExists(filePath);
+            const result = {
+                name: this.getDisplayName(name),
+                path: filePath,
+                exists,
+                size: 0,
+                valid: false
+            };
+
+            if (exists) {
+                try {
+                    const stats = await fs.stat(filePath);
+                    result.size = stats.size;
+                    result.valid = this.validateFileSize(name, stats.size);
+
+                    if (name === 'keys') {
+                        result.valid = await this.validateKeysFile(filePath);
+                    }
+                } catch (error) {
+                    result.valid = false;
+                }
+            }
+
+            results.push(result);
+            allValid = allValid && result.valid;
+        }
+
+        // 显示验证结果
+        this.displayResults(results);
+
+        if (!allValid) {
+            console.log('\n❌ 模型文件不完整或损坏');
+            console.log('💡 运行以下命令重新下载:');
+            console.log('   yarn download-models');
+            process.exit(1);
+        } else {
+            console.log('\n✅ 所有模型文件验证通过!');
+        }
+
+        return allValid;
+    }
+
+    getDisplayName(name) {
+        const names = {
+            detection: '检测模型',
+            recognition: '识别模型',
+            classification: '分类模型',
+            keys: '字符集文件'
+        };
+        return names[name] || name;
+    }
+
+    validateFileSize(name, size) {
+        const minSizes = {
+            detection: 1000000,    // 1MB
+            recognition: 5000000,  // 5MB
+            classification: 1000000, // 1MB
+            keys: 1000            // 1KB
+        };
+        return size > (minSizes[name] || 0);
+    }
+
+    async validateKeysFile(filePath) {
+        try {
+            const content = await fs.readFile(filePath, 'utf8');
+            const lines = content.split('\n').filter(line => line.trim());
+            return lines.length > 1000; // 至少1000个字符
+        } catch {
+            return false;
+        }
+    }
+
+    displayResults(results) {
+        results.forEach(result => {
+            const status = result.exists && result.valid ? '✅' : '❌';
+            const sizeInfo = result.exists ? ` (${(result.size / 1024 / 1024).toFixed(2)} MB)` : '';
+            console.log(`${status} ${result.name}${sizeInfo}`);
+
+            if (!result.exists) {
+                console.log(`   文件不存在: ${result.path}`);
+            } else if (!result.valid) {
+                console.log(`   文件可能损坏: ${result.path}`);
+            }
+        });
+    }
+}
+
+// 执行验证
+const validator = new ModelValidator();
+validator.validateModels().catch(console.error);

+ 0 - 468
server/server.js

@@ -1,468 +0,0 @@
-const express = require('express')
-const cors = require('cors')
-const multer = require('multer')
-const path = require('path')
-const fs = require('fs-extra')
-const { calculateFileMD5 } = require('./utils.js')
-const { initDatabase, FileService } = require('../database/database.js')
-
-// 新增 OCR 相关依赖
-const Tesseract = require('tesseract.js')
-const sharp = require('sharp')
-const { createCanvas, loadImage } = require('canvas')
-
-const app = express()
-const PORT = 3000
-
-// 初始化数据库
-initDatabase()
-const fileService = new FileService()
-
-// 确保上传目录和临时目录存在
-const uploadDir = path.join(process.cwd(), 'uploads')
-const tempDir = path.join(process.cwd(), 'temp')
-fs.ensureDirSync(uploadDir)
-fs.ensureDirSync(tempDir)
-
-// 配置 multer - 修复中文文件名问题
-const storage = multer.diskStorage({
-    destination: (req, file, cb) => {
-        cb(null, uploadDir)
-    },
-    filename: (req, file, cb) => {
-        // 处理中文文件名 - 使用原始文件名但确保安全
-        const originalName = Buffer.from(file.originalname, 'latin1').toString('utf8')
-        const ext = path.extname(originalName)
-        const name = path.basename(originalName, ext)
-
-        // 清理文件名,移除特殊字符
-        const safeName = name.replace(/[^a-zA-Z0-9\u4e00-\u9fa5]/g, '_')
-        const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9)
-        const filename = safeName + '-' + uniqueSuffix + ext
-
-        cb(null, filename)
-    }
-})
-
-const upload = multer({
-    storage,
-    fileFilter: (req, file, cb) => {
-        // 处理文件名编码
-        file.originalname = Buffer.from(file.originalname, 'latin1').toString('utf8')
-        cb(null, true)
-    }
-})
-
-// 设置响应头,确保使用 UTF-8 编码
-app.use((req, res, next) => {
-    res.setHeader('Content-Type', 'application/json; charset=utf-8')
-    next()
-})
-
-app.use(cors())
-app.use(express.json({ limit: '50mb' }))
-app.use(express.urlencoded({ extended: true, limit: '50mb' }))
-
-// 文件上传接口
-app.post('/api/upload', upload.single('file'), async (req, res) => {
-    try {
-        if (!req.file) {
-            return res.status(400).json({ error: 'No file uploaded' })
-        }
-
-        // 确保文件名正确编码
-        const originalName = Buffer.from(req.file.originalname, 'latin1').toString('utf8')
-
-        const fileInfo = {
-            originalName: originalName,
-            fileName: req.file.filename,
-            filePath: req.file.path,
-            fileSize: req.file.size,
-            mimeType: req.file.mimetype
-        }
-
-        // 计算 MD5
-        const md5 = await calculateFileMD5(req.file.path)
-
-        // 保存到数据库
-        const fileRecord = await fileService.createFile({
-            ...fileInfo,
-            md5
-        })
-
-        res.json({
-            success: true,
-            data: fileRecord
-        })
-    } catch (error) {
-        console.error('Upload error:', error)
-        res.status(500).json({ error: 'Upload failed: ' + error.message })
-    }
-})
-
-// 修复获取文件列表接口 - 确保返回正确的数据结构
-app.get('/api/files', async (req, res) => {
-    try {
-        const page = parseInt(req.query.page) || 1
-        const pageSize = parseInt(req.query.pageSize) || 100
-
-        const result = await fileService.getFilesPaginated(page, pageSize)
-
-        // 返回统一的数据结构
-        res.json({
-            success: true,
-            data: result.files, // 直接返回文件数组
-            pagination: result.pagination
-        })
-    } catch (error) {
-        console.error('Get files error:', error)
-        res.status(500).json({
-            success: false,
-            error: 'Failed to get files: ' + error.message
-        })
-    }
-})
-
-// MD5 检查接口
-app.post('/api/files/:id/check-md5', async (req, res) => {
-    try {
-        const fileId = parseInt(req.params.id)
-        const file = await fileService.getFileById(fileId)
-
-        if (!file) {
-            return res.status(404).json({ error: 'File not found' })
-        }
-
-        const currentMD5 = await calculateFileMD5(file.filePath)
-        const isChanged = currentMD5 !== file.md5
-
-        res.json({
-            isChanged,
-            currentMD5,
-            originalMD5: file.md5,
-            file
-        })
-    } catch (error) {
-        console.error('MD5 check error:', error)
-        res.status(500).json({ error: 'MD5 check failed' })
-    }
-})
-
-// 更新 MD5 接口
-app.put('/api/files/:id/update-md5', async (req, res) => {
-    try {
-        const fileId = parseInt(req.params.id)
-        const { md5 } = req.body
-
-        await fileService.updateFileMD5(fileId, md5)
-        res.json({ success: true })
-    } catch (error) {
-        console.error('Update MD5 error:', error)
-        res.status(500).json({ error: 'Update failed' })
-    }
-})
-
-// 新增 OCR 识别接口
-app.post('/api/ocr/recognize', async (req, res) => {
-    try {
-        const { fileId, page } = req.body
-
-        if (!fileId) {
-            return res.status(400).json({ error: 'File ID is required' })
-        }
-
-        const file = await fileService.getFileById(parseInt(fileId))
-        if (!file) {
-            return res.status(404).json({ error: 'File not found' })
-        }
-
-        console.log(`开始OCR识别: ${file.originalName}`)
-
-        // 预处理图像
-        const processedImagePath = await preprocessImage(file.filePath)
-
-        // 使用 Tesseract 进行 OCR 识别
-        const result = await performOCR(processedImagePath)
-
-        // 清理临时文件
-        await fs.remove(processedImagePath)
-
-        res.json({
-            success: true,
-            data: {
-                textBlocks: result.textBlocks,
-                totalPages: result.totalPages || 1,
-                processingTime: result.processingTime,
-                confidence: result.confidence
-            }
-        })
-
-    } catch (error) {
-        console.error('OCR recognition error:', error)
-        res.status(500).json({ error: 'OCR recognition failed: ' + error.message })
-    }
-})
-
-// 添加 OCR 结果相关的 API 接口
-
-// 保存 OCR 结果
-app.post('/api/ocr/save-result', async (req, res) => {
-    try {
-        const { fileId, ocrData } = req.body
-
-        if (!fileId || !ocrData) {
-            return res.status(400).json({ error: '文件ID和OCR数据是必需的' })
-        }
-
-        await fileService.saveOcrResult(parseInt(fileId), ocrData)
-
-        res.json({ success: true })
-    } catch (error) {
-        console.error('保存OCR结果失败:', error)
-        res.status(500).json({ error: '保存OCR结果失败: ' + error.message })
-    }
-})
-
-// 获取 OCR 结果
-app.get('/api/ocr/result/:fileId', async (req, res) => {
-    try {
-        const fileId = parseInt(req.params.fileId)
-        const result = await fileService.getOcrResult(fileId)
-
-        if (result) {
-            res.json({
-                success: true,
-                data: result.ocr_data
-            })
-        } else {
-            res.json({
-                success: false,
-                error: '未找到OCR结果'
-            })
-        }
-    } catch (error) {
-        console.error('获取OCR结果失败:', error)
-        res.status(500).json({ error: '获取OCR结果失败: ' + error.message })
-    }
-})
-
-// 更新 OCR 文本(人工纠错)
-app.put('/api/ocr/update-text', async (req, res) => {
-    try {
-        const { fileId, textBlocks } = req.body
-
-        if (!fileId || !textBlocks) {
-            return res.status(400).json({ error: '文件ID和文本数据是必需的' })
-        }
-
-        await fileService.updateOcrText(parseInt(fileId), textBlocks)
-
-        res.json({ success: true })
-    } catch (error) {
-        console.error('更新OCR文本失败:', error)
-        res.status(500).json({ error: '更新OCR文本失败: ' + error.message })
-    }
-})
-
-// 图像预处理函数
-async function preprocessImage(imagePath) {
-    const tempOutputPath = path.join(tempDir, `preprocessed-${Date.now()}.png`)
-
-    try {
-        // 使用 sharp 进行图像预处理
-        await sharp(imagePath)
-            .grayscale() // 转为灰度图
-            .normalize() // 标准化图像
-            .linear(1.5, 0) // 增加对比度
-            .sharpen() // 锐化
-            .png()
-            .toFile(tempOutputPath)
-
-        return tempOutputPath
-    } catch (error) {
-        console.error('Image preprocessing failed:', error)
-        // 如果预处理失败,返回原图
-        return imagePath
-    }
-}
-
-// OCR 识别函数
-async function performOCR(imagePath) {
-    return new Promise((resolve, reject) => {
-        const startTime = Date.now()
-
-        Tesseract.recognize(
-            imagePath,
-            'chi_sim+eng', // 中文简体 + 英文
-            {
-                logger: m => console.log(m),
-                tessedit_pageseg_mode: Tesseract.PSM.AUTO,
-                tessedit_char_whitelist: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\u4e00-\u9fa5,。!?;:"'/'()【】《》…—·'
-            }
-        ).then(({ data: { text, confidence } }) => {
-            const processingTime = Date.now() - startTime
-
-            // 解析文本块
-            const textBlocks = parseOCRText(text)
-
-            resolve({
-                textBlocks,
-                confidence,
-                processingTime
-            })
-        }).catch(error => {
-            reject(error)
-        })
-    })
-}
-
-// 解析 OCR 文本结果
-function parseOCRText(text) {
-    const blocks = []
-    const lines = text.split('\n').filter(line => line.trim())
-
-    for (const line of lines) {
-        const trimmedLine = line.trim()
-        if (!trimmedLine) continue
-
-        // 检测参考文献
-        if (isReference(trimmedLine)) {
-            blocks.push({
-                type: 'reference',
-                content: trimmedLine
-            })
-        }
-        // 检测引用
-        else if (isCitation(trimmedLine)) {
-            blocks.push({
-                type: 'citation',
-                content: trimmedLine.replace(/^\[\d+\]\s*/, ''),
-                number: extractCitationNumber(trimmedLine)
-            })
-        }
-        // 检测图片标记
-        else if (isImageMarker(trimmedLine)) {
-            blocks.push({
-                type: 'image',
-                content: trimmedLine
-            })
-        }
-        // 普通文本
-        else {
-            blocks.push({
-                type: 'text',
-                content: trimmedLine
-            })
-        }
-    }
-
-    return blocks
-}
-
-// 辅助函数
-function isReference(text) {
-    const refPatterns = [
-        /^参考文献/i,
-        /^references/i,
-        /^bibliography/i,
-        /^\[?\d+\]?\s*\.?\s*[A-Za-z].*\.\s*\d{4}/
-    ]
-    return refPatterns.some(pattern => pattern.test(text))
-}
-
-function isCitation(text) {
-    return /^\[\d+\]/.test(text)
-}
-
-function extractCitationNumber(text) {
-    const match = text.match(/^\[(\d+)\]/)
-    return match ? parseInt(match[1]) : null
-}
-
-function isImageMarker(text) {
-    const imagePatterns = [
-        /^图\s*\d+/i,
-        /^figure\s*\d+/i,
-        /^图片\d*/i
-    ]
-    return imagePatterns.some(pattern => pattern.test(text))
-}
-
-// 获取文件预览接口
-app.get('/api/files/:id/preview', async (req, res) => {
-    try {
-        const fileId = parseInt(req.params.id)
-        const file = await fileService.getFileById(fileId)
-
-        if (!file) {
-            return res.status(404).json({ error: 'File not found' })
-        }
-
-        // 检查文件是否存在
-        if (!fs.existsSync(file.filePath)) {
-            return res.status(404).json({ error: 'File not found on disk' })
-        }
-
-        // 设置正确的 Content-Type
-        res.setHeader('Content-Type', file.mimeType)
-
-        // 直接发送文件
-        res.sendFile(path.resolve(file.filePath))
-
-    } catch (error) {
-        console.error('File preview error:', error)
-        res.status(500).json({ error: 'Failed to get file preview' })
-    }
-})
-
-// 获取文件缩略图接口
-app.get('/api/files/:id/thumbnail', async (req, res) => {
-    try {
-        const fileId = parseInt(req.params.id)
-        const file = await fileService.getFileById(fileId)
-
-        if (!file) {
-            return res.status(404).json({ error: 'File not found' })
-        }
-
-        // 只对图片生成缩略图
-        if (!file.mimeType.startsWith('image/')) {
-            return res.status(400).json({ error: 'Not an image file' })
-        }
-
-        const thumbnailPath = path.join(tempDir, `thumbnail-${fileId}.jpg`)
-
-        // 生成缩略图
-        await sharp(file.filePath)
-            .resize(100, 100, {
-                fit: 'inside',
-                withoutEnlargement: true
-            })
-            .jpeg({ quality: 80 })
-            .toFile(thumbnailPath)
-
-        res.sendFile(path.resolve(thumbnailPath))
-
-    } catch (error) {
-        console.error('Thumbnail generation error:', error)
-        // 如果缩略图生成失败,返回原图
-        res.sendFile(path.resolve(file.filePath))
-    }
-})
-
-// 健康检查接口
-app.get('/api/health', (req, res) => {
-    res.json({
-        status: 'OK',
-        timestamp: new Date().toISOString(),
-        service: 'file-management-api'
-    })
-})
-
-function startServer() {
-    app.listen(PORT, () => {
-        console.log(`Server running on http://localhost:${PORT}`)
-    })
-}
-
-module.exports = { startServer }

+ 487 - 0
server/server.ts

@@ -0,0 +1,487 @@
+import express from 'express';
+import cors from 'cors';
+import multer from 'multer';
+import path from 'path';
+import fs from 'fs-extra';
+import { calculateFileMD5 } from './utils.js';
+import { initDatabase, FileService } from '../database/database.js';
+import onnxOcrManager from "./utils/onnxOcrManager.js";
+
+import sharp from "sharp";
+import fse from "fs-extra";
+
+
+const app = express();
+const PORT = 3000;
+
+// 初始化数据库
+initDatabase();
+const fileService = new FileService();
+
+// 确保上传目录和临时目录存在
+const uploadDir = path.join(process.cwd(), 'uploads');
+const tempDir = path.join(process.cwd(), 'temp');
+const processedDir = path.join(process.cwd(), 'processed');
+fs.ensureDirSync(uploadDir);
+fs.ensureDirSync(tempDir);
+fs.ensureDirSync(processedDir);
+
+// 配置 multer - 修复中文文件名问题
+const storage = multer.diskStorage({
+    destination: (req, file, cb) => {
+        cb(null, uploadDir);
+    },
+    filename: (req, file, cb) => {
+        // 处理中文文件名 - 使用原始文件名但确保安全
+        const originalName = Buffer.from(file.originalname, 'latin1').toString('utf8');
+        const ext = path.extname(originalName);
+        const name = path.basename(originalName, ext);
+
+        // 清理文件名,移除特殊字符
+        const safeName = name.replace(/[^a-zA-Z0-9\u4e00-\u9fa5]/g, '_');
+        const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
+        const filename = safeName + '-' + uniqueSuffix + ext;
+
+        cb(null, filename);
+    }
+});
+
+const upload = multer({
+    storage,
+    fileFilter: (req, file, cb) => {
+        // 处理文件名编码
+        file.originalname = Buffer.from(file.originalname, 'latin1').toString('utf8');
+        cb(null, true);
+    }
+});
+
+// 设置响应头,确保使用 UTF-8 编码
+app.use((req, res, next) => {
+    res.setHeader('Content-Type', 'application/json; charset=utf-8');
+    next();
+});
+
+app.use(cors());
+app.use(express.json({ limit: '50mb' }));
+app.use(express.urlencoded({ extended: true, limit: '50mb' }));
+
+// 文件上传接口
+app.post('/api/upload', upload.single('file'), async (req, res) => {
+    try {
+        if (!req.file) {
+            return res.status(400).json({ error: 'No file uploaded' });
+        }
+
+        // 确保文件名正确编码
+        const originalName = Buffer.from(req.file.originalname, 'latin1').toString('utf8');
+
+        const fileInfo = {
+            originalName: originalName,
+            fileName: req.file.filename,
+            filePath: req.file.path,
+            fileSize: req.file.size,
+            mimeType: req.file.mimetype
+        };
+
+        // 计算 MD5
+        const md5 = await calculateFileMD5(req.file.path);
+
+        // 保存到数据库
+        const fileRecord = await fileService.createFile({
+            ...fileInfo,
+            md5
+        });
+
+        res.json({
+            success: true,
+            data: fileRecord
+        });
+    } catch (error) {
+        console.error('Upload error:', error);
+        res.status(500).json({ error: 'Upload failed: ' + error.message });
+    }
+});
+
+// 获取文件列表接口
+app.get('/api/files', async (req, res) => {
+    try {
+        const page = parseInt(req.query.page as string) || 1;
+        const pageSize = parseInt(req.query.pageSize as string) || 100;
+
+        const result = await fileService.getFilesPaginated(page, pageSize);
+
+        // 返回统一的数据结构
+        res.json({
+            success: true,
+            data: result.files, // 直接返回文件数组
+            pagination: result.pagination
+        });
+    } catch (error) {
+        console.error('Get files error:', error);
+        res.status(500).json({
+            success: false,
+            error: 'Failed to get files: ' + error.message
+        });
+    }
+});
+
+// MD5 检查接口
+app.post('/api/files/:id/check-md5', async (req, res) => {
+    try {
+        const fileId = parseInt(req.params.id);
+        const file = await fileService.getFileById(fileId);
+
+        if (!file) {
+            return res.status(404).json({ error: 'File not found' });
+        }
+
+        const currentMD5 = await calculateFileMD5(file.filePath);
+        const isChanged = currentMD5 !== file.md5;
+
+        res.json({
+            isChanged,
+            currentMD5,
+            originalMD5: file.md5,
+            file
+        });
+    } catch (error) {
+        console.error('MD5 check error:', error);
+        res.status(500).json({ error: 'MD5 check failed' });
+    }
+});
+
+// 更新 MD5 接口
+app.put('/api/files/:id/update-md5', async (req, res) => {
+    try {
+        const fileId = parseInt(req.params.id);
+        const { md5 } = req.body;
+
+        await fileService.updateFileMD5(fileId, md5);
+        res.json({ success: true });
+    } catch (error) {
+        console.error('Update MD5 error:', error);
+        res.status(500).json({ error: 'Update failed' });
+    }
+});
+
+// OCR 识别接口 - 使用 OfflineOcrManager
+app.post('/api/ocr/recognize', async (req, res) => {
+    try {
+        const { fileId, config } = req.body;
+
+        if (!fileId) {
+            return res.status(400).json({ error: 'File ID is required' });
+        }
+
+        const file = await fileService.getFileById(parseInt(fileId));
+        if (!file) {
+            return res.status(404).json({ error: 'File not found' });
+        }
+
+        console.log(`开始ONNX OCR识别: ${file.originalName}`);
+
+        // 使用ONNX OCR管理器进行识别
+        const result = await onnxOcrManager.recognizeImage(file.filePath, config);
+
+        res.json({
+            success: true,
+            data: {
+                textBlocks: result.textBlocks,
+                totalPages: result.totalPages,
+                processingTime: result.processingTime,
+                confidence: result.confidence,
+                processedImageUrl: '', // ONNX版本暂时不提供处理后的图片
+                imageInfo: result.imageInfo,
+                isOffline: result.isOffline
+            }
+        });
+
+    } catch (error) {
+        console.error('ONNX OCR识别失败:', error);
+        res.status(500).json({ error: 'OCR识别失败: ' + error.message });
+    }
+});
+// 保存处理后的图片
+async function saveProcessedImage(fileId: number, processedImagePath: string): Promise<string> {
+    try {
+        const targetPath = path.join(processedDir, `processed-${fileId}.png`);
+
+        // 使用sharp处理并保存图片
+        await sharp(processedImagePath)
+            .grayscale()
+            .normalize()
+            .sharpen()
+            .png()
+            .toFile(targetPath);
+
+        return `/api/files/${fileId}/processed-image`;
+    } catch (error) {
+        console.error('保存处理后的图片失败:', error);
+        return '';
+    }
+}
+
+// 获取处理后的图片
+app.get('/api/files/:id/processed-image', async (req, res) => {
+    try {
+        const fileId = parseInt(req.params.id);
+        const processedImagePath = path.join(processedDir, `processed-${fileId}.png`);
+
+        if (!fs.existsSync(processedImagePath)) {
+            return res.status(404).json({ error: 'Processed image not found' });
+        }
+
+        res.setHeader('Content-Type', 'image/png');
+        res.sendFile(path.resolve(processedImagePath));
+
+    } catch (error) {
+        console.error('Get processed image error:', error);
+        res.status(500).json({ error: 'Failed to get processed image' });
+    }
+});
+
+// 保存 OCR 结果
+app.post('/api/ocr/save-result', async (req, res) => {
+    try {
+        const { fileId, ocrData } = req.body;
+
+        if (!fileId || !ocrData) {
+            return res.status(400).json({ error: '文件ID和OCR数据是必需的' });
+        }
+
+        await fileService.saveOcrResult(parseInt(fileId), ocrData);
+
+        res.json({ success: true });
+    } catch (error) {
+        console.error('保存OCR结果失败:', error);
+        res.status(500).json({ error: '保存OCR结果失败: ' + error.message });
+    }
+});
+
+// 获取 OCR 结果
+app.get('/api/ocr/result/:fileId', async (req, res) => {
+    try {
+        const fileId = parseInt(req.params.fileId);
+        const result = await fileService.getOcrResult(fileId);
+
+        if (result) {
+            res.json({
+                success: true,
+                data: result.ocr_data
+            });
+        } else {
+            res.json({
+                success: false,
+                error: '未找到OCR结果'
+            });
+        }
+    } catch (error) {
+        console.error('获取OCR结果失败:', error);
+        res.status(500).json({ error: '获取OCR结果失败: ' + error.message });
+    }
+});
+
+// 更新 OCR 文本(人工纠错)
+app.put('/api/ocr/update-text', async (req, res) => {
+    try {
+        const { fileId, textBlocks } = req.body;
+
+        if (!fileId || !textBlocks) {
+            return res.status(400).json({ error: '文件ID和文本数据是必需的' });
+        }
+
+        await fileService.updateOcrText(parseInt(fileId), textBlocks);
+
+        res.json({ success: true });
+    } catch (error) {
+        console.error('更新OCR文本失败:', error);
+        res.status(500).json({ error: '更新OCR文本失败: ' + error.message });
+    }
+});
+
+// 获取文件预览接口
+app.get('/api/files/:id/preview', async (req, res) => {
+    try {
+        const fileId = parseInt(req.params.id);
+        const file = await fileService.getFileById(fileId);
+
+        if (!file) {
+            return res.status(404).json({ error: 'File not found' });
+        }
+
+        // 检查文件是否存在
+        if (!fs.existsSync(file.filePath)) {
+            return res.status(404).json({ error: 'File not found on disk' });
+        }
+
+        // 设置正确的 Content-Type
+        res.setHeader('Content-Type', file.mimeType);
+
+        // 直接发送文件
+        res.sendFile(path.resolve(file.filePath));
+
+    } catch (error) {
+        console.error('File preview error:', error);
+        res.status(500).json({ error: 'Failed to get file preview' });
+    }
+});
+// 更新批量OCR接口
+app.post('/api/ocr/batch-recognize', async (req, res) => {
+    try {
+        const { fileIds, config } = req.body;
+
+        if (!fileIds || !Array.isArray(fileIds)) {
+            return res.status(400).json({ error: 'File IDs array is required' });
+        }
+
+        const filePaths = [];
+        for (const fileId of fileIds) {
+            const file = await fileService.getFileById(parseInt(fileId));
+            if (file) {
+                filePaths.push(file.filePath);
+            }
+        }
+
+        const results = await onnxOcrManager.batchRecognize(filePaths, config);
+
+        res.json({
+            success: true,
+            data: results
+        });
+
+    } catch (error) {
+        console.error('批量ONNX OCR识别失败:', error);
+        res.status(500).json({ error: '批量识别失败: ' + error.message });
+    }
+});
+// 获取预处理后的图片
+app.get('/api/ocr/processed-image', async (req, res) => {
+    try {
+        const imagePath = req.query.path as string;
+
+        if (!imagePath) {
+            return res.status(400).json({ error: '图片路径是必需的' });
+        }
+
+        // 解码路径
+        const decodedPath = decodeURIComponent(imagePath);
+
+        if (!fse.existsSync(decodedPath)) {
+            return res.status(404).json({ error: '预处理图片不存在' });
+        }
+
+        res.setHeader('Content-Type', 'image/png');
+        res.sendFile(path.resolve(decodedPath));
+
+    } catch (error) {
+        console.error('获取预处理图片失败:', error);
+        res.status(500).json({ error: '获取预处理图片失败' });
+    }
+});
+
+// 在 server/server.ts 中添加调试接口
+app.post('/api/ocr/debug-recognition', async (req, res) => {
+    try {
+        const { fileId, boxIndex } = req.body;
+
+        if (!fileId || boxIndex === undefined) {
+            return res.status(400).json({ error: '文件ID和框索引是必需的' });
+        }
+
+        const file = await fileService.getFileById(parseInt(fileId));
+        if (!file) {
+            return res.status(404).json({ error: '文件未找到' });
+        }
+
+        // 这里可以添加具体的调试逻辑
+        console.log(`🔧 调试文件 ${fileId} 的第 ${boxIndex} 个文本框`);
+
+        res.json({
+            success: true,
+            message: '调试信息已输出到控制台'
+        });
+
+    } catch (error) {
+        console.error('调试失败:', error);
+        res.status(500).json({ error: '调试失败: ' + error.message });
+    }
+});
+// 更新OCR状态接口
+app.get('/api/ocr/status', async (req, res) => {
+    try {
+        const status = onnxOcrManager.getStatus();
+        res.json({
+            success: true,
+            data: status
+        });
+    } catch (error) {
+        console.error('获取ONNX OCR状态失败:', error);
+        res.status(500).json({ error: '获取状态失败: ' + error.message });
+    }
+});
+// 获取文件缩略图接口
+app.get('/api/files/:id/thumbnail', async (req, res) => {
+    const fileId = parseInt(req.params.id);
+    const file = await fileService.getFileById(fileId);
+    try {
+
+        if (!file) {
+            return res.status(404).json({ error: 'File not found' });
+        }
+
+        // 只对图片生成缩略图
+        if (!file.mimeType.startsWith('image/')) {
+            return res.status(400).json({ error: 'Not an image file' });
+        }
+
+        const thumbnailPath = path.join(tempDir, `thumbnail-${fileId}.jpg`);
+
+        // 生成缩略图
+        await sharp(file.filePath)
+            .resize(100, 100, {
+                fit: 'inside',
+                withoutEnlargement: true
+            })
+            .jpeg({ quality: 80 })
+            .toFile(thumbnailPath);
+
+        res.sendFile(path.resolve(thumbnailPath));
+
+    } catch (error) {
+        console.error('Thumbnail generation error:', error);
+        // 如果缩略图生成失败,返回原图
+        res.sendFile(path.resolve(file.filePath));
+    }
+});
+
+// 健康检查接口
+app.get('/api/health', (req, res) => {
+    res.json({
+        status: 'OK',
+        timestamp: new Date().toISOString(),
+        service: 'file-management-api'
+    });
+});
+
+
+// 服务器启动时初始化OCR引擎
+async function initializeOcrEngine() {
+    try {
+        console.log('正在初始化ONNX OCR引擎...');
+        await onnxOcrManager.initialize();
+        console.log('ONNX OCR引擎初始化完成');
+    } catch (error) {
+        console.error('ONNX OCR引擎初始化失败:', error);
+    }
+}
+
+function startServer() {
+    // 启动时初始化OCR引擎
+    initializeOcrEngine();
+
+    app.listen(PORT, () => {
+        console.log(`Server running on http://localhost:${PORT}`);
+    });
+}
+
+export { startServer };

+ 271 - 0
server/utils/detectionProcessor.js

@@ -0,0 +1,271 @@
+// server/utils/detectionProcessor.js
+import { Tensor } from 'onnxruntime-node';
+import sharp from 'sharp';
+
+class DetectionProcessor {
+    constructor() {
+        this.session = null;
+        this.config = null;
+    }
+
+    initialize(session, config) {
+        this.session = session;
+        this.config = config;
+    }
+
+    async detectText(processedImage) {
+        try {
+            const inputTensor = await this.prepareDetectionInput(processedImage);
+            const outputs = await this.session.run({ [this.session.inputNames[0]]: inputTensor });
+            const textBoxes = this.postprocessDetection(outputs, processedImage);
+            return textBoxes;
+        } catch (error) {
+            console.error('文本检测失败:', error);
+            return [];
+        }
+    }
+
+    async prepareDetectionInput(processedImage) {
+        const { buffer, width, height } = processedImage;
+
+        const imageData = await sharp(buffer)
+            .ensureAlpha()
+            .raw()
+            .toBuffer({ resolveWithObject: true });
+
+        const inputData = new Float32Array(3 * height * width);
+        const data = imageData.data;
+        const channels = imageData.info.channels;
+
+        for (let i = 0; i < data.length; i += channels) {
+            const pixelIndex = Math.floor(i / channels);
+            const channel = Math.floor(pixelIndex / (height * width));
+            const posInChannel = pixelIndex % (height * width);
+
+            if (channel < 3) {
+                const y = Math.floor(posInChannel / width);
+                const x = posInChannel % width;
+                const inputIndex = channel * height * width + y * width + x;
+
+                if (inputIndex < inputData.length) {
+                    inputData[inputIndex] = data[i] / 255.0;
+                }
+            }
+        }
+
+        return new Tensor('float32', inputData, [1, 3, height, width]);
+    }
+
+    postprocessDetection(outputs, processedImage) {
+        try {
+            const boxes = [];
+            const outputNames = this.session.outputNames;
+            const detectionOutput = outputs[outputNames[0]];
+
+            if (!detectionOutput) {
+                return boxes;
+            }
+
+            const [batch, channels, height, width] = detectionOutput.dims;
+            const data = detectionOutput.data;
+
+            // 降低检测阈值,提高召回率
+            const threshold = this.config.detThresh || 0.05;
+            const points = [];
+
+            // 改进的点收集逻辑
+            for (let y = 0; y < height; y++) {
+                for (let x = 0; x < width; x++) {
+                    const idx = y * width + x;
+                    const prob = data[idx];
+                    if (prob > threshold) {
+                        points.push({
+                            x,
+                            y,
+                            prob,
+                            localMax: this.isLocalMaximum(data, x, y, width, height, 2)
+                        });
+                    }
+                }
+            }
+
+            if (points.length === 0) {
+                return boxes;
+            }
+
+            // 改进的聚类算法
+            const clusters = this.enhancedCluster(points, 8);
+
+            for (const cluster of clusters) {
+                // 降低最小点数要求
+                if (cluster.length < 2) continue;
+
+                const minX = Math.min(...cluster.map(p => p.x));
+                const maxX = Math.max(...cluster.map(p => p.x));
+                const minY = Math.min(...cluster.map(p => p.y));
+                const maxY = Math.max(...cluster.map(p => p.y));
+
+                const boxWidth = maxX - minX;
+                const boxHeight = maxY - minY;
+
+                // 放宽尺寸限制
+                if (boxWidth < 2 || boxHeight < 2) continue;
+
+                const aspectRatio = boxWidth / boxHeight;
+                // 放宽宽高比限制
+                if (aspectRatio > 100 || aspectRatio < 0.01) continue;
+
+                const avgConfidence = cluster.reduce((sum, p) => sum + p.prob, 0) / cluster.length;
+
+                // 降低框置信度阈值
+                const boxThreshold = this.config.detBoxThresh || 0.1;
+                if (avgConfidence > boxThreshold) {
+                    const box = this.scaleBoxToProcessedImage({
+                        x1: minX, y1: minY,
+                        x2: maxX, y2: minY,
+                        x3: maxX, y3: maxY,
+                        x4: minX, y4: maxY
+                    }, processedImage);
+                    box.confidence = avgConfidence;
+                    boxes.push(box);
+                }
+            }
+
+            boxes.sort((a, b) => b.confidence - a.confidence);
+            console.log(`✅ 检测到 ${boxes.length} 个文本区域`);
+            return boxes;
+
+        } catch (error) {
+            console.error('检测后处理错误:', error);
+            return [];
+        }
+    }
+
+    // 添加局部最大值检测
+    isLocalMaximum(data, x, y, width, height, radius) {
+        const centerProb = data[y * width + x];
+        for (let dy = -radius; dy <= radius; dy++) {
+            for (let dx = -radius; dx <= radius; dx++) {
+                if (dx === 0 && dy === 0) continue;
+                const nx = x + dx;
+                const ny = y + dy;
+                if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
+                    if (data[ny * width + nx] > centerProb) {
+                        return false;
+                    }
+                }
+            }
+        }
+        return true;
+    }
+
+    // 改进的聚类算法
+    enhancedCluster(points, distanceThreshold) {
+        const clusters = [];
+        const visited = new Set();
+
+        // 按概率降序排序,优先处理高置信度点
+        const sortedPoints = [...points].sort((a, b) => b.prob - a.prob);
+
+        for (let i = 0; i < sortedPoints.length; i++) {
+            if (visited.has(i)) continue;
+
+            const cluster = [];
+            const queue = [i];
+            visited.add(i);
+
+            while (queue.length > 0) {
+                const currentIndex = queue.shift();
+                const currentPoint = sortedPoints[currentIndex];
+                cluster.push(currentPoint);
+
+                // 动态调整搜索半径
+                const adaptiveThreshold = distanceThreshold *
+                    (1 + (1 - currentPoint.prob) * 0.5);
+
+                for (let j = 0; j < sortedPoints.length; j++) {
+                    if (visited.has(j)) continue;
+
+                    const targetPoint = sortedPoints[j];
+                    const dist = Math.sqrt(
+                        Math.pow(targetPoint.x - currentPoint.x, 2) +
+                        Math.pow(targetPoint.y - currentPoint.y, 2)
+                    );
+
+                    if (dist < adaptiveThreshold) {
+                        queue.push(j);
+                        visited.add(j);
+                    }
+                }
+            }
+
+            if (cluster.length > 0) {
+                clusters.push(cluster);
+            }
+        }
+
+        return clusters;
+    }
+
+    scaleBoxToProcessedImage(box, processedImage) {
+        const { width: processedWidth, height: processedHeight } = processedImage;
+
+        const scaledBox = {
+            x1: box.x1,
+            y1: box.y1,
+            x2: box.x2,
+            y2: box.y2,
+            x3: box.x3,
+            y3: box.y3,
+            x4: box.x4,
+            y4: box.y4
+        };
+
+        const clamp = (value, max) => Math.max(0, Math.min(max, value));
+
+        return {
+            x1: clamp(scaledBox.x1, processedWidth - 1),
+            y1: clamp(scaledBox.y1, processedHeight - 1),
+            x2: clamp(scaledBox.x2, processedWidth - 1),
+            y2: clamp(scaledBox.y2, processedHeight - 1),
+            x3: clamp(scaledBox.x3, processedWidth - 1),
+            y3: clamp(scaledBox.y3, processedHeight - 1),
+            x4: clamp(scaledBox.x4, processedWidth - 1),
+            y4: clamp(scaledBox.y4, processedHeight - 1)
+        };
+    }
+
+    scaleBoxToOriginalImage(box, processedImage) {
+        const {
+            scaleX, scaleY,
+            paddingX, paddingY,
+            originalWidth, originalHeight
+        } = processedImage;
+
+        const paddedX1 = box.x1 * scaleX;
+        const paddedY1 = box.y1 * scaleY;
+        const paddedX3 = box.x3 * scaleX;
+        const paddedY3 = box.y3 * scaleY;
+
+        const originalX1 = paddedX1 - paddingX;
+        const originalY1 = paddedY1 - paddingY;
+        const originalX3 = paddedX3 - paddingX;
+        const originalY3 = paddedY3 - paddingY;
+
+        const clamp = (value, max) => Math.max(0, Math.min(max, value));
+
+        return {
+            x1: clamp(originalX1, originalWidth - 1),
+            y1: clamp(originalY1, originalHeight - 1),
+            x2: clamp(originalX3, originalWidth - 1),
+            y2: clamp(originalY1, originalHeight - 1),
+            x3: clamp(originalX3, originalWidth - 1),
+            y3: clamp(originalY3, originalHeight - 1),
+            x4: clamp(originalX1, originalWidth - 1),
+            y4: clamp(originalY3, originalHeight - 1),
+            confidence: box.confidence
+        };
+    }
+}
+
+export default DetectionProcessor;

+ 104 - 0
server/utils/imagePreprocessor.js

@@ -0,0 +1,104 @@
+// server/utils/imagePreprocessor.js
+import sharp from 'sharp';
+
+class ImagePreprocessor {
+    constructor() {
+        this.tempDir = './temp/processed';
+    }
+
+    async preprocessWithPadding(imagePath, config) {
+        try {
+            const metadata = await sharp(imagePath).metadata();
+
+            // 减少填充,避免过度改变图像
+            const minPadding = 30;
+            const paddingX = Math.max(minPadding, Math.floor(metadata.width * 0.05));
+            const paddingY = Math.max(minPadding, Math.floor(metadata.height * 0.05));
+
+            const paddedWidth = metadata.width + paddingX * 2;
+            const paddedHeight = metadata.height + paddingY * 2;
+
+            const paddedBuffer = await sharp(imagePath)
+                .extend({
+                    top: paddingY,
+                    bottom: paddingY,
+                    left: paddingX,
+                    right: paddingX,
+                    background: { r: 255, g: 255, b: 255 }
+                })
+                .png()
+                .toBuffer();
+
+            const { width, height } = this.resizeForDetection({
+                width: paddedWidth,
+                height: paddedHeight
+            }, config);
+
+            const resizedBuffer = await sharp(paddedBuffer)
+                .resize(width, height)
+                .png()
+                .toBuffer();
+
+            console.log(`🖼️ 图像预处理完成: ${metadata.width}x${metadata.height} -> ${width}x${height}`);
+
+            return {
+                processedImage: {
+                    buffer: resizedBuffer,
+                    width,
+                    height,
+                    originalWidth: metadata.width,
+                    originalHeight: metadata.height,
+                    paddedWidth: paddedWidth,
+                    paddedHeight: paddedHeight,
+                    paddingX,
+                    paddingY,
+                    scaleX: paddedWidth / width,
+                    scaleY: paddedHeight / height
+                }
+            };
+
+        } catch (error) {
+            console.error('预处理错误:', error);
+            throw error;
+        }
+    }
+
+    resizeForDetection(metadata, config) {
+        const { width, height } = metadata;
+        const limitSideLen = config.detLimitSideLen || 960;
+
+        let ratio = 1;
+        if (Math.max(width, height) > limitSideLen) {
+            ratio = limitSideLen / Math.max(width, height);
+        }
+
+        const newWidth = Math.floor(width * ratio);
+        const newHeight = Math.floor(height * ratio);
+
+        return {
+            width: Math.max(32, Math.floor(newWidth / 32) * 32),
+            height: Math.max(32, Math.floor(newHeight / 32) * 32)
+        };
+    }
+
+    async getImageInfo(imagePath) {
+        try {
+            const metadata = await sharp(imagePath).metadata();
+            return {
+                width: metadata.width || 0,
+                height: metadata.height || 0,
+                format: metadata.format || 'unknown',
+                processed: false
+            };
+        } catch (error) {
+            return {
+                width: 0,
+                height: 0,
+                format: 'unknown',
+                processed: false
+            };
+        }
+    }
+}
+
+export default ImagePreprocessor;

+ 201 - 0
server/utils/onnxOcrManager.js

@@ -0,0 +1,201 @@
+// server/utils/onnxOcrManager.js
+import { InferenceSession } from 'onnxruntime-node';
+import fse from 'fs-extra';
+import * as path from 'path';
+import { fileURLToPath } from 'url';
+
+import DetectionProcessor from './detectionProcessor.js';
+import RecognitionProcessor from './recognitionProcessor.js';
+import ImagePreprocessor from './imagePreprocessor.js';
+import TextPostProcessor from './textPostProcessor.js';
+
+const __dirname = path.dirname(fileURLToPath(import.meta.url));
+
+class OnnxOcrManager {
+    constructor() {
+        this.detSession = null;
+        this.recSession = null;
+        this.clsSession = null;
+        this.isInitialized = false;
+
+        this.modelDir = path.join(process.cwd(), 'models', 'ocr');
+        this.detModelPath = path.join(this.modelDir, 'Det', '中文_OCRv3.onnx');
+        this.recModelPath = path.join(this.modelDir, 'Rec', '中文简体_OCRv3.onnx');
+        this.clsModelPath = path.join(this.modelDir, 'Cls', '原始分类器模型.onnx');
+        this.keysPath = path.join(this.modelDir, 'Keys', '中文简体_OCRv3.txt');
+
+        this.detectionProcessor = new DetectionProcessor();
+        this.recognitionProcessor = new RecognitionProcessor();
+        this.imagePreprocessor = new ImagePreprocessor();
+        this.textPostProcessor = new TextPostProcessor();
+
+        // 更新默认配置,优化识别效果
+        this.defaultConfig = {
+            language: 'ch',
+            detLimitSideLen: 960,
+            detThresh: 0.05,        // 降低检测阈值
+            detBoxThresh: 0.1,      // 降低框阈值
+            detUnclipRatio: 1.8,    // 调整解压缩比例
+            maxTextLength: 50,      // 增加最大文本长度
+            recImageHeight: 48,
+            clsThresh: 0.8,         // 降低分类阈值
+            minTextHeight: 2,       // 降低最小文本高度
+            minTextWidth: 2,        // 降低最小文本宽度
+            clusterDistance: 8,     // 调整聚类距离
+            minClusterPoints: 2     // 降低最小聚类点数
+        };
+    }
+
+    async initialize(config = {}) {
+        if (this.isInitialized) {
+            console.log('🔁 OCR管理器已初始化');
+            return;
+        }
+
+        try {
+            console.log('🚀 开始初始化OCR管理器...');
+            await this.validateModelFiles();
+            await this.recognitionProcessor.loadCharacterSet(this.keysPath);
+
+            const [detSession, recSession, clsSession] = await Promise.all([
+                InferenceSession.create(this.detModelPath, { executionProviders: ['cpu'] }),
+                InferenceSession.create(this.recModelPath, { executionProviders: ['cpu'] }),
+                InferenceSession.create(this.clsModelPath, { executionProviders: ['cpu'] })
+            ]);
+
+            this.detSession = detSession;
+            this.recSession = recSession;
+            this.clsSession = clsSession;
+
+            const mergedConfig = { ...this.defaultConfig, ...config };
+
+            this.detectionProcessor.initialize(this.detSession, mergedConfig);
+            this.recognitionProcessor.initialize(this.recSession, this.clsSession, mergedConfig);
+
+            this.isInitialized = true;
+            console.log('✅ OCR管理器初始化完成');
+
+        } catch (error) {
+            console.error('❌ OCR管理器初始化失败:', error);
+            throw error;
+        }
+    }
+
+    async validateModelFiles() {
+        const requiredFiles = [
+            { path: this.detModelPath, name: '检测模型' },
+            { path: this.recModelPath, name: '识别模型' },
+            { path: this.clsModelPath, name: '分类模型' },
+            { path: this.keysPath, name: '字符集文件' }
+        ];
+
+        for (const { path: filePath, name } of requiredFiles) {
+            const exists = await fse.pathExists(filePath);
+            if (!exists) {
+                throw new Error(`模型文件不存在: ${filePath}`);
+            }
+        }
+        console.log('✅ 所有模型文件验证通过');
+    }
+
+    async recognizeImage(imagePath, config = {}) {
+        if (!this.isInitialized) {
+            await this.initialize(config);
+        }
+
+        if (!imagePath || typeof imagePath !== 'string') {
+            throw new Error(`无效的图片路径: ${imagePath}`);
+        }
+
+        if (!fse.existsSync(imagePath)) {
+            throw new Error(`图片文件不存在: ${imagePath}`);
+        }
+
+        try {
+            console.log(`\n🎯 开始OCR识别: ${path.basename(imagePath)}`);
+            const startTime = Date.now();
+
+            const preprocessResult = await this.imagePreprocessor.preprocessWithPadding(imagePath, config);
+            const { processedImage } = preprocessResult;
+
+            const textBoxes = await this.detectionProcessor.detectText(processedImage);
+            const recognitionResults = await this.recognitionProcessor.recognizeTextWithCls(processedImage, textBoxes);
+
+            const processingTime = Date.now() - startTime;
+
+            const textBlocks = this.textPostProcessor.buildTextBlocks(recognitionResults);
+            const imageInfo = await this.imagePreprocessor.getImageInfo(imagePath);
+
+            const rawText = textBlocks.map(block => block.content).join('\n');
+            const overallConfidence = this.textPostProcessor.calculateOverallConfidence(recognitionResults);
+
+            const result = {
+                textBlocks,
+                confidence: overallConfidence,
+                processingTime,
+                isOffline: true,
+                imagePath,
+                totalPages: 1,
+                rawText,
+                imageInfo,
+                recognitionCount: recognitionResults.length
+            };
+
+            console.log(`\n📊 OCR识别统计:`);
+            console.log(`   - 处理时间: ${processingTime}ms`);
+            console.log(`   - 检测区域: ${textBoxes.length} 个`);
+            console.log(`   - 成功识别: ${recognitionResults.length} 个`);
+            console.log(`   - 总体置信度: ${overallConfidence.toFixed(4)}`);
+            console.log(`   - 最终文本长度: ${rawText.length} 字符`);
+
+            return result;
+
+        } catch (error) {
+            console.error(`❌ OCR识别失败: ${error.message}`);
+            throw new Error(`OCR识别失败: ${error.message}`);
+        }
+    }
+
+    getStatus() {
+        return {
+            isInitialized: this.isInitialized,
+            isOffline: true,
+            engine: 'PP-OCRv3 (ONNX Runtime)',
+            version: '1.0.0',
+            models: {
+                detection: path.relative(process.cwd(), this.detModelPath),
+                recognition: path.relative(process.cwd(), this.recModelPath),
+                classification: path.relative(process.cwd(), this.clsModelPath),
+                characterSet: this.recognitionProcessor.getCharacterSetSize()
+            },
+            config: {
+                detThresh: this.defaultConfig.detThresh,
+                detBoxThresh: this.defaultConfig.detBoxThresh,
+                clsThresh: this.defaultConfig.clsThresh,
+                preprocessing: 'enabled with padding'
+            },
+            backend: 'CPU'
+        };
+    }
+
+    async terminate() {
+        if (this.detSession) {
+            this.detSession.release();
+            this.detSession = null;
+        }
+        if (this.recSession) {
+            this.recSession.release();
+            this.recSession = null;
+        }
+        if (this.clsSession) {
+            this.clsSession.release();
+            this.clsSession = null;
+        }
+        this.isInitialized = false;
+        console.log('🛑 OCR管理器已终止');
+    }
+}
+
+const onnxOcrManager = new OnnxOcrManager();
+
+export default onnxOcrManager;

+ 131 - 0
server/utils/recognitionProcessor.js

@@ -0,0 +1,131 @@
+// server/utils/recognitionProcessor.js
+import TextDirectionClassifier from './textDirectionClassifier.js';
+import TextRecognizer from './textRecognizer.js';
+import TextRegionCropper from './textRegionCropper.js';
+
+class RecognitionProcessor {
+    constructor() {
+        this.recSession = null;
+        this.clsSession = null;
+        this.config = null;
+
+        this.textDirectionClassifier = new TextDirectionClassifier();
+        this.textRecognizer = new TextRecognizer();
+        this.textRegionCropper = new TextRegionCropper();
+    }
+
+    initialize(recSession, clsSession, config) {
+        this.recSession = recSession;
+        this.clsSession = clsSession;
+        this.config = config;
+
+        this.textDirectionClassifier.initialize(clsSession, config);
+        this.textRecognizer.initialize(recSession, config);
+    }
+
+    async loadCharacterSet(keysPath) {
+        await this.textRecognizer.loadCharacterSet(keysPath);
+    }
+
+    getCharacterSetSize() {
+        return this.textRecognizer.getCharacterSetSize();
+    }
+
+    async recognizeTextWithCls(processedImage, textBoxes) {
+        const results = [];
+
+        try {
+            console.log(`🔄 开始处理 ${textBoxes.length} 个文本区域`);
+
+            for (let i = 0; i < textBoxes.length; i++) {
+                const box = textBoxes[i];
+
+                try {
+                    console.log(`\n📦 处理区域 ${i + 1}/${textBoxes.length}, 置信度: ${box.confidence.toFixed(4)}`);
+
+                    const textRegion = await this.textRegionCropper.cropTextRegion(
+                        processedImage.buffer, box, i + 1
+                    );
+                    if (!textRegion) {
+                        console.log(`⏭️ 区域 ${i + 1}: 跳过无效区域`);
+                        continue;
+                    }
+
+                    const { clsResult, clsConfidence } = await this.textDirectionClassifier.classifyTextDirection(
+                        textRegion.buffer
+                    );
+
+                    let recognitionImage = textRegion.buffer;
+                    if (clsResult === 180 && clsConfidence > this.config.clsThresh) {
+                        console.log(`🔄 区域 ${i + 1}: 旋转 180°`);
+                        recognitionImage = await this.textRegionCropper.rotateImage(textRegion.buffer, 180);
+                    }
+
+                    const textResult = await this.textRecognizer.recognizeText(recognitionImage);
+
+                    if (textResult.text && textResult.text.trim().length > 0 && textResult.confidence > 0.05) {
+                        const originalBox = this.scaleBoxToOriginalImage(box, processedImage);
+
+                        results.push({
+                            text: textResult.text.trim(),
+                            confidence: textResult.confidence * clsConfidence,
+                            box: originalBox,
+                            clsResult,
+                            clsConfidence,
+                            regionIndex: i + 1
+                        });
+
+                        console.log(`✅ 区域 ${i + 1}: 识别成功 "${textResult.text}"`);
+                    } else {
+                        console.log(`❌ 区域 ${i + 1}: 识别失败或置信度过低`);
+                    }
+
+                } catch (error) {
+                    console.error(`💥 区域 ${i + 1}: 处理失败`, error.message);
+                    continue;
+                }
+            }
+
+            console.log(`\n🎯 识别完成: ${results.length}/${textBoxes.length} 个区域成功`);
+            return results;
+
+        } catch (error) {
+            console.error('❌ 整体识别失败:', error);
+            throw error;
+        }
+    }
+
+    scaleBoxToOriginalImage(box, processedImage) {
+        const {
+            scaleX, scaleY,
+            paddingX, paddingY,
+            originalWidth, originalHeight
+        } = processedImage;
+
+        const paddedX1 = box.x1 * scaleX;
+        const paddedY1 = box.y1 * scaleY;
+        const paddedX3 = box.x3 * scaleX;
+        const paddedY3 = box.y3 * scaleY;
+
+        const originalX1 = paddedX1 - paddingX;
+        const originalY1 = paddedY1 - paddingY;
+        const originalX3 = paddedX3 - paddingX;
+        const originalY3 = paddedY3 - paddingY;
+
+        const clamp = (value, max) => Math.max(0, Math.min(max, value));
+
+        return {
+            x1: clamp(originalX1, originalWidth - 1),
+            y1: clamp(originalY1, originalHeight - 1),
+            x2: clamp(originalX3, originalWidth - 1),
+            y2: clamp(originalY1, originalHeight - 1),
+            x3: clamp(originalX3, originalWidth - 1),
+            y3: clamp(originalY3, originalHeight - 1),
+            x4: clamp(originalX1, originalWidth - 1),
+            y4: clamp(originalY3, originalHeight - 1),
+            confidence: box.confidence
+        };
+    }
+}
+
+export default RecognitionProcessor;

+ 85 - 0
server/utils/textDirectionClassifier.js

@@ -0,0 +1,85 @@
+// server/utils/textDirectionClassifier.js
+import { Tensor } from 'onnxruntime-node';
+import sharp from 'sharp';
+
+class TextDirectionClassifier {
+    constructor() {
+        this.clsSession = null;
+        this.config = null;
+    }
+
+    initialize(clsSession, config) {
+        this.clsSession = clsSession;
+        this.config = config;
+    }
+
+    async classifyTextDirection(textRegionBuffer) {
+        try {
+            const inputTensor = await this.prepareClsInput(textRegionBuffer);
+            const outputs = await this.clsSession.run({ [this.clsSession.inputNames[0]]: inputTensor });
+            return this.postprocessCls(outputs);
+        } catch (error) {
+            console.error('文本方向分类失败:', error);
+            return { clsResult: 0, clsConfidence: 1.0 };
+        }
+    }
+
+    async prepareClsInput(textRegionBuffer) {
+        const targetHeight = 48;
+        const targetWidth = 192;
+
+        const resizedBuffer = await sharp(textRegionBuffer)
+            .resize(targetWidth, targetHeight)
+            .png()
+            .toBuffer();
+
+        const imageData = await sharp(resizedBuffer)
+            .ensureAlpha()
+            .raw()
+            .toBuffer({ resolveWithObject: true });
+
+        const inputData = new Float32Array(3 * targetHeight * targetWidth);
+        const data = imageData.data;
+        const channels = imageData.info.channels;
+
+        for (let i = 0; i < data.length; i += channels) {
+            const pixelIndex = Math.floor(i / channels);
+            const channel = Math.floor(pixelIndex / (targetHeight * targetWidth));
+            const posInChannel = pixelIndex % (targetHeight * targetWidth);
+
+            if (channel < 3) {
+                const y = Math.floor(posInChannel / targetWidth);
+                const x = posInChannel % targetWidth;
+                const inputIndex = channel * targetHeight * targetWidth + y * targetWidth + x;
+
+                if (inputIndex < inputData.length) {
+                    inputData[inputIndex] = data[i] / 255.0;
+                }
+            }
+        }
+
+        return new Tensor('float32', inputData, [1, 3, targetHeight, targetWidth]);
+    }
+
+    postprocessCls(outputs) {
+        const outputNames = this.clsSession.outputNames;
+        const clsOutput = outputs[outputNames[0]];
+
+        if (!clsOutput) return { clsResult: 0, clsConfidence: 1.0 };
+
+        const data = clsOutput.data;
+
+        let clsResult = 0;
+        let clsConfidence = data[0];
+
+        if (data.length >= 2 && data[1] > data[0]) {
+            clsResult = 180;
+            clsConfidence = data[1];
+        }
+
+        console.log(`🧭 文本方向分类: ${clsResult}°, 置信度: ${clsConfidence.toFixed(4)}`);
+        return { clsResult, clsConfidence };
+    }
+}
+
+export default TextDirectionClassifier;

+ 163 - 0
server/utils/textPostProcessor.js

@@ -0,0 +1,163 @@
+// server/utils/textPostProcessor.js
+class TextPostProcessor {
+    buildTextBlocks(recognitionResults) {
+        if (!recognitionResults || recognitionResults.length === 0) {
+            return [{
+                type: 'text',
+                content: '未识别到文本',
+                confidence: 0
+            }];
+        }
+
+        console.log(`📊 开始构建文本块,共 ${recognitionResults.length} 个识别结果`);
+
+        const lines = this.groupTextIntoLines(recognitionResults);
+        const blocks = [];
+
+        for (const line of lines) {
+            const content = line.map(item => item.text).join('');
+            const avgConfidence = line.reduce((sum, item) => sum + item.confidence, 0) / line.length;
+
+            const type = this.classifyTextType(content);
+
+            blocks.push({
+                type,
+                content,
+                confidence: avgConfidence,
+                ...(type === 'citation' && { number: this.extractCitationNumber(content) })
+            });
+
+            console.log(`📝 文本行: "${content}" (${type}, 置信度: ${avgConfidence.toFixed(4)})`);
+        }
+
+        const mergedBlocks = this.mergeShortTextBlocks(blocks);
+        console.log(`✅ 文本块构建完成: ${mergedBlocks.length} 个块`);
+
+        return mergedBlocks;
+    }
+
+    groupTextIntoLines(results) {
+        if (results.length === 0) return [];
+
+        const lines = [];
+        const sortedResults = [...results].sort((a, b) => a.box.y1 - b.box.y1);
+
+        let currentLine = [];
+        let currentY = -1;
+        const lineThreshold = 0.8 * this.calculateAverageHeight(results);
+
+        for (const result of sortedResults) {
+            if (currentY === -1 || Math.abs(result.box.y1 - currentY) < lineThreshold) {
+                currentLine.push(result);
+                if (currentY === -1) currentY = result.box.y1;
+                else currentY = (currentY + result.box.y1) / 2;
+            } else {
+                if (currentLine.length > 0) {
+                    currentLine.sort((a, b) => a.box.x1 - b.box.x1);
+                    lines.push(currentLine);
+                }
+                currentLine = [result];
+                currentY = result.box.y1;
+            }
+        }
+
+        if (currentLine.length > 0) {
+            currentLine.sort((a, b) => a.box.x1 - b.box.x1);
+            lines.push(currentLine);
+        }
+
+        return lines;
+    }
+
+    calculateAverageHeight(results) {
+        if (results.length === 0) return 0;
+        const totalHeight = results.reduce((sum, result) => {
+            const height = Math.max(result.box.y1, result.box.y2, result.box.y3, result.box.y4) -
+                Math.min(result.box.y1, result.box.y2, result.box.y3, result.box.y4);
+            return sum + height;
+        }, 0);
+        return totalHeight / results.length;
+    }
+
+    classifyTextType(text) {
+        if (this.isReference(text)) return 'reference';
+        if (this.isCitation(text)) return 'citation';
+        if (this.isImageMarker(text)) return 'image';
+        if (this.isTableMarker(text)) return 'table';
+        return 'text';
+    }
+
+    isReference(text) {
+        const refPatterns = [
+            /^参考文献/i,
+            /^references/i,
+            /^bibliography/i,
+            /^引用文献/i,
+            /^参考书目/i
+        ];
+        return refPatterns.some(pattern => pattern.test(text));
+    }
+
+    isCitation(text) {
+        return /^\[\d+\]/.test(text);
+    }
+
+    extractCitationNumber(text) {
+        const match = text.match(/^\[(\d+)\]/);
+        return match ? parseInt(match[1]) : null;
+    }
+
+    isImageMarker(text) {
+        const imagePatterns = [
+            /^图\s*\d+/i,
+            /^figure\s*\d+/i,
+            /^图片\s*\d+/i,
+            /^图表\s*\d+/i,
+            /^fig\.?\s*\d+/i
+        ];
+        return imagePatterns.some(pattern => pattern.test(text));
+    }
+
+    isTableMarker(text) {
+        const tablePatterns = [
+            /^表\s*\d+/i,
+            /^table\s*\d+/i,
+            /^表格\s*\d+/i
+        ];
+        return tablePatterns.some(pattern => pattern.test(text));
+    }
+
+    mergeShortTextBlocks(blocks) {
+        if (blocks.length <= 1) return blocks;
+
+        const mergedBlocks = [];
+        let currentBlock = { ...blocks[0] };
+
+        for (let i = 1; i < blocks.length; i++) {
+            const block = blocks[i];
+
+            // 放宽合并条件
+            if (currentBlock.type === 'text' &&
+                block.type === 'text' &&
+                currentBlock.content.length < 100) { // 增加长度限制
+
+                currentBlock.content += ' ' + block.content;
+                currentBlock.confidence = (currentBlock.confidence + block.confidence) / 2;
+            } else {
+                mergedBlocks.push(currentBlock);
+                currentBlock = { ...block };
+            }
+        }
+
+        mergedBlocks.push(currentBlock);
+        return mergedBlocks;
+    }
+
+    calculateOverallConfidence(results) {
+        if (results.length === 0) return 0;
+        const total = results.reduce((sum, result) => sum + result.confidence, 0);
+        return total / results.length;
+    }
+}
+
+export default TextPostProcessor;

+ 370 - 0
server/utils/textRecognizer.js

@@ -0,0 +1,370 @@
+// server/utils/textRecognizer.js
+import { Tensor } from 'onnxruntime-node';
+import sharp from 'sharp';
+import fse from 'fs-extra';
+import * as path from 'path';
+
+class TextRecognizer {
+    constructor() {
+        this.recSession = null;
+        this.config = null;
+        this.characterSet = [];
+        this.debugDir = path.join(process.cwd(), 'temp', 'debug');
+        fse.ensureDirSync(this.debugDir);
+    }
+
+    initialize(recSession, config) {
+        this.recSession = recSession;
+        this.config = config;
+    }
+
+    async loadCharacterSet(keysPath) {
+        try {
+            const keysContent = await fse.readFile(keysPath, 'utf8');
+            this.characterSet = [];
+            const lines = keysContent.split('\n');
+
+            for (const line of lines) {
+                const trimmed = line.trim();
+                if (trimmed && !trimmed.startsWith('#')) {
+                    for (const char of trimmed) {
+                        if (char.trim() && !this.characterSet.includes(char)) {
+                            this.characterSet.push(char);
+                        }
+                    }
+                }
+            }
+
+            if (this.characterSet.length === 0) {
+                throw new Error('字符集文件为空或格式不正确');
+            }
+
+            console.log(`✅ 字符集加载完成,共 ${this.characterSet.length} 个字符`);
+
+        } catch (error) {
+            console.error('❌ 加载字符集失败,使用默认字符集:', error.message);
+            this.characterSet = this.getDefaultCharacterSet();
+        }
+    }
+
+    getDefaultCharacterSet() {
+        const defaultSet = [];
+        for (let i = 0; i <= 9; i++) defaultSet.push(i.toString());
+        for (let i = 97; i <= 122; i++) defaultSet.push(String.fromCharCode(i));
+        for (let i = 65; i <= 90; i++) defaultSet.push(String.fromCharCode(i));
+        defaultSet.push(...' ,。!?;:""()【】《》…—·'.split(''));
+
+        const commonChinese = '的一是不了在人有的我他这个们中来就时大地为子中你说道生国年着就那和要她出也得里后自以会家可下而过天去能对小多然于心学么之都好看起发当没成只如事把还用第样道想作种开美总从无情已面最女但现前些所同日手又行意动方期它头经长儿回位分爱老因很给名法间斯知世什两次使身者被高已亲其进此话常与活正感';
+        for (const char of commonChinese) {
+            defaultSet.push(char);
+        }
+
+        console.log(`📝 使用默认字符集,共 ${defaultSet.length} 个字符`);
+        return defaultSet;
+    }
+
+    getCharacterSetSize() {
+        return this.characterSet.length;
+    }
+
+    async recognizeText(textRegionBuffer) {
+        console.log('🔠 === 开始文本识别流程 ===');
+
+        try {
+            console.log('📥 1. 准备识别输入...');
+            console.log(`   - 输入图像大小: ${textRegionBuffer.length} 字节`);
+
+            const inputTensor = await this.prepareRecognitionInput(textRegionBuffer);
+            console.log('✅ 输入张量准备完成');
+            console.log(`   - 张量形状: [${inputTensor.dims.join(', ')}]`);
+            console.log(`   - 张量类型: ${inputTensor.type}`);
+            console.log(`   - 数据长度: ${inputTensor.data.length}`);
+
+            // 数据验证
+            const tensorData = inputTensor.data;
+            let minVal = Infinity;
+            let maxVal = -Infinity;
+            let sumVal = 0;
+            let validCount = 0;
+
+            for (let i = 0; i < Math.min(100, tensorData.length); i++) {
+                const val = tensorData[i];
+                if (!isNaN(val) && isFinite(val)) {
+                    minVal = Math.min(minVal, val);
+                    maxVal = Math.max(maxVal, val);
+                    sumVal += val;
+                    validCount++;
+                }
+            }
+
+            console.log(`   - 数据范围: ${minVal.toFixed(4)} ~ ${maxVal.toFixed(4)}`);
+            console.log(`   - 数据均值: ${(sumVal / validCount).toFixed(4)}`);
+
+            console.log('🧠 2. 执行模型推理...');
+            const startInference = Date.now();
+            const outputs = await this.recSession.run({ [this.recSession.inputNames[0]]: inputTensor });
+            const inferenceTime = Date.now() - startInference;
+            console.log(`✅ 模型推理完成 (${inferenceTime}ms)`);
+
+            const outputNames = this.recSession.outputNames;
+            console.log(`   - 输出数量: ${outputNames.length}`);
+
+            outputNames.forEach((name, index) => {
+                const output = outputs[name];
+                if (output) {
+                    console.log(`   - 输出 ${index + 1} (${name}): 形状 [${output.dims.join(', ')}]`);
+                }
+            });
+
+            console.log('🔍 3. 后处理识别结果...');
+            const result = this.postprocessRecognition(outputs);
+            console.log('✅ 后处理完成');
+            console.log(`   - 识别文本: "${result.text}"`);
+            console.log(`   - 置信度: ${result.confidence.toFixed(4)}`);
+            console.log(`   - 文本长度: ${result.text.length} 字符`);
+
+            console.log('🎉 === 文本识别流程完成 ===');
+            return result;
+
+        } catch (error) {
+            console.error('❌ 文本识别失败:');
+            console.error(`   - 错误信息: ${error.message}`);
+            return { text: '', confidence: 0 };
+        }
+    }
+
+    async prepareRecognitionInput(textRegionBuffer) {
+        console.log('   📝 准备识别输入详情:');
+
+        try {
+            const targetHeight = 48;
+            const targetWidth = 320;
+
+            const metadata = await sharp(textRegionBuffer).metadata();
+            console.log(`     - 原始图像尺寸: ${metadata.width}x${metadata.height}`);
+
+            // 保存原始图像用于调试
+            const originalPath = path.join(this.debugDir, `original-${Date.now()}.png`);
+            await fse.writeFile(originalPath, textRegionBuffer);
+
+            // 关键修复:正确的预处理流程
+            let processedBuffer = textRegionBuffer;
+
+            // 1. 分析图像特性
+            const stats = await sharp(processedBuffer)
+                .grayscale()
+                .stats();
+            const meanBrightness = stats.channels[0].mean;
+            const stdDev = stats.channels[0].stdev;
+
+            console.log(`     - 图像统计: 均值=${meanBrightness.toFixed(1)}, 标准差=${stdDev.toFixed(1)}`);
+
+            // 2. 改进的预处理策略
+            if (meanBrightness > 200 && stdDev < 30) {
+                console.log('     - 检测到高亮度图像,进行对比度增强');
+                processedBuffer = await sharp(processedBuffer)
+                    .linear(1.5, -50)
+                    .normalize()
+                    .grayscale()
+                    .toBuffer();
+            } else if (meanBrightness < 80) {
+                console.log('     - 检测到低亮度图像,进行亮度调整');
+                processedBuffer = await sharp(processedBuffer)
+                    .linear(1.2, 30)
+                    .normalize()
+                    .grayscale()
+                    .toBuffer();
+            } else {
+                console.log('     - 使用标准化灰度处理');
+                processedBuffer = await sharp(processedBuffer)
+                    .normalize()
+                    .grayscale()
+                    .toBuffer();
+            }
+
+            // 3. 保持宽高比的resize
+            const originalAspectRatio = metadata.width / metadata.height;
+            const targetAspectRatio = targetWidth / targetHeight;
+
+            let resizeWidth, resizeHeight;
+
+            if (originalAspectRatio > targetAspectRatio) {
+                // 宽度限制
+                resizeWidth = targetWidth;
+                resizeHeight = Math.round(targetWidth / originalAspectRatio);
+            } else {
+                // 高度限制
+                resizeHeight = targetHeight;
+                resizeWidth = Math.round(targetHeight * originalAspectRatio);
+            }
+
+            // 确保尺寸有效
+            resizeWidth = Math.max(1, Math.min(resizeWidth, targetWidth));
+            resizeHeight = Math.max(1, Math.min(resizeHeight, targetHeight));
+
+            processedBuffer = await sharp(processedBuffer)
+                .resize(resizeWidth, resizeHeight, {
+                    fit: 'contain',
+                    background: { r: 255, g: 255, b: 255 }
+                })
+                .extend({
+                    top: 0,
+                    bottom: targetHeight - resizeHeight,
+                    left: 0,
+                    right: targetWidth - resizeWidth,
+                    background: { r: 255, g: 255, b: 255 }
+                })
+                .png()
+                .toBuffer();
+
+            const processedMetadata = await sharp(processedBuffer).metadata();
+            console.log(`     - 处理后尺寸: ${processedMetadata.width}x${processedMetadata.height}`);
+
+            // 保存预处理后的图像用于调试
+            const processedPath = path.join(this.debugDir, `processed-${Date.now()}.png`);
+            await fse.writeFile(processedPath, processedBuffer);
+
+            // 4. 转换为张量 - 关键修复:正确的归一化
+            console.log('     - 转换为张量数据...');
+            const imageData = await sharp(processedBuffer)
+                .ensureAlpha()
+                .raw()
+                .toBuffer({ resolveWithObject: true });
+
+            const inputData = new Float32Array(3 * targetHeight * targetWidth);
+            const data = imageData.data;
+            const channels = imageData.info.channels;
+
+            // 使用正确的归一化方法
+            for (let i = 0; i < data.length; i += channels) {
+                const pixelIndex = Math.floor(i / channels);
+                const y = Math.floor(pixelIndex / targetWidth);
+                const x = pixelIndex % targetWidth;
+
+                // 对每个位置,三个通道使用相同的灰度值
+                const grayValue = data[i] / 255.0;
+
+                for (let c = 0; c < 3; c++) {
+                    const inputIndex = c * targetHeight * targetWidth + y * targetWidth + x;
+                    if (inputIndex < inputData.length) {
+                        inputData[inputIndex] = grayValue;
+                    }
+                }
+            }
+
+            console.log(`     - 输入数据长度: ${inputData.length}`);
+
+            // 数据验证
+            let validCount = 0;
+            let sumValue = 0;
+            let minValue = Infinity;
+            let maxValue = -Infinity;
+
+            for (let i = 0; i < Math.min(100, inputData.length); i++) {
+                const val = inputData[i];
+                if (!isNaN(val) && isFinite(val)) {
+                    validCount++;
+                    sumValue += val;
+                    minValue = Math.min(minValue, val);
+                    maxValue = Math.max(maxValue, val);
+                }
+            }
+
+            console.log(`     - 数据验证: 有效=${validCount}`);
+            console.log(`     - 数据范围: ${minValue.toFixed(4)} ~ ${maxValue.toFixed(4)}`);
+            console.log(`     - 数据均值: ${(sumValue / validCount).toFixed(4)}`);
+
+            return new Tensor('float32', inputData, [1, 3, targetHeight, targetWidth]);
+
+        } catch (error) {
+            console.error(`     ❌ 准备输入失败: ${error.message}`);
+            // 返回有效的默认张量
+            return new Tensor('float32', new Float32Array(3 * 48 * 320).fill(0.5), [1, 3, 48, 320]);
+        }
+    }
+
+    postprocessRecognition(outputs) {
+        console.log('   📝 后处理识别结果详情:');
+
+        try {
+            const outputNames = this.recSession.outputNames;
+            const recognitionOutput = outputs[outputNames[0]];
+
+            if (!recognitionOutput) {
+                console.log('     ❌ 识别输出为空');
+                return { text: '', confidence: 0 };
+            }
+
+            const data = recognitionOutput.data;
+            const [batch, seqLen, vocabSize] = recognitionOutput.dims;
+
+            console.log(`     - 序列长度: ${seqLen}, 词汇表大小: ${vocabSize}`);
+            console.log(`     - 输出数据总数: ${data.length}`);
+            console.log(`     - 字符集大小: ${this.characterSet.length}`);
+
+            if (this.characterSet.length === 0) {
+                console.log('     ❌ 字符集为空');
+                return { text: '', confidence: 0 };
+            }
+
+            // 改进的CTC解码算法
+            let text = '';
+            let lastCharIndex = -1;
+            let confidenceSum = 0;
+            let charCount = 0;
+
+            // 降低置信度阈值,提高召回率
+            const confidenceThreshold = 0.05;
+
+            console.log('     - 处理每个时间步:');
+            for (let t = 0; t < seqLen; t++) {
+                let maxProb = -1;
+                let maxIndex = -1;
+
+                // 找到当前时间步的最大概率字符
+                for (let i = 0; i < vocabSize; i++) {
+                    const prob = data[t * vocabSize + i];
+                    if (prob > maxProb) {
+                        maxProb = prob;
+                        maxIndex = i;
+                    }
+                }
+
+                // 改进的解码逻辑
+                if (maxIndex > 0 && maxProb > confidenceThreshold) {
+                    const char = this.characterSet[maxIndex - 1] || '';
+
+                    // 放宽重复字符限制
+                    if (maxIndex !== lastCharIndex || maxProb > 0.8) {
+                        if (char && char.trim() !== '') {
+                            text += char;
+                            confidenceSum += maxProb;
+                            charCount++;
+                            console.log(`       [位置 ${t}] 字符: "${char}", 置信度: ${maxProb.toFixed(4)}`);
+                        }
+                        lastCharIndex = maxIndex;
+                    }
+                } else if (maxIndex === 0) {
+                    // 空白符,重置lastCharIndex
+                    lastCharIndex = -1;
+                }
+            }
+
+            const avgConfidence = charCount > 0 ? confidenceSum / charCount : 0;
+
+            console.log(`     - 识别结果: "${text}"`);
+            console.log(`     - 字符数: ${charCount}, 平均置信度: ${avgConfidence.toFixed(4)}`);
+
+            return {
+                text: text,
+                confidence: avgConfidence
+            };
+
+        } catch (error) {
+            console.error(`     ❌ 后处理失败: ${error.message}`);
+            return { text: '', confidence: 0 };
+        }
+    }
+}
+
+export default TextRecognizer;

+ 127 - 0
server/utils/textRegionCropper.js

@@ -0,0 +1,127 @@
+// server/utils/textRegionCropper.js
+import sharp from 'sharp';
+
+class TextRegionCropper {
+    constructor() {
+        // 可以在这里添加配置参数
+    }
+
+    async cropTextRegion(imageBuffer, box, regionIndex) {
+        try {
+            const metadata = await sharp(imageBuffer).metadata();
+            const imgWidth = metadata.width;
+            const imgHeight = metadata.height;
+
+            const left = Math.min(box.x1, box.x2, box.x3, box.x4);
+            const top = Math.min(box.y1, box.y2, box.y3, box.y4);
+            const right = Math.max(box.x1, box.x2, box.x3, box.x4);
+            const bottom = Math.max(box.y1, box.y2, box.y3, box.y4);
+
+            const originalWidth = right - left;
+            const originalHeight = bottom - top;
+
+            // 减少扩展,避免引入过多背景
+            const widthExpand = 10;
+            const heightExpand = 10;
+
+            const newWidth = originalWidth + widthExpand;
+            const newHeight = originalHeight + heightExpand;
+
+            const centerX = (left + right) / 2;
+            const centerY = (top + bottom) / 2;
+
+            const expandedLeft = Math.max(0, centerX - newWidth / 2);
+            const expandedTop = Math.max(0, centerY - newHeight / 2);
+            const expandedRight = Math.min(imgWidth - 1, centerX + newWidth / 2);
+            const expandedBottom = Math.min(imgHeight - 1, centerY + newHeight / 2);
+
+            const finalWidth = expandedRight - expandedLeft;
+            const finalHeight = expandedBottom - expandedTop;
+
+            if (finalWidth <= 0 || finalHeight <= 0) {
+                console.log(`❌ 区域 ${regionIndex}: 无效的裁剪区域`);
+                return null;
+            }
+
+            let adjustedLeft = expandedLeft;
+            let adjustedTop = expandedTop;
+            let adjustedWidth = finalWidth;
+            let adjustedHeight = finalHeight;
+
+            if (expandedLeft < 0) {
+                adjustedLeft = 0;
+                adjustedWidth = expandedRight;
+            }
+            if (expandedTop < 0) {
+                adjustedTop = 0;
+                adjustedHeight = expandedBottom;
+            }
+            if (expandedRight > imgWidth) {
+                adjustedWidth = imgWidth - adjustedLeft;
+            }
+            if (expandedBottom > imgHeight) {
+                adjustedHeight = imgHeight - adjustedTop;
+            }
+
+            const croppedBuffer = await sharp(imageBuffer)
+                .extract({
+                    left: Math.floor(adjustedLeft),
+                    top: Math.floor(adjustedTop),
+                    width: Math.floor(adjustedWidth),
+                    height: Math.floor(adjustedHeight)
+                })
+                .png()
+                .toBuffer();
+
+            console.log(`✂️ 区域 ${regionIndex}: 裁剪 ${Math.floor(adjustedWidth)}x${Math.floor(adjustedHeight)}`);
+
+            return {
+                buffer: croppedBuffer,
+                boxInfo: {
+                    original: { left, top, right, bottom, width: originalWidth, height: originalHeight },
+                    expanded: {
+                        left: adjustedLeft,
+                        top: adjustedTop,
+                        right: adjustedLeft + adjustedWidth,
+                        bottom: adjustedTop + adjustedHeight,
+                        width: adjustedWidth,
+                        height: adjustedHeight
+                    }
+                }
+            };
+
+        } catch (error) {
+            console.error(`❌ 区域 ${regionIndex}: 裁剪失败`, error);
+            return null;
+        }
+    }
+
+    async rotateImage(imageBuffer, degrees) {
+        return await sharp(imageBuffer)
+            .rotate(degrees)
+            .png()
+            .toBuffer();
+    }
+
+    calculateExpansion(originalWidth, originalHeight, expansionFactor = 1.2) {
+        return {
+            width: originalWidth * expansionFactor,
+            height: originalHeight * expansionFactor
+        };
+    }
+
+    validateCropRegion(left, top, width, height, imgWidth, imgHeight) {
+        if (width <= 0 || height <= 0) {
+            return false;
+        }
+        if (left < 0 || top < 0) {
+            return false;
+        }
+        if (left + width > imgWidth || top + height > imgHeight) {
+            return false;
+        }
+        return true;
+    }
+}
+
+export default TextRegionCropper;

+ 13 - 13
src/main/main.js

@@ -1,6 +1,6 @@
 const { app, BrowserWindow, Tray, Menu, ipcMain } = require('electron')
 const path = require('path')
-const { startServer } = require('../../server/server.js')
+const { startServer } = require('../../server/server.ts')
 const net = require('net')
 const dns = require('dns')
 
@@ -103,19 +103,19 @@ async function determineApiService() {
 }
 
 // 定期检查网络状态(每30秒)
-function startNetworkMonitoring() {
-    setInterval(async () => {
-        const serviceInfo = await determineApiService()
-        if (serviceInfo.baseUrl !== currentApiBaseUrl) {
-            console.log('API服务地址变更:', currentApiBaseUrl, '->', serviceInfo.baseUrl)
-            currentApiBaseUrl = serviceInfo.baseUrl
-
-            // 通知渲染进程服务地址变更
-            if (mainWindow) {
-                mainWindow.webContents.send('api-base-url-changed', currentApiBaseUrl)
-            }
+async function startNetworkMonitoring() {
+    // setInterval(async () => {
+    const serviceInfo = await determineApiService()
+    if (serviceInfo.baseUrl !== currentApiBaseUrl) {
+        console.log('API服务地址变更:', currentApiBaseUrl, '->', serviceInfo.baseUrl)
+        currentApiBaseUrl = serviceInfo.baseUrl
+
+        // 通知渲染进程服务地址变更
+        if (mainWindow) {
+            mainWindow.webContents.send('api-base-url-changed', currentApiBaseUrl)
         }
-    }, 30000) // 30秒检查一次
+    }
+    // }, 30000) // 30秒检查一次
 }
 
 function createWindow() {

+ 97 - 953
src/renderer/components/OCRPage.vue

@@ -19,247 +19,50 @@
     </header>
 
     <div class="ocr-content">
-      <!-- 左侧文件列表 -->
-      <div class="file-panel">
-        <div class="panel-header">
-          <h3>源文件</h3>
-          <span class="file-count">共 {{ files.length }} 个文件</span>
-        </div>
-        <div class="file-list">
-          <div
-              v-for="file in files"
-              :key="file.id"
-              class="file-item"
-              :class="{ active: currentFile?.id === file.id }"
-              @click="selectFile(file)"
-          >
-            <div class="file-icon">
-              <img
-                  v-if="isImage(file)"
-                  :src="getFileThumbnail(file)"
-                  :alt="file.originalName"
-                  class="file-thumbnail"
-                  @error="handleImageError"
-              />
-              <div v-else class="file-type-icon" :class="getFileTypeClass(file)">
-                {{ getFileTypeIcon(file) }}
-              </div>
-            </div>
-            <div class="file-info">
-              <div class="file-name" :title="file.originalName">
-                {{ file.originalName }}
-              </div>
-              <div class="file-meta">
-                {{ formatFileSize(file.fileSize) }}
-              </div>
-              <div v-if="file.hasOcrResult" class="ocr-indicator">
-                ✓ 已识别
-              </div>
-            </div>
-          </div>
-        </div>
-      </div>
-
-      <!-- 中间文件详情 -->
-      <div class="detail-panel">
-        <div class="panel-header">
-          <h3>文件详情</h3>
-          <div class="preview-controls" v-if="currentFile && isImage(currentFile)">
-            <button @click="zoomOut" class="zoom-btn">−</button>
-            <span class="zoom-level">{{ (zoomLevel * 100).toFixed(0) }}%</span>
-            <button @click="zoomIn" class="zoom-btn">+</button>
-            <button @click="resetZoom" class="reset-btn">重置</button>
-          </div>
-        </div>
-        <div class="file-preview-container" ref="previewContainer">
-          <div class="file-preview"
-               @mousedown="startDrag"
-               @mousemove="doDrag"
-               @mouseup="stopDrag"
-               @mouseleave="stopDrag"
-               @wheel="handleWheel">
-            <div v-if="currentFile" class="preview-content">
-              <!-- 图片预览 - 添加缩放拖拽 -->
-              <div class="image-wrapper" ref="imageWrapper" v-if="isImage(currentFile)">
-                <img
-                    :src="getCurrentPageImage(currentFile)"
-                    :alt="currentFile.originalName"
-                    class="preview-image"
-                    :style="{
-                    transform: `scale(${zoomLevel}) translate(${dragOffset.x}px, ${dragOffset.y}px)`,
-                    cursor: isDragging ? 'grabbing' : 'grab'
-                  }"
-                    @load="handleImageLoad"
-                    @error="handlePreviewError"
-                    ref="previewImage"
-                />
-              </div>
-              <div v-else class="unsupported-preview">
-                <div class="file-type-large" :class="getFileTypeClass(currentFile)">
-                  {{ getFileTypeIcon(currentFile) }}
-                </div>
-                <p>该文件类型不支持预览</p>
-                <p class="file-format">格式: {{ currentFile.mimeType }}</p>
-                <p class="hint">目前仅支持图片文件的OCR识别</p>
-              </div>
-            </div>
-            <div v-else class="no-file-selected">
-              <p>请选择要识别的文件</p>
-            </div>
-          </div>
-        </div>
-      </div>
-
-      <!-- 右侧识别结果 -->
-      <div class="result-panel">
-        <div class="panel-header">
-          <h3>识别结果</h3>
-          <div class="result-actions">
-            <button class="btn btn-sm" @click="copyResult" :disabled="!ocrResult">
-              复制文本
-            </button>
-            <div v-if="ocrResult" class="confidence">
-              置信度: {{ (ocrResult.confidence * 100).toFixed(1) }}%
-              <span v-if="ocrResult.manuallyCorrected" class="corrected-badge">已校对</span>
-            </div>
-          </div>
-        </div>
-        <div class="ocr-result" ref="resultContainer">
-          <div v-if="isProcessing" class="processing">
-            <div class="spinner"></div>
-            <p>正在识别中,请稍候...</p>
-            <p class="processing-time">已用时: {{ processingTime }}s</p>
-          </div>
-
-          <div v-else-if="ocrResult" class="result-content">
-            <!-- 可编辑的文本内容 -->
-            <div
-                v-for="(block, index) in ocrResult.textBlocks"
-                :key="index"
-                class="text-block"
-                :class="block.type"
-            >
-              <div v-if="block.type === 'text'" class="text-content">
-                <textarea
-                    v-if="isEditing"
-                    v-model="block.content"
-                    class="editable-text"
-                    @blur="saveTextEdit"
-                    @input="autoResizeTextarea"
-                    ref="textareas"
-                ></textarea>
-                <div v-else class="static-text">
-                  {{ block.content }}
-                </div>
-              </div>
-
-              <div v-else-if="block.type === 'image'" class="image-block">
-                <div class="image-caption">{{ block.content }}</div>
-              </div>
-
-              <div v-else-if="block.type === 'reference'" class="reference-block">
-                <div class="reference-title">📚 参考文献</div>
-                <div class="reference-content">
-                  <textarea
-                      v-if="isEditing"
-                      v-model="block.content"
-                      class="editable-text"
-                      @blur="saveTextEdit"
-                      @input="autoResizeTextarea"
-                      ref="textareas"
-                  ></textarea>
-                  <span v-else>{{ block.content }}</span>
-                </div>
-                <button class="search-btn" @click="searchReference(block.content)">
-                  查找原文
-                </button>
-              </div>
-
-              <div v-else-if="block.type === 'citation'" class="citation-block">
-                <div class="citation-content">
-                  <span class="citation-marker">[{{ block.number }}]</span>
-                  <textarea
-                      v-if="isEditing"
-                      v-model="block.content"
-                      class="editable-text"
-                      @blur="saveTextEdit"
-                      @input="autoResizeTextarea"
-                      ref="textareas"
-                  ></textarea>
-                  <span v-else>{{ block.content }}</span>
-                </div>
-              </div>
-
-              <!-- 编辑模式下的操作按钮 -->
-              <div v-if="isEditing" class="block-actions">
-                <button class="btn-delete" @click="removeBlock(index)">删除</button>
-                <button class="btn-add" @click="addBlockAfter(index)">添加</button>
-              </div>
-            </div>
-
-            <!-- 添加新文本块 -->
-            <div v-if="isEditing" class="add-block-section">
-              <button class="btn-add-block" @click="addNewBlock">
-                + 添加文本块
-              </button>
-            </div>
-
-            <div class="result-summary">
-              <p>识别完成,共 {{ ocrResult.textBlocks.length }} 个文本块</p>
-              <p>处理时间: {{ (ocrResult.processingTime / 1000).toFixed(2) }} 秒</p>
-              <p v-if="ocrResult.manuallyCorrected" class="corrected-info">
-                ✅ 此结果已人工校对
-              </p>
-            </div>
-          </div>
-
-          <div v-else class="no-result">
-            <p>识别结果将显示在这里</p>
-            <p class="hint">支持中英文混合识别,自动识别参考文献和图片标注</p>
-          </div>
-        </div>
-      </div>
+      <FilePanel
+          :files="files"
+          :currentFile="currentFile"
+          @file-selected="selectFile"
+      />
+
+      <!-- 原图预览 -->
+      <ImagePanel
+          :currentFile="currentFile"
+          :imageUrl="originalImageUrl"
+          title="原图预览"
+      />
+
+      <!-- 预处理后图片预览 -->
+      <ImagePanel
+          :currentFile="currentFile"
+          :imageUrl="processedImageUrl"
+          title="预处理后预览"
+          :showProcessing="showProcessedImage"
+      />
+
+      <ResultPanel
+          :isProcessing="isProcessing"
+          :processingTime="processingTime"
+          :ocrResult="ocrResult"
+          :isEditing="isEditing"
+          @copy-result="copyResult"
+          @update-block="updateBlockContent"
+          @remove-block="removeBlock"
+          @add-block-after="addBlockAfter"
+          @add-new-block="addNewBlock"
+      />
     </div>
   </div>
 </template>
 
 <script setup lang="ts">
-import { ref, computed, onMounted, onUnmounted, nextTick } from 'vue'
+import { ref, onMounted, onUnmounted, watch } from 'vue'
 import { useRoute, useRouter } from 'vue-router'
 import apiManager from '../utils/apiManager'
-
-interface FileRecord {
-  id: number
-  originalName: string
-  fileName: string
-  filePath: string
-  fileSize: number
-  mimeType: string
-  md5: string
-  createdAt: string
-  updatedAt: string
-  hasOcrResult?: boolean
-}
-
-interface ApiResponse<T> {
-  success: boolean
-  data?: T
-  pagination?: any
-  error?: string
-}
-
-interface OcrResult {
-  textBlocks: Array<{
-    type: 'text' | 'image' | 'reference' | 'citation'
-    content: string
-    number?: number
-    confidence?: number
-  }>
-  totalPages: number
-  processingTime: number
-  confidence: number
-  manuallyCorrected?: boolean
-}
+import { FileRecord, OcrResult, ApiResponse, OcrConfig } from '../types/ocr'
+import FilePanel from './ocr/FilePanel.vue'
+import ImagePanel from './ocr/ImagePanel.vue'
+import ResultPanel from './ocr/ResultPanel.vue'
 
 const route = useRoute()
 const router = useRouter()
@@ -269,213 +72,37 @@ const currentFile = ref<FileRecord | null>(null)
 const isProcessing = ref(false)
 const ocrResult = ref<OcrResult | null>(null)
 const processingTime = ref(0)
-let processingInterval: number | null = null
-
-// 新增变量
 const isEditing = ref(false)
-const zoomLevel = ref(1)
-const dragOffset = ref({ x: 0, y: 0 })
-const isDragging = ref(false)
-const lastDragPos = ref({ x: 0, y: 0 })
-const resultContainer = ref<HTMLElement | null>(null)
-const previewContainer = ref<HTMLElement | null>(null)
-const previewImage = ref<HTMLImageElement | null>(null)
-const imageWrapper = ref<HTMLElement | null>(null)
-const textareas = ref<HTMLTextAreaElement[]>([])
-
-// 计算属性
-const isMultiPage = computed(() => {
-  if (!currentFile.value) return false
-  return false // 目前只支持单页
-})
-
-// 方法
-const isImage = (file: FileRecord): boolean => {
-  return file.mimeType.startsWith('image/')
-}
-
-const getFileTypeClass = (file: FileRecord): string => {
-  if (file.mimeType.includes('pdf')) return 'file-pdf'
-  if (file.mimeType.includes('word') || file.mimeType.includes('document')) return 'file-word'
-  if (file.mimeType.includes('excel') || file.mimeType.includes('spreadsheet')) return 'file-excel'
-  if (file.mimeType.includes('powerpoint') || file.mimeType.includes('presentation')) return 'file-ppt'
-  return 'file-other'
-}
-
-const getFileTypeIcon = (file: FileRecord): string => {
-  if (file.mimeType.includes('pdf')) return '📄'
-  if (file.mimeType.includes('word') || file.mimeType.includes('document')) return '📝'
-  if (file.mimeType.includes('excel') || file.mimeType.includes('spreadsheet')) return '📊'
-  if (file.mimeType.includes('powerpoint') || file.mimeType.includes('presentation')) return '📑'
-  return '📎'
-}
-
-const getFileThumbnail = (file: FileRecord): string => {
-  return apiManager.buildUrl(`/api/files/${file.id}/thumbnail`)
-}
-
-const getCurrentPageImage = (file: FileRecord): string => {
-  return apiManager.buildUrl(`/api/files/${file.id}/preview`)
-}
+const originalImageUrl = ref('')
+const processedImageUrl = ref('')
+const showProcessedImage = ref(false)
+let processingInterval: number | null = null
 
-const formatFileSize = (bytes: number): string => {
-  const units = ['B', 'KB', 'MB', 'GB']
-  let size = bytes
-  let unitIndex = 0
-  while (size >= 1024 && unitIndex < units.length - 1) {
-    size /= 1024
-    unitIndex++
+// 监听当前文件变化
+watch(currentFile, async (newFile) => {
+  if (newFile) {
+    originalImageUrl.value = apiManager.buildUrl(`/api/files/${newFile.id}/preview`)
+    processedImageUrl.value = '' // 清空预处理图片
+    showProcessedImage.value = false
   }
-  return `${size.toFixed(1)} ${units[unitIndex]}`
-}
+})
 
 const selectFile = async (file: FileRecord): Promise<void> => {
   currentFile.value = file
   ocrResult.value = null
   isEditing.value = false
-  resetZoom() // 重置缩放和拖拽
-
-  // 加载已有的OCR结果
   await loadExistingOcrResult(file.id)
 }
 
-// 图片加载完成后的处理
-const handleImageLoad = (): void => {
-  // 确保图片在可视区域内
-  nextTick(() => {
-    resetZoom()
-    centerImage()
-  })
-}
-
-// 居中图片
-const centerImage = (): void => {
-  if (!previewImage.value || !imageWrapper.value) return
-
-  const container = imageWrapper.value
-  const img = previewImage.value
-
-  // 计算居中偏移
-  const containerRect = container.getBoundingClientRect()
-  const imgRect = img.getBoundingClientRect()
-
-  // 如果图片比容器小,居中显示
-  if (imgRect.width < containerRect.width && imgRect.height < containerRect.height) {
-    dragOffset.value = { x: 0, y: 0 }
-  }
-}
-
-// 缩放功能
-const zoomIn = (): void => {
-  zoomLevel.value = Math.min(zoomLevel.value + 0.1, 3)
-  constrainDragOffset() // 限制拖拽范围
-}
-
-const zoomOut = (): void => {
-  zoomLevel.value = Math.max(zoomLevel.value - 0.1, 0.5)
-  constrainDragOffset() // 限制拖拽范围
-}
-
-const resetZoom = (): void => {
-  zoomLevel.value = 1
-  dragOffset.value = { x: 0, y: 0 }
-}
-
-// 限制拖拽范围,防止图片被拖出可视区域
-const constrainDragOffset = (): void => {
-  if (!previewImage.value || !imageWrapper.value) return
-
-  const container = imageWrapper.value
-  const img = previewImage.value
-
-  const containerRect = container.getBoundingClientRect()
-  const imgRect = {
-    width: img.naturalWidth * zoomLevel.value,
-    height: img.naturalHeight * zoomLevel.value
-  }
-
-  // 计算最大允许的拖拽偏移
-  const maxX = Math.max(0, (imgRect.width - containerRect.width) / 2)
-  const maxY = Math.max(0, (imgRect.height - containerRect.height) / 2)
-
-  // 限制拖拽范围
-  dragOffset.value.x = Math.max(-maxX, Math.min(maxX, dragOffset.value.x))
-  dragOffset.value.y = Math.max(-maxY, Math.min(maxY, dragOffset.value.y))
-}
-
-// 拖拽功能
-const startDrag = (event: MouseEvent): void => {
-  if (!currentFile.value || !isImage(currentFile.value)) return
-
-  isDragging.value = true
-  lastDragPos.value = { x: event.clientX, y: event.clientY }
-  event.preventDefault()
-}
-
-const doDrag = (event: MouseEvent): void => {
-  if (!isDragging.value) return
-
-  const deltaX = event.clientX - lastDragPos.value.x
-  const deltaY = event.clientY - lastDragPos.value.y
-
-  dragOffset.value.x += deltaX
-  dragOffset.value.y += deltaY
-
-  // 限制拖拽范围
-  constrainDragOffset()
-
-  lastDragPos.value = { x: event.clientX, y: event.clientY }
-}
-
-const stopDrag = (): void => {
-  isDragging.value = false
-}
-
-// 鼠标滚轮缩放
-const handleWheel = (event: WheelEvent): void => {
-  if (!currentFile.value || !isImage(currentFile.value)) return
-
-  event.preventDefault()
-  if (event.deltaY < 0) {
-    zoomIn()
-  } else {
-    zoomOut()
-  }
-}
-
-// 编辑功能
 const toggleEditMode = async (): Promise<void> => {
   if (isEditing.value) {
-    // 保存修改
     await saveTextEdit()
     isEditing.value = false
   } else {
     isEditing.value = true
-    // 在下一个tick中调整textarea高度
-    await nextTick()
-    autoResizeAllTextareas()
   }
 }
 
-// 自动调整所有textarea高度
-const autoResizeAllTextareas = (): void => {
-  textareas.value.forEach(textarea => {
-    autoResizeTextarea({ target: textarea })
-  })
-}
-
-// 自动调整textarea高度
-const autoResizeTextarea = (event: { target: EventTarget | null }): void => {
-  const textarea = event.target as HTMLTextAreaElement
-  if (!textarea) return
-
-  // 重置高度以获取正确的scrollHeight
-  textarea.style.height = 'auto'
-  // 设置新高度,但限制最大高度
-  const newHeight = Math.min(textarea.scrollHeight, 300) // 最大300px
-  textarea.style.height = `${newHeight}px`
-}
-
 const saveTextEdit = async (): Promise<void> => {
   if (!ocrResult.value || !currentFile.value) return
 
@@ -485,7 +112,6 @@ const saveTextEdit = async (): Promise<void> => {
       textBlocks: ocrResult.value.textBlocks
     })
 
-    // 标记为已校对
     ocrResult.value.manuallyCorrected = true
     console.log('文本修改已保存')
   } catch (error) {
@@ -494,6 +120,12 @@ const saveTextEdit = async (): Promise<void> => {
   }
 }
 
+const updateBlockContent = (index: number, content: string): void => {
+  if (ocrResult.value) {
+    ocrResult.value.textBlocks[index].content = content
+  }
+}
+
 const removeBlock = (index: number): void => {
   if (ocrResult.value) {
     ocrResult.value.textBlocks.splice(index, 1)
@@ -506,11 +138,6 @@ const addBlockAfter = (index: number): void => {
       type: 'text',
       content: '请输入文本...'
     })
-
-    // 在下一个tick中调整新textarea的高度
-    nextTick(() => {
-      autoResizeAllTextareas()
-    })
   }
 }
 
@@ -520,15 +147,6 @@ const addNewBlock = (): void => {
       type: 'text',
       content: '请输入文本...'
     })
-
-    // 在下一个tick中调整新textarea的高度
-    nextTick(() => {
-      autoResizeAllTextareas()
-      // 滚动到底部
-      if (resultContainer.value) {
-        resultContainer.value.scrollTop = resultContainer.value.scrollHeight
-      }
-    })
   }
 }
 
@@ -538,43 +156,45 @@ const startOcr = async (): Promise<void> => {
     return
   }
 
-  if (!isImage(currentFile.value)) {
+  if (!currentFile.value.mimeType.startsWith('image/')) {
     alert('目前仅支持图片文件的OCR识别')
     return
   }
 
   isProcessing.value = true
   processingTime.value = 0
+  showProcessedImage.value = true
 
-  // 开始计时
   processingInterval = window.setInterval(() => {
     processingTime.value++
   }, 1000)
 
   try {
-    const result = await apiManager.post<{
-      success: boolean
-      data: OcrResult
-    }>('/api/ocr/recognize', {
-      fileId: currentFile.value.id
+    const config: Partial<OcrConfig> = {
+      language: 'chi_sim+eng',
+      psm: 6,
+      debug: true // 启用调试模式以获取预处理图片
+    }
+
+    const result = await apiManager.post<ApiResponse<OcrResult>>('/api/ocr/recognize', {
+      fileId: currentFile.value.id,
+      config
     })
 
     if (result.success && result.data) {
       ocrResult.value = result.data
-      // 保存识别结果到数据库
       await saveOcrResult(currentFile.value.id, result.data)
-      // 更新文件的OCR状态
+
+      // 获取预处理后的图片
+      if (result.data.processedImageUrl) {
+        processedImageUrl.value = result.data.processedImageUrl
+      }
+
       if (currentFile.value) {
         currentFile.value.hasOcrResult = true
       }
-
-      // 识别成功后重置图片位置,确保在可视区域内
-      resetZoom()
-      nextTick(() => {
-        centerImage()
-      })
     } else {
-      throw new Error('OCR识别失败')
+      throw new Error(result.error || 'OCR识别失败')
     }
   } catch (error) {
     console.error('OCR识别失败:', error)
@@ -588,7 +208,6 @@ const startOcr = async (): Promise<void> => {
   }
 }
 
-// 保存OCR结果到数据库
 const saveOcrResult = async (fileId: number, ocrData: OcrResult): Promise<void> => {
   try {
     await apiManager.post('/api/ocr/save-result', {
@@ -602,14 +221,9 @@ const saveOcrResult = async (fileId: number, ocrData: OcrResult): Promise<void>
   }
 }
 
-// 加载已有的OCR结果
 const loadExistingOcrResult = async (fileId: number): Promise<void> => {
   try {
-    const result = await apiManager.get<{
-      success: boolean
-      data: OcrResult
-    }>(`/api/ocr/result/${fileId}`)
-
+    const result = await apiManager.get<ApiResponse<OcrResult>>(`/api/ocr/result/${fileId}`)
     if (result.success && result.data) {
       ocrResult.value = result.data
       console.log('已加载历史识别结果')
@@ -632,7 +246,6 @@ const copyResult = async (): Promise<void> => {
     alert('文本已复制到剪贴板')
   } catch (error) {
     console.error('复制失败:', error)
-    // 降级方案
     const textArea = document.createElement('textarea')
     textArea.value = text
     document.body.appendChild(textArea)
@@ -674,29 +287,13 @@ const exportResult = (): void => {
   URL.revokeObjectURL(url)
 }
 
-const searchReference = (reference: string): void => {
-  const searchUrl = `https://scholar.google.com/scholar?q=${encodeURIComponent(reference)}`
-  window.open(searchUrl, '_blank')
-}
-
 const goBack = (): void => {
   router.back()
 }
 
-const handleImageError = (event: Event): void => {
-  const img = event.target as HTMLImageElement
-  img.style.display = 'none'
-}
-
-const handlePreviewError = (event: Event): void => {
-  console.error('图片预览加载失败')
-  // 可以在这里添加错误处理逻辑,比如显示默认图片
-}
-
-// 检查文件是否有OCR结果
 const checkOcrStatus = async (file: FileRecord): Promise<boolean> => {
   try {
-    const result = await apiManager.get<{ success: boolean; data: any }>(
+    const result = await apiManager.get<ApiResponse<any>>(
         `/api/ocr/result/${file.id}`
     )
     return result.success && result.data !== null
@@ -705,35 +302,26 @@ const checkOcrStatus = async (file: FileRecord): Promise<boolean> => {
   }
 }
 
-// 初始化
 onMounted(async () => {
   try {
-    // 获取所有文件列表
     const response = await apiManager.get<ApiResponse<FileRecord[]>>('/api/files')
-
     if (response.success && response.data) {
-      // 检查每个文件的OCR状态
       const filesWithOcrStatus = await Promise.all(
           response.data.map(async (file) => {
             const hasOcrResult = await checkOcrStatus(file)
             return { ...file, hasOcrResult }
           })
       )
-
       files.value = filesWithOcrStatus
-      console.log('成功获取文件列表,文件数量:', files.value.length)
     } else {
-      console.error('获取文件列表失败:', response.error)
       files.value = []
     }
 
-    // 如果URL中有fileId参数,自动选择该文件
     const fileId = route.query.fileId as string
     if (fileId && files.value.length > 0) {
       const file = files.value.find(f => f.id.toString() === fileId)
       if (file) {
         await selectFile(file)
-        console.log('自动选择文件:', file.originalName)
       }
     }
   } catch (error) {
@@ -755,7 +343,7 @@ onUnmounted(() => {
   display: flex;
   flex-direction: column;
   background: #f8f9fa;
-  overflow: hidden; /* 容器不滚动 */
+  overflow: hidden;
 }
 
 .ocr-header {
@@ -765,7 +353,7 @@ onUnmounted(() => {
   display: flex;
   justify-content: space-between;
   align-items: center;
-  flex-shrink: 0; /* 防止头部被压缩 */
+  flex-shrink: 0;
 }
 
 .back-btn {
@@ -829,489 +417,45 @@ onUnmounted(() => {
   background: #5a6268;
 }
 
-.btn-sm {
-  padding: 0.25rem 0.5rem;
-  font-size: 0.75rem;
-}
-
 .ocr-content {
   flex: 1;
   display: grid;
-  grid-template-columns: 300px 1fr 400px;
+  grid-template-columns: 1fr 1fr 1fr 1fr;
   gap: 1px;
   background: #e9ecef;
   overflow: hidden;
-  min-height: 0; /* 重要:允许内容缩小 */
-}
-
-.file-panel,
-.detail-panel,
-.result-panel {
-  background: white;
-  display: flex;
-  flex-direction: column;
-  min-height: 0; /* 重要:允许内容缩小 */
-}
-
-.panel-header {
-  padding: 1rem;
-  border-bottom: 1px solid #e9ecef;
-  display: flex;
-  justify-content: space-between;
-  align-items: center;
-  flex-shrink: 0; /* 防止头部被压缩 */
-}
-
-.panel-header h3 {
-  margin: 0;
-  font-size: 1rem;
-}
-
-.file-count {
-  font-size: 0.875rem;
-  color: #6c757d;
-}
-
-/* 预览控制按钮 */
-.preview-controls {
-  display: flex;
-  align-items: center;
-  gap: 0.5rem;
-}
-
-.zoom-btn, .reset-btn {
-  background: #6c757d;
-  color: white;
-  border: none;
-  width: 30px;
-  height: 30px;
-  border-radius: 4px;
-  cursor: pointer;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  transition: background-color 0.2s;
-}
-
-.zoom-btn:hover, .reset-btn:hover {
-  background: #5a6268;
-}
-
-.zoom-level {
-  font-size: 0.875rem;
-  min-width: 40px;
-  text-align: center;
-}
-
-/* 修复图片预览容器 */
-.file-preview-container {
-  flex: 1;
-  overflow: hidden; /* 防止内部溢出 */
-  display: flex;
-  flex-direction: column;
-  min-height: 0; /* 重要:允许内容缩小 */
-}
-
-.file-preview {
-  flex: 1;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  padding: 1rem;
-  background: #f8f9fa;
-  overflow: hidden; /* 防止拖拽时出现滚动条 */
-  cursor: grab;
-  position: relative;
-  min-height: 0; /* 重要:允许内容缩小 */
-}
-
-.file-preview:active {
-  cursor: grabbing;
-}
-
-.preview-content {
-  width: 100%;
-  height: 100%;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  position: relative;
-}
-
-.image-wrapper {
-  width: 100%;
-  height: 100%;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  overflow: hidden;
-  position: relative;
-}
-
-.preview-image {
-  max-width: 100%;
-  max-height: 100%;
-  object-fit: contain;
-  border: 1px solid #e9ecef;
-  border-radius: 4px;
-  transition: transform 0.1s ease;
-  transform-origin: center center;
-  position: relative;
-}
-
-.file-list {
-  flex: 1;
-  overflow-y: auto;
-  min-height: 0; /* 重要:允许内容缩小 */
-}
-
-.file-item {
-  display: flex;
-  align-items: center;
-  padding: 0.75rem;
-  cursor: pointer;
-  border-bottom: 1px solid #f8f9fa;
-  transition: background-color 0.2s;
-}
-
-.file-item:hover {
-  background: #f8f9fa;
-}
-
-.file-item.active {
-  background: #e3f2fd;
-  border-left: 3px solid #2196f3;
-}
-
-.file-icon {
-  width: 40px;
-  height: 40px;
-  margin-right: 0.75rem;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  flex-shrink: 0;
-}
-
-.file-thumbnail {
-  width: 100%;
-  height: 100%;
-  object-fit: cover;
-  border-radius: 4px;
-}
-
-.file-type-icon {
-  font-size: 1.5rem;
-}
-
-.file-pdf { color: #f44336; }
-.file-word { color: #2196f3; }
-.file-excel { color: #4caf50; }
-.file-ppt { color: #ff9800; }
-.file-other { color: #9e9e9e; }
-
-.file-info {
-  flex: 1;
-  min-width: 0;
-}
-
-.file-name {
-  font-weight: 500;
-  white-space: nowrap;
-  overflow: hidden;
-  text-overflow: ellipsis;
-}
-
-.file-meta {
-  font-size: 0.75rem;
-  color: #6c757d;
-}
-
-.ocr-indicator {
-  font-size: 0.7rem;
-  color: #28a745;
-  font-weight: bold;
-  margin-top: 0.25rem;
-}
-
-.file-type-large {
-  font-size: 4rem;
-  margin-bottom: 1rem;
-}
-
-.unsupported-preview,
-.no-file-selected {
-  text-align: center;
-  color: #6c757d;
-}
-
-.file-format {
-  font-size: 0.875rem;
-  margin-top: 0.5rem;
-}
-
-.hint {
-  font-size: 0.875rem;
-  margin-top: 0.5rem;
-  color: #6c757d;
-}
-
-/* 修复识别结果滚动问题 */
-.ocr-result {
-  flex: 1;
-  display: flex;
-  flex-direction: column;
-  min-height: 0; /* 重要:允许内容缩小 */
-  overflow: hidden; /* 外层隐藏滚动 */
-}
-
-.result-content {
-  flex: 1;
-  overflow-y: auto; /* 内容区域滚动 */
-  padding: 0 1rem 1rem 1rem;
-  min-height: 0; /* 重要:允许内容缩小 */
-}
-
-.processing {
-  text-align: center;
-  padding: 2rem;
-  color: #6c757d;
-  flex: 1;
-  display: flex;
-  flex-direction: column;
-  justify-content: center;
-  align-items: center;
-}
-
-.spinner {
-  border: 3px solid #f3f3f3;
-  border-top: 3px solid #007bff;
-  border-radius: 50%;
-  width: 40px;
-  height: 40px;
-  animation: spin 1s linear infinite;
-  margin: 0 auto 1rem;
-}
-
-@keyframes spin {
-  0% { transform: rotate(0deg); }
-  100% { transform: rotate(360deg); }
-}
-
-.processing-time {
-  font-size: 0.875rem;
-  margin-top: 0.5rem;
-}
-
-.text-block {
-  margin-bottom: 1rem;
-  padding: 0.5rem;
-  border-radius: 4px;
-  transition: background-color 0.2s;
-}
-
-.text-block:hover {
-  background-color: #f8f9fa;
-}
-
-.text-content {
-  white-space: pre-wrap;
-  word-wrap: break-word;
-}
-
-/* 可编辑文本 - 修复滚动问题 */
-.editable-text {
-  width: 100%;
-  min-height: 60px;
-  max-height: 300px; /* 限制最大高度 */
-  padding: 0.5rem;
-  border: 1px solid #007bff;
-  border-radius: 4px;
-  font-family: inherit;
-  font-size: inherit;
-  resize: vertical;
-  transition: border-color 0.2s;
-  overflow-y: auto; /* 确保可以滚动 */
+  min-height: 0;
 }
 
-.editable-text:focus {
-  outline: none;
-  border-color: #0056b3;
-}
-
-.static-text {
-  white-space: pre-wrap;
-  word-wrap: break-word;
-}
-
-.image-block {
-  text-align: center;
-  margin: 1rem 0;
-  padding: 0.5rem;
-  background: #f8f9fa;
-  border-radius: 4px;
-}
-
-.image-caption {
-  font-size: 0.875rem;
-  color: #6c757d;
-}
-
-.reference-block {
-  background: #fff3cd;
-  border: 1px solid #ffeaa7;
-  border-radius: 4px;
-  padding: 1rem;
-  margin: 1rem 0;
-}
-
-.reference-title {
-  font-weight: bold;
-  margin-bottom: 0.5rem;
-  color: #856404;
-}
-
-.search-btn {
-  background: #856404;
-  color: white;
-  border: none;
-  padding: 0.25rem 0.5rem;
-  border-radius: 4px;
-  font-size: 0.75rem;
-  cursor: pointer;
-  margin-top: 0.5rem;
-  transition: background-color 0.2s;
-}
-
-.search-btn:hover {
-  background: #6c4d03;
-}
-
-.citation-block {
-  background: #e7f3ff;
-  border-left: 3px solid #2196f3;
-  padding: 0.5rem;
-  margin: 0.5rem 0;
-}
-
-.citation-marker {
-  font-weight: bold;
-  color: #2196f3;
-  margin-right: 0.5rem;
-}
-
-/* 文本块操作 */
-.block-actions {
-  display: flex;
-  gap: 0.5rem;
-  margin-top: 0.5rem;
-}
-
-.btn-delete {
-  background: #dc3545;
-  color: white;
-  border: none;
-  padding: 0.25rem 0.5rem;
-  border-radius: 3px;
-  font-size: 0.75rem;
-  cursor: pointer;
-  transition: background-color 0.2s;
-}
-
-.btn-delete:hover {
-  background: #c82333;
-}
-
-.btn-add {
-  background: #28a745;
-  color: white;
-  border: none;
-  padding: 0.25rem 0.5rem;
-  border-radius: 3px;
-  font-size: 0.75rem;
-  cursor: pointer;
-  transition: background-color 0.2s;
-}
-
-.btn-add:hover {
-  background: #218838;
-}
-
-/* 添加文本块区域 */
-.add-block-section {
-  margin: 1rem 0;
-  text-align: center;
-}
-
-.btn-add-block {
-  background: #17a2b8;
-  color: white;
-  border: none;
-  padding: 0.5rem 1rem;
-  border-radius: 4px;
-  cursor: pointer;
-  transition: background-color 0.2s;
-}
-
-.btn-add-block:hover {
-  background: #138496;
-}
-
-.no-result {
-  text-align: center;
-  padding: 2rem;
-  color: #6c757d;
-  flex: 1;
-  display: flex;
-  flex-direction: column;
-  justify-content: center;
-  align-items: center;
-}
-
-.result-summary {
-  margin-top: 2rem;
-  padding-top: 1rem;
-  border-top: 1px solid #e9ecef;
-  font-size: 0.875rem;
-  color: #6c757d;
-}
+@media (max-width: 1400px) {
+  .ocr-content {
+    grid-template-columns: 1fr 1fr;
+    grid-template-rows: 1fr 1fr;
+  }
 
-.confidence {
-  font-size: 0.75rem;
-  color: #28a745;
-  font-weight: bold;
-}
+  .file-panel {
+    grid-column: 1;
+  }
 
-/* 校对标记 */
-.corrected-badge {
-  background: #28a745;
-  color: white;
-  padding: 0.1rem 0.4rem;
-  border-radius: 10px;
-  font-size: 0.7rem;
-  margin-left: 0.5rem;
-}
+  .image-panel:first-of-type {
+    grid-column: 2;
+  }
 
-.corrected-info {
-  color: #28a745;
-  font-weight: bold;
-}
+  .image-panel:last-of-type {
+    grid-column: 1;
+    grid-row: 2;
+  }
 
-/* 响应式设计 */
-@media (max-width: 1200px) {
-  .ocr-content {
-    grid-template-columns: 250px 1fr 350px;
+  .result-panel {
+    grid-column: 2;
+    grid-row: 2;
   }
 }
 
 @media (max-width: 768px) {
   .ocr-content {
     grid-template-columns: 1fr;
-    grid-template-rows: 200px 1fr 400px;
-  }
-
-  .file-panel, .detail-panel, .result-panel {
-    min-height: 0;
+    grid-template-rows: 1fr 1fr 1fr 1fr;
   }
 
   .header-actions {

+ 223 - 0
src/renderer/components/ocr/FilePanel.vue

@@ -0,0 +1,223 @@
+<template>
+  <div class="file-panel">
+    <div class="panel-header">
+      <h3>源文件</h3>
+      <span class="file-count">共 {{ files.length }} 个文件</span>
+    </div>
+    <div class="file-list">
+      <div
+          v-for="file in files"
+          :key="file.id"
+          class="file-item"
+          :class="{ active: currentFile?.id === file.id }"
+          @click="$emit('file-selected', file)"
+      >
+        <div class="file-icon">
+          <img
+              v-if="isImage(file)"
+              :src="getFileThumbnail(file)"
+              :alt="file.originalName"
+              class="file-thumbnail"
+              @error="handleImageError"
+          />
+          <div v-else class="file-type-icon" :class="getFileTypeClass(file)">
+            {{ getFileTypeIcon(file) }}
+          </div>
+        </div>
+        <div class="file-info">
+          <div class="file-name" :title="file.originalName">
+            {{ file.originalName }}
+          </div>
+          <div class="file-meta">
+            {{ formatFileSize(file.fileSize) }}
+          </div>
+          <div v-if="file.hasOcrResult" class="ocr-indicator">
+            ✓ 已识别
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { FileRecord } from '../../types/ocr'
+import apiManager from '../../utils/apiManager'
+
+defineProps<{
+  files: FileRecord[]
+  currentFile: FileRecord | null
+}>()
+
+defineEmits<{
+  'file-selected': [file: FileRecord]
+}>()
+
+const isImage = (file: FileRecord): boolean => {
+  return file.mimeType.startsWith('image/')
+}
+
+const getFileTypeClass = (file: FileRecord): string => {
+  if (file.mimeType.includes('pdf')) return 'file-pdf'
+  if (file.mimeType.includes('word') || file.mimeType.includes('document')) return 'file-word'
+  if (file.mimeType.includes('excel') || file.mimeType.includes('spreadsheet')) return 'file-excel'
+  if (file.mimeType.includes('powerpoint') || file.mimeType.includes('presentation')) return 'file-ppt'
+  return 'file-other'
+}
+
+const getFileTypeIcon = (file: FileRecord): string => {
+  if (file.mimeType.includes('pdf')) return '📄'
+  if (file.mimeType.includes('word') || file.mimeType.includes('document')) return '📝'
+  if (file.mimeType.includes('excel') || file.mimeType.includes('spreadsheet')) return '📊'
+  if (file.mimeType.includes('powerpoint') || file.mimeType.includes('presentation')) return '📑'
+  return '📎'
+}
+
+const getFileThumbnail = (file: FileRecord): string => {
+  return apiManager.buildUrl(`/api/files/${file.id}/thumbnail`)
+}
+
+const formatFileSize = (bytes: number): string => {
+  const units = ['B', 'KB', 'MB', 'GB']
+  let size = bytes
+  let unitIndex = 0
+  while (size >= 1024 && unitIndex < units.length - 1) {
+    size /= 1024
+    unitIndex++
+  }
+  return `${size.toFixed(1)} ${units[unitIndex]}`
+}
+
+const handleImageError = (event: Event): void => {
+  const img = event.target as HTMLImageElement
+  img.style.display = 'none'
+}
+</script>
+
+<style scoped>
+.file-panel {
+  background: white;
+  display: flex;
+  flex-direction: column;
+  min-height: 0;
+}
+
+.panel-header {
+  padding: 1rem;
+  border-bottom: 1px solid #e9ecef;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  flex-shrink: 0;
+}
+
+.panel-header h3 {
+  margin: 0;
+  font-size: 1rem;
+}
+
+.file-count {
+  font-size: 0.875rem;
+  color: #6c757d;
+}
+
+.file-list {
+  flex: 1;
+  overflow-y: auto;
+  padding: 0.5rem;
+}
+
+.file-item {
+  display: flex;
+  align-items: center;
+  padding: 0.75rem;
+  border-radius: 6px;
+  cursor: pointer;
+  transition: background-color 0.2s;
+  margin-bottom: 0.5rem;
+}
+
+.file-item:hover {
+  background-color: #f8f9fa;
+}
+
+.file-item.active {
+  background-color: #e7f3ff;
+  border: 1px solid #2196f3;
+}
+
+.file-icon {
+  margin-right: 0.75rem;
+  flex-shrink: 0;
+}
+
+.file-thumbnail {
+  width: 40px;
+  height: 40px;
+  object-fit: cover;
+  border-radius: 4px;
+}
+
+.file-type-icon {
+  width: 40px;
+  height: 40px;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  border-radius: 4px;
+  font-size: 1.25rem;
+}
+
+.file-pdf {
+  background: #ffebee;
+  color: #f44336;
+}
+
+.file-word {
+  background: #e3f2fd;
+  color: #2196f3;
+}
+
+.file-excel {
+  background: #e8f5e8;
+  color: #4caf50;
+}
+
+.file-ppt {
+  background: #fce4ec;
+  color: #e91e63;
+}
+
+.file-other {
+  background: #f5f5f5;
+  color: #757575;
+}
+
+.file-info {
+  flex: 1;
+  min-width: 0;
+}
+
+.file-name {
+  font-weight: 500;
+  margin-bottom: 0.25rem;
+  white-space: nowrap;
+  overflow: hidden;
+  text-overflow: ellipsis;
+}
+
+.file-meta {
+  font-size: 0.75rem;
+  color: #6c757d;
+}
+
+.ocr-indicator {
+  font-size: 0.7rem;
+  color: #28a745;
+  background: #e8f5e8;
+  padding: 0.1rem 0.4rem;
+  border-radius: 10px;
+  margin-top: 0.25rem;
+  display: inline-block;
+}
+</style>

+ 303 - 0
src/renderer/components/ocr/ImagePanel.vue

@@ -0,0 +1,303 @@
+<template>
+  <div class="image-panel">
+    <div class="panel-header">
+      <h3>{{ title }}</h3>
+      <div class="preview-controls" v-if="currentFile && isImage(currentFile) && imageUrl">
+        <button @click="zoomOut" class="zoom-btn">−</button>
+        <span class="zoom-level">{{ (zoomLevel * 100).toFixed(0) }}%</span>
+        <button @click="zoomIn" class="zoom-btn">+</button>
+        <button @click="resetZoom" class="reset-btn">重置</button>
+      </div>
+    </div>
+    <div class="image-preview-container" ref="previewContainer">
+      <div class="image-preview"
+           @mousedown="startDrag($event)"
+           @mousemove="doDrag($event)"
+           @mouseup="stopDrag"
+           @mouseleave="stopDrag"
+           @wheel="handleWheel($event)">
+        <div v-if="currentFile && isImage(currentFile) && imageUrl" class="preview-content">
+          <div class="image-wrapper" ref="imageWrapper">
+            <img
+                :src="imageUrl"
+                :alt="currentFile.originalName"
+                class="preview-image"
+                :style="{
+                transform: `scale(${zoomLevel}) translate(${dragOffset.x}px, ${dragOffset.y}px)`,
+                cursor: isDragging ? 'grabbing' : 'grab'
+              }"
+                @load="handleImageLoad"
+                @error="handlePreviewError"
+                ref="previewImage"
+            />
+          </div>
+        </div>
+        <div v-else-if="showProcessing" class="processing-indicator">
+          <div class="spinner"></div>
+          <p>预处理图片生成中...</p>
+        </div>
+        <div v-else class="no-image">
+          <p>{{ title === '预处理后预览' ? '识别后显示预处理图片' : '请选择图片文件' }}</p>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, nextTick, computed } from 'vue'
+import { FileRecord } from '../../types/ocr'
+
+interface Props {
+  currentFile: FileRecord | null
+  imageUrl?: string
+  title?: string
+  showProcessing?: boolean
+}
+
+const props = withDefaults(defineProps<Props>(), {
+  title: '图片预览',
+  showProcessing: false
+})
+
+const zoomLevel = ref(1)
+const dragOffset = ref({ x: 0, y: 0 })
+const isDragging = ref(false)
+const lastDragPos = ref({ x: 0, y: 0 })
+const previewImage = ref<HTMLImageElement | null>(null)
+const imageWrapper = ref<HTMLElement | null>(null)
+
+const isImage = computed(() => (file: FileRecord): boolean => {
+  return file.mimeType.startsWith('image/')
+})
+
+const handleImageLoad = (): void => {
+  nextTick(() => {
+    resetZoom()
+    centerImage()
+  })
+}
+
+const centerImage = (): void => {
+  if (!previewImage.value || !imageWrapper.value) return
+
+  const container = imageWrapper.value
+  const img = previewImage.value
+
+  const containerRect = container.getBoundingClientRect()
+  const imgRect = img.getBoundingClientRect()
+
+  if (imgRect.width < containerRect.width && imgRect.height < containerRect.height) {
+    dragOffset.value = { x: 0, y: 0 }
+  }
+}
+
+const zoomIn = (): void => {
+  zoomLevel.value = Math.min(zoomLevel.value + 0.1, 3)
+  constrainDragOffset()
+}
+
+const zoomOut = (): void => {
+  zoomLevel.value = Math.max(zoomLevel.value - 0.1, 0.5)
+  constrainDragOffset()
+}
+
+const resetZoom = (): void => {
+  zoomLevel.value = 1
+  dragOffset.value = { x: 0, y: 0 }
+}
+
+const constrainDragOffset = (): void => {
+  if (!previewImage.value || !imageWrapper.value) return
+
+  const container = imageWrapper.value
+  const img = previewImage.value
+
+  const containerRect = container.getBoundingClientRect()
+  const imgRect = {
+    width: img.naturalWidth * zoomLevel.value,
+    height: img.naturalHeight * zoomLevel.value
+  }
+
+  const maxX = Math.max(0, (imgRect.width - containerRect.width) / 2)
+  const maxY = Math.max(0, (imgRect.height - containerRect.height) / 2)
+
+  dragOffset.value.x = Math.max(-maxX, Math.min(maxX, dragOffset.value.x))
+  dragOffset.value.y = Math.max(-maxY, Math.min(maxY, dragOffset.value.y))
+}
+
+const startDrag = (event: MouseEvent): void => {
+  if (!props.currentFile || !isImage.value(props.currentFile)) return
+
+  isDragging.value = true
+  lastDragPos.value = { x: event.clientX, y: event.clientY }
+  event.preventDefault()
+}
+
+const doDrag = (event: MouseEvent): void => {
+  if (!isDragging.value) return
+
+  const deltaX = event.clientX - lastDragPos.value.x
+  const deltaY = event.clientY - lastDragPos.value.y
+
+  dragOffset.value.x += deltaX
+  dragOffset.value.y += deltaY
+
+  constrainDragOffset()
+  lastDragPos.value = { x: event.clientX, y: event.clientY }
+}
+
+const stopDrag = (): void => {
+  isDragging.value = false
+}
+
+const handleWheel = (event: WheelEvent): void => {
+  if (!props.currentFile || !isImage.value(props.currentFile)) return
+
+  event.preventDefault()
+  if (event.deltaY < 0) {
+    zoomIn()
+  } else {
+    zoomOut()
+  }
+}
+
+const handlePreviewError = (): void => {
+  console.error('图片加载失败')
+}
+</script>
+
+<style scoped>
+.image-panel {
+  background: white;
+  display: flex;
+  flex-direction: column;
+  min-height: 0;
+}
+
+.panel-header {
+  padding: 1rem;
+  border-bottom: 1px solid #e9ecef;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  flex-shrink: 0;
+}
+
+.panel-header h3 {
+  margin: 0;
+  font-size: 1rem;
+}
+
+.preview-controls {
+  display: flex;
+  align-items: center;
+  gap: 0.5rem;
+}
+
+.zoom-btn, .reset-btn {
+  background: #6c757d;
+  color: white;
+  border: none;
+  width: 30px;
+  height: 30px;
+  border-radius: 4px;
+  cursor: pointer;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  transition: background-color 0.2s;
+}
+
+.zoom-btn:hover, .reset-btn:hover {
+  background: #5a6268;
+}
+
+.zoom-level {
+  font-size: 0.875rem;
+  min-width: 40px;
+  text-align: center;
+}
+
+.image-preview-container {
+  flex: 1;
+  overflow: hidden;
+  display: flex;
+  flex-direction: column;
+  min-height: 0;
+}
+
+.image-preview {
+  flex: 1;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  padding: 1rem;
+  background: #f8f9fa;
+  overflow: hidden;
+  cursor: grab;
+  position: relative;
+  min-height: 0;
+}
+
+.image-preview:active {
+  cursor: grabbing;
+}
+
+.preview-content {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  position: relative;
+}
+
+.image-wrapper {
+  width: 100%;
+  height: 100%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  overflow: hidden;
+  position: relative;
+}
+
+.preview-image {
+  max-width: 100%;
+  max-height: 100%;
+  object-fit: contain;
+  border: 1px solid #e9ecef;
+  border-radius: 4px;
+  transition: transform 0.1s ease;
+  transform-origin: center center;
+  position: relative;
+}
+
+.processing-indicator {
+  text-align: center;
+  color: #6c757d;
+  padding: 2rem;
+}
+
+.processing-indicator .spinner {
+  border: 3px solid #f3f3f3;
+  border-top: 3px solid #007bff;
+  border-radius: 50%;
+  width: 40px;
+  height: 40px;
+  animation: spin 1s linear infinite;
+  margin: 0 auto 1rem;
+}
+
+@keyframes spin {
+  0% { transform: rotate(0deg); }
+  100% { transform: rotate(360deg); }
+}
+
+.no-image {
+  text-align: center;
+  color: #6c757d;
+  padding: 2rem;
+}
+</style>

+ 256 - 0
src/renderer/components/ocr/ResultPanel.vue

@@ -0,0 +1,256 @@
+<template>
+  <div class="result-panel">
+    <div class="panel-header">
+      <h3>识别结果</h3>
+      <div class="result-actions">
+        <button class="btn btn-sm" @click="copyResult" :disabled="!ocrResult">
+          复制文本
+        </button>
+        <div v-if="ocrResult" class="confidence">
+          置信度: {{ (ocrResult.confidence * 100).toFixed(1) }}%
+          <span v-if="ocrResult.manuallyCorrected" class="corrected-badge">已校对</span>
+        </div>
+      </div>
+    </div>
+    <div class="ocr-result" ref="resultContainer">
+      <div v-if="isProcessing" class="processing">
+        <div class="spinner"></div>
+        <p>正在识别中,请稍候...</p>
+        <p class="processing-time">已用时: {{ processingTime }}s</p>
+      </div>
+
+      <div v-else-if="ocrResult" class="result-content">
+        <TextBlock
+            v-for="(block, index) in ocrResult.textBlocks"
+            :key="index"
+            :block="block"
+            :isEditing="isEditing"
+            @update:content="updateBlockContent(index, $event)"
+            @remove="removeBlock(index)"
+            @add-after="addBlockAfter(index)"
+        />
+
+        <div v-if="isEditing" class="add-block-section">
+          <button class="btn-add-block" @click="addNewBlock">
+            + 添加文本块
+          </button>
+        </div>
+
+        <div class="result-summary">
+          <p>识别完成,共 {{ ocrResult.textBlocks.length }} 个文本块</p>
+          <p>处理时间: {{ (ocrResult.processingTime / 1000).toFixed(2) }} 秒</p>
+          <p v-if="ocrResult.manuallyCorrected" class="corrected-info">
+            ✅ 此结果已人工校对
+          </p>
+        </div>
+      </div>
+
+      <div v-else class="no-result">
+        <p>识别结果将显示在这里</p>
+        <p class="hint">支持中英文混合识别,自动识别参考文献和图片标注</p>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, nextTick } from 'vue'
+import { OcrResult, OcrTextBlock } from '../../types/ocr'
+import TextBlock from './TextBlock.vue'
+
+defineProps<{
+  isProcessing: boolean
+  processingTime: number
+  ocrResult: OcrResult | null
+  isEditing: boolean
+}>()
+
+const emit = defineEmits<{
+  'update:ocrResult': [result: OcrResult]
+  'copy-result': []
+  'update-block': [index: number, content: string]
+  'remove-block': [index: number]
+  'add-block-after': [index: number]
+  'add-new-block': []
+}>()
+
+const resultContainer = ref<HTMLElement | null>(null)
+
+const copyResult = (): void => {
+  emit('copy-result')
+}
+
+const updateBlockContent = (index: number, content: string): void => {
+  emit('update-block', index, content)
+}
+
+const removeBlock = (index: number): void => {
+  emit('remove-block', index)
+}
+
+const addBlockAfter = (index: number): void => {
+  emit('add-block-after', index)
+}
+
+const addNewBlock = (): void => {
+  emit('add-new-block')
+}
+</script>
+
+<style scoped>
+.result-panel {
+  background: white;
+  display: flex;
+  flex-direction: column;
+  min-height: 0;
+}
+
+.panel-header {
+  padding: 1rem;
+  border-bottom: 1px solid #e9ecef;
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  flex-shrink: 0;
+}
+
+.panel-header h3 {
+  margin: 0;
+  font-size: 1rem;
+}
+
+.result-actions {
+  display: flex;
+  align-items: center;
+  gap: 1rem;
+}
+
+.btn {
+  padding: 0.5rem 1rem;
+  border: none;
+  border-radius: 4px;
+  cursor: pointer;
+  font-size: 0.875rem;
+  transition: background-color 0.2s;
+}
+
+.btn:disabled {
+  opacity: 0.6;
+  cursor: not-allowed;
+}
+
+.btn-sm {
+  padding: 0.25rem 0.5rem;
+  font-size: 0.75rem;
+}
+
+.confidence {
+  font-size: 0.75rem;
+  color: #28a745;
+  font-weight: bold;
+}
+
+.corrected-badge {
+  background: #28a745;
+  color: white;
+  padding: 0.1rem 0.4rem;
+  border-radius: 10px;
+  font-size: 0.7rem;
+  margin-left: 0.5rem;
+}
+
+.ocr-result {
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  min-height: 0;
+  overflow: hidden;
+}
+
+.result-content {
+  flex: 1;
+  overflow-y: auto;
+  padding: 0 1rem 1rem 1rem;
+  min-height: 0;
+}
+
+.processing {
+  text-align: center;
+  padding: 2rem;
+  color: #6c757d;
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+}
+
+.spinner {
+  border: 3px solid #f3f3f3;
+  border-top: 3px solid #007bff;
+  border-radius: 50%;
+  width: 40px;
+  height: 40px;
+  animation: spin 1s linear infinite;
+  margin: 0 auto 1rem;
+}
+
+@keyframes spin {
+  0% { transform: rotate(0deg); }
+  100% { transform: rotate(360deg); }
+}
+
+.processing-time {
+  font-size: 0.875rem;
+  margin-top: 0.5rem;
+}
+
+.add-block-section {
+  margin: 1rem 0;
+  text-align: center;
+}
+
+.btn-add-block {
+  background: #17a2b8;
+  color: white;
+  border: none;
+  padding: 0.5rem 1rem;
+  border-radius: 4px;
+  cursor: pointer;
+  transition: background-color 0.2s;
+}
+
+.btn-add-block:hover {
+  background: #138496;
+}
+
+.no-result {
+  text-align: center;
+  padding: 2rem;
+  color: #6c757d;
+  flex: 1;
+  display: flex;
+  flex-direction: column;
+  justify-content: center;
+  align-items: center;
+}
+
+.result-summary {
+  margin-top: 2rem;
+  padding-top: 1rem;
+  border-top: 1px solid #e9ecef;
+  font-size: 0.875rem;
+  color: #6c757d;
+}
+
+.corrected-info {
+  color: #28a745;
+  font-weight: bold;
+}
+
+.hint {
+  font-size: 0.875rem;
+  margin-top: 0.5rem;
+  color: #6c757d;
+}
+</style>

+ 215 - 0
src/renderer/components/ocr/TextBlock.vue

@@ -0,0 +1,215 @@
+<template>
+  <div class="text-block" :class="block.type">
+    <div v-if="block.type === 'text'" class="text-content">
+      <textarea
+          v-if="isEditing"
+          :value="block.content"
+          @input="handleInput($event)"
+          class="editable-text"
+          @blur="$emit('update:content', block.content)"
+          ref="textarea"
+      ></textarea>
+      <div v-else class="static-text">
+        {{ block.content }}
+      </div>
+    </div>
+
+    <div v-else-if="block.type === 'image'" class="image-block">
+      <div class="image-caption">{{ block.content }}</div>
+    </div>
+
+    <div v-else-if="block.type === 'reference'" class="reference-block">
+      <div class="reference-title">📚 参考文献</div>
+      <div class="reference-content">
+        <textarea
+            v-if="isEditing"
+            :value="block.content"
+            @input="handleInput($event)"
+            class="editable-text"
+            @blur="$emit('update:content', block.content)"
+            ref="textarea"
+        ></textarea>
+        <span v-else>{{ block.content }}</span>
+      </div>
+    </div>
+
+    <div v-else-if="block.type === 'citation'" class="citation-block">
+      <div class="citation-content">
+        <span class="citation-marker">[{{ block.number }}]</span>
+        <textarea
+            v-if="isEditing"
+            :value="block.content"
+            @input="handleInput($event)"
+            class="editable-text"
+            @blur="$emit('update:content', block.content)"
+            ref="textarea"
+        ></textarea>
+        <span v-else>{{ block.content }}</span>
+      </div>
+    </div>
+
+    <div v-if="isEditing" class="block-actions">
+      <button class="btn-delete" @click="$emit('remove')">删除</button>
+      <button class="btn-add" @click="$emit('add-after')">添加</button>
+    </div>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { ref, nextTick, watch } from 'vue'
+import { OcrTextBlock } from '../../types/ocr'
+
+interface Props {
+  block: OcrTextBlock
+  isEditing: boolean
+}
+
+defineProps<Props>()
+
+const emit = defineEmits<{
+  'update:content': [content: string]
+  'remove': []
+  'add-after': []
+}>()
+
+const textarea = ref<HTMLTextAreaElement | null>(null)
+
+const handleInput = (event: Event): void => {
+  const target = event.target as HTMLTextAreaElement
+  emit('update:content', target.value)
+  autoResizeTextarea(target)
+}
+
+const autoResizeTextarea = (textarea: HTMLTextAreaElement): void => {
+  textarea.style.height = 'auto'
+  const newHeight = Math.min(textarea.scrollHeight, 300)
+  textarea.style.height = `${newHeight}px`
+}
+
+// 当编辑模式改变时,调整textarea高度
+watch(() => textarea.value, (newTextarea) => {
+  if (newTextarea) {
+    nextTick(() => {
+      autoResizeTextarea(newTextarea)
+    })
+  }
+})
+</script>
+
+<style scoped>
+.text-block {
+  margin-bottom: 1rem;
+  padding: 0.5rem;
+  border-radius: 4px;
+  transition: background-color 0.2s;
+}
+
+.text-block:hover {
+  background-color: #f8f9fa;
+}
+
+.text-content {
+  white-space: pre-wrap;
+  word-wrap: break-word;
+}
+
+.editable-text {
+  width: 100%;
+  min-height: 60px;
+  max-height: 300px;
+  padding: 0.5rem;
+  border: 1px solid #007bff;
+  border-radius: 4px;
+  font-family: inherit;
+  font-size: inherit;
+  resize: vertical;
+  transition: border-color 0.2s;
+  overflow-y: auto;
+}
+
+.editable-text:focus {
+  outline: none;
+  border-color: #0056b3;
+}
+
+.static-text {
+  white-space: pre-wrap;
+  word-wrap: break-word;
+}
+
+.image-block {
+  text-align: center;
+  margin: 1rem 0;
+  padding: 0.5rem;
+  background: #f8f9fa;
+  border-radius: 4px;
+}
+
+.image-caption {
+  font-size: 0.875rem;
+  color: #6c757d;
+}
+
+.reference-block {
+  background: #fff3cd;
+  border: 1px solid #ffeaa7;
+  border-radius: 4px;
+  padding: 1rem;
+  margin: 1rem 0;
+}
+
+.reference-title {
+  font-weight: bold;
+  margin-bottom: 0.5rem;
+  color: #856404;
+}
+
+.citation-block {
+  background: #e7f3ff;
+  border-left: 3px solid #2196f3;
+  padding: 0.5rem;
+  margin: 0.5rem 0;
+}
+
+.citation-marker {
+  font-weight: bold;
+  color: #2196f3;
+  margin-right: 0.5rem;
+}
+
+.block-actions {
+  display: flex;
+  gap: 0.5rem;
+  margin-top: 0.5rem;
+}
+
+.btn-delete {
+  background: #dc3545;
+  color: white;
+  border: none;
+  padding: 0.25rem 0.5rem;
+  border-radius: 3px;
+  font-size: 0.75rem;
+  cursor: pointer;
+  transition: background-color 0.2s;
+}
+
+.btn-delete:hover {
+  background: #c82333;
+}
+
+.btn-add {
+  background: #28a745;
+  color: white;
+  border: none;
+  padding: 0.25rem 0.5rem;
+  border-radius: 3px;
+  font-size: 0.75rem;
+  cursor: pointer;
+  transition: background-color 0.2s;
+}
+
+.btn-add:hover {
+  background: #218838;
+}
+</style>

+ 60 - 0
src/renderer/types/ocr.ts

@@ -0,0 +1,60 @@
+export interface FileRecord {
+    id: number
+    originalName: string
+    fileName: string
+    filePath: string
+    fileSize: number
+    mimeType: string
+    md5: string
+    createdAt: string
+    updatedAt: string
+    hasOcrResult?: boolean
+}
+
+export interface OcrTextBlock {
+    type: 'text' | 'image' | 'reference' | 'citation'
+    content: string
+    number?: number
+    confidence?: number
+    bbox?: { x: number; y: number; width: number; height: number }
+}
+
+export interface ApiResponse<T> {
+    success: boolean
+    data?: T
+    pagination?: any
+    error?: string
+    message?: string
+}
+
+export interface OcrConfig {
+    language: string;
+    preprocessing: {
+        enable: boolean;
+        denoise: boolean;
+        sharpen: boolean;
+        binarize: boolean;
+        deskew: boolean;
+        enhance_contrast: boolean;
+    };
+    detLimitSideLen?: number;
+    detThresh?: number;
+    detBoxThresh?: number;
+}
+
+export interface OcrResult {
+    textBlocks: OcrTextBlock[];
+    confidence: number;
+    processingTime: number;
+    isOffline: boolean;
+    imagePath?: string;
+    totalPages: number;
+    rawText: string;
+    imageInfo?: {
+        width: number;
+        height: number;
+        format: string;
+        processed: boolean;
+    };
+    manuallyCorrected?: boolean;
+}

+ 654 - 2
yarn.lock

@@ -370,6 +370,286 @@
   resolved "https://registry.yarnpkg.com/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz#a81ffb00e69267cd0a1d626eaedb8a8430b2b2f8"
   integrity sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==
 
+"@isaacs/fs-minipass@^4.0.0":
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz#2d59ae3ab4b38fb4270bfa23d30f8e2e86c7fe32"
+  integrity sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==
+  dependencies:
+    minipass "^7.0.4"
+
+"@jimp/core@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/core/-/core-1.6.0.tgz#3ef241bf02f40431bb382aea665e5187a2c05eef"
+  integrity sha512-EQQlKU3s9QfdJqiSrZWNTxBs3rKXgO2W+GxNXDtwchF3a4IqxDheFX1ti+Env9hdJXDiYLp2jTRjlxhPthsk8w==
+  dependencies:
+    "@jimp/file-ops" "1.6.0"
+    "@jimp/types" "1.6.0"
+    "@jimp/utils" "1.6.0"
+    await-to-js "^3.0.0"
+    exif-parser "^0.1.12"
+    file-type "^16.0.0"
+    mime "3"
+
+"@jimp/diff@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/diff/-/diff-1.6.0.tgz#f8d058bfad64751c5e5c135499d1a784f797c5c8"
+  integrity sha512-+yUAQ5gvRC5D1WHYxjBHZI7JBRusGGSLf8AmPRPCenTzh4PA+wZ1xv2+cYqQwTfQHU5tXYOhA0xDytfHUf1Zyw==
+  dependencies:
+    "@jimp/plugin-resize" "1.6.0"
+    "@jimp/types" "1.6.0"
+    "@jimp/utils" "1.6.0"
+    pixelmatch "^5.3.0"
+
+"@jimp/file-ops@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/file-ops/-/file-ops-1.6.0.tgz#ae9c6aa65b2c9a5a16515a8fdf83b55f51100087"
+  integrity sha512-Dx/bVDmgnRe1AlniRpCKrGRm5YvGmUwbDzt+MAkgmLGf+jvBT75hmMEZ003n9HQI/aPnm/YKnXjg/hOpzNCpHQ==
+
+"@jimp/js-bmp@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/js-bmp/-/js-bmp-1.6.0.tgz#ff7c4306e764745063e249ee926d0dd807924abf"
+  integrity sha512-FU6Q5PC/e3yzLyBDXupR3SnL3htU7S3KEs4e6rjDP6gNEOXRFsWs6YD3hXuXd50jd8ummy+q2WSwuGkr8wi+Gw==
+  dependencies:
+    "@jimp/core" "1.6.0"
+    "@jimp/types" "1.6.0"
+    "@jimp/utils" "1.6.0"
+    bmp-ts "^1.0.9"
+
+"@jimp/js-gif@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/js-gif/-/js-gif-1.6.0.tgz#0efa5d83317a89d6eda936e2ae1df2b7d122a38d"
+  integrity sha512-N9CZPHOrJTsAUoWkWZstLPpwT5AwJ0wge+47+ix3++SdSL/H2QzyMqxbcDYNFe4MoI5MIhATfb0/dl/wmX221g==
+  dependencies:
+    "@jimp/core" "1.6.0"
+    "@jimp/types" "1.6.0"
+    gifwrap "^0.10.1"
+    omggif "^1.0.10"
+
+"@jimp/js-jpeg@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/js-jpeg/-/js-jpeg-1.6.0.tgz#e47da6758346548079f0ac8ff215d0d9d1ec435e"
+  integrity sha512-6vgFDqeusblf5Pok6B2DUiMXplH8RhIKAryj1yn+007SIAQ0khM1Uptxmpku/0MfbClx2r7pnJv9gWpAEJdMVA==
+  dependencies:
+    "@jimp/core" "1.6.0"
+    "@jimp/types" "1.6.0"
+    jpeg-js "^0.4.4"
+
+"@jimp/js-png@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/js-png/-/js-png-1.6.0.tgz#c857adfdbfcb7107a6511c3b2939ffbad0fefedc"
+  integrity sha512-AbQHScy3hDDgMRNfG0tPjL88AV6qKAILGReIa3ATpW5QFjBKpisvUaOqhzJ7Reic1oawx3Riyv152gaPfqsBVg==
+  dependencies:
+    "@jimp/core" "1.6.0"
+    "@jimp/types" "1.6.0"
+    pngjs "^7.0.0"
+
+"@jimp/js-tiff@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/js-tiff/-/js-tiff-1.6.0.tgz#f18fa3d59f52fda339acfdcadbe7363bed912e81"
+  integrity sha512-zhReR8/7KO+adijj3h0ZQUOiun3mXUv79zYEAKvE0O+rP7EhgtKvWJOZfRzdZSNv0Pu1rKtgM72qgtwe2tFvyw==
+  dependencies:
+    "@jimp/core" "1.6.0"
+    "@jimp/types" "1.6.0"
+    utif2 "^4.1.0"
+
+"@jimp/plugin-blit@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/plugin-blit/-/plugin-blit-1.6.0.tgz#fed35aefbb5757599a4299a9ff6c06cc3466f46f"
+  integrity sha512-M+uRWl1csi7qilnSK8uxK4RJMSuVeBiO1AY0+7APnfUbQNZm6hCe0CCFv1Iyw1D/Dhb8ph8fQgm5mwM0eSxgVA==
+  dependencies:
+    "@jimp/types" "1.6.0"
+    "@jimp/utils" "1.6.0"
+    zod "^3.23.8"
+
+"@jimp/plugin-blur@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/plugin-blur/-/plugin-blur-1.6.0.tgz#781b3be9de2744e5eb6ab86ec05ee7d2ce5092e8"
+  integrity sha512-zrM7iic1OTwUCb0g/rN5y+UnmdEsT3IfuCXCJJNs8SZzP0MkZ1eTvuwK9ZidCuMo4+J3xkzCidRwYXB5CyGZTw==
+  dependencies:
+    "@jimp/core" "1.6.0"
+    "@jimp/utils" "1.6.0"
+
+"@jimp/plugin-circle@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/plugin-circle/-/plugin-circle-1.6.0.tgz#2314dc7955068cb4a000de4eceb02890eb131c88"
+  integrity sha512-xt1Gp+LtdMKAXfDp3HNaG30SPZW6AQ7dtAtTnoRKorRi+5yCJjKqXRgkewS5bvj8DEh87Ko1ydJfzqS3P2tdWw==
+  dependencies:
+    "@jimp/types" "1.6.0"
+    zod "^3.23.8"
+
+"@jimp/plugin-color@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/plugin-color/-/plugin-color-1.6.0.tgz#927c83ee932070ad285266840728c21ac39bf27b"
+  integrity sha512-J5q8IVCpkBsxIXM+45XOXTrsyfblyMZg3a9eAo0P7VPH4+CrvyNQwaYatbAIamSIN1YzxmO3DkIZXzRjFSz1SA==
+  dependencies:
+    "@jimp/core" "1.6.0"
+    "@jimp/types" "1.6.0"
+    "@jimp/utils" "1.6.0"
+    tinycolor2 "^1.6.0"
+    zod "^3.23.8"
+
+"@jimp/plugin-contain@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/plugin-contain/-/plugin-contain-1.6.0.tgz#d08900ecf85ac564a6f9f3fc0d61cc8d5e43626e"
+  integrity sha512-oN/n+Vdq/Qg9bB4yOBOxtY9IPAtEfES8J1n9Ddx+XhGBYT1/QTU/JYkGaAkIGoPnyYvmLEDqMz2SGihqlpqfzQ==
+  dependencies:
+    "@jimp/core" "1.6.0"
+    "@jimp/plugin-blit" "1.6.0"
+    "@jimp/plugin-resize" "1.6.0"
+    "@jimp/types" "1.6.0"
+    "@jimp/utils" "1.6.0"
+    zod "^3.23.8"
+
+"@jimp/plugin-cover@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/plugin-cover/-/plugin-cover-1.6.0.tgz#07ffb2f3d6ac53616c66f1131cd66ced17e3ca3e"
+  integrity sha512-Iow0h6yqSC269YUJ8HC3Q/MpCi2V55sMlbkkTTx4zPvd8mWZlC0ykrNDeAy9IJegrQ7v5E99rJwmQu25lygKLA==
+  dependencies:
+    "@jimp/core" "1.6.0"
+    "@jimp/plugin-crop" "1.6.0"
+    "@jimp/plugin-resize" "1.6.0"
+    "@jimp/types" "1.6.0"
+    zod "^3.23.8"
+
+"@jimp/plugin-crop@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/plugin-crop/-/plugin-crop-1.6.0.tgz#59f2b20869330fd768d1743d845b8ba9ed9bc52a"
+  integrity sha512-KqZkEhvs+21USdySCUDI+GFa393eDIzbi1smBqkUPTE+pRwSWMAf01D5OC3ZWB+xZsNla93BDS9iCkLHA8wang==
+  dependencies:
+    "@jimp/core" "1.6.0"
+    "@jimp/types" "1.6.0"
+    "@jimp/utils" "1.6.0"
+    zod "^3.23.8"
+
+"@jimp/plugin-displace@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/plugin-displace/-/plugin-displace-1.6.0.tgz#41b3257a6c0f64c749c29c1a2e64ba7df31a7a25"
+  integrity sha512-4Y10X9qwr5F+Bo5ME356XSACEF55485j5nGdiyJ9hYzjQP9nGgxNJaZ4SAOqpd+k5sFaIeD7SQ0Occ26uIng5Q==
+  dependencies:
+    "@jimp/types" "1.6.0"
+    "@jimp/utils" "1.6.0"
+    zod "^3.23.8"
+
+"@jimp/plugin-dither@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/plugin-dither/-/plugin-dither-1.6.0.tgz#10c17070dcbec565904f11b7986e90ae20850b6f"
+  integrity sha512-600d1RxY0pKwgyU0tgMahLNKsqEcxGdbgXadCiVCoGd6V6glyCvkNrnnwC0n5aJ56Htkj88PToSdF88tNVZEEQ==
+  dependencies:
+    "@jimp/types" "1.6.0"
+
+"@jimp/plugin-fisheye@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/plugin-fisheye/-/plugin-fisheye-1.6.0.tgz#2831c0060598b27bf004bf8a70adfeec003d4fcc"
+  integrity sha512-E5QHKWSCBFtpgZarlmN3Q6+rTQxjirFqo44ohoTjzYVrDI6B6beXNnPIThJgPr0Y9GwfzgyarKvQuQuqCnnfbA==
+  dependencies:
+    "@jimp/types" "1.6.0"
+    "@jimp/utils" "1.6.0"
+    zod "^3.23.8"
+
+"@jimp/plugin-flip@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/plugin-flip/-/plugin-flip-1.6.0.tgz#75c87bdb0f0ca9db44b320cc9671aa201e52b5c3"
+  integrity sha512-/+rJVDuBIVOgwoyVkBjUFHtP+wmW0r+r5OQ2GpatQofToPVbJw1DdYWXlwviSx7hvixTWLKVgRWQ5Dw862emDg==
+  dependencies:
+    "@jimp/types" "1.6.0"
+    zod "^3.23.8"
+
+"@jimp/plugin-hash@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/plugin-hash/-/plugin-hash-1.6.0.tgz#8de89dfbbb6be671f9cdb2b59816acf3f07c4298"
+  integrity sha512-wWzl0kTpDJgYVbZdajTf+4NBSKvmI3bRI8q6EH9CVeIHps9VWVsUvEyb7rpbcwVLWYuzDtP2R0lTT6WeBNQH9Q==
+  dependencies:
+    "@jimp/core" "1.6.0"
+    "@jimp/js-bmp" "1.6.0"
+    "@jimp/js-jpeg" "1.6.0"
+    "@jimp/js-png" "1.6.0"
+    "@jimp/js-tiff" "1.6.0"
+    "@jimp/plugin-color" "1.6.0"
+    "@jimp/plugin-resize" "1.6.0"
+    "@jimp/types" "1.6.0"
+    "@jimp/utils" "1.6.0"
+    any-base "^1.1.0"
+
+"@jimp/plugin-mask@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/plugin-mask/-/plugin-mask-1.6.0.tgz#2b5a437e5d9a9906dcabb7a7baf4d5cd7d2361b1"
+  integrity sha512-Cwy7ExSJMZszvkad8NV8o/Z92X2kFUFM8mcDAhNVxU0Q6tA0op2UKRJY51eoK8r6eds/qak3FQkXakvNabdLnA==
+  dependencies:
+    "@jimp/types" "1.6.0"
+    zod "^3.23.8"
+
+"@jimp/plugin-print@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/plugin-print/-/plugin-print-1.6.0.tgz#ccef327f53afb47617aa66ca65435447380faf34"
+  integrity sha512-zarTIJi8fjoGMSI/M3Xh5yY9T65p03XJmPsuNet19K/Q7mwRU6EV2pfj+28++2PV2NJ+htDF5uecAlnGyxFN2A==
+  dependencies:
+    "@jimp/core" "1.6.0"
+    "@jimp/js-jpeg" "1.6.0"
+    "@jimp/js-png" "1.6.0"
+    "@jimp/plugin-blit" "1.6.0"
+    "@jimp/types" "1.6.0"
+    parse-bmfont-ascii "^1.0.6"
+    parse-bmfont-binary "^1.0.6"
+    parse-bmfont-xml "^1.1.6"
+    simple-xml-to-json "^1.2.2"
+    zod "^3.23.8"
+
+"@jimp/plugin-quantize@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/plugin-quantize/-/plugin-quantize-1.6.0.tgz#880095fc0ead41321d94bf54895e366dd7d079d6"
+  integrity sha512-EmzZ/s9StYQwbpG6rUGBCisc3f64JIhSH+ncTJd+iFGtGo0YvSeMdAd+zqgiHpfZoOL54dNavZNjF4otK+mvlg==
+  dependencies:
+    image-q "^4.0.0"
+    zod "^3.23.8"
+
+"@jimp/plugin-resize@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/plugin-resize/-/plugin-resize-1.6.0.tgz#331e8912ed68746846145019bc6e2ea057e6f175"
+  integrity sha512-uSUD1mqXN9i1SGSz5ov3keRZ7S9L32/mAQG08wUwZiEi5FpbV0K8A8l1zkazAIZi9IJzLlTauRNU41Mi8IF9fA==
+  dependencies:
+    "@jimp/core" "1.6.0"
+    "@jimp/types" "1.6.0"
+    zod "^3.23.8"
+
+"@jimp/plugin-rotate@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/plugin-rotate/-/plugin-rotate-1.6.0.tgz#de271f39a3ac9e853b02e01d3d44ab086d12e099"
+  integrity sha512-JagdjBLnUZGSG4xjCLkIpQOZZ3Mjbg8aGCCi4G69qR+OjNpOeGI7N2EQlfK/WE8BEHOW5vdjSyglNqcYbQBWRw==
+  dependencies:
+    "@jimp/core" "1.6.0"
+    "@jimp/plugin-crop" "1.6.0"
+    "@jimp/plugin-resize" "1.6.0"
+    "@jimp/types" "1.6.0"
+    "@jimp/utils" "1.6.0"
+    zod "^3.23.8"
+
+"@jimp/plugin-threshold@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/plugin-threshold/-/plugin-threshold-1.6.0.tgz#11479cf59131ea95dcaff6a1403af1964593a3fa"
+  integrity sha512-M59m5dzLoHOVWdM41O8z9SyySzcDn43xHseOH0HavjsfQsT56GGCC4QzU1banJidbUrePhzoEdS42uFE8Fei8w==
+  dependencies:
+    "@jimp/core" "1.6.0"
+    "@jimp/plugin-color" "1.6.0"
+    "@jimp/plugin-hash" "1.6.0"
+    "@jimp/types" "1.6.0"
+    "@jimp/utils" "1.6.0"
+    zod "^3.23.8"
+
+"@jimp/types@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/types/-/types-1.6.0.tgz#27022730fd673653e1430e6bd8ac6f6de1596f89"
+  integrity sha512-7UfRsiKo5GZTAATxm2qQ7jqmUXP0DxTArztllTcYdyw6Xi5oT4RaoXynVtCD4UyLK5gJgkZJcwonoijrhYFKfg==
+  dependencies:
+    zod "^3.23.8"
+
+"@jimp/utils@1.6.0":
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/@jimp/utils/-/utils-1.6.0.tgz#e196f3953ea1ebc88f50cf0d490adb24aeffe596"
+  integrity sha512-gqFTGEosKbOkYF/WFj26jMHOI5OH2jeP1MmC/zbK6BF6VJBf8rIC5898dPfSzZEbSA0wbbV5slbntWVc5PKLFA==
+  dependencies:
+    "@jimp/types" "1.6.0"
+    tinycolor2 "^1.6.0"
+
 "@jridgewell/sourcemap-codec@^1.5.5":
   version "1.5.5"
   resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba"
@@ -523,6 +803,16 @@
   dependencies:
     defer-to-connect "^2.0.0"
 
+"@techstark/opencv-js@^4.12.0-release.1":
+  version "4.12.0-release.1"
+  resolved "https://registry.yarnpkg.com/@techstark/opencv-js/-/opencv-js-4.12.0-release.1.tgz#4d6823e69b70ef6d2705ba77f09c60be8b6d53ee"
+  integrity sha512-LtTaph9v/HqLPXEg3m1xs2h7QJh10pUpuDT0nj8g77lelWnTwwQrehtd+fXElLOdrkqc4Fea6Z/sJBvEJLYPfw==
+
+"@tokenizer/token@^0.3.0":
+  version "0.3.0"
+  resolved "https://registry.yarnpkg.com/@tokenizer/token/-/token-0.3.0.tgz#fe98a93fe789247e998c75e74e9c7c63217aa276"
+  integrity sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==
+
 "@tootallnate/once@1":
   version "1.1.2"
   resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82"
@@ -584,6 +874,14 @@
     "@types/express-serve-static-core" "^5.0.0"
     "@types/serve-static" "^1"
 
+"@types/fs-extra@^11.0.4":
+  version "11.0.4"
+  resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-11.0.4.tgz#e16a863bb8843fba8c5004362b5a73e17becca45"
+  integrity sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==
+  dependencies:
+    "@types/jsonfile" "*"
+    "@types/node" "*"
+
 "@types/http-cache-semantics@*":
   version "4.0.4"
   resolved "https://registry.yarnpkg.com/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz#b979ebad3919799c979b17c72621c0bc0a31c6c4"
@@ -594,6 +892,13 @@
   resolved "https://registry.yarnpkg.com/@types/http-errors/-/http-errors-2.0.5.tgz#5b749ab2b16ba113423feb1a64a95dcd30398472"
   integrity sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==
 
+"@types/jsonfile@*":
+  version "6.1.4"
+  resolved "https://registry.yarnpkg.com/@types/jsonfile/-/jsonfile-6.1.4.tgz#614afec1a1164e7d670b4a7ad64df3e7beb7b702"
+  integrity sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==
+  dependencies:
+    "@types/node" "*"
+
 "@types/keyv@^3.1.4":
   version "3.1.4"
   resolved "https://registry.yarnpkg.com/@types/keyv/-/keyv-3.1.4.tgz#3ccdb1c6751b0c7e52300bcdacd5bcbf8faa75b6"
@@ -620,6 +925,11 @@
   dependencies:
     undici-types "~7.16.0"
 
+"@types/node@16.9.1":
+  version "16.9.1"
+  resolved "https://registry.yarnpkg.com/@types/node/-/node-16.9.1.tgz#0611b37db4246c937feef529ddcc018cf8e35708"
+  integrity sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==
+
 "@types/node@^22.7.7":
   version "22.19.0"
   resolved "https://registry.yarnpkg.com/@types/node/-/node-22.19.0.tgz#849606ef3920850583a4e7ee0930987c35ad80be"
@@ -811,6 +1121,13 @@ abbrev@1:
   resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
   integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
 
+abort-controller@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
+  integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
+  dependencies:
+    event-target-shim "^5.0.0"
+
 accepts@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/accepts/-/accepts-2.0.0.tgz#bbcf4ba5075467f3f2131eab3cffc73c2f5d7895"
@@ -819,6 +1136,11 @@ accepts@^2.0.0:
     mime-types "^3.0.0"
     negotiator "^1.0.0"
 
+adm-zip@^0.5.16:
+  version "0.5.16"
+  resolved "https://registry.yarnpkg.com/adm-zip/-/adm-zip-0.5.16.tgz#0b5e4c779f07dedea5805cdccb1147071d94a909"
+  integrity sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==
+
 agent-base@6, agent-base@^6.0.2:
   version "6.0.2"
   resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
@@ -858,6 +1180,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0:
   dependencies:
     color-convert "^2.0.1"
 
+any-base@^1.1.0:
+  version "1.1.0"
+  resolved "https://registry.yarnpkg.com/any-base/-/any-base-1.1.0.tgz#ae101a62bc08a597b4c9ab5b7089d456630549fe"
+  integrity sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==
+
 append-field@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/append-field/-/append-field-1.0.0.tgz#1e3440e915f0b1203d23748e78edd7b9b5b43e56"
@@ -881,6 +1208,11 @@ asynckit@^0.4.0:
   resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
   integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
 
+await-to-js@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/await-to-js/-/await-to-js-3.0.0.tgz#70929994185616f4675a91af6167eb61cc92868f"
+  integrity sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g==
+
 axios@^1.12.2:
   version "1.13.2"
   resolved "https://registry.yarnpkg.com/axios/-/axios-1.13.2.tgz#9ada120b7b5ab24509553ec3e40123521117f687"
@@ -921,6 +1253,11 @@ bmp-js@^0.1.0:
   resolved "https://registry.yarnpkg.com/bmp-js/-/bmp-js-0.1.0.tgz#e05a63f796a6c1ff25f4771ec7adadc148c07233"
   integrity sha512-vHdS19CnY3hwiNdkaqk93DvjVLfbEcI8mys4UjuWrlX1haDmroo8o4xCzh4wD6DGV6HxRCyauwhHRqMTfERtjw==
 
+bmp-ts@^1.0.9:
+  version "1.0.9"
+  resolved "https://registry.yarnpkg.com/bmp-ts/-/bmp-ts-1.0.9.tgz#0fd124ba812be9b786b29e5b186ee76d74ff5538"
+  integrity sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw==
+
 body-parser@^2.2.0:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-2.2.0.tgz#f7a9656de305249a715b549b7b8fd1ab9dfddcfa"
@@ -967,6 +1304,14 @@ buffer@^5.5.0:
     base64-js "^1.3.1"
     ieee754 "^1.1.13"
 
+buffer@^6.0.3:
+  version "6.0.3"
+  resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
+  integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==
+  dependencies:
+    base64-js "^1.3.1"
+    ieee754 "^1.2.1"
+
 busboy@^1.6.0:
   version "1.6.0"
   resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893"
@@ -1063,6 +1408,11 @@ chownr@^2.0.0:
   resolved "https://registry.yarnpkg.com/chownr/-/chownr-2.0.0.tgz#15bfbe53d2eab4cf70f18a8cd68ebe5b3cb1dece"
   integrity sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==
 
+chownr@^3.0.0:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/chownr/-/chownr-3.0.0.tgz#9855e64ecd240a9cc4267ce8a4aa5d24a1da15e4"
+  integrity sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==
+
 clean-stack@^2.0.0:
   version "2.2.0"
   resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b"
@@ -1199,6 +1549,11 @@ csstype@^3.1.3:
   resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
   integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
 
+data-uri-to-buffer@^4.0.0:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz#d8feb2b2881e6a4f58c2e08acfd0e2834e26222e"
+  integrity sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==
+
 debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.3, debug@^4.3.5, debug@^4.4.0:
   version "4.4.3"
   resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.3.tgz#c6ae432d9bd9662582fce08709b038c58e9e3d6a"
@@ -1417,6 +1772,21 @@ etag@^1.8.1:
   resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887"
   integrity sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==
 
+event-target-shim@^5.0.0:
+  version "5.0.1"
+  resolved "https://registry.yarnpkg.com/event-target-shim/-/event-target-shim-5.0.1.tgz#5d4d3ebdf9583d63a5333ce2deb7480ab2b05789"
+  integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
+
+events@^3.3.0:
+  version "3.3.0"
+  resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
+  integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
+
+exif-parser@^0.1.12:
+  version "0.1.12"
+  resolved "https://registry.yarnpkg.com/exif-parser/-/exif-parser-0.1.12.tgz#58a9d2d72c02c1f6f02a0ef4a9166272b7760922"
+  integrity sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==
+
 expand-template@^2.0.3:
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c"
@@ -1478,6 +1848,23 @@ fdir@^6.5.0:
   resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350"
   integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==
 
+fetch-blob@^3.1.2, fetch-blob@^3.1.4:
+  version "3.2.0"
+  resolved "https://registry.yarnpkg.com/fetch-blob/-/fetch-blob-3.2.0.tgz#f09b8d4bbd45adc6f0c20b7e787e793e309dcce9"
+  integrity sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==
+  dependencies:
+    node-domexception "^1.0.0"
+    web-streams-polyfill "^3.0.3"
+
+file-type@^16.0.0:
+  version "16.5.4"
+  resolved "https://registry.yarnpkg.com/file-type/-/file-type-16.5.4.tgz#474fb4f704bee427681f98dd390058a172a6c2fd"
+  integrity sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==
+  dependencies:
+    readable-web-to-node-stream "^3.0.0"
+    strtok3 "^6.2.4"
+    token-types "^4.1.1"
+
 file-uri-to-path@1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
@@ -1511,6 +1898,13 @@ form-data@^4.0.4:
     hasown "^2.0.2"
     mime-types "^2.1.12"
 
+formdata-polyfill@^4.0.10:
+  version "4.0.10"
+  resolved "https://registry.yarnpkg.com/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz#24807c31c9d402e002ab3d8c720144ceb8848423"
+  integrity sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==
+  dependencies:
+    fetch-blob "^3.1.2"
+
 forwarded@0.2.0:
   version "0.2.0"
   resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.2.0.tgz#2269936428aad4c15c7ebe9779a84bf0b2a81811"
@@ -1616,6 +2010,14 @@ get-stream@^5.1.0:
   dependencies:
     pump "^3.0.0"
 
+gifwrap@^0.10.1:
+  version "0.10.1"
+  resolved "https://registry.yarnpkg.com/gifwrap/-/gifwrap-0.10.1.tgz#9ed46a5d51913b482d4221ce9c727080260b681e"
+  integrity sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw==
+  dependencies:
+    image-q "^4.0.0"
+    omggif "^1.0.10"
+
 github-from-package@0.0.0:
   version "0.0.0"
   resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce"
@@ -1783,11 +2185,18 @@ idb-keyval@^6.2.0:
   resolved "https://registry.yarnpkg.com/idb-keyval/-/idb-keyval-6.2.2.tgz#b0171b5f73944854a3291a5cdba8e12768c4854a"
   integrity sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg==
 
-ieee754@^1.1.13:
+ieee754@^1.1.13, ieee754@^1.2.1:
   version "1.2.1"
   resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
   integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
 
+image-q@^4.0.0:
+  version "4.0.0"
+  resolved "https://registry.yarnpkg.com/image-q/-/image-q-4.0.0.tgz#31e075be7bae3c1f42a85c469b4732c358981776"
+  integrity sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==
+  dependencies:
+    "@types/node" "16.9.1"
+
 imurmurhash@^0.1.4:
   version "0.1.4"
   resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
@@ -1856,6 +2265,39 @@ isexe@^2.0.0:
   resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
   integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
 
+jimp@^1.6.0:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/jimp/-/jimp-1.6.0.tgz#7c7e5133c8dc06706e1ed35e771c685af393bfd2"
+  integrity sha512-YcwCHw1kiqEeI5xRpDlPPBGL2EOpBKLwO4yIBJcXWHPj5PnA5urGq0jbyhM5KoNpypQ6VboSoxc9D8HyfvngSg==
+  dependencies:
+    "@jimp/core" "1.6.0"
+    "@jimp/diff" "1.6.0"
+    "@jimp/js-bmp" "1.6.0"
+    "@jimp/js-gif" "1.6.0"
+    "@jimp/js-jpeg" "1.6.0"
+    "@jimp/js-png" "1.6.0"
+    "@jimp/js-tiff" "1.6.0"
+    "@jimp/plugin-blit" "1.6.0"
+    "@jimp/plugin-blur" "1.6.0"
+    "@jimp/plugin-circle" "1.6.0"
+    "@jimp/plugin-color" "1.6.0"
+    "@jimp/plugin-contain" "1.6.0"
+    "@jimp/plugin-cover" "1.6.0"
+    "@jimp/plugin-crop" "1.6.0"
+    "@jimp/plugin-displace" "1.6.0"
+    "@jimp/plugin-dither" "1.6.0"
+    "@jimp/plugin-fisheye" "1.6.0"
+    "@jimp/plugin-flip" "1.6.0"
+    "@jimp/plugin-hash" "1.6.0"
+    "@jimp/plugin-mask" "1.6.0"
+    "@jimp/plugin-print" "1.6.0"
+    "@jimp/plugin-quantize" "1.6.0"
+    "@jimp/plugin-resize" "1.6.0"
+    "@jimp/plugin-rotate" "1.6.0"
+    "@jimp/plugin-threshold" "1.6.0"
+    "@jimp/types" "1.6.0"
+    "@jimp/utils" "1.6.0"
+
 joi@^18.0.1:
   version "18.0.1"
   resolved "https://registry.yarnpkg.com/joi/-/joi-18.0.1.tgz#1e1885d035cc6ca1624e81bf22112e7c1ee38e1b"
@@ -1869,6 +2311,11 @@ joi@^18.0.1:
     "@hapi/topo" "^6.0.2"
     "@standard-schema/spec" "^1.0.0"
 
+jpeg-js@^0.4.4:
+  version "0.4.4"
+  resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.4.4.tgz#a9f1c6f1f9f0fa80cdb3484ed9635054d28936aa"
+  integrity sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==
+
 json-buffer@3.0.1:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/json-buffer/-/json-buffer-3.0.1.tgz#9338802a30d3b6605fbe0613e094008ca8c05a13"
@@ -1999,6 +2446,11 @@ mime-types@^3.0.0, mime-types@^3.0.1:
   dependencies:
     mime-db "^1.54.0"
 
+mime@3:
+  version "3.0.0"
+  resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7"
+  integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==
+
 mimic-response@^1.0.0:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-1.0.1.tgz#4923538878eef42063cb8a3e3b0798781487ab1b"
@@ -2072,6 +2524,11 @@ minipass@^5.0.0:
   resolved "https://registry.yarnpkg.com/minipass/-/minipass-5.0.0.tgz#3e9788ffb90b694a5d0ec94479a45b5d8738133d"
   integrity sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==
 
+minipass@^7.0.4, minipass@^7.1.2:
+  version "7.1.2"
+  resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707"
+  integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==
+
 minizlib@^2.0.0, minizlib@^2.1.1:
   version "2.1.2"
   resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-2.1.2.tgz#e90d3466ba209b932451508a11ce3d3632145931"
@@ -2080,6 +2537,13 @@ minizlib@^2.0.0, minizlib@^2.1.1:
     minipass "^3.0.0"
     yallist "^4.0.0"
 
+minizlib@^3.1.0:
+  version "3.1.0"
+  resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-3.1.0.tgz#6ad76c3a8f10227c9b51d1c9ac8e30b27f5a251c"
+  integrity sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==
+  dependencies:
+    minipass "^7.1.2"
+
 mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3:
   version "0.5.3"
   resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113"
@@ -2152,6 +2616,11 @@ node-addon-api@^7.0.0:
   resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-7.1.1.tgz#1aba6693b0f255258a049d621329329322aad558"
   integrity sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==
 
+node-domexception@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/node-domexception/-/node-domexception-1.0.0.tgz#6888db46a1f71c0b76b3f7555016b63fe64766e5"
+  integrity sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==
+
 node-fetch@^2.6.9:
   version "2.7.0"
   resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
@@ -2159,6 +2628,15 @@ node-fetch@^2.6.9:
   dependencies:
     whatwg-url "^5.0.0"
 
+node-fetch@^3.3.2:
+  version "3.3.2"
+  resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-3.3.2.tgz#d1e889bacdf733b4ff3b2b243eb7a12866a0b78b"
+  integrity sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==
+  dependencies:
+    data-uri-to-buffer "^4.0.0"
+    fetch-blob "^3.1.4"
+    formdata-polyfill "^4.0.10"
+
 node-gyp@8.x:
   version "8.4.1"
   resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-8.4.1.tgz#3d49308fc31f768180957d6b5746845fbd429937"
@@ -2217,6 +2695,11 @@ object-keys@^1.1.1:
   resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e"
   integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==
 
+omggif@^1.0.10:
+  version "1.0.10"
+  resolved "https://registry.yarnpkg.com/omggif/-/omggif-1.0.10.tgz#ddaaf90d4a42f532e9e7cb3a95ecdd47f17c7b19"
+  integrity sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==
+
 on-finished@^2.4.1:
   version "2.4.1"
   resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.4.1.tgz#58c8c44116e54845ad57f14ab10b03533184ac3f"
@@ -2231,11 +2714,30 @@ once@^1.3.0, once@^1.3.1, once@^1.4.0:
   dependencies:
     wrappy "1"
 
+onnxruntime-common@1.23.2:
+  version "1.23.2"
+  resolved "https://registry.yarnpkg.com/onnxruntime-common/-/onnxruntime-common-1.23.2.tgz#669892f8d2b7de273ac60a76151781a97d01ab49"
+  integrity sha512-5LFsC9Dukzp2WV6kNHYLNzp8sT6V02IubLCbzw2Xd6X5GOlr65gAX6xiJwyi2URJol/s71gaQLC5F2C25AAR2w==
+
+onnxruntime-node@^1.23.2:
+  version "1.23.2"
+  resolved "https://registry.yarnpkg.com/onnxruntime-node/-/onnxruntime-node-1.23.2.tgz#6e205a32111bf6657ac469f8fc7fb35b765324a5"
+  integrity sha512-OBTsG0W8ddBVOeVVVychpVBS87A9YV5sa2hJ6lc025T97Le+J4v++PwSC4XFs1C62SWyNdof0Mh4KvnZgtt4aw==
+  dependencies:
+    adm-zip "^0.5.16"
+    global-agent "^3.0.0"
+    onnxruntime-common "1.23.2"
+
 opencollective-postinstall@^2.0.3:
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/opencollective-postinstall/-/opencollective-postinstall-2.0.3.tgz#7a0fff978f6dbfa4d006238fbac98ed4198c3259"
   integrity sha512-8AV/sCtuzUeTo8gQK5qDZzARrulB3egtLzFgteqB2tcT4Mw7B8Kt7JcDHmltjz6FOAHsvTevk70gZEbhM4ZS9Q==
 
+opencv.js@^1.2.1:
+  version "1.2.1"
+  resolved "https://registry.yarnpkg.com/opencv.js/-/opencv.js-1.2.1.tgz#9e89fd669a749f80574ba5d4615a5ff3e3c09a16"
+  integrity sha512-+ji5Pk3eyz+RRSeZr2kLZNJpjsKoGyPJOjFWng7+Cuq9ylHakBqJMxDGlBW1+qdju3k8DadWOiHJ6JaF28UpKA==
+
 p-cancelable@^2.0.0:
   version "2.1.1"
   resolved "https://registry.yarnpkg.com/p-cancelable/-/p-cancelable-2.1.1.tgz#aab7fbd416582fa32a3db49859c122487c5ed2cf"
@@ -2248,6 +2750,29 @@ p-map@^4.0.0:
   dependencies:
     aggregate-error "^3.0.0"
 
+pako@^1.0.11:
+  version "1.0.11"
+  resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf"
+  integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==
+
+parse-bmfont-ascii@^1.0.6:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz#11ac3c3ff58f7c2020ab22769079108d4dfa0285"
+  integrity sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA==
+
+parse-bmfont-binary@^1.0.6:
+  version "1.0.6"
+  resolved "https://registry.yarnpkg.com/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz#d038b476d3e9dd9db1e11a0b0e53a22792b69006"
+  integrity sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA==
+
+parse-bmfont-xml@^1.1.6:
+  version "1.1.6"
+  resolved "https://registry.yarnpkg.com/parse-bmfont-xml/-/parse-bmfont-xml-1.1.6.tgz#016b655da7aebe6da38c906aca16bf0415773767"
+  integrity sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA==
+  dependencies:
+    xml-parse-from-string "^1.0.0"
+    xml2js "^0.5.0"
+
 parseurl@^1.3.3:
   version "1.3.3"
   resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4"
@@ -2273,6 +2798,11 @@ path-to-regexp@^8.0.0:
   resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-8.3.0.tgz#aa818a6981f99321003a08987d3cec9c3474cd1f"
   integrity sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==
 
+peek-readable@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/peek-readable/-/peek-readable-4.1.0.tgz#4ece1111bf5c2ad8867c314c81356847e8a62e72"
+  integrity sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==
+
 pend@~1.2.0:
   version "1.2.0"
   resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50"
@@ -2288,6 +2818,23 @@ picomatch@^4.0.2, picomatch@^4.0.3:
   resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042"
   integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==
 
+pixelmatch@^5.3.0:
+  version "5.3.0"
+  resolved "https://registry.yarnpkg.com/pixelmatch/-/pixelmatch-5.3.0.tgz#5e5321a7abedfb7962d60dbf345deda87cb9560a"
+  integrity sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q==
+  dependencies:
+    pngjs "^6.0.0"
+
+pngjs@^6.0.0:
+  version "6.0.0"
+  resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-6.0.0.tgz#ca9e5d2aa48db0228a52c419c3308e87720da821"
+  integrity sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==
+
+pngjs@^7.0.0:
+  version "7.0.0"
+  resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-7.0.0.tgz#a8b7446020ebbc6ac739db6c5415a65d17090e26"
+  integrity sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==
+
 postcss@^8.5.6:
   version "8.5.6"
   resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c"
@@ -2315,6 +2862,11 @@ prebuild-install@^7.1.1, prebuild-install@^7.1.3:
     tar-fs "^2.0.0"
     tunnel-agent "^0.6.0"
 
+process@^0.11.10:
+  version "0.11.10"
+  resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
+  integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==
+
 progress@^2.0.3:
   version "2.0.3"
   resolved "https://registry.yarnpkg.com/progress/-/progress-2.0.3.tgz#7e8cf8d8f5b8f239c1bc68beb4eb78567d572ef8"
@@ -2400,6 +2952,24 @@ readable-stream@^3.0.2, readable-stream@^3.1.1, readable-stream@^3.4.0, readable
     string_decoder "^1.1.1"
     util-deprecate "^1.0.1"
 
+readable-stream@^4.7.0:
+  version "4.7.0"
+  resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-4.7.0.tgz#cedbd8a1146c13dfff8dab14068028d58c15ac91"
+  integrity sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==
+  dependencies:
+    abort-controller "^3.0.0"
+    buffer "^6.0.3"
+    events "^3.3.0"
+    process "^0.11.10"
+    string_decoder "^1.3.0"
+
+readable-web-to-node-stream@^3.0.0:
+  version "3.0.4"
+  resolved "https://registry.yarnpkg.com/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.4.tgz#392ba37707af5bf62d725c36c1b5d6ef4119eefc"
+  integrity sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw==
+  dependencies:
+    readable-stream "^4.7.0"
+
 regenerator-runtime@^0.13.3:
   version "0.13.11"
   resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz#f6dca3e7ceec20590d07ada785636a90cdca17f9"
@@ -2505,6 +3075,11 @@ safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@~5.2.0:
   resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
   integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
 
+sax@>=0.6.0:
+  version "1.4.3"
+  resolved "https://registry.yarnpkg.com/sax/-/sax-1.4.3.tgz#fcebae3b756cdc8428321805f4b70f16ec0ab5db"
+  integrity sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==
+
 semver-compare@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/semver-compare/-/semver-compare-1.0.0.tgz#0dee216a1c941ab37e9efb1788f6afc5ff5537fc"
@@ -2674,6 +3249,11 @@ simple-get@^4.0.0:
     once "^1.3.1"
     simple-concat "^1.0.0"
 
+simple-xml-to-json@^1.2.2:
+  version "1.2.3"
+  resolved "https://registry.yarnpkg.com/simple-xml-to-json/-/simple-xml-to-json-1.2.3.tgz#79c7188ff99ae209a267b70ee0db06b0e4597787"
+  integrity sha512-kWJDCr9EWtZ+/EYYM5MareWj2cRnZGF93YDNpH4jQiHB+hBIZnfPFSQiVMzZOdk+zXWqTZ/9fTeQNu2DqeiudA==
+
 smart-buffer@^4.2.0:
   version "4.2.0"
   resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae"
@@ -2754,7 +3334,7 @@ streamsearch@^1.1.0:
     is-fullwidth-code-point "^3.0.0"
     strip-ansi "^6.0.1"
 
-string_decoder@^1.1.1:
+string_decoder@^1.1.1, string_decoder@^1.3.0:
   version "1.3.0"
   resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e"
   integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==
@@ -2773,6 +3353,14 @@ strip-json-comments@~2.0.1:
   resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
   integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==
 
+strtok3@^6.2.4:
+  version "6.3.0"
+  resolved "https://registry.yarnpkg.com/strtok3/-/strtok3-6.3.0.tgz#358b80ffe6d5d5620e19a073aa78ce947a90f9a0"
+  integrity sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==
+  dependencies:
+    "@tokenizer/token" "^0.3.0"
+    peek-readable "^4.1.0"
+
 sumchecker@^3.0.1:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/sumchecker/-/sumchecker-3.0.1.tgz#6377e996795abb0b6d348e9b3e1dfb24345a8e42"
@@ -2827,6 +3415,17 @@ tar@^6.0.2, tar@^6.1.11, tar@^6.1.2:
     mkdirp "^1.0.3"
     yallist "^4.0.0"
 
+tar@^7.4.3:
+  version "7.5.2"
+  resolved "https://registry.yarnpkg.com/tar/-/tar-7.5.2.tgz#115c061495ec51ff3c6745ff8f6d0871c5b1dedc"
+  integrity sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==
+  dependencies:
+    "@isaacs/fs-minipass" "^4.0.0"
+    chownr "^3.0.0"
+    minipass "^7.1.2"
+    minizlib "^3.1.0"
+    yallist "^5.0.0"
+
 tesseract.js-core@^6.0.0:
   version "6.0.0"
   resolved "https://registry.yarnpkg.com/tesseract.js-core/-/tesseract.js-core-6.0.0.tgz#6f25da94f70f8e8f02aff47a43be61d49e6f67c3"
@@ -2847,6 +3446,11 @@ tesseract.js@^6.0.1:
     wasm-feature-detect "^1.2.11"
     zlibjs "^0.3.1"
 
+tinycolor2@^1.6.0:
+  version "1.6.0"
+  resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.6.0.tgz#f98007460169b0263b97072c5ae92484ce02d09e"
+  integrity sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==
+
 tinyglobby@^0.2.15:
   version "0.2.15"
   resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.15.tgz#e228dd1e638cea993d2fdb4fcd2d4602a79951c2"
@@ -2860,6 +3464,14 @@ toidentifier@1.0.1:
   resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
   integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
 
+token-types@^4.1.1:
+  version "4.2.1"
+  resolved "https://registry.yarnpkg.com/token-types/-/token-types-4.2.1.tgz#0f897f03665846982806e138977dbe72d44df753"
+  integrity sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==
+  dependencies:
+    "@tokenizer/token" "^0.3.0"
+    ieee754 "^1.2.1"
+
 tr46@~0.0.3:
   version "0.0.3"
   resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a"
@@ -2958,6 +3570,13 @@ unpipe@1.0.0:
   resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec"
   integrity sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==
 
+utif2@^4.1.0:
+  version "4.1.0"
+  resolved "https://registry.yarnpkg.com/utif2/-/utif2-4.1.0.tgz#e768d37bd619b995d56d9780b5d2b4611a3d932b"
+  integrity sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w==
+  dependencies:
+    pako "^1.0.11"
+
 util-deprecate@^1.0.1:
   version "1.0.2"
   resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
@@ -3039,6 +3658,11 @@ wasm-feature-detect@^1.2.11:
   resolved "https://registry.yarnpkg.com/wasm-feature-detect/-/wasm-feature-detect-1.8.0.tgz#4e9f55b0a64d801f372fbb0324ed11ad3abd0c78"
   integrity sha512-zksaLKM2fVlnB5jQQDqKXXwYHLQUVH9es+5TOOHwGOVJOCeRBCiPjwSg+3tN2AdTCzjgli4jijCH290kXb/zWQ==
 
+web-streams-polyfill@^3.0.3:
+  version "3.3.3"
+  resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b"
+  integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==
+
 webidl-conversions@^3.0.0:
   version "3.0.1"
   resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
@@ -3080,6 +3704,24 @@ wrappy@1:
   resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
   integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
 
+xml-parse-from-string@^1.0.0:
+  version "1.0.1"
+  resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28"
+  integrity sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==
+
+xml2js@^0.5.0:
+  version "0.5.0"
+  resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7"
+  integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==
+  dependencies:
+    sax ">=0.6.0"
+    xmlbuilder "~11.0.0"
+
+xmlbuilder@~11.0.0:
+  version "11.0.1"
+  resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
+  integrity sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==
+
 xtend@^4.0.2:
   version "4.0.2"
   resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
@@ -3095,6 +3737,11 @@ yallist@^4.0.0:
   resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
   integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
 
+yallist@^5.0.0:
+  version "5.0.0"
+  resolved "https://registry.yarnpkg.com/yallist/-/yallist-5.0.0.tgz#00e2de443639ed0d78fd87de0d27469fbcffb533"
+  integrity sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==
+
 yargs-parser@^21.1.1:
   version "21.1.1"
   resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35"
@@ -3125,3 +3772,8 @@ zlibjs@^0.3.1:
   version "0.3.1"
   resolved "https://registry.yarnpkg.com/zlibjs/-/zlibjs-0.3.1.tgz#50197edb28a1c42ca659cc8b4e6a9ddd6d444554"
   integrity sha512-+J9RrgTKOmlxFSDHo0pI1xM6BLVUv+o0ZT9ANtCxGkjIVCCUdx9alUF8Gm+dGLKbkkkidWIHFDZHDMpfITt4+w==
+
+zod@^3.23.8:
+  version "3.25.76"
+  resolved "https://registry.yarnpkg.com/zod/-/zod-3.25.76.tgz#26841c3f6fd22a6a2760e7ccb719179768471e34"
+  integrity sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==