shikeying
2024-01-11 3b67e947e36133e2a40eb2737b15ea375e157ea0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
package com.walker.openocr.table;
 
import com.walker.openocr.util.TableConfigUtils;
 
import java.util.ArrayList;
import java.util.List;
 
public class TableConfig {
 
    // 表格类型定义的关键词集合,用于确定表格类型,String[]里面为完全匹配(and),List中为任意一个匹配(or)
    private List<String[]> tableTypeKeys = new ArrayList<>(8);
 
    // 单元格计算时,容差像素
    private int cellTolerance = 5;
 
    // 标题匹配时,容错百分比,如:姓名 --> 名,则也算匹配上
//    private float titleTolerance = 0.5f;
    private float titleTolerance = 1.0f;
 
    // 要移除的单元格名称集合
    private String[] removeColumnsName = null;
 
    // 单元格配置参数集合,一个为一格
    private List<CellConfigItem> cellConfigItems = new ArrayList<>(32);
 
    // 字段列配置属性集合,一个为一列
    private List<ColumnConfigItem> columnConfigItems = new ArrayList<>(8);
 
    // 多行文本,每行之间容差距离(匹配2行单元格)
    private int multiLineTolerance = 30;
 
    // 表头名称,用户配置
    private String tableTitle;
 
    public String getTableTitle() {
        return tableTitle;
    }
 
    public void setTableTitle(String tableTitle) {
        this.tableTitle = tableTitle;
    }
 
    public int getMultiLineTolerance() {
        return multiLineTolerance;
    }
 
    public void setMultiLineTolerance(int multiLineTolerance) {
        this.multiLineTolerance = multiLineTolerance;
    }
 
    public int getCellTolerance() {
        return cellTolerance;
    }
 
    public void setCellTolerance(int cellTolerance) {
        this.cellTolerance = cellTolerance;
    }
 
    public float getTitleTolerance() {
        return titleTolerance;
    }
 
    public void setTitleTolerance(float titleTolerance) {
        this.titleTolerance = titleTolerance;
    }
 
    public String[] getRemoveColumnsName() {
        return removeColumnsName;
    }
 
    public void setRemoveColumnsName(String[] removeColumnsName) {
        this.removeColumnsName = removeColumnsName;
    }
 
    public List<String[]> getTableTypeKeys() {
        return tableTypeKeys;
    }
 
    /**
     * 设置表格分类关键词。
     * @param text 如:大地,保险,机动车
     */
    public void setTableTypeKeys(String text){
        if(text == null || text.equals("")){
            throw new IllegalArgumentException("tableTypeKeys is required!");
        }
        String[] array = text.split("\\|");
        if(array == null || array.length == 0){
            throw new IllegalArgumentException("分隔字符串错误:tableConfig参数错误:" + text);
        }
 
        String[] keys = null;
        for (String one : array){
//            System.out.println(one);
            keys = one.split(",");
            this.tableTypeKeys.add(keys);
        }
    }
 
    public void addCellConfig(CellConfigItem item){
        if(item == null){
            return;
        }
        if(this.cellConfigItems.contains(item)){
            return;
        }
        this.cellConfigItems.add(item);
    }
 
    public void addColumnConfig(ColumnConfigItem item){
        if(item == null){
            return;
        }
        if(this.columnConfigItems.contains(item)){
            return;
        }
        this.columnConfigItems.add(item);
    }
 
    /**
     * 根据单元格配置ID,返回配置项。
     * @param id
     * @return
     * @date 2022-09-30
     */
    public CellConfigItem getCellConfigItem(String id){
        if(this.cellConfigItems.size() == 0){
            return null;
        }
        for(CellConfigItem item : this.cellConfigItems){
            if(item.getId().equals(id)){
                return item;
            }
        }
        return null;
    }
 
    public CellConfigItem getCellConfig(String name){
        if(this.cellConfigItems.size() == 0){
            return null;
        }
        for(CellConfigItem item : this.cellConfigItems){
            if(item.getName().equals(name)){
                return item;
            }
        }
        return null;
    }
 
    public ColumnConfigItem getColumnConfig(String name){
        if(this.columnConfigItems.size() == 0){
            return null;
        }
        for(ColumnConfigItem item : this.columnConfigItems){
            if(item.getName().equals(name)){
                return item;
            }
        }
        return null;
    }
 
    @Override
    public String toString(){
        StringBuilder sb = new StringBuilder();
        for(String[] keys : this.tableTypeKeys){
            for(String s : keys){
                sb.append(s).append(",");
            }
        }
        return sb.toString();
    }
 
    /**
     * 查找是否存在匹配的配置对象(单元格或列对象)
     * @param text 给定的识别文本
     * @return
     */
    public ConfigItem findConfigItem(String text){
        List<CellConfigItem> matchedList = new ArrayList<>(2);
        for(CellConfigItem item : this.cellConfigItems){
            if(TableConfigUtils.isCellConfigItem(item, text, this)){
//                return item;
                matchedList.add(item);  // 因为可能存在多个匹配的,所以暂缓返回,最终统一比较最匹配的
            }
        }
        if(matchedList.size() == 1){
            return matchedList.get(0);
        }
 
//        if(text.equals("无责任死亡伤残赔偿限额18000元")){
//            System.out.println("++++++++++");
//        }
        // 如:配置项(死亡伤残赔偿限额)
        // “死亡伤残赔偿限额180000元” 和 “无责任死亡伤残赔偿限额18000元” 都匹配该项
        if(matchedList.size() > 1){
            float[] scores = new float[matchedList.size()];
            for(int i=0; i<matchedList.size(); i++){
                scores[i] = TableConfigUtils.getSimpleSimilarScore(matchedList.get(i).getName(), text);
            }
            // 获取最大分值的
            float maxScore = 0;
            int maxIndex = 0;
            for (int j=0; j<scores.length; j++){
                if(scores[j] > maxScore){
                    maxScore = scores[j];
                    maxIndex = j;
                }
            }
            System.out.println("发现多个配置匹配,找到最高评分:" + maxScore + ", config=" + matchedList.get(maxIndex).getName());
            return matchedList.get(maxIndex);
        }
 
//        for(ColumnConfigItem item : this.columnConfigItems){
//
//        }
        return null;
    }
 
    public List<String> getTableTitleNotKey() {
        return tableTitleNotKey;
    }
 
    /**
     * 设置表格(类型)标题不能包含的关键词。
     * <pre>
     *     1) 因为有些加油小票,会存在大类、小类关键词,如:中石油,中油联合,这种情况包含:"中国石油"都会匹配上,油联合就没法弄了。
     * </pre>
     * @param tableTitleNotKey
     * @date 2023-11-01
     */
    public void setTableTitleNotKey(List<String> tableTitleNotKey) {
        this.tableTitleNotKey = tableTitleNotKey;
    }
 
    private List<String> tableTitleNotKey = new ArrayList<>(4);
}