Explorar el Código

Remove deprecated scripts and files related to OCR processing and Docker setup

- Deleted `curl_ollama.sh` script which was responsible for image processing and API requests.
- Removed `docker_startup_7085.sh` script that handled Docker container startup and configuration.
- Eliminated `mp_infer.py` script used for multiprocessing inference tasks.
- Deleted `omnidocbench_converted_result.json` which contained converted results from document processing.
zhch158_admin hace 3 meses
padre
commit
36ede66a13

+ 0 - 241
zhch/BLUE算法说明.md

@@ -1,241 +0,0 @@
-
-## compute_bleu算法原理详解
-
-### 1. BLEU算法概述
-
-BLEU (Bilingual Evaluation Understudy) 是评估**机器翻译**和**文本生成**质量的标准算法,通过计算候选翻译与参考翻译的**N-gram重叠度**来衡量翻译质量。
-
-### 2. 核心算法流程
-
-```mermaid
-graph TD
-    A[输入: 候选翻译 + 参考翻译] --> B[提取N-gram]
-    B --> C[计算N-gram重叠]
-    C --> D[计算精确度]
-    D --> E[几何平均]
-    E --> F[计算简洁惩罚BP]
-    F --> G[最终BLEU分数]
-    
-    B --> B1[1-gram: 单词级别]
-    B --> B2[2-gram: 词对级别]
-    B --> B3[3-gram: 三词组合]
-    B --> B4[4-gram: 四词组合]
-    
-    style A fill:#e1f5fe
-    style G fill:#e8f5e8
-    style E fill:#fff3e0
-    style F fill:#ffebee
-```
-
-### 3. 详细算法步骤
-
-#### 3.1 N-gram提取
-
-````python
-def _get_ngrams(segment, max_order):
-    """提取所有n-gram直到最大阶数"""
-    ngram_counts = collections.Counter()
-    for order in range(1, max_order + 1):
-        for i in range(0, len(segment) - order + 1):
-            ngram = tuple(segment[i : i + order])
-            ngram_counts[ngram] += 1
-    return ngram_counts
-````
-
-**示例:**
-```python
-segment = ["the", "cat", "is", "on", "the", "mat"]
-
-# 1-gram: ("the",), ("cat",), ("is",), ("on",), ("the",), ("mat",)
-# 2-gram: ("the","cat"), ("cat","is"), ("is","on"), ("on","the"), ("the","mat")
-# 3-gram: ("the","cat","is"), ("cat","is","on"), ("is","on","the"), ("on","the","mat")
-# 4-gram: ("the","cat","is","on"), ("cat","is","on","the"), ("is","on","the","mat")
-```
-
-#### 3.2 N-gram重叠计算
-
-````python
-# 合并多个参考翻译的n-gram
-merged_ref_ngram_counts = collections.Counter()
-for reference in references:
-    merged_ref_ngram_counts |= _get_ngrams(reference, max_order)
-
-# 计算候选翻译的n-gram
-translation_ngram_counts = _get_ngrams(translation, max_order)
-
-# 计算重叠
-overlap = translation_ngram_counts & merged_ref_ngram_counts
-for ngram in overlap:
-    matches_by_order[len(ngram) - 1] += overlap[ngram]
-````
-
-**重叠计算原理:**
-- 对每个n-gram,取候选翻译和参考翻译中的**最小出现次数**
-- 避免重复计算同一个n-gram
-
-#### 3.3 精确度计算
-
-````python
-precisions = [0] * max_order
-for i in range(0, max_order):
-    if smooth:
-        # Lin et al. 2004 平滑
-        precisions[i] = (matches_by_order[i] + 1.0) / (
-            possible_matches_by_order[i] + 1.0
-        )
-    else:
-        if possible_matches_by_order[i] > 0:
-            precisions[i] = (
-                float(matches_by_order[i]) / possible_matches_by_order[i]
-            )
-        else:
-            precisions[i] = 0.0
-````
-
-**精确度公式:**
-```
-P_n = 匹配的n-gram数量 / 候选翻译中的n-gram总数
-```
-
-#### 3.4 几何平均计算
-
-````python
-if min(precisions) > 0:
-    p_log_sum = sum((1.0 / max_order) * math.log(p) for p in precisions)
-    geo_mean = math.exp(p_log_sum)
-else:
-    geo_mean = 0
-````
-
-**几何平均公式:**
-```
-geo_mean = (P_1 × P_2 × P_3 × P_4)^(1/4)
-```
-
-#### 3.5 简洁惩罚 (Brevity Penalty)
-
-````python
-ratio = float(translation_length) / reference_length
-
-if ratio > 1.0:
-    bp = 1.0  # 候选翻译较长,无惩罚
-else:
-    bp = math.exp(1 - 1.0 / ratio)  # 候选翻译较短,施加惩罚
-````
-
-**BP作用:**
-- 防止过短的翻译获得虚高分数
-- 鼓励生成适当长度的翻译
-
-### 4. 最终BLEU分数
-
-````python
-bleu = geo_mean * bp
-````
-
-**完整公式:**
-```
-BLEU = BP × exp(∑(w_n × log(P_n)))
-```
-
-其中:
-- `BP`: 简洁惩罚因子
-- `w_n`: N-gram权重(通常为1/N)
-- `P_n`: N-gram精确度
-
-### 5. 算法示例演示
-
-#### 5.1 具体计算过程
-
-**候选翻译:** "the cat is on the mat"
-**参考翻译:** "the cat sits on the mat"
-
-**步骤1: N-gram提取**
-```python
-# 候选翻译 n-grams:
-1-gram: the(2), cat(1), is(1), on(1), mat(1)
-2-gram: (the,cat)(1), (cat,is)(1), (is,on)(1), (on,the)(1), (the,mat)(1)
-
-# 参考翻译 n-grams:
-1-gram: the(2), cat(1), sits(1), on(1), mat(1)  
-2-gram: (the,cat)(1), (cat,sits)(1), (sits,on)(1), (on,the)(1), (the,mat)(1)
-```
-
-**步骤2: 重叠计算**
-```python
-# 1-gram匹配: the(2), cat(1), on(1), mat(1) = 5个
-# 2-gram匹配: (the,cat)(1), (on,the)(1), (the,mat)(1) = 3个
-# 3-gram匹配: 0个
-# 4-gram匹配: 0个
-```
-
-**步骤3: 精确度计算**
-```python
-P1 = 5/6 = 0.833  # 5个匹配 / 6个总计
-P2 = 3/5 = 0.600  # 3个匹配 / 5个总计
-P3 = 0/4 = 0.000  # 0个匹配 / 4个总计
-P4 = 0/3 = 0.000  # 0个匹配 / 3个总计
-```
-
-**步骤4: 几何平均**
-```python
-# 由于P3和P4为0,几何平均为0
-geo_mean = 0
-```
-
-**步骤5: 简洁惩罚**
-```python
-ratio = 6/6 = 1.0
-BP = 1.0  # 无惩罚
-```
-
-**最终BLEU: 0 × 1.0 = 0**
-
-### 6. 平滑策略
-
-当某个n-gram精确度为0时,几何平均也为0,导致BLEU分数为0。平滑策略解决这个问题:
-
-````python
-if smooth:
-    precisions[i] = (matches_by_order[i] + 1.0) / (
-        possible_matches_by_order[i] + 1.0
-    )
-````
-
-**Lin et al. 2004平滑:** 给分子分母都加1,避免零值。
-
-### 7. 多参考翻译处理
-
-````python
-# 合并多个参考翻译
-merged_ref_ngram_counts = collections.Counter()
-for reference in references:
-    merged_ref_ngram_counts |= _get_ngrams(reference, max_order)
-````
-
-**策略:** 对每个n-gram,在所有参考翻译中取**最大出现次数**。
-
-### 8. 算法特点
-
-#### 8.1 优点
-- **标准化**: 国际通用的评估标准
-- **多粒度**: 同时考虑1-4gram的匹配
-- **鲁棒性**: 处理多参考翻译
-- **惩罚机制**: 防止过短翻译
-
-#### 8.2 局限性
-- **词序敏感**: 相同词汇不同顺序得分不同
-- **同义词盲**: 不识别语义相似的词汇
-- **参考依赖**: 依赖高质量参考翻译
-
-### 9. 在PaddleOCR中的应用效果
-
-根据文档显示的典型BLEU分数:
-
-| 模型 | 任务 | BLEU分数 | 说明 |
-|------|------|----------|------|
-| UniMERNet | 数学公式识别 | 85.91% | 高质量公式识别 |
-| LaTeX-OCR | LaTeX公式识别 | ~80% | 复杂公式处理 |
-| PP-FormulaNet | 公式识别 | ~75% | 平衡精度与速度 |
-
-BLEU算法为PaddleOCR的序列生成任务(特别是公式识别)提供了国际标准的质量评估机制,能够全面衡量生成文本的准确性和流畅性。

+ 0 - 1379
zhch/PaddleOCR评估算法说明.md

