zouyu
2025-09-26 3fbbfcc8f509c352c58dc8a126220b49b72ed5a0
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
package com.xindao.ocr.smartjavaai.factory;
 
import cn.smartjavaai.common.config.Config;
import com.xindao.ocr.smartjavaai.config.PlateDetModelConfig;
import com.xindao.ocr.smartjavaai.config.PlateRecModelConfig;
import com.xindao.ocr.smartjavaai.enums.PlateDetModelEnum;
import com.xindao.ocr.smartjavaai.enums.PlateRecModelEnum;
import com.xindao.ocr.smartjavaai.exception.OcrException;
import com.xindao.ocr.smartjavaai.model.plate.CRNNPlateRecModel;
import com.xindao.ocr.smartjavaai.model.plate.PlateDetModel;
import com.xindao.ocr.smartjavaai.model.plate.PlateRecModel;
import com.xindao.ocr.smartjavaai.model.plate.Yolov5PlateDetModel;
import lombok.extern.slf4j.Slf4j;
 
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
 
/**
 * 车牌识别模型工厂
 * @author dwj
 */
@Slf4j
public class PlateModelFactory {
 
    // 使用 volatile 和双重检查锁定来确保线程安全的单例模式
    private static volatile PlateModelFactory instance;
 
    /**
     * 模型缓存
     */
    private static final ConcurrentHashMap<PlateDetModelEnum, PlateDetModel> detModelMap = new ConcurrentHashMap<>();
 
    /**
     * 模型缓存
     */
    private static final ConcurrentHashMap<PlateRecModelEnum, PlateRecModel> recModelMap = new ConcurrentHashMap<>();
 
 
    /**
     * 模型注册表
     */
    private static final Map<PlateDetModelEnum, Class<? extends PlateDetModel>> detModelRegistry =
            new ConcurrentHashMap<>();
 
    /**
     * 模型注册表
     */
    private static final Map<PlateRecModelEnum, Class<? extends PlateRecModel>> recModelRegistry =
            new ConcurrentHashMap<>();
 
 
    public static PlateModelFactory getInstance() {
        if (instance == null) {
            synchronized (PlateModelFactory.class) {
                if (instance == null) {
                    instance = new PlateModelFactory();
                }
            }
        }
        return instance;
    }
 
 
 
    /**
     * 注册模型
     * @param plateDetModelEnum
     * @param clazz
     */
    private static void registerDetModel(PlateDetModelEnum plateDetModelEnum, Class<? extends PlateDetModel> clazz) {
        detModelRegistry.put(plateDetModelEnum, clazz);
    }
 
    /**
     * 注册模型
     * @param plateRecModelEnum
     * @param clazz
     */
    private static void registerRecModel(PlateRecModelEnum plateRecModelEnum, Class<? extends PlateRecModel> clazz) {
        recModelRegistry.put(plateRecModelEnum, clazz);
    }
 
 
    /**
     * 获取模型
     * @param config
     * @return
     */
    public PlateDetModel getDetModel(PlateDetModelConfig config) {
        if(Objects.isNull(config) || Objects.isNull(config.getModelEnum())){
            throw new OcrException("未配置OCR模型");
        }
        return detModelMap.computeIfAbsent(config.getModelEnum(), k -> {
            return createDetModel(config);
        });
    }
 
    /**
     * 获取模型
     * @param config
     * @return
     */
    public PlateRecModel getRecModel(PlateRecModelConfig config) {
        if(Objects.isNull(config) || Objects.isNull(config.getModelEnum())){
            throw new OcrException("未配置OCR模型");
        }
        return recModelMap.computeIfAbsent(config.getModelEnum(), k -> {
            return createRecModel(config);
        });
    }
 
 
 
    /**
     * 创建检测模型
     * @param config
     * @return
     */
    private PlateDetModel createDetModel(PlateDetModelConfig config) {
        Class<?> clazz = detModelRegistry.get(config.getModelEnum());
        if(clazz == null){
            throw new OcrException("Unsupported model");
        }
        PlateDetModel model = null;
        try {
            model = (PlateDetModel) clazz.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new OcrException(e);
        }
        model.loadModel(config);
        return model;
    }
 
    /**
     * 创建识别模型
     * @param config
     * @return
     */
    private PlateRecModel createRecModel(PlateRecModelConfig config) {
        Class<?> clazz = recModelRegistry.get(config.getModelEnum());
        if(clazz == null){
            throw new OcrException("Unsupported model");
        }
        PlateRecModel model = null;
        try {
            model = (PlateRecModel) clazz.newInstance();
        } catch (InstantiationException | IllegalAccessException e) {
            throw new OcrException(e);
        }
        model.loadModel(config);
        return model;
    }
 
 
    // 初始化默认算法
    static {
        registerDetModel(PlateDetModelEnum.YOLOV5, Yolov5PlateDetModel.class);
        registerDetModel(PlateDetModelEnum.YOLOV7, Yolov5PlateDetModel.class);
        registerRecModel(PlateRecModelEnum.PLATE_REC_CRNN, CRNNPlateRecModel.class);
        log.debug("缓存目录:{}", Config.getCachePath());
    }
 
}