@@ -1,1379 +0,0 @@
-# 表格识别评估算法详细说明
-```
-zhch158: @workspace 结合/Users/zhch158/workspace/repository.git/PaddleX/dataset/table_rec_dataset_examples目录下的数据集详细说明评估算法,并给出mermaid流程序,标明各节点间传递的数据
-```
-
-PaddleOCR的表格识别评估主要通过`eval.py`脚本进行,核心评估指标在`table_metric.py`中实现。
-
-### 数据集格式
-基于table_rec_dataset_examples目录,表格识别数据集通常包含:
-- 图像文件(表格图片)
-- 标注文件(HTML结构标注)
-- 边界框标注(可选,用于检测评估)
-
-### 评估指标
-
-1. **结构准确率 (Structure Accuracy)**:预测的HTML结构与真实结构完全匹配的比例
-2. **边界框检测指标**(可选):包括精确度、召回率、F1分数等
-3. **TEDS (Tree-Edit-Distance-based Similarity)**:在README_ch.md中提到的树编辑距离评估
-
-### 评估流程
-
-```mermaid
-graph TD
-    A[开始评估] --> B[加载配置文件]
-    B --> C[构建数据加载器]
-    C --> D[构建后处理器]
-    D --> E[构建模型]
-    E --> F[加载预训练模型]
-    F --> G[构建评估指标]
-    G --> H[开始批量推理]
-    
-    H --> I[获取一个batch数据]
-    I --> J{是否有更多数据?}
-    J -->|否| W[计算最终指标]
-    J -->|是| K[模型前向推理]
-    
-    K --> L[后处理得到预测结果]
-    L --> M[提取结构序列]
-    M --> N[提取边界框序列]
-    
-    N --> O[结构准确率计算]
-    O --> P[边界框检测计算]
-    P --> Q[累计统计信息]
-    Q --> I
-    
-    W --> X[输出评估结果]
-    X --> Y[结束]
-    
-    subgraph "数据传递详情"
-        I1[batch数据:<br/>- 图像张量<br/>- 结构标签<br/>- 边界框标签]
-        K1[模型输出:<br/>- 结构预测logits<br/>- 边界框预测]
-        L1[后处理结果:<br/>- 结构token序列<br/>- 置信度分数<br/>- 格式化边界框]
-        M1[结构数据:<br/>- pred_structure_batch_list<br/>- gt_structure_batch_list]
-        N1[边界框数据:<br/>- bbox_batch_list<br/>- 格式化坐标]
-    end
-    
-    style A fill:#e1f5fe
-    style Y fill:#e8f5e8
-    style O fill:#fff3e0
-    style P fill:#fff3e0
-```
-
-### 详细算法步骤
-
-#### 1. 结构准确率计算(TableStructureMetric)
-
-````python
-def __call__(self, pred_label, batch=None, *args, **kwargs):
-    preds, labels = pred_label
-    pred_structure_batch_list = preds["structure_batch_list"]
-    gt_structure_batch_list = labels["structure_batch_list"]
-    
-    for (pred, pred_conf), target in zip(pred_structure_batch_list, gt_structure_batch_list):
-        pred_str = "".join(pred)  # 预测的HTML结构字符串
-        target_str = "".join(target)  # 真实的HTML结构字符串
-        
-        # 可选:移除thead/tbody标签
-        if self.del_thead_tbody:
-            pred_str = pred_str.replace("<thead>", "").replace("</thead>", "")
-            target_str = target_str.replace("<thead>", "").replace("</thead>", "")
-        
-        # 完全匹配则计数
-        if pred_str == target_str:
-            correct_num += 1
-        all_num += 1
-````
-
-#### 2. 边界框检测评估(DetMetric)
-
-边界框评估复用检测模块的评估指标,支持多种坐标格式:
-- `xyxy`: 左上角和右下角坐标
-- `xywh`: 中心点和宽高
-- `xyxyxyxy`: 四个顶点坐标
-
-#### 3. 数据流转详情
-
-**输入数据格式:**
-```python
-batch = {
-    'image': tensor,  # 图像张量
-    'structure_batch_list': [['<html>', '<body>', '<table>', ...], ...],  # HTML结构序列
-    'bbox_batch_list': [[[x1,y1,x2,y2], ...], ...],  # 边界框列表
-}
-```
-
-**模型输出格式:**
-```python
-preds = {
-    'structure_batch_list': [(['<html>', '<body>', ...], [0.95, 0.87, ...]), ...],  # (结构序列, 置信度)
-    'bbox_batch_list': [[[x1,y1,x2,y2], ...], ...],  # 预测边界框
-}
-```
-
-**最终评估结果:**
-```python
-metrics = {
-    'acc': 0.95,  # 结构准确率
-    'bbox_metric_precision': 0.92,  # 边界框精确度(可选)
-    'bbox_metric_recall': 0.89,     # 边界框召回率(可选)
-    'bbox_metric_hmean': 0.905,     # 边界框F1分数(可选)
-}
-```
-
-### 关键特性
-
-1. **支持多种评估模式**:纯结构评估 + 可选的边界框评估
-2. **灵活的标签处理**:可选择是否忽略`<thead>`、`<tbody>`等标签
-3. **批量处理**:支持批量数据的高效评估
-4. **多格式支持**:兼容不同的边界框坐标格式
-
-这种评估算法能够全面衡量表格识别模型在结构理解和空间定位两个维度的性能,为模型优化提供详细的反馈信息。
-
-# 边界框评估算法
-
-## 边界框检测评估算法详解
-```
-@workspace  请详细说明边界框检测算法
-```
-
-### 1. 核心评估类
-
-PaddleOCR使用`DetectionIoUEvaluator`作为核心评估器,主要在`DetMetric`中调用。
-
-### 2. 算法流程
-
-```mermaid
-flowchart TD
-    Start([开始评估]) --> Input[输入数据]
-    
-    Input --> BatchLoop{遍历Batch}
-    BatchLoop --> PrepareGT[准备GT数据结构]
-    BatchLoop --> PreparePred[准备预测数据结构]
-    
-    PrepareGT --> GTFormat["GT格式化:<br/>points: 多边形坐标<br/>text: 空字符串<br/>ignore: 忽略标签"]
-    
-    PreparePred --> PredFormat["预测格式化:<br/>points: 检测框坐标<br/>text: 空字符串<br/>score: 置信度(FCE)"]
-    
-    GTFormat --> Evaluate[调用evaluator.evaluate_image]
-    PredFormat --> Evaluate
-    
-    Evaluate --> IoUCalc[计算IoU矩阵]
-    IoUCalc --> Match[执行匹配算法]
-    Match --> SingleResult[单图评估结果]
-    
-    SingleResult --> StoreResult[存储到results列表]
-    StoreResult --> BatchLoop
-    
-    BatchLoop -->|所有batch处理完成| Combine[combine_results合并结果]
-    Combine --> FinalMetrics[最终指标计算]
-    
-    FinalMetrics --> Output["输出:<br/>precision: 精确度<br/>recall: 召回率<br/>hmean: 调和平均"]
-    Output --> End([结束])
-    
-    classDef inputOutput fill:#e3f2fd
-    classDef process fill:#f3e5f5
-    classDef calculation fill:#fff3e0
-    
-    class Start,End,Input,Output inputOutput
-    class PrepareGT,PreparePred,Evaluate,Match process
-    class IoUCalc,Combine,FinalMetrics calculation
-```
-
-### 3. 详细算法实现
-
-#### 3.1 数据预处理
-
-````python
-def __call__(self, preds, batch, **kwargs):
-    gt_polyons_batch = batch[2]  # 真实标注多边形
-    ignore_tags_batch = batch[3]  # 忽略标签
-    
-    for pred, gt_polyons, ignore_tags in zip(preds, gt_polyons_batch, ignore_tags_batch):
-        # 构建GT信息
-        gt_info_list = [
-            {"points": gt_polyon, "text": "", "ignore": ignore_tag}
-            for gt_polyon, ignore_tag in zip(gt_polyons, ignore_tags)
-        ]
-        # 构建检测信息
-        det_info_list = [
-            {"points": det_polyon, "text": ""} for det_polyon in pred["points"]
-        ]
-````
-
-#### 3.2 IoU计算核心算法
-
-````python
-def get_intersection_over_union(pD, pG):
-    """计算两个多边形的IoU"""
-    return get_intersection(pD, pG) / get_union(pD, pG)
-
-def get_intersection(pD, pG):
-    """计算交集面积"""
-    return Polygon(pD).intersection(Polygon(pG)).area
-
-def get_union(pD, pG):
-    """计算并集面积"""
-    return Polygon(pD).union(Polygon(pG)).area
-````
-
-#### 3.3 匹配策略
-
-算法采用**贪心匹配**策略:
-
-````python
-# 构建IoU矩阵
-iouMat = np.empty([len(gtPols), len(detPols)])
-for gtNum in range(len(gtPols)):
-    for detNum in range(len(detPols)):
-        pG = gtPols[gtNum]
-        pD = detPols[detNum]
-        iouMat[gtNum, detNum] = get_intersection_over_union(pD, pG)
-
-# 执行匹配
-for gtNum in range(len(gtPols)):
-    for detNum in range(len(detPols)):
-        if (gtRectMat[gtNum] == 0 and detRectMat[detNum] == 0 and 
-            gtNum not in gtDontCarePolsNum and detNum not in detDontCarePolsNum):
-            if iouMat[gtNum, detNum] > self.iou_constraint:  # 默认0.5
-                gtRectMat[gtNum] = 1      # 标记GT已匹配
-                detRectMat[detNum] = 1    # 标记检测框已匹配
-                detMatched += 1           # 增加匹配计数
-````
-
-### 4. 评估指标计算
-
-#### 4.1 基础指标
-
-- **Precision (精确度)**: `matched_detections / total_care_detections`
-- **Recall (召回率)**: `matched_detections / total_care_ground_truths`
-- **H-mean (调和平均数)**: `2 * precision * recall / (precision + recall)`
-
-#### 4.2 特殊情况处理
-
-````python
-if numGtCare == 0:
-    recall = float(1)
-    precision = float(0) if numDetCare > 0 else float(1)
-else:
-    recall = float(detMatched) / numGtCare
-    precision = 0 if numDetCare == 0 else float(detMatched) / numDetCare
-
-hmean = (0 if (precision + recall) == 0 
-         else 2.0 * precision * recall / (precision + recall))
-````
-
-### 5. Don't Care区域处理
-
-算法支持忽略特定区域的评估:
-
-````python
-# 标记GT中的don't care区域
-if dontCare:
-    gtDontCarePolsNum.append(len(gtPols) - 1)
-
-# 检测框与don't care区域的重叠处理
-for dontCarePol in gtDontCarePolsNum:
-    intersected_area = get_intersection(dontCarePol, detPol)
-    pdDimensions = Polygon(detPol).area
-    precision = (0 if pdDimensions == 0 else intersected_area / pdDimensions)
-    if precision > self.area_precision_constraint:  # 默认0.5
-        detDontCarePolsNum.append(len(detPols) - 1)
-````
-
-### 6. 多阈值评估 (DetFCEMetric)
-
-对于FCE模型,支持多个置信度阈值的评估:
-
-````python
-class DetFCEMetric(object):
-    def reset(self):
-        self.results = {0.3: [], 0.4: [], 0.5: [], 0.6: [], 0.7: [], 0.8: [], 0.9: []}
-    
-    def __call__(self, preds, batch, **kwargs):
-        for score_thr in self.results.keys():
-            det_info_list_thr = [
-                det_info for det_info in det_info_list 
-                if det_info["score"] >= score_thr
-            ]
-            result = self.evaluator.evaluate_image(gt_info_list, det_info_list_thr)
-            self.results[score_thr].append(result)
-````
-
-### 7. 算法特点
-
-1. **多边形支持**: 支持任意多边形检测框,不限于矩形
-2. **严格匹配**: 采用一对一匹配,避免重复计算
-3. **IoU阈值**: 默认0.5,可配置
-4. **忽略区域**: 支持don't care标注
-5. **鲁棒性**: 处理无效多边形和边界情况
-
-### 8. 与通用目标检测的差异
-
-- **多边形vs矩形**: 文本检测通常使用四边形而非轴对齐矩形
-- **密集场景**: 文本区域通常更密集,需要更精确的匹配策略
-- **形状敏感**: 文本的几何形状对识别影响更大
-
-这套算法已在ICDAR等国际文本检测竞赛中验证,能够准确评估各种文本检测模型的性能。
-
-# KIE说明
-
-## KIEMetric算法详解
-
-### 1. 算法概述
-
-`KIEMetric`是PaddleOCR中专门用于**关键信息抽取(Key Information Extraction, KIE)**任务的评估指标类,主要通过计算F1分数来评估模型性能。
-
-### 2. 应用场景
-
-KIEMetric主要用于以下KIE算法的评估:
-
-#### 2.1 支持的KIE算法
-- **VI-LayoutXLM**: 参考VI-LayoutXLM算法文档
-- **LayoutXLM**: 参考LayoutXLM算法文档
-- **SDMGR**: 参考SDMGR算法文档
-
-#### 2.2 KIE任务类型
-- **SER (Semantic Entity Recognition)**: 语义实体识别
-- **RE (Relation Extraction)**: 关系抽取
-
-### 3. 算法核心机制
-
-#### 3.1 数据处理流程
-
-```python
-def __call__(self, preds, batch, **kwargs):
-    nodes, _ = preds  # 模型预测结果
-    gts, tag = batch[4].squeeze(0), batch[5].tolist()[0]  # 真实标签
-    gts = gts[: tag[0], :1].reshape([-1])  # 有效标签截取
-    self.node.append(nodes.numpy())  # 累积预测结果
-    self.gt.append(gts)  # 累积真实标签
-```
-
-#### 3.2 F1分数计算
-
-```python
-def compute_f1_score(self, preds, gts):
-    ignores = [0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 25]  # 忽略的类别
-    C = preds.shape[1]  # 类别总数
-    classes = np.array(sorted(set(range(C)) - set(ignores)))  # 有效类别
-    
-    # 构建混淆矩阵
-    hist = (np.bincount((gts * C).astype("int64") + preds.argmax(1), minlength=C**2)
-            .reshape([C, C]).astype("float32"))
-    
-    # 计算各类别的precision、recall、F1
-    diag = np.diag(hist)
-    recalls = diag / hist.sum(1).clip(min=1)
-    precisions = diag / hist.sum(0).clip(min=1)
-    f1 = 2 * recalls * precisions / (recalls + precisions).clip(min=1e-8)
-    
-    return f1[classes]  # 返回有效类别的F1分数
-```
-
-### 4. 评估指标
-
-#### 4.1 主要指标
-- **H-mean**: 所有有效类别F1分数的调和平均数
-- **类别级F1**: 每个实体类别的F1分数
-
-#### 4.2 在XFUND数据集上的表现
-
-根据文档显示,在XFUND_zh数据集上:
-
-| 模型 | 任务 | H-mean |
-|------|------|--------|
-| VI-LayoutXLM | SER | 93.19% |
-| VI-LayoutXLM | RE | 83.92% |
-| LayoutXLM | SER | 90.38% |
-| LayoutXLM | RE | 74.83% |
-
-### 5. 使用示例
-
-#### 5.1 模型评估命令
-
-```bash
-# VI-LayoutXLM SER评估
-python3 tools/eval.py -c configs/kie/vi_layoutxlm/ser_vi_layoutxlm_xfund_zh.yml \
-  -o Architecture.Backbone.checkpoints=./output/ser_vi_layoutxlm_xfund_zh/best_accuracy
-```
-
-#### 5.2 评估输出示例
-
-```bash
-[2022/08/10 05:22:23] ppocr INFO: metric eval ***************
-[2022/08/10 05:22:23] ppocr INFO: hmean:0.8670120239257812
-[2022/08/10 05:22:23] ppocr INFO: fps:10.18816520530961
-```
-
-### 6. 算法特点
-
-#### 6.1 类别过滤机制
-- 忽略特定类别(如背景、填充等)
-- 只计算有意义的实体类别的F1分数
-
-#### 6.2 批量累积评估
-- 支持多批次数据的累积评估
-- 最终统一计算整体指标
-
-#### 6.3 标签动态截取
-- 根据`tag`信息动态截取有效标签长度
-- 避免填充标签影响评估结果
-
-### 7. 应用场景举例
-
-#### 7.1 文档信息抽取
-- **发票信息抽取**: 提取发票号、金额、日期等关键信息
-- **身份证信息抽取**: 提取姓名、身份证号、地址等
-- **表单信息抽取**: 提取表单中的各类字段信息
-
-#### 7.2 数据要求
-根据KIE使用指南,一般来说:
-- **训练数据量**: 对于固定场景,50张左右的训练图片即可达到可接受效果
-- **标注工具**: 推荐使用[PPOCRLabel](https://github.com/PFCCLab/PPOCRLabel/blob/main/README_ch.md)完成KIE标注
-
-KIEMetric作为KIE任务的核心评估工具,为模型性能提供了标准化、可靠的评估机制,是PaddleOCR文档理解能力的重要组成部分。
-
-# RecMetric说明
-
-## RecMetric算法详解
-
-### 1. 算法概述
-
-`RecMetric`是PaddleOCR中专门用于**文本识别(Text Recognition)**任务的评估指标类,通过计算准确率和编辑距离来评估模型性能。
-
-### 2. 应用场景
-
-RecMetric主要用于以下文本识别算法的评估:
-
-#### 2.1 支持的文本识别算法
-根据文档显示,RecMetric广泛应用于:
-
-**基础识别算法:**
-- **CRNN**: 参考CRNN算法文档
-- **RARE**: 参考RARE算法文档
-- **StarNet**: 参考StarNet算法文档
-- **Rosetta**: 参考Rosetta算法文档
-
-**高级识别算法:**
-- **NRTR**: 参考NRTR算法文档
-- **SAR**: 参考SAR算法文档
-- **SRN**: 参考SRN算法文档
-- **RFL**: 参考RFL算法文档
-- **ParseQ**: 参考ParseQ算法文档
-- **CPPD**: 参考CPPD算法文档
-
-### 3. 核心算法机制
-
-#### 3.1 主要评估指标
-
-```python
-def __call__(self, pred_label, *args, **kwargs):
-    preds, labels = pred_label
-    correct_num = 0
-    all_num = 0
-    norm_edit_dis = 0.0
-    
-    for (pred, pred_conf), (target, _) in zip(preds, labels):
-        # 文本预处理
-        if self.ignore_space:
-            pred = pred.replace(" ", "")
-            target = target.replace(" ", "")
-        if self.is_filter:
-            pred = self._normalize_text(pred)
-            target = self._normalize_text(target)
-            
-        # 计算编辑距离
-        norm_edit_dis += Levenshtein.normalized_distance(pred, target)
-        
-        # 计算精确匹配
-        if pred == target:
-            correct_num += 1
-        all_num += 1
-```
-
-#### 3.2 核心评估指标
-
-**1. 准确率 (Accuracy)**
-- **计算方式**: `acc = correct_num / total_num`
-- **含义**: 完全正确识别的样本比例
-
-**2. 归一化编辑距离 (Normalized Edit Distance)**
-- **计算方式**: `norm_edit_dis = 1 - total_edit_distance / total_num`
-- **含义**: 基于Levenshtein距离的相似度指标
-- **范围**: [0, 1],值越大表示识别效果越好
-
-#### 3.3 文本预处理机制
-
-```python
-def _normalize_text(self, text):
-    text = "".join(
-        filter(lambda x: x in (string.digits + string.ascii_letters), text)
-    )
-    return text.lower()
-```
-
-**预处理选项:**
-- `ignore_space`: 忽略空格字符
-- `is_filter`: 只保留数字和字母,转为小写
-
-### 4. 典型性能表现
-
-根据算法概览文档,各算法在标准数据集上的表现:
-
-| 算法 | 骨干网络 | 准确率 | 配置文件 |
-|------|----------|--------|----------|
-| CRNN | Resnet34_vd | 81.04% | rec_r34_vd_none_bilstm_ctc |
-| RARE | Resnet34_vd | 83.98% | rec_r34_vd_tps_bilstm_att |
-| StarNet | Resnet34_vd | 84.44% | rec_r34_vd_tps_bilstm_ctc |
-| NRTR | MTB | 84.21% | rec_mtb_nrtr |
-| RFL | ResNetRFL | 88.63% | rec_resnet_rfl_att |
-| ParseQ | VIT | 91.24% | rec_vit_parseq_synth |
-
-### 5. 使用示例
-
-#### 5.1 评估命令示例
-
-```bash
-# CRNN模型评估
-python3 tools/eval.py -c configs/rec/rec_r34_vd_none_bilstm_ctc.yml \
-  -o Global.pretrained_model=./rec_r34_vd_none_bilstm_ctc_v2.0_train/best_accuracy
-
-# NRTR模型评估
-python3 tools/eval.py -c configs/rec/rec_mtb_nrtr.yml \
-  -o Global.pretrained_model=./rec_mtb_nrtr_train/best_accuracy
-```
-
-#### 5.2 评估输出示例
-
-```bash
-[2022/08/10 05:22:23] ppocr INFO: metric eval ***************
-[2022/08/10 05:22:23] ppocr INFO: acc: 0.8563
-[2022/08/10 05:22:23] ppocr INFO: norm_edit_dis: 0.9124
-[2022/08/10 05:22:23] ppocr INFO: fps: 156.25
-```
-
-### 6. 算法特点
-
-#### 6.1 灵活的文本处理
-- 支持空格忽略
-- 支持字符过滤和标准化
-- 适应不同语言和字符集
-
-#### 6.2 双重评估机制
-- **严格评估**: 完全匹配的准确率
-- **宽松评估**: 基于编辑距离的相似度
-
-#### 6.3 批量累积统计
-- 支持多批次数据的累积评估
-- 提供实时和最终评估结果
-
-### 7. 应用场景举例
-
-#### 7.1 场景文本识别
-- **自然场景**: 街景、广告牌、标识等文本识别
-- **文档识别**: 扫描文档、票据、表单等
-- **验证码识别**: 网站验证码、安全码等
-
-#### 7.2 多语言文本识别
-- **英文识别**: 基于MJSynth和SynthText训练
-- **中文识别**: 支持中文字符识别评估
-- **多语言**: 支持各种语言的文本识别评估
-
-#### 7.3 不同复杂度场景
-根据CPPD算法文档显示的评估结果:
-
-| 场景类型 | CPPD Base准确率 |
-|----------|----------------|
-| 一般场景 | 97.44% |
-| 弯曲文本 | 74.4% |
-| 多方向文本 | 76.1% |
-| 艺术字体 | 98.6% |
-| 无上下文 | 55.3% |
-
-### 8. 与其他评估指标的关系
-
-在PaddleOCR中,除了RecMetric外,还有:
-- `CANMetric`: 专用于手写公式识别
-- `LaTeXOCRMetric`: 专用于LaTeX公式识别
-- `CNTMetric`: 简化版的计数评估
-
-RecMetric作为通用文本识别评估工具,为各种文本识别算法提供了标准化、可靠的性能评估机制,是PaddleOCR文本识别能力评估的核心组件。
-
-## Levenshtein算法详解
-```
-详细说明RecMetric引用的Levenshtein算法
-```
-
-### 1. 算法概述
-
-Levenshtein距离(编辑距离)是衡量两个字符串相似度的重要算法,在PaddleOCR的RecMetric中通过`rapidfuzz.distance.Levenshtein`库实现。
-
-### 2. 在RecMetric中的应用
-
-#### 2.1 核心使用位置
-
-````python
-from rapidfuzz.distance import Levenshtein
-
-def __call__(self, pred_label, *args, **kwargs):
-    for (pred, pred_conf), (target, _) in zip(preds, labels):
-        # 文本预处理
-        if self.ignore_space:
-            pred = pred.replace(" ", "")
-            target = target.replace(" ", "")
-        if self.is_filter:
-            pred = self._normalize_text(pred)
-            target = self._normalize_text(target)
-            
-        # 计算归一化编辑距离
-        norm_edit_dis += Levenshtein.normalized_distance(pred, target)
-````
-
-### 3. Levenshtein算法原理
-
-#### 3.1 基本定义
-
-Levenshtein距离是指两个字符串之间,由一个转换成另一个所需的**最少编辑操作次数**。
-
-**允许的编辑操作:**
-- **插入** (Insertion): 在字符串中插入一个字符
-- **删除** (Deletion): 从字符串中删除一个字符  
-- **替换** (Substitution): 将字符串中的一个字符替换为另一个字符
-
-#### 3.2 动态规划算法
-
-```python
-def levenshtein_distance(s1, s2):
-    """计算两个字符串的Levenshtein距离"""
-    m, n = len(s1), len(s2)
-    
-    # 创建DP表
-    dp = [[0] * (n + 1) for _ in range(m + 1)]
-    
-    # 初始化边界条件
-    for i in range(m + 1):
-        dp[i][0] = i  # 删除s1中的i个字符
-    for j in range(n + 1):
-        dp[0][j] = j  # 插入s2中的j个字符
-    
-    # 填充DP表
-    for i in range(1, m + 1):
-        for j in range(1, n + 1):
-            if s1[i-1] == s2[j-1]:
-                dp[i][j] = dp[i-1][j-1]  # 字符相同,无需操作
-            else:
-                dp[i][j] = 1 + min(
-                    dp[i-1][j],    # 删除s1[i-1]
-                    dp[i][j-1],    # 插入s2[j-1]
-                    dp[i-1][j-1]   # 替换s1[i-1]为s2[j-1]
-                )
-    
-    return dp[m][n]
-
-def normalized_distance(s1, s2):
-    """计算归一化编辑距离"""
-    distance = levenshtein_distance(s1, s2)
-    max_len = max(len(s1), len(s2))
-    return distance / max_len if max_len > 0 else 0.0
-```
-
-### 4. 算法示例演示
-
-#### 4.1 具体计算过程
-
-**示例:** 计算 "kitten" 和 "sitting" 的编辑距离
-
-```
-    ""  s  i  t  t  i  n  g
-""   0  1  2  3  4  5  6  7
-k    1  1  2  3  4  5  6  7
-i    2  2  1  2  3  4  5  6
-t    3  3  2  1  2  3  4  5
-t    4  4  3  2  1  2  3  4
-e    5  5  4  3  2  2  3  4
-n    6  6  5  4  3  3  2  3
-```
-
-**编辑操作序列:**
-1. k → s (替换)
-2. i → i (无操作)
-3. t → t (无操作)
-4. t → t (无操作)
-5. e → i (替换)
-6. n → n (无操作)
-7. 插入 g
-
-**结果:** 编辑距离 = 3,归一化距离 = 3/7 ≈ 0.429
-
-### 5. 在不同Metric中的应用
-
-#### 5.1 RecMetric中的应用
-
-````python
-# 基础文本识别评估
-norm_edit_dis += Levenshtein.normalized_distance(pred, target)
-final_score = 1 - norm_edit_dis / (all_num + self.eps)  # 转换为相似度分数
-````
-
-#### 5.2 LaTeXOCRMetric中的应用
-
-````python
-# LaTeX公式识别评估
-lev_dist.append(Levenshtein.normalized_distance(prediction, labels))
-self.edit_dist = sum(lev_dist)  # 累积编辑距离
-cur_edit_distance = sum(self.edit_right) / self.exp_total_num
-````
-
-### 6. 性能优化特性
-
-#### 6.1 RapidFuzz库优势
-
-PaddleOCR使用[`rapidfuzz`](https://github.com/maxbachmann/RapidFuzz)库而非标准库:
-
-- **高性能**: C++实现,比纯Python快10-100倍
-- **内存优化**: 针对大量文本比较进行了优化
-- **多种距离算法**: 支持多种字符串相似度算法
-
-#### 6.2 复杂度分析
-
-- **时间复杂度**: O(m×n),其中m和n是两个字符串的长度
-- **空间复杂度**: O(m×n),可优化为O(min(m,n))
-
-### 7. 文本识别场景中的意义
-
-#### 7.1 评估指标含义
-
-**归一化编辑距离 (norm_edit_dis)**:
-- **范围**: [0, 1]
-- **0**: 完全不同
-- **1**: 完全相同
-- **意义**: 即使不完全匹配,也能量化相似程度
-
-#### 7.2 实际应用效果
-
-```python
-# 示例评估结果
-predictions = ["hello", "wrold", "paddle"]
-targets =     ["hello", "world", "paddle"]
-
-# 计算结果:
-# "hello" vs "hello": distance=0, normalized=0, similarity=1.0
-# "wrold" vs "world": distance=2, normalized=0.4, similarity=0.6  
-# "paddle" vs "paddle": distance=0, normalized=0, similarity=1.0
-# 
-# 平均相似度 = (1.0 + 0.6 + 1.0) / 3 = 0.867
-```
-
-### 8. 与其他相似度算法的比较
-
-| 算法 | 特点 | 应用场景 |
-|------|------|----------|
-| **Levenshtein** | 考虑插入、删除、替换 | 通用文本相似度 |
-| **Jaro-Winkler** | 重视字符串开头的匹配 | 姓名匹配 |
-| **Cosine** | 基于向量空间 | 文档相似度 |
-| **BLEU** | N-gram匹配 | 机器翻译评估 |
-
-### 9. 在PaddleOCR中的优势
-
-1. **鲁棒性**: 对于部分错误识别仍能给出合理评分
-2. **标准化**: 提供业界标准的文本相似度评估
-3. **实时性**: 高效计算支持大规模评估
-4. **可解释性**: 编辑距离直观反映识别错误程度
-
-Levenshtein算法在RecMetric中提供了比简单准确率更细粒度的评估能力,能够更好地反映文本识别模型的真实性能水平。
-
-# CTMetric说明
-
-## CTMetric算法详解
-
-### 1. 算法概述
-
-`CTMetric`是PaddleOCR中专门用于**CentripetalText (CT)文本检测算法**评估的指标类。CT是一种高效的场景文本检测方法,CTMetric用于评估其检测性能。
-
-### 2. 应用场景
-
-#### 2.1 CT算法简介
-根据CT算法文档:
-
-**论文信息:**
-> [CentripetalText: An Efficient Text Instance Representation for Scene Text Detection](https://arxiv.org/abs/2107.05945)
-> Tao Sheng, Jie Chen, Zhouhui Lian
-> NeurIPS, 2021
-
-**性能表现:**
-在Total-Text文本检测公开数据集上:
-
-| 模型 | 骨干网络 | 配置文件 | Precision | Recall | Hmean | 下载链接 |
-|------|----------|----------|-----------|--------|-------|----------|
-| CT | ResNet18_vd | det_r18_vd_ct.yml | 88.68% | 81.70% | 85.05% | [训练模型](https://paddleocr.bj.bcebos.com/dygraph_v2.0/en/det_r18_ct_train.tar) |
-
-### 3. 核心算法机制
-
-#### 3.1 评估流程
-
-```python
-def __call__(self, preds, batch, **kwargs):
-    # 注意:目前只支持batch_size=1,因为不同样本的标签长度不等
-    assert len(preds) == 1, "CentripetalText test now only support batch_size=1."
-    
-    label = batch[2]    # 真实标注信息
-    text = batch[3]     # 真实文本内容
-    pred = preds[0]["points"]  # 预测的检测框点坐标
-    
-    # 计算CT特定的评估分数
-    result = get_score_C(label, text, pred)
-    self.results.append(result)
-```
-
-#### 3.2 CT特定评估方法
-
-根据`get_score_C`函数实现,CT算法使用特殊的评估方式:
-
-```python
-def get_score_C(gt_label, text, pred_bboxes):
-    """
-    get score for CentripetalText (CT) prediction.
-    """
-    # 处理预测结果
-    detections = []
-    for item in pred_bboxes:
-        detections.append(item[:, ::-1].reshape(-1))
-    
-    # 读取真实标注
-    groundtruths = gt_reading_mod(gt_label, text)
-    
-    # 过滤检测结果
-    detections = detection_filtering(detections, groundtruths)
-    
-    # 计算sigma和tau指标
-    local_sigma_table = np.zeros((len(groundtruths), len(detections)))
-    local_tau_table = np.zeros((len(groundtruths), len(detections)))
-    
-    for gt_id, gt in enumerate(groundtruths):
-        for det_id, detection in enumerate(detections):
-            # sigma = 交集面积 / GT面积
-            local_sigma_table[gt_id, det_id] = sigma_calculation(det_p, gt_p)
-            # tau = 交集面积 / 检测面积  
-            local_tau_table[gt_id, det_id] = tau_calculation(det_p, gt_p)
-```
-
-#### 3.3 关键评估指标
-
-**1. Sigma计算**
-```python
-def sigma_calculation(det_p, gt_p):
-    """
-    sigma = inter_area / gt_area
-    """
-    if gt_p.area() == 0.0:
-        return 0
-    return get_intersection(det_p, gt_p) / gt_p.area()
-```
-
-**2. Tau计算**
-```python
-def tau_calculation(det_p, gt_p):
-    """
-    tau = inter_area / det_area
-    """
-    if det_p.area() == 0.0:
-        return 0
-    return get_intersection(det_p, gt_p) / det_p.area()
-```
-
-### 4. 后处理机制
-
-CT算法配合专门的后处理类`CTPostProcess`:
-
-```python
-class CTPostProcess(object):
-    """
-    The post process for Centripetal Text (CT).
-    """
-    def __init__(self, min_score=0.88, min_area=16, box_type="poly", **kwargs):
-        self.min_score = min_score      # 最小置信度阈值
-        self.min_area = min_area        # 最小区域面积
-        self.box_type = box_type        # 输出框类型:rect/poly
-```
-
-### 5. 使用示例
-
-#### 5.1 模型训练
-```bash
-# CT模型训练
-python3 tools/train.py -c configs/det/det_r18_vd_ct.yml
-```
-
-#### 5.2 模型评估
-```bash
-# CT模型评估
-python3 tools/eval.py -c configs/det/det_r18_vd_ct.yml \
-  -o Global.pretrained_model=./det_r18_ct_train/best_accuracy
-```
-
-#### 5.3 模型推理
-```bash
-# CT模型推理
-python3 tools/infer_det.py -c configs/det/det_r18_vd_ct.yml \
-  -o Global.pretrained_model=./inference/det_ct/inference.pdmodel \
-     Global.infer_img=./doc/imgs_en/img_10.jpg
-```
-
-### 6. 算法特点
-
-#### 6.1 CT算法优势
-- **高效表示**: 使用向心力文本表示方法
-- **任意形状**: 支持弯曲、倾斜等复杂文本检测
-- **端到端**: 统一的检测和识别框架
-
-#### 6.2 评估特点
-- **专用指标**: 使用sigma和tau指标评估重叠度
-- **批量限制**: 目前只支持batch_size=1的评估
-- **多边形支持**: 支持任意多边形检测框评估
-
-### 7. 与其他检测算法的对比
-
-| 算法 | 骨干网络 | CTW1500数据集 | 特点 |
-|------|----------|---------------|------|
-| FCE | ResNet50_dcn | Hmean: 85.27% | 傅里叶轮廓嵌入 |
-| DRRG | ResNet50_vd | Hmean: 85.18% | 深度关系推理图 |
-| **CT** | **ResNet18_vd** | **Hmean: 85.05%** | **向心力文本表示** |
-
-### 8. 实际应用场景
-
-#### 8.1 复杂场景文本检测
-- **弯曲文本**: 商品包装、广告牌等弯曲文本
-- **任意方向**: 旋转、倾斜的文本检测
-- **密集文本**: 文档、海报等密集排列的文本
-
-#### 8.2 数据集适用性
-- **Total-Text**: 专门用于弯曲文本检测的数据集
-- **CTW1500**: 包含大量弯曲文本的中英文数据集
-- **ICDAR系列**: 各种文本检测竞赛数据集
-
-CTMetric作为CT算法的专用评估工具,为这种先进的文本检测方法提供了准确、可靠的性能评估机制,特别适用于复杂场景下的文本检测任务评估。
-
-# blue说明
-
-## compute_bleu_score函数详解
-
-### 1. 函数概述
-
-`compute_bleu_score`是PaddleOCR中用于计算**BLEU (Bilingual Evaluation Understudy)分数**的核心函数,主要用于评估**序列到序列**任务的质量,特别是**公式识别**和**机器翻译**类任务。
-
-### 2. 主要应用场景
-
-#### 2.1 公式识别模型评估
-
-根据工作空间信息,BLEU分数广泛用于以下公式识别算法:
-
-**UniMERNet模型:**
-- 在UniMERNet算法文档中提到的各个测试集评估
-- SPE-BLEU、CPE-BLEU、SCE-BLEU、HWE-BLEU等指标
-
-**PP-FormulaNet系列:**
-- PP-FormulaNet算法文档中的En-BLEU评估
-- PP-FormulaNet-S/L、PP-FormulaNet_plus系列模型
-
-**LaTeX-OCR模型:**
-- LaTeX-OCR算法文档中的BLEU score评估
-
-#### 2.2 评估命令中的应用
-
-在`eval.py`中自动启用BLEU评估:
-
-```python
-if config["Architecture"]["algorithm"] == "LaTeX_OCR":
-    model_type = "latex_ocr"
-    config["Metric"]["cal_bleu_score"] = True
-elif config["Architecture"]["algorithm"] == "UniMERNet":
-    model_type = "unimernet"
-    config["Metric"]["cal_bleu_score"] = True
-elif config["Architecture"]["algorithm"] in [
-    "PP-FormulaNet-S", "PP-FormulaNet-L",
-    "PP-FormulaNet_plus-S", "PP-FormulaNet_plus-M", "PP-FormulaNet_plus-L",
-]:
-    model_type = "pp_formulanet"
-    config["Metric"]["cal_bleu_score"] = True
-```
-
-### 3. 算法实现细节
-
-#### 3.1 核心函数结构
-
-```python
-def compute_bleu_score(predictions, references, tokenizer=Tokenizer13a(), max_order=4, smooth=False):
-    # 处理单一参考的情况
-    if isinstance(references[0], str):
-        references = [[ref] for ref in references]
-    
-    # 分词处理
-    references = [[tokenizer(r) for r in ref] for ref in references]
-    predictions = [tokenizer(p) for p in predictions]
-    
-    # 计算BLEU分数
-    score = compute_bleu(
-        reference_corpus=references,
-        translation_corpus=predictions,
-        max_order=max_order,
-        smooth=smooth,
-    )
-    (bleu, precisions, bp, ratio, translation_length, reference_length) = score
-    return bleu
-```
-
-#### 3.2 BLEU分数计算流程
-
-**1. N-gram提取:**
-```python
-def _get_ngrams(segment, max_order):
-    ngram_counts = collections.Counter()
-    for order in range(1, max_order + 1):
-        for i in range(0, len(segment) - order + 1):
-            ngram = tuple(segment[i : i + order])
-            ngram_counts[ngram] += 1
-    return ngram_counts
-```
-
-**2. 精确度计算:**
-```python
-# 对每个n-gram阶数计算精确度
-for i in range(0, max_order):
-    if possible_matches_by_order[i] > 0:
-        precisions[i] = float(matches_by_order[i]) / possible_matches_by_order[i]
-    else:
-        precisions[i] = 0.0
-```
-
-**3. 几何平均和惩罚因子:**
-```python
-# 几何平均
-if min(precisions) > 0:
-    p_log_sum = sum((1.0 / max_order) * math.log(p) for p in precisions)
-    geo_mean = math.exp(p_log_sum)
-else:
-    geo_mean = 0
-
-# 简洁惩罚 (Brevity Penalty)
-ratio = float(translation_length) / reference_length
-if ratio > 1.0:
-    bp = 1.0
-else:
-    bp = math.exp(1 - 1.0 / ratio)
-
-bleu = geo_mean * bp
-```
-
-### 4. 分词器 (Tokenizer) 类型
-
-#### 4.1 Tokenizer13a(默认)
-- **标准化处理**: 替换HTML实体、移除换行等
-- **正则表达式分词**: 处理标点符号、数字等
-- **兼容mteval-v13a**: 与WMT评估标准对齐
-
-#### 4.2 TokenizerRegexp
-- **基础正则分词**: 更简单的分词规则
-- **快速处理**: 适用于简单文本
-
-### 5. 典型性能表现
-
-根据文档中的评估结果:
-
-#### 5.1 UniMERNet模型
-| 测试集 | BLEU分数 | 说明 |
-|--------|----------|------|
-| SPE | 85.91% | 简单印刷表达式 |
-| CPE | ~75% | 复杂印刷表达式 |
-| SCE | ~70% | 屏幕截图表达式 |
-| HWE | ~65% | 手写表达式 |
-
-#### 5.2 PP-FormulaNet模型
-| 模型 | En-BLEU | GPU推理耗时 |
-|------|---------|-------------|
-| UniMERNet | 85.91% | 2266.96ms |
-| PP-FormulaNet-L | ~80% | <1000ms |
-
-### 6. 使用示例
-
-#### 6.1 评估命令
-```bash
-# UniMERNet SPE测试集评估
-python3 tools/eval.py -c configs/rec/UniMERNet.yaml -o \
-  Eval.dataset.data_dir=./train_data/UniMERNet/UniMER-Test/spe \
-  Eval.dataset.label_file_list=["./train_data/UniMERNet/test_unimernet_spe.txt"] \
-  Global.pretrained_model=./rec_unimernet_train/best_accuracy.pdparams
-
-# LaTeX-OCR评估
-python3 tools/eval.py -c configs/rec/latex_ocr.yml \
-  -o Global.pretrained_model=./latex_ocr_train/best_accuracy
-```
-
-#### 6.2 在RecMetric中的集成
-```python
-class LaTeXOCRMetric(object):
-    def __call__(self, preds, batch, **kwargs):
-        for labels, prediction in zip(word_label, word_pred):
-            # 计算BLEU分数
-            bleu_list.append(compute_bleu_score([prediction], [labels]))
-            # 计算编辑距离
-            lev_dist.append(Levenshtein.normalized_distance(prediction, labels))
-```
-
-### 7. 算法特点
-
-#### 7.1 多级N-gram评估
-- **1-gram**: 词汇重叠度
-- **2-gram**: 短语流畅度
-- **3-gram**: 局部连贯性
-- **4-gram**: 整体质量
-
-#### 7.2 长度惩罚机制
-- 防止过短翻译获得虚高分数
-- 平衡精确度和召回率
-
-#### 7.3 多参考支持
-- 支持多个标准答案
-- 取最佳匹配分数
-
-### 8. 与编辑距离的对比
-
-| 指标 | BLEU | 编辑距离 |
-|------|------|----------|
-| 粒度 | N-gram级别 | 字符/词级别 |
-| 重点 | 流畅度+准确性 | 准确性 |
-| 应用 | 长序列生成 | 精确匹配 |
-| 计算 | 复杂 | 简单 |
-
-`compute_bleu_score`作为国际标准的文本生成质量评估指标,为PaddleOCR的公式识别等序列生成任务提供了专业、可靠的评估机制,是衡量模型在复杂文本生成任务中性能的重要工具。
-
-# E2EMetric说明
-```
-@workspace  详细解释E2EMetric算法,用在哪里?
-```
-
-## E2EMetric算法详解
-
-### 1. 算法概述
-
-[`E2EMetric`]e2e_metric.py )是PaddleOCR中专门用于**端到端(End-to-End)OCR**任务评估的指标类,能够同时评估文本检测和识别的综合性能。
-
-### 2. 主要应用场景
-
-#### 2.1 PGNet端到端算法评估
-
-algorithm_e2e_pgnet.md ):
-
-**PGNet性能表现(Total-Text数据集):**
-
-| 模型 | det_precision | det_recall | det_f_score | e2e_precision | e2e_recall | e2e_f_score | FPS |
-|------|---------------|------------|-------------|---------------|------------|-------------|-----|
-| Paper | 85.30% | 86.80% | 86.10% | - | - | 61.70% | 38.20 |
-| PaddleOCR | 87.03% | 82.48% | 84.69% | 61.71% | 58.43% | **60.03%** | 48.73 |
-
-#### 2.2 评估命令使用
-
-```bash
-# PGNet端到端模型评估
-python3 tools/eval.py -c configs/e2e/e2e_r50_vd_pg.yml \
-  -o Global.checkpoints="./output/e2e_pgnet/best_accuracy"
-```
-
-### 3. 核心算法机制
-
-#### 3.1 双模式评估
-
-```python
-def __call__(self, preds, batch, **kwargs):
-    if self.mode == "A":
-        # 模式A:直接从batch中获取GT信息
-        gt_polyons_batch = batch[2]      # 真实多边形坐标
-        temp_gt_strs_batch = batch[3][0] # 真实文本索引
-        ignore_tags_batch = batch[4]     # 忽略标签
-        
-        # 将索引转换为文本字符串
-        for temp_list in temp_gt_strs_batch:
-            t = ""
-            for index in temp_list:
-                if index < self.max_index:
-                    t += self.label_list[index]
-            gt_strs_batch.append(t)
-            
-        result = get_socre_A(gt_info_list, e2e_info_list)
-    else:
-        # 模式B:从预定义的GT文件中读取信息
-        img_id = batch[5][0]
-        result = get_socre_B(self.gt_mat_dir, img_id, e2e_info_list)
-```
-
-#### 3.2 评估流程
-
-```mermaid
-graph TD
-    A[输入预测结果和GT] --> B{选择评估模式}
-    B -->|模式A| C[从batch解析GT]
-    B -->|模式B| D[从文件读取GT]
-    
-    C --> E[构造GT信息列表]
-    D --> E
-    
-    E --> F[构造预测信息列表]
-    F --> G[计算检测匹配]
-    G --> H[计算识别匹配]
-    H --> I[累计评估结果]
-    I --> J[返回综合指标]
-    
-    G --> G1[sigma计算:<br/>交集/GT面积]
-    G --> G2[tau计算:<br/>交集/预测面积]
-    
-    H --> H1[一对一匹配]
-    H --> H2[一对多匹配]
-    H --> H3[多对一匹配]
-    
-    J --> K[检测指标:<br/>precision, recall, hmean]
-    J --> L[端到端指标:<br/>precision_e2e, recall_e2e, f_score_e2e]
-    
-    style A fill:#e1f5fe
-    style J fill:#e8f5e8
-    style K fill:#fff3e0
-    style L fill:#fff3e0
-```
-
-### 4. 核心评估指标
-
-#### 4.1 检测层面指标
-- **precision**: 正确检测框 / 总预测框
-- **recall**: 正确检测框 / 总真实框  
-- **hmean**: 检测精确率和召回率的调和平均数
-
-#### 4.2 端到端指标
-- **precision_e2e**: 检测+识别都正确的数量 / 总预测数量
-- **recall_e2e**: 检测+识别都正确的数量 / 总真实数量
-- **f_score_e2e**: 端到端精确率和召回率的调和平均数
-
-#### 4.3 匹配策略
-
-基于[`Deteval.py`]Deteval.py )实现:
-
-```python
-# 关键参数设置
-tr = 0.7  # 检测阈值
-tp = 0.6  # 识别阈值  
-fsc_k = 0.8  # 多对一/一对多匹配权重
-k = 2  # 最小重叠数量
-
-# 三种匹配模式
-def one_to_one():    # 一对一精确匹配
-def one_to_many():   # 一个GT对应多个预测
-def many_to_one():   # 多个GT对应一个预测
-```
-
-### 5. 评估结果输出
-
-#### 5.1 典型输出示例
-
-根据[`eval_end2end.py`]eval_end2end.py ):
-
-```bash
-hit, dt_count, gt_count 1250 1420 1380
-character_acc: 89.45%
-avg_edit_dist_field: 0.18
-avg_edit_dist_img: 2.50
-precision: 88.03%
-recall: 90.58%
-fmeasure: 89.29%
-```
-
-#### 5.2 详细指标含义
-
-| 指标 | 含义 | 计算方式 |
-|------|------|----------|
-| character_acc | 字符准确率 | 1 - 总编辑距离/总字符数 |
-| avg_edit_dist_field | 平均字段编辑距离 | 总编辑距离/GT字段数 |
-| avg_edit_dist_img | 平均图像编辑距离 | 总编辑距离/图像数 |
-| precision | 检测精确率 | 匹配成功数/预测总数 |
-| recall | 检测召回率 | 匹配成功数/GT总数 |
-| fmeasure | 检测F1分数 | 2×precision×recall/(precision+recall) |
-
-### 6. 数据格式要求
-
-#### 6.1 预测结果格式
-
-```python
-preds = {
-    "points": [[[x1,y1], [x2,y2], [x3,y3], [x4,y4]], ...],  # 检测框坐标
-    "texts": ["识别文本1", "识别文本2", ...]                    # 识别结果
-}
-```
-
-#### 6.2 真实标注格式
-
-```python
-# 模式A:从batch获取
-batch = [
-    image,           # batch[0]: 图像数据
-    shape,           # batch[1]: 图像形状
-    gt_polyons,      # batch[2]: GT多边形坐标
-    gt_text_indices, # batch[3]: GT文本索引  
-    ignore_tags,     # batch[4]: 忽略标签
-    img_id          # batch[5]: 图像ID(模式B使用)
-]
-
-# 模式B:从GT文件读取
-gt_file_format = {
-    "points": [[x1,y1], [x2,y2], [x3,y3], [x4,y4]],
-    "text": "真实文本内容",
-    "ignore": False
-}
-```
-
-### 7. 使用示例
-
-#### 7.1 配置文件设置
-
-```yaml
-# configs/e2e/e2e_r50_vd_pg.yml
-Metric:
-  name: E2EMetric
-  mode: "A"  # 或 "B"
-  gt_mat_dir: "./path/to/gt_files"  # 模式B需要
-  character_dict_path: "./ppocr/utils/ppocr_keys_v1.txt"
-  main_indicator: "f_score_e2e"
-```
-
-#### 7.2 推理和评估
-
-```bash
-# PGNet四边形文本(ICDAR2015)
-python3 tools/infer/predict_e2e.py \
-  --e2e_algorithm="PGNet" \
-  --image_dir="./doc/imgs_en/img_10.jpg" \
-  --e2e_model_dir="./inference/e2e/" \
-  --e2e_pgnet_valid_set="partvgg"
-
-# PGNet弯曲文本(Total-Text)  
-python3 tools/infer/predict_e2e.py \
-  --e2e_algorithm="PGNet" \
-  --image_dir="./doc/imgs_en/img623.jpg" \
-  --e2e_model_dir="./inference/e2e/" \
-  --e2e_pgnet_valid_set="totaltext"
-```
-
-### 8. 算法特点
-
-#### 8.1 综合评估
-- 同时评估检测和识别性能
-- 提供端到端综合指标
-- 支持复杂匹配策略
-
-#### 8.2 灵活配置
-- 支持两种评估模式
-- 可配置匹配阈值
-- 适应不同数据集格式
-
-#### 8.3 鲁棒性强
-- 处理各种匹配情况
-- 支持忽略区域
-- 容错能力强
-
-E2EMetric作为端到端OCR评估的核心工具,为PGNet等算法提供了全面、准确的性能评估机制,特别适用于需要同时考虑检测和识别质量的应用场景。

+ 0 - 200
zhch/TEDS算法说明.md

@@ -1,200 +0,0 @@
-## TEDS算法详解
-![1754273457856](image/TEDS算法说明/1754273457856.png)
-详细说明TEDS(Tree-Edit-Distance-based Similarity)算法及其在PaddleOCR中的应用。
-
-### 1. 算法概述
-
-**TEDS (Tree-Edit-Distance-based Similarity)** 是专门用于**表格识别评估**的指标,由IBM研究院开发。它通过计算预测表格HTML结构与真实表格HTML结构之间的树编辑距离来评估表格识别的准确性。
-
-### 2. 核心原理
-
-#### 2.1 树编辑距离计算
-
-TEDS基于**APTED (All-Pairs Tree Edit Distance)**算法:
-
-```python
-def evaluate(self, pred, true):
-    """计算单个样本的TEDS分数"""
-    # 解析HTML为树结构
-    pred = html.fromstring(pred, parser=parser)
-    true = html.fromstring(true, parser=parser)
-    
-    # 转换为TableTree格式
-    tree_pred = self.load_html_tree(pred)
-    tree_true = self.load_html_tree(true)
-    
-    # 计算树编辑距离
-    distance = APTED(tree_pred, tree_true, CustomConfig()).compute_edit_distance()
-    
-    # 归一化为相似度分数
-    return 1.0 - (float(distance) / n_nodes)
-```
-
-#### 2.2 TableTree结构
-
-```python
-class TableTree(Tree):
-    def __init__(self, tag, colspan=None, rowspan=None, content=None, *children):
-        self.tag = tag          # HTML标签 (table, tr, td等)
-        self.colspan = colspan  # 列跨度
-        self.rowspan = rowspan  # 行跨度  
-        self.content = content  # 单元格内容
-        self.children = list(children)  # 子节点
-```
-
-### 3. 评估指标计算
-
-#### 3.1 节点比较策略
-
-```python
-class CustomConfig(Config):
-    def rename(self, node1, node2):
-        """比较两个节点的相似度"""
-        # 结构不匹配的惩罚
-        if ((node1.tag != node2.tag) or 
-            (node1.colspan != node2.colspan) or 
-            (node1.rowspan != node2.rowspan)):
-            return 1.0
-            
-        # td节点的内容比较
-        if node1.tag == "td":
-            if node1.content or node2.content:
-                return Levenshtein.normalized_distance(node1.content, node2.content)
-        return 0.0
-```
-
-#### 3.2 多种比较模式
-
-**1. 标准模式 (CustomConfig)**
-- 同时考虑结构和内容
-- 使用Levenshtein距离比较文本内容
-
-**2. 忽略短文本模式 (CustomConfig_del_short)**
-```python
-if len(node1_content) < 3:
-    node1_content = ["####"]  # 替换短文本为占位符
-```
-
-**3. 忽略空格模式 (CustomConfig_del_block)**
-```python
-while " " in node1_content:
-    node1_content.pop(node1_content.index(" "))  # 移除所有空格
-```
-
-### 4. 在PaddleOCR中的应用
-
-#### 4.1 性能表现
-
-根据文档显示,在PubTabNet数据集上的评估结果:
-
-| 算法 | Acc | TEDS | Speed |
-|------|-----|------|-------|
-| EDD | - | 88.30% | - |
-| TableRec-RARE | 71.73% | **93.88%** | 779ms |
-| SLANet | 76.31% | **95.89%** | 766ms |
-
-#### 4.2 评估流程
-
-```mermaid
-graph TD
-    A[输入表格图像] --> B[文本检测OCR]
-    B --> C[表格结构识别]
-    C --> D[OCR结果与结构匹配]
-    D --> E[生成预测HTML]
-    E --> F[加载真实HTML]
-    F --> G[HTML解析为树结构]
-    G --> H[计算树编辑距离]
-    H --> I[归一化为TEDS分数]
-    
-    B --> B1[检测框坐标dt_boxes]
-    B --> B2[识别结果rec_res]
-    C --> C1[表格结构structure_res]
-    D --> D1[match函数匹配]
-    
-    G --> G1[TableTree转换]
-    G --> G2[tokenize单元格内容]
-    H --> H1[APTED算法]
-    H --> H2[CustomConfig比较策略]
-    
-    style A fill:#e1f5fe
-    style I fill:#e8f5e8
-    style H fill:#fff3e0
-```
-
-### 5. 具体使用方法
-
-#### 5.1 表格评估脚本
-
-使用[`eval_table.py`]eval_table.py )进行完整的表格识别评估:
-
-```bash
-python ppstructure/table/eval_table.py \
-    --det_model_dir=inference/en_PP-OCRv3_det_infer \
-    --rec_model_dir=inference/en_PP-OCRv3_rec_infer \
-    --table_model_dir=inference/en_ppstructure_mobile_v2.0_SLANet_infer \
-    --image_dir=train_data/table/pubtabnet/val/ \
-    --rec_char_dict_path=../ppocr/utils/dict/table_dict.txt \
-    --table_char_dict_path=../ppocr/utils/dict/table_structure_dict.txt \
-    --det_limit_side_len=736 \
-    --det_limit_type=min \
-    --rec_image_shape=3,32,320 \
-    --gt_path=path/to/gt.txt
-```
-
-#### 5.2 GT数据格式
-
-```txt
-PMC5755158_010_00.png    <html><body><table><thead><tr><td></td><td><b>Weaning</b></td><td><b>Week 15</b></td><td><b>Off-test</b></td></tr></thead><tbody><tr><td>Weaning</td><td>–</td><td>–</td><td>–</td></tr><tr><td>Week 15</td><td>–</td><td>0.17 ± 0.08</td><td>0.16 ± 0.03</td></tr><tr><td>Off-test</td><td>–</td><td>0.80 ± 0.24</td><td>0.19 ± 0.09</td></tr></tbody></table></body></html>
-```
-
-#### 5.3 直接使用TEDS类
-
-```python
-from ppstructure.table.table_metric import TEDS
-
-# 初始化TEDS评估器
-teds = TEDS(n_jobs=16)  # 支持多进程加速
-
-# 批量评估HTML
-pred_htmls = ["<html><body><table>...</table></body></html>", ...]
-true_htmls = ["<html><body><table>...</table></body></html>", ...]
-
-scores = teds.batch_evaluate_html(pred_htmls, true_htmls)
-avg_teds = sum(scores) / len(scores)
-print(f"TEDS: {avg_teds:.4f}")
-```
-
-### 6. 算法特点
-
-#### 6.1 综合评估能力
-- **结构评估**: 表格的行列结构、跨度属性
-- **内容评估**: 单元格内的文本内容准确性
-- **整体一致性**: 表格的完整性和一致性
-
-#### 6.2 灵活配置
-- **structure_only**: 仅评估结构,忽略内容
-- **ignore_nodes**: 忽略特定HTML节点
-- **多进程支持**: 大规模数据集的高效评估
-
-#### 6.3 鲁棒性
-- **容错处理**: 处理不完整或格式错误的HTML
-- **多种比较策略**: 适应不同的评估需求
-- **归一化分数**: 0-1范围内的直观分数
-
-### 7. 评估输出示例
-
-```bash
-# 运行评估后的输出
-[2022/08/10 05:22:23] ppocr INFO: teds: 95.89
-```
-
-### 8. 与其他指标的对比
-
-| 指标 | 评估维度 | 适用场景 | 优势 |
-|------|----------|----------|------|
-| **TEDS** | 结构+内容 | 表格识别 | 综合评估、国际标准 |
-| Acc | 仅结构 | 结构识别 | 简单直观 |
-| BLEU | 序列相似度 | 文本生成 | 流畅度评估 |
-| Edit Distance | 字符级别 | 文本识别 | 精确匹配 |
-
-TEDS作为表格识别领域的黄金标准,为PaddleOCR的表格识别算法提供了权威、可靠的评估机制,特别适用于需要同时考虑结构准确性和内容准确性的复杂表格识别任务。

+ 0 - 54
zhch/check_cuda_env.py

@@ -1,54 +0,0 @@
-import subprocess
-import sys
-
-def check_nvidia_environment():
-    print("=== NVIDIA环境检查 ===")
-    
-    # 检查nvidia-smi
-    try:
-        result = subprocess.run(['nvidia-smi'], capture_output=True, text=True, timeout=10)
-        if result.returncode == 0:
-            print("✓ nvidia-smi 正常运行")
-            # 提取驱动版本
-            lines = result.stdout.split('\n')
-            for line in lines:
-                if 'Driver Version:' in line:
-                    print(f"  {line.strip()}")
-                    break
-        else:
-            print("✗ nvidia-smi 失败:")
-            print(result.stderr)
-    except Exception as e:
-        print(f"✗ nvidia-smi 错误: {e}")
-    
-    # 检查NVML
-    try:
-        import pynvml
-        pynvml.nvmlInit()
-        driver_version = pynvml.nvmlSystemGetDriverVersion()
-        print(f"✓ NVML初始化成功,驱动版本: {driver_version}")
-        
-        device_count = pynvml.nvmlDeviceGetCount()
-        print(f"✓ 检测到 {device_count} 个GPU设备")
-        
-        for i in range(device_count):
-            handle = pynvml.nvmlDeviceGetHandleByIndex(i)
-            name = pynvml.nvmlDeviceGetName(handle)
-            print(f"  GPU {i}: {name}")
-            
-    except Exception as e:
-        print(f"✗ NVML错误: {e}")
-    
-    # 检查PaddlePaddle
-    try:
-        import paddle
-        print(f"✓ PaddlePaddle版本: {paddle.__version__}")
-        print(f"✓ CUDA编译支持: {paddle.device.is_compiled_with_cuda()}")
-        if paddle.device.is_compiled_with_cuda():
-            gpu_count = paddle.device.cuda.device_count()
-            print(f"✓ PaddlePaddle检测到 {gpu_count} 个GPU")
-    except Exception as e:
-        print(f"✗ PaddlePaddle错误: {e}")
-
-if __name__ == "__main__":
-    check_nvidia_environment()

+ 0 - 55
zhch/check_registry.py

@@ -1,55 +0,0 @@
-import sys
-import os
-
-# 添加PaddleX路径
-sys.path.insert(0, '/Users/zhch158/workspace/repository.git/PaddleX')
-
-def check_registration():
-    """检查模型注册状态"""
-    
-    # 1. 检查基础注册机制
-    try:
-        from paddlex.repo_apis.base.register import MODEL_INFO_REGISTRY
-        print(f"初始注册数量: {len(MODEL_INFO_REGISTRY._table)}")
-    except Exception as e:
-        print(f"导入注册表失败: {e}")
-        return
-    
-    # 2. 手动导入各个注册模块
-    registration_modules = [
-        'paddlex.repo_apis.PaddleOCR_api.text_det.register',
-        'paddlex.repo_apis.PaddleOCR_api.text_rec.register', 
-        'paddlex.repo_apis.PaddleOCR_api.table_rec.register',
-        'paddlex.repo_apis.PaddleOCR_api.textline_orientation.register',
-        'paddlex.repo_apis.PaddleDetection_api.layout_detection.register',
-        'paddlex.repo_apis.PaddleClas_api.image_classification.register'
-    ]
-    
-    for module_name in registration_modules:
-        try:
-            __import__(module_name)
-            print(f"✓ 成功导入: {module_name}")
-            print(f"  当前注册数量: {len(MODEL_INFO_REGISTRY._table)}")
-        except Exception as e:
-            print(f"✗ 导入失败: {module_name} - {e}")
-    
-    # 3. 显示所有已注册模型
-    print(f"\n最终已注册的模型({len(MODEL_INFO_REGISTRY._table)}):")
-    for model_name in sorted(MODEL_INFO_REGISTRY._table.keys()):
-        print(f"  - {model_name}")
-    
-    # 4. 检查SLANet_plus是否存在
-    if 'SLANet_plus' in MODEL_INFO_REGISTRY._table:
-        print(f"\n✓ SLANet_plus 已注册!")
-        model_info = MODEL_INFO_REGISTRY._table['SLANet_plus']
-        print(f"  配置路径: {model_info.get('config_path', 'N/A')}")
-    else:
-        print(f"\n✗ SLANet_plus 未注册")
-        # 查找相似模型
-        similar_models = [name for name in MODEL_INFO_REGISTRY._table.keys() 
-                         if 'sla' in name.lower() or 'table' in name.lower()]
-        if similar_models:
-            print(f"  相似模型: {similar_models}")
-
-if __name__ == "__main__":
-    check_registration()

+ 0 - 24
zhch/cuda_utils.py

@@ -1,24 +0,0 @@
-import paddle
-from typing import List
-def detect_available_gpus() -> List[int]:
-    """检测可用的GPU"""
-    try:
-        gpu_count = paddle.device.cuda.device_count()
-        available_gpus = list(range(gpu_count))
-        print(f"检测到 {gpu_count} 个可用GPU: {available_gpus}")
-        return available_gpus
-    except Exception as e:
-        print(f"GPU检测失败: {e}")
-        return []
-
-def monitor_gpu_memory(gpu_ids: List[int] = [0, 1]):
-    """监控GPU内存使用情况"""
-    try:
-        for gpu_id in gpu_ids:
-            paddle.device.set_device(f"gpu:{gpu_id}")
-            total = paddle.device.cuda.get_device_properties(gpu_id).total_memory / 1024**3
-            allocated = paddle.device.cuda.memory_allocated() / 1024**3
-            reserved = paddle.device.cuda.memory_reserved() / 1024**3
-            print(f"GPU {gpu_id} - 显存: {total:.2f}GB, 已分配: {allocated:.2f}GB, 已预留: {reserved:.2f}GB")
-    except Exception as e:
-        print(f"GPU内存监控失败: {e}")

+ 0 - 37
zhch/curl_ollama.sh

@@ -1,37 +0,0 @@
-#!/bin/bash
-
-# 检查图片文件是否存在
-if [ ! -f "./sample_data/PictureCheckCode.jpeg" ]; then
-    echo "错误:图片文件不存在"
-    exit 1
-fi
-
-# 将图片转换为 base64
-image1_base64=$(base64 -i ./sample_data/PictureCheckCode.jpeg)
-
-# 检查 base64 转换是否成功
-if [ -z "$image1_base64" ]; then
-    echo "错误:base64 转换失败"
-    exit 1
-fi
-
-# 第一个请求:提取验证码
-echo "发送第一个请求..."
-response=$(curl -X POST "http://localhost:11434/api/generate" \
-    -H "Content-Type: application/json" \
-    --max-time 300 \
-    --silent \
-    --data "{
-        \"model\": \"gemma3n\",
-        \"prompt\": \"提取图片中的验证码,只返回数字\",
-        \"images\": [\"${image1_base64}\"],
-        \"stream\": false
-    }")
-
-# 检查响应
-if [ $? -eq 0 ]; then
-    echo "响应:"
-    echo "$response" | jq -r '.response' 2>/dev/null || echo "$response"
-else
-    echo "请求失败"
-fi

+ 0 - 533
zhch/docker_startup_7085.sh

@@ -1,533 +0,0 @@
-#########################################################################
-# File Name: docker_start.sh
-# Version: v1.3
-# Author: yangyangen
-# Mail: yangyangen@exocr.com
-# Created Time: 2024-12-19 12:39:10
-#########################################################################
-
-#!/bin/bash
-# startup docker container
-
-echo "-----------------------------易道博识DeepOCR识别服务Docker版本执行开始--------------------------------"
-
-port="7085" # 设置docker run -p参数中对外映射的端口号
-
-nvidia="5" # 设置要挂载的Nvidia显卡,默认全部显卡all,如果要修改指定显卡的话,举例:nvidia="0,2,3"
-
-forward="y" # 设置docker容器的端口转发模式:
-# 当forward="y"时,使用-p和--mac-address参数生效:将容器的端口映射到主机的端口上,可以从主机访问容器内部的服务;允许在启动容器时指定一个固定的 MAC 地址。
-# 当forward="n"时,指定对外映射端口的port参数和指定mac地址参数不在生效,将使用容器内的server.conf配置文件中指定的端口。表示容器内的所有端口将直接暴露在主机上,意味着容器和主机共享使用网络接口、IP 地址和端口。
-
-use_cpu="n" # 设置OCR识别服务是否需要CPU方式启动,y表示使用cpu模式,n表示不使用cpu模式,默认为不使用CPU模式。
-
-ip_port_node="5000" # 设置docker run -p参数中容器内的端口号,通常禁止修改,除非很清楚的知道修改该参数值的意义和造成的影响。
-
-pod_name="httpsrv_7085" # 指定容器名称,默认即可,通常不建议修改,否则会影响docker_shutdown.sh脚本的执行过程
-
-# 检查 forward 是否为 y 或 n
-if [[ "$forward" != "y" && "$forward" != "n" ]]; then
-    echo "报错:forward 参数的值无效,请修改为等于 y 或 n。"
-    exit 1
-fi
-
-
-# 检查 forward 是否为 y 或 n
-if [[ "$use_cpu" != "y" && "$use_cpu" != "n" ]]; then
-    echo "报错:use_cpu 参数的值无效,请修改为等于 y 或 n。"
-    exit 1
-fi
-
-
-# 检查系统是否安装了系统常见的命令工具包
-packages_list=(
-    "pciutils" # 用于支持lspci命令
-    "iproute" # 用于支持ss命令
-)
-
-# 用来记录未安装的包
-missing_packages_list=()
-
-
-echo "检查以下系统依赖相关部署包是否已安装:"
-for package in "${packages_list[@]}"; do
-    if command -v dpkg &>/dev/null; then
-        pkg_check_cmd="dpkg -l"
-        pkg_name_check_cmd="dpkg -s"
-    elif command -v rpm &>/dev/null; then
-        pkg_check_cmd="rpm -q"
-        pkg_name_check_cmd="rpm -q"
-    else
-        echo "错误:无法找到适用的包管理工具(dpkg 或 rpm)。"
-        exit 1
-    fi
-
-    # 检查包是否已安装
-    if $pkg_check_cmd "$package" &>/dev/null; then
-        echo "$package 已安装"
-    else
-        echo "$package 未安装"
-        missing_packages_list+=("$package")
-    fi
-done
-
-# 如果有未安装的包,则退出并提示
-if [ ${#missing_packages_list[@]} -gt 0 ]; then
-    echo "错误:以下部署包未安装,请安装后再试。"
-    for pkg in "${missing_packages_list[@]}"; do
-        echo "- $pkg"
-    done
-    exit 1
-fi
-
-echo "-------------------------------------------------------------------------------------------------"
-
-# 检查端口号是否为合法数字,且在有效范围内
-if [ "$forward" = "y" ]; then
-    if ! [[ "$port" =~ ^[1-9][0-9]{0,4}$ ]] || (( port < 1 || port > 65535 )); then
-        echo "报错:端口号 $port 无效。端口号必须是1到65535之间的正整数。"
-        exit 1
-    fi
-    # 检查端口号是否已被占用
-    if ss -tuln | grep ":$port " > /dev/null; then
-        echo "报错:端口号 $port 已被占用。"
-        exit 1
-    fi
-    # 端口号校验通过
-    echo "DeepOCR服务端口号为 $port 校验通过,可以使用。"
-
-    forwarding=$(sysctl net.ipv4.ip_forward | awk '{print $3}')
-    if [ "$forwarding" -eq 1 ]; then
-        echo "IPv4转发已开启。"
-    else
-        echo "报错:IPv4转发未开启,端口转发功能不可用,IPv4开启方法请参考:"
-        echo "1.临时开启IPv4转发:临时开启会在操作系统重启后失效,执行命令为:sudo sysctl -w net.ipv4.ip_forward=1"
-        echo "2.永久开启IPv4转发:请在/etc/sysctl.conf文件中将net.ipv4.ip_forward的值改为1,然后:wq进行保存。"
-        echo "请注意:必须运行该命令将设置的参数生效:sudo sysctl -p && sudo systemctl restart docker"
-        exit 1
-    fi
-
-else
-    # 如果 forward="n",提示不进行端口号校验
-    echo "跳过转发的端口号校验,将使用 ${pod_name} 容器中DeepOCR服务的 /root/dist/conf/server.conf 中配置的端口进行对外访问。"
-    echo "请检查 ${pod_name} 容器内的DeeoOCR端口号与宿主机端口号是否冲突,端口号是否被其他程序占用。"
-fi
-
-
-echo "-------------------------------------------------------------------------------------------------"
-
-# 检查是否存在 log 目录,如果没有则创建
-if [ ! -d "./log_7085/" ]; then
-  # 尝试创建 log 目录
-  if ! mkdir -p log_7085; then
-    echo "报错:无法创建 log 目录,可能是没有写入权限。"
-    exit 1
-  fi
-  log_created=true
-else
-  # 检查是否有写入权限
-  if [ ! -w "./log_7085" ]; then
-    echo "报错:log 目录存在,但没有写入权限。"
-    exit 1
-  fi
-  log_created=true
-fi
-
-# 如果目录创建成功并且有权限,输出创建成功的信息
-if [ "$log_created" = true ]; then
-  echo "已创建DeepOCR服务日志目录,绝对路径为:$PWD/log"
-  echo "日志名称默认为:httplog.txt,可以通过修改DeepOCR的server.conf配置文件的suffix=y参数进行控制是否要对脚本添加主机名,例如日志格式为:httplog_testdemo.txt"
-fi
-
-echo "-------------------------------------------------------------------------------------------------"
-
-# 查找当前目录下的所有.lic文件
-lic_file=($(find . -maxdepth 1 -type f -name '*.lic'))
-
-# 检查是否找到了lic授权文件
-if [ ${#lic_file[@]} -eq 0 ]; then
-    echo "报错:没有找到后缀为.lic的授权文件。"
-    exit 1
-elif [ ${#lic_file[@]} -gt 1 ]; then
-    echo "报错:发现多个后缀为lic文件,请只保留一个。"
-    exit 1
-fi
-echo "当前目录下的授权文件名称为: $(basename "$lic_file")"
-
-echo "-------------------------------------------------------------------------------------------------"
-
-# 检查 Docker 是否安装,并且版本是否大于等于 19.06
-if command -v docker &> /dev/null; then
-    # 获取 Docker 版本
-    docker_version=$(docker --version | awk '{print $3}' | sed 's/,//')
-
-    # 提取主版本号和次版本号
-    IFS='.' read -r major minor patch <<< "$docker_version"
-
-    # 删除次版本号的前导零
-    minor=$(echo $minor | sed 's/^0*//')
-
-    # 检查版本是否大于等于 18.06
-    if [ "$major" -gt 19 ] || { [ "$major" -eq 19 ] && [ "$minor" -ge 6 ]; }; then
-        echo "Docker已安装,版本号为:$docker_version,符合版本要求。"
-    else
-        echo "报错:Docker版本 $docker_version 小于 19.06,不符合版本要求,请升级到 Docker 19.06 或以上版本。"
-        exit 1
-    fi
-
-    # 检查 Docker 服务是否启动并正常运行
-    if systemctl is-active --quiet docker; then
-        echo "Docker服务已启动并正常运行。"
-    else
-        echo "报错:Docker服务未启动或运行异常,可执行命令尝试重新启动 Docker 服务:sudo systemctl restart docker"
-        exit 1
-    fi
-else
-    echo "报错:Docker服务未安装,请联系易道博识获取 Docker 部署包和部署手册,待安装 Docker 后重试。"
-    exit 1
-fi
-
-
-
-echo "-------------------------------------------------------------------------------------------------"
-
-# 检查当前用户是否具有执行docker命令的权限
-# 检查当前用户是否是 root
-if [ "$(whoami)" = "root" ]; then
-    echo "当前用户 $(whoami) 有权限执行 Docker 命令。"
-else
-    # 检查当前用户是否在 docker 组中
-    if ! groups $(whoami) | grep -q '\bdocker\b'; then
-        echo "报错:当前用户 $(whoami) 不在 docker 组中,无法执行 Docker 命令。"
-        echo "请将当前用户添加到 docker 组:sudo usermod -aG docker $(whoami)"
-        echo "然后退出bash并重新登录,或者运行 'newgrp docker' 来应用更改。"
-        exit 1
-    else
-        echo "当前用户 $(whoami) 有权限执行 Docker 命令。"
-    fi
-fi
-
-echo "-------------------------------------------------------------------------------------------------"
-
-
-# 检查设置模型使用显卡显存的系数。
-# 初始化环境变量命令
-env_command=""
-
-if [ $# -eq 2 ]; then
-    echo "设置模型使用显卡显存的系数的环境变量"
-    arg1="$1"
-    arg2="$2"
-
-    if [ "$1" != "limit_gpu_memory" ]; then
-        echo "参数错误:第一个参数只能是 'limit_gpu_memory'"
-        exit 1
-    fi
-
-    if [ "$arg1" = "limit_gpu_memory" ]; then
-        # 检查第二个参数是否为小数点后最多两位的小数,并且值不大于1.0
-        if [[ "$arg2" =~ ^0(\.[0-9]{1,2})?$|^1(\.0{1,2})?$ ]]; then
-            env_command="-e TF_PER_PROCESS_GPU_MEMORY_FRACTION=$arg2"
-            # echo "env set $arg1=$arg2"
-        else
-            echo "请将limit_gpu_memory的值修改为小于1.0的浮点值,小数点后保留两位"
-            exit 1
-        fi
-    fi
-fi
-
-if [ -z "$env_command" ]; then
-    echo "没有指定 limit_gpu_memory 的显存系数。"
-else
-    echo "limit_gpu_memory 的显存系数为:$arg1=$arg2"
-fi
-
-
-echo "-------------------------------------------------------------------------------------------------"
-
-# 检查docker中是否存在当前需要部署的docker镜像
-if [ ! -s version.txt ]; then
-    echo "报错:文件 version.txt 不存在或内容为空。"
-    exit 1
-fi
-image_name=$(cat version.txt)
-
-if docker inspect --type=image $image_name &> /dev/null; then
-    echo "镜像为 $image_name 已存在,无需重复导入"
-else
-    echo "请耐心等待,正在导入Docker镜像"
-    if ! docker load -i ${PWD}/Deep_OCR_Docker.tar; then
-        echo "导入Docker镜像失败"
-        exit 1
-    fi
-    echo "导入已完成,镜像名称为: ${image_name}"
-fi
-
-
-echo "-------------------------------------------------------------------------------------------------"
-
-# 查找当前目录下的server.conf配置文件
-server_conf=$(find . -maxdepth 1 -type f -name 'server.conf')
-server_conf_arg=""
-if [ -n "$server_conf" ]; then
-  server_conf_arg="-v ${PWD}/server.conf:/root/dist/conf/server.conf"
-  echo "已向容器内部映射server.conf文件"
-fi
-
-# 查找当前目录下的httpsrv启动文件
-httpsrv=$(find . -maxdepth 1 -type f -name 'httpsrv')
-httpsrv_arg=""
-if [ -n "$httpsrv" ]; then
-  chmod +x httpsrv
-  httpsrv_arg="-v ${PWD}/httpsrv:/root/dist/httpsrv/httpsrv"
-  echo "已向容器内部映射httpsrv文件"
-fi
-
-# 查找当前目录下的apis.conf启动文件
-apis_conf=$(find . -maxdepth 1 -type f -name 'apis.conf')
-apis_conf_arg=""
-if [ -n "$apis_conf" ]; then
-  apis_conf_arg="-v ${PWD}/apis.conf:/root/dist/conf/apis.conf"
-  echo "已向容器内部映射apis.conf文件"
-fi
-
-# 查找当前目录下的libpywrap_tc.so启动文件
-libpywrap_tc=$(find . -maxdepth 1 -type f -name 'libpywrap_tc.so')
-libpywrap_tc_arg=""
-if [ -n "$libpywrap_tc" ]; then
-  libpywrap_tc_arg="-v ${PWD}/libpywrap_tc.so:/root/dist/httpsrv/libpywrap_tc.so"
-  echo "已向容器内部映射libpywrap_tc.so文件"
-fi
-
-# 查找当前目录下的libpywrap.so启动文件
-libpywrap=$(find . -maxdepth 1 -type f -name 'libpywrap.so')
-libpywrap_arg=""
-if [ -n "$libpywrap" ]; then
-  libpywrap_arg="-v ${PWD}/libpywrap.so:/root/dist/httpsrv/libpywrap.so"
-  echo "已向容器内部映射libpywrap.so文件"
-fi
-
-# 查找当前目录下的libpywrap.so启动文件
-libpaddle_inference=$(find . -maxdepth 1 -type f -name 'libpaddle_inference.so')
-libpaddle_inference_arg=""
-if [ -n "$libpaddle_inference" ]; then
-  libpaddle_inference_arg="-v ${PWD}/libpaddle_inference.so:/root/dist/httpsrv/libpaddle_inference.so"
-  echo "已向容器内部映射libpaddle_inference.so文件,建议仅限CPU模式时使用。"
-fi
-
-echo "-------------------------------------------------------------------------------------------------"
-
-# 检查系统是否安装了 nvidia-smi 驱动工具,并且是否有显卡设备
-nvidia_gpus=""
-# 设置cpu模式的docker命令参数
-cpu_mode=""
-packages=(
-    "libnvidia-container1" # docker挂载显卡时需要
-    "nvidia-container-toolkit" # docker挂载显卡时需要
-    #"nvidia-container-toolkit-base"
-    "libnvidia-container-tools" # docker挂载显卡时需要
-)
-
-
-# 用来记录未安装的包
-missing_packages=()
-if [ -f "./libpaddle_inference.so" ] || [ "$use_cpu" = "y" ]; then
-    echo "检测到当前目录下存在 libpaddle_inference.so 文件,或者环境变量 use_cpu=y ,跳过显卡加载过程。将使用 CPU 模式启动OCR识别服务。"
-    cpu_mode="-e use_cpu=y"
-    nvidia_gpus="" # 如果检测到该文件,设置显卡挂载为空
-else
-    cpu_mode=""
-    # 检查 PCIe 总线上是否存在 NVIDIA 硬件设备
-    if lspci | grep -i "nvidia" >/dev/null 2>&1; then
-        echo "检测到 NVIDIA 显卡硬件设备。"
-
-        # 检查是否安装了 nvidia-smi 驱动工具
-        if command -v nvidia-smi &>/dev/null; then
-            echo "检测到 nvidia-smi 驱动工具。"
-
-            # 检查是否可以检测到 NVIDIA GPU
-            if nvidia-smi -L >/dev/null 2>&1; then
-                echo "已检测到 NVIDIA GPU。"
-                # 根据 nvidia 的值来设置 nvidia_gpus
-                if [ "$nvidia" = "all" ]; then
-                    nvidia_gpus="--gpus all"
-                    echo "默认已向容器内部挂载所有 NVIDIA 显卡。"
-                elif [[ "$nvidia" =~ ^[0-9,]+$ ]]; then
-                    nvidia_gpus="--gpus '\"device=$nvidia\"'"
-                    echo "指定了显卡设备 $nvidia,已挂载指定显卡。"
-                else
-                    echo "警告:指定的显卡的内容格式无效,无法挂载。请重新修改第16行的值。"
-                    nvidia_gpus=""
-                    exit 1
-                fi
-                # 如果检测到显卡驱动,才检查相关的 NVIDIA 容器包
-                echo "检查以下 NVIDIA 相关部署包是否已安装:"
-                for package in "${packages[@]}"; do
-                    if command -v dpkg &>/dev/null; then
-                        pkg_check_cmd="dpkg -l"
-                        pkg_name_check_cmd="dpkg -s"
-                    elif command -v rpm &>/dev/null; then
-                        pkg_check_cmd="rpm -q"
-                        pkg_name_check_cmd="rpm -q"
-                    else
-                        echo "错误:无法找到适用的包管理工具(dpkg 或 rpm)。"
-                        exit 1
-                    fi
-
-                    # 检查包是否已安装
-                    if $pkg_check_cmd "$package" &>/dev/null; then
-                        echo "$package 已安装"
-                    else
-                        echo "$package 未安装"
-                        missing_packages+=("$package")
-                    fi
-                done
-
-                # 如果有未安装的包,则退出并提示
-                if [ ${#missing_packages[@]} -gt 0 ]; then
-                    echo "错误:以下部署包未安装,不能挂载nvidia显卡设备到OCR识别容器中进行使用,请安装后再试。"
-                    for pkg in "${missing_packages[@]}"; do
-                        echo "- $pkg"
-                    done
-                    exit 1
-                fi
-            else
-                echo "警告:未检测到 NVIDIA GPU,可能是驱动安装不正确或没有 GPU 显卡。将使用CPU模式运行OCR服务。CPU模式请修改该启动脚本的第22行为use_cpu="y",或者请联系易道博识获取 libpaddle_inference.so 文件才能进行识别。"
-                nvidia_gpus=""
-            fi
-        else
-            echo "警告:未检测到 nvidia-smi 驱动工具,无法使用 NVIDIA 显卡,将使用CPU模式运行OCR服务。CPU模式请修改该启动脚本的第22行为use_cpu="y",或者请联系易道博识获取 libpaddle_inference.so 文件才能进行识别。"
-            nvidia_gpus=""
-        fi
-    else
-        echo "警告:未检测到 NVIDIA 显卡硬件设备,将使用CPU模式运行OCR服务。CPU模式请修改该启动脚本的第22行为use_cpu="y",或者请联系易道博识获取 libpaddle_inference.so 文件才能进行识别。"
-        nvidia_gpus=""
-    fi
-fi
-
-echo "挂载到 ${pod_name} 容器内的显卡为:nvidia_gpus: $nvidia_gpus"
-
-echo "-------------------------------------------------------------------------------------------------"
-
-network=""
-mac_address=""
-# 如果 forward 为 y,检测 MAC 地址和端口号
-if [ "$forward" = "y" ]; then
-    # 获取已启动并有效网卡的 MAC 地址
-    mac_address=$(ip link show | awk '/state UP/ && !/lo/ {getline; print $2; exit}')
-
-    if [ -z "$mac_address" ]; then
-        echo "警告:没有检测到已启动并且有效的网卡MAC地址。"
-        exit 1
-    fi
-    ip_port="-p ${port}:${ip_port_node}"
-    mac_address="--mac-address ${mac_address}"
-    echo "检测到的MAC地址为: ${mac_address}"
-    echo "指定端口映射为:${ip_port}"
-
-else
-    # 如果 forward 为 n,设置 network 为 host
-    network="--network host"
-    echo "指定 ${pod_name} 容器使用 主机网络模式 :${network}"
-    echo "对外映射端口的 port 参数不在生效,将使用 ${pod_name} 容器内的 /root/dist/conf/server.conf 配置文件中 listening_port 指定的端口。"
-
-fi
-
-echo "-------------------------------------------------------------------------------------------------"
-docker_cmd="docker run -itd --name=${pod_name} \
-  ${ip_port} \
-  ${network} \
-  ${cpu_mode} \
-  ${mac_address} \
-  ${nvidia_gpus} \
-  --restart=on-failure \
-  --workdir /root/dist \
-  -v ${PWD}/log_7085:/root/dist/log \
-  -v ${PWD}/$(basename $lic_file):/root/dist/licence/$(basename $lic_file) \
-  -v ${PWD}/ptxas.12.2:/root/dist/httpsrv/ptxas \
-  -v /usr/lib/x86_64-linux-gnu/libcuda.so.570.169:/root/dist/httpsrv/libcuda.so.1 \
-  -v /usr/lib/x86_64-linux-gnu/libnvidia-ml.so.570.169:/root/dist/httpsrv/libnvidia-ml.so.1 \
-  ${libpaddle_inference_arg} \
-  ${apis_conf_arg} \
-  ${env_command} \
-  ${server_conf_arg} \
-  ${httpsrv_arg} \
-  ${libpywrap_tc_arg} \
-  ${libpywrap_arg} \
-  ${image_name} sh startup.sh"
-
-# 打印完整的 docker run 命令
-echo "执行的 Docker 命令为:$docker_cmd"
-
-# 执行 docker run 命令
-if ! eval "$docker_cmd"; then
-    echo "启动 Docker 容器失败"
-    exit 1
-fi
-
-echo "------------------${pod_name} 容器已启动,正在检查容器运行状态,请耐心等待------------------------------"
-
-# 获取 容器的 ID 或名称
-container_id=$(docker ps -aq  --filter "name=^${pod_name}$" | tr -d '\r\n\t ')
-
-# 等待 3 秒后,检查容器状态
-sleep 3
-
-# 获取容器当前的状态
-container_status=$(docker inspect --format '{{.State.Status}}' $container_id | tr -d '\r\n\t ')
-
-# 如果容器状态是 running,则认为启动成功
-if [ "$container_status" == "running" ]; then
-    # 再次确认 3 秒内容器状态是否稳定为 running
-    sleep 3
-    container_status=$(docker inspect --format '{{.State.Status}}' $container_id | tr -d '\r\n\t ')
-
-    if [ "$container_status" == "running" ]; then
-        echo "易道博识Docker版本DeepOCR服务启动完成。 ${pod_name} 容器状态为:$container_status"
-    else
-        echo "Docker中容器名称为 ${pod_name} 启动失败,再次检查容器状态不再是 running。当前状态为:$container_status ,请联系易道博识的技术支持人员排查问题。"
-        exit 1
-    fi
-else
-    echo "报错:Docker中容器名称为 ${pod_name} 启动失败,容器状态为:$container_status ,请联系易道博识的技术支持人员排查问题。"
-    exit 1
-fi
-
-echo "-------------------------------------------------------------------------------------------------"
-
-# 根据不同的端口映射方式,输出不同提示内容
-listening_port=$(docker exec -it ${pod_name} bash -c "grep '^listening_port' /root/dist/conf/server.conf | awk -F'=' '{print \$2}'" | tr -d '\r\n\t ')
-port_value=$(echo $ip_port | cut -d ':' -f 2)
-
-
-if [ "$forward" = "y" ]; then
-    # 检查 listening_port 和 port_value 是否一致
-    if [ "$listening_port" != "$port_value" ]; then
-        echo "警告:${pod_name} 容器虽然启动成功,但是 ${pod_name} 容器内/root/dist/conf/server.conf的listening_port:($listening_port) 与 脚本第21行的 ip_port_node :($ip_port_node) 中指定容器内端口号不一致!"
-        echo "请将 ${pod_name} 容器内/root/dist/conf/server.conf的listening_port:($listening_port) ,修改为默认的 (5000);或者修改本脚本第22行 ip_port_node 的值与之保持一致。"
-        echo "修改一致后,需要停止并删除运行当前 ${pod_name} 容器后: docker rm -f ${pod_name} ,重新执行该脚本再次启动容器生效。"
-        exit 1
-    fi
-    echo "DeepOCR服务当前端口号为:${port},如需修改DeepOCR转发端口号,请将该脚本第14行 port 的 ${port} 修改为指定的有效值。"
-    echo "查看DeepOCR服务的版本号:curl http://localhost:${port}/version"
-    echo "查看DeepOCR服务授权信息:curl http://localhost:${port}/authorize"
-else
-    # 如果 forward="n",提示不进行端口号校验
-    # 使用 docker exec 获取 listening_port,并去除多余的换行符或空格
-    echo "DeepOCR服务当前端口号为:$listening_port"
-    # 检查端口号是否已被占用
-    if ss -tuln | grep ":$listening_port " > /dev/null; then
-        echo "报错:httpsrv 容器内的 /root/dist/conf/server.conf 中配置的 listening_port 端口号 $listening_port 已被占用。"
-        echo "端口号与宿主机共用,如需指定DeepOCR服务端口,请对 ${pod_name} 容器内的 /root/dist/conf/server.conf 中配置的 listening_port 端口进行修改,已确保端口号不与其他进程端口号造成冲突。"
-        exit 1
-    fi
-    echo "查看DeepOCR服务的版本号:curl http://localhost:${listening_port}/version"
-    echo "查看DeepOCR服务授权信息:curl http://localhost:${listening_port}/authorize"
-fi
-
-
-echo "1.如需限制OCR模型占用显卡显存资源,可以执行命令,例如:./docker_startup.sh limit_gpu_memory 0.8"
-echo "2.如需查看服务日志,可以通过执行命令:tail -100f log/httplog.txt 或 docker exec -it ${pod_name} tail -f log/httplog.txt"
-echo "3.如需查看服务运行状态,可以通过执行命令:docker ps -a | grep ${pod_name}"
-echo "4.如需查看容器内的DeepOR服务进程运行情况,可以通过执行命令:docker exec -it ${pod_name} ps -ef | grep httpsrv"
-echo "---------------------------易道博识DeepOCR识别服务Docker版本执行已完毕-------------------------------"

+ 0 - 222
zhch/mp_infer.py

@@ -1,222 +0,0 @@
-import argparse
-import sys
-import os
-import time
-import traceback
-from multiprocessing import Manager, Process
-from pathlib import Path
-from queue import Empty
-
-from paddlex import create_pipeline
-from paddlex.utils.device import constr_device, parse_device
-
-
-def worker(pipeline_name_or_config_path, device, task_queue, batch_size, output_dir):
-    import paddle
-    paddle.utils.run_check()
-
-    # 限制GPU内存使用,减少CUDA冲突
-    # os.environ["FLAGS_fraction_of_gpu_memory_to_use"] = "0.6"
-
-    # 使用确定性算法
-    # os.environ["FLAGS_cudnn_deterministic"] = "1"
-
-    # 立即释放内存
-    # os.environ["FLAGS_eager_delete_tensor_gb"] = "0.0"
-
-    pipeline = create_pipeline(pipeline_name_or_config_path, device=device)
-
-    should_end = False
-    batch = []
-    processed_count = 0
-
-    while not should_end:
-        try:
-            input_path = task_queue.get_nowait()
-        except Empty:
-            should_end = True
-        except Exception as e:
-            # 处理其他可能的异常
-            print(f"Unexpected error while getting task: {e}", file=sys.stderr)
-            traceback.print_exc()
-            should_end = True
-        else:
-            if input_path is None:
-                should_end = True
-            else:
-                batch.append(input_path)
-
-        if batch and (len(batch) == batch_size or should_end):
-            try:
-                start_time = time.time()
-
-                # 使用pipeline预测,添加PP-StructureV3的参数
-                results = pipeline.predict(
-                    batch,
-                    use_doc_orientation_classify=True,
-                    use_doc_unwarping=False,
-                    use_seal_recognition=True,
-                    use_chart_recognition=True,
-                    use_table_recognition=True,
-                    use_formula_recognition=True,
-                )
-
-                batch_processing_time = time.time() - start_time
-
-                for result in results:
-                    try:
-                        input_path = Path(result["input_path"])
-
-                        # 保存结果 - 按照ppstructurev3的方式处理文件名
-                        if result.get("page_index") is not None:
-                            output_filename = f"{input_path.stem}_{result['page_index']}"
-                        else:
-                            output_filename = f"{input_path.stem}"
-
-                        # 保存JSON和Markdown文件
-                        json_output_path = str(Path(output_dir, f"{output_filename}.json"))
-                        md_output_path = str(Path(output_dir, f"{output_filename}.md"))
-
-                        result.save_to_json(json_output_path)
-                        result.save_to_markdown(md_output_path)
-
-                        processed_count += 1
-                        print(
-                            f"Processed {repr(str(input_path))} -> {json_output_path}, {md_output_path}"
-                        )
-
-                    except Exception as e:
-                        print(
-                            f"Error saving result for {result.get('input_path', 'unknown')}: {e}",
-                            file=sys.stderr,
-                        )
-                        traceback.print_exc()
-
-                print(
-                    f"Batch processed: {len(batch)} files in {batch_processing_time:.2f}s on {device}"
-                )
-
-            except Exception as e:
-                print(f"Error processing batch {batch} on {repr(device)}: {e}", file=sys.stderr)
-                traceback.print_exc()
-
-            batch.clear()
-
-
-def main():
-    parser = argparse.ArgumentParser()
-    parser.add_argument(
-        "--pipeline", type=str, required=True, help="Pipeline name or config path."
-    )
-    parser.add_argument("--input_dir", type=str, required=True, help="Input directory.")
-    parser.add_argument(
-        "--device",
-        type=str,
-        required=True,
-        help="Specifies the devices for performing parallel inference.",
-    )
-    parser.add_argument(
-        "--output_dir", type=str, default="output", help="Output directory."
-    )
-    parser.add_argument(
-        "--instances_per_device",
-        type=int,
-        default=1,
-        help="Number of pipeline instances per device.",
-    )
-    parser.add_argument(
-        "--batch_size",
-        type=int,
-        default=1,
-        help="Inference batch size for each pipeline instance.",
-    )
-    parser.add_argument(
-        "--input_glob_pattern",
-        type=str,
-        default="*",
-        help="Pattern to find the input files.",
-    )
-    parser.add_argument(
-        "--test_mode", 
-        action="store_true", 
-        help="Test mode (process only 20 images)"
-    )
-    args = parser.parse_args()
-
-    input_dir = Path(args.input_dir).resolve()
-    print(f"Input directory: {input_dir}")
-    if not input_dir.exists():
-        print(f"The input directory does not exist: {input_dir}", file=sys.stderr)
-        return 2
-    if not input_dir.is_dir():
-        print(f"{repr(str(input_dir))} is not a directory.", file=sys.stderr)
-        return 2
-
-    output_dir = Path(args.output_dir).resolve()
-    print(f"Output directory: {output_dir}")
-    if output_dir.exists() and not output_dir.is_dir():
-        print(f"{repr(str(output_dir))} is not a directory.", file=sys.stderr)
-        return 2
-    output_dir.mkdir(parents=True, exist_ok=True)
-
-    device_type, device_ids = parse_device(args.device)
-    if device_ids is None or len(device_ids) == 1:
-        print(
-            "Please specify at least two devices for performing parallel inference.",
-            file=sys.stderr,
-        )
-        return 2
-
-    if args.batch_size <= 0:
-        print("Batch size must be greater than 0.", file=sys.stderr)
-        return 2
-
-    # 查找图像文件
-    image_extensions = [".jpg", ".jpeg", ".png", ".bmp", ".tiff", ".tif"]
-    image_files = []
-    for ext in image_extensions:
-        image_files.extend(list(input_dir.glob(f"*{ext}")))
-        image_files.extend(list(input_dir.glob(f"*{ext.upper()}")))
-    print(f"Found {len(image_files)} image files")
-
-    if args.test_mode:
-        image_files = image_files[:20]
-        print(f"Test mode: processing only {len(image_files)} images")
-
-    with Manager() as manager:
-        task_queue = manager.Queue()
-
-        # 将图像文件路径放入队列
-        for img_path in image_files:
-            task_queue.put(str(img_path))
-
-        processes = []
-        for device_id in device_ids:
-            for _ in range(args.instances_per_device):
-                device = constr_device(device_type, [device_id])
-                p = Process(
-                    target=worker,
-                    args=(
-                        args.pipeline,
-                        device,
-                        task_queue,
-                        args.batch_size,
-                        str(output_dir),
-                    ),
-                )
-                p.start()
-                processes.append(p)
-
-        # 发送结束信号
-        for _ in range(len(device_ids) * args.instances_per_device):
-            task_queue.put(None)
-
-        for p in processes:
-            p.join()
-
-    print("All done")
-    return 0
-
-
-if __name__ == "__main__":
-    sys.exit(main())

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 0 - 41
zhch/omnidocbench_converted_result.json


Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio