|
@@ -1,500 +1,32 @@
|
|
|
-def validate_rule_ranges(data: dict, path: str = "") -> (bool, str):
|
|
|
|
|
- """
|
|
|
|
|
- 递归检查配置中看起来像评分规则的列表。
|
|
|
|
|
- 规则:
|
|
|
|
|
- 1. 列表中的元素必须包含 min, max, deduction。
|
|
|
|
|
- 2. 第一个元素的 min 必须为 0。
|
|
|
|
|
- 3. 当前元素的 min 必须等于上一个元素的 max。
|
|
|
|
|
- """
|
|
|
|
|
- if isinstance(data, dict):
|
|
|
|
|
- for key, value in data.items():
|
|
|
|
|
- is_valid, error = validate_rule_ranges(value, path=f"{path}.{key}" if path else key)
|
|
|
|
|
- if not is_valid:
|
|
|
|
|
- return False, error
|
|
|
|
|
-
|
|
|
|
|
- elif isinstance(data, list):
|
|
|
|
|
- # 检查这是否是一个规则列表(通过检查第一个元素是否包含特定key)
|
|
|
|
|
- if len(data) > 0 and isinstance(data[0], dict) and "min" in data[0] and "max" in data[0] and "deduction" in \
|
|
|
|
|
- data[0]:
|
|
|
|
|
- current_path = path
|
|
|
|
|
-
|
|
|
|
|
- # 1. 检查首项 min 是否为 0
|
|
|
|
|
- first_min = data[0].get("min")
|
|
|
|
|
- if first_min != 0:
|
|
|
|
|
- return False, f"范围错误 [{current_path}]: 第一个区间的 min 必须为 0,当前为 {first_min}"
|
|
|
|
|
-
|
|
|
|
|
- # 2. 检查连续性
|
|
|
|
|
- prev_max = None
|
|
|
|
|
- for idx, rule in enumerate(data):
|
|
|
|
|
- current_min = rule.get("min")
|
|
|
|
|
- current_max = rule.get("max")
|
|
|
|
|
-
|
|
|
|
|
- # 处理 inf 字符串
|
|
|
|
|
- if current_max == "inf":
|
|
|
|
|
- current_max_val = float("inf")
|
|
|
|
|
- else:
|
|
|
|
|
- try:
|
|
|
|
|
- current_max_val = float(current_max)
|
|
|
|
|
- except (ValueError, TypeError):
|
|
|
|
|
- return False, f"数值错误 [{current_path}]: max 值 '{current_max}' 无效"
|
|
|
|
|
-
|
|
|
|
|
- try:
|
|
|
|
|
- current_min_val = float(current_min)
|
|
|
|
|
- except (ValueError, TypeError):
|
|
|
|
|
- return False, f"数值错误 [{current_path}]: min 值 '{current_min}' 无效"
|
|
|
|
|
-
|
|
|
|
|
- # 检查连续性 (除了第一个元素)
|
|
|
|
|
- if idx > 0:
|
|
|
|
|
- # 使用一个微小的容差处理浮点数比较,或者直接相等
|
|
|
|
|
- if prev_max == "inf":
|
|
|
|
|
- return False, f"逻辑错误 [{current_path}]: 'inf' 只能出现在最后一个区间的 max"
|
|
|
|
|
-
|
|
|
|
|
- prev_max_val = float(prev_max) if prev_max != "inf" else float("inf")
|
|
|
|
|
-
|
|
|
|
|
- if current_min_val != prev_max_val:
|
|
|
|
|
- return False, f"不连续错误 [{current_path}]: 第 {idx + 1} 项的 min ({current_min}) 不等于上一项的 max ({prev_max})"
|
|
|
|
|
-
|
|
|
|
|
- prev_max = current_max
|
|
|
|
|
-
|
|
|
|
|
- return True, "验证通过"
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-if __name__ == '__main__':
|
|
|
|
|
- new_config = {
|
|
|
|
|
- "base_score": 10,
|
|
|
|
|
- "corner": {
|
|
|
|
|
- "rules": {
|
|
|
|
|
- "wear_area": [
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0,
|
|
|
|
|
- "max": 0.05,
|
|
|
|
|
- "deduction": -0.1
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.05,
|
|
|
|
|
- "max": 0.1,
|
|
|
|
|
- "deduction": -0.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.1,
|
|
|
|
|
- "max": 0.25,
|
|
|
|
|
- "deduction": -1.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.25,
|
|
|
|
|
- "max": 0.5,
|
|
|
|
|
- "deduction": -3
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.5,
|
|
|
|
|
- "max": "inf",
|
|
|
|
|
- "deduction": -5
|
|
|
|
|
- }
|
|
|
|
|
- ],
|
|
|
|
|
- "loss_area": [
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0,
|
|
|
|
|
- "max": 0.05,
|
|
|
|
|
- "deduction": -0.1
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.05,
|
|
|
|
|
- "max": 0.1,
|
|
|
|
|
- "deduction": -0.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.1,
|
|
|
|
|
- "max": 0.25,
|
|
|
|
|
- "deduction": -1.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.25,
|
|
|
|
|
- "max": 0.5,
|
|
|
|
|
- "deduction": -3
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.5,
|
|
|
|
|
- "max": "inf",
|
|
|
|
|
- "deduction": -5
|
|
|
|
|
- }
|
|
|
|
|
- ]
|
|
|
|
|
- },
|
|
|
|
|
- "front_weights": {
|
|
|
|
|
- "wear_area": 0.3,
|
|
|
|
|
- "loss_area": 0.7
|
|
|
|
|
- },
|
|
|
|
|
- "back_weights": {
|
|
|
|
|
- "wear_area": 0.3,
|
|
|
|
|
- "loss_area": 0.7
|
|
|
|
|
- },
|
|
|
|
|
- "final_weights": {
|
|
|
|
|
- "front": 0.7,
|
|
|
|
|
- "back": 0.3
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- "edge": {
|
|
|
|
|
- "rules": {
|
|
|
|
|
- "wear_area": [
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0,
|
|
|
|
|
- "max": 0.05,
|
|
|
|
|
- "deduction": -0.1
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.05,
|
|
|
|
|
- "max": 0.1,
|
|
|
|
|
- "deduction": -0.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.1,
|
|
|
|
|
- "max": 0.25,
|
|
|
|
|
- "deduction": -1.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.25,
|
|
|
|
|
- "max": 0.5,
|
|
|
|
|
- "deduction": -3
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.5,
|
|
|
|
|
- "max": "inf",
|
|
|
|
|
- "deduction": -5
|
|
|
|
|
- }
|
|
|
|
|
- ],
|
|
|
|
|
- "loss_area": [
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0,
|
|
|
|
|
- "max": 0.05,
|
|
|
|
|
- "deduction": -0.1
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.05,
|
|
|
|
|
- "max": 0.1,
|
|
|
|
|
- "deduction": -0.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.1,
|
|
|
|
|
- "max": 0.25,
|
|
|
|
|
- "deduction": -1.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.25,
|
|
|
|
|
- "max": 0.5,
|
|
|
|
|
- "deduction": -3
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.5,
|
|
|
|
|
- "max": "inf",
|
|
|
|
|
- "deduction": -5
|
|
|
|
|
- }
|
|
|
|
|
- ]
|
|
|
|
|
- },
|
|
|
|
|
- "front_weights": {
|
|
|
|
|
- "wear_area": 0.4,
|
|
|
|
|
- "loss_area": 0.6
|
|
|
|
|
- },
|
|
|
|
|
- "back_weights": {
|
|
|
|
|
- "wear_area": 0.4,
|
|
|
|
|
- "loss_area": 0.6
|
|
|
|
|
- },
|
|
|
|
|
- "final_weights": {
|
|
|
|
|
- "front": 0.7,
|
|
|
|
|
- "back": 0.3
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- "face": {
|
|
|
|
|
- "rules": {
|
|
|
|
|
- "wear_area": [
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0,
|
|
|
|
|
- "max": 0.05,
|
|
|
|
|
- "deduction": -0.1
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.05,
|
|
|
|
|
- "max": 0.1,
|
|
|
|
|
- "deduction": -0.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.1,
|
|
|
|
|
- "max": 0.25,
|
|
|
|
|
- "deduction": -1.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.25,
|
|
|
|
|
- "max": 0.5,
|
|
|
|
|
- "deduction": -3
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.5,
|
|
|
|
|
- "max": "inf",
|
|
|
|
|
- "deduction": -5
|
|
|
|
|
- }
|
|
|
|
|
- ],
|
|
|
|
|
- "pit_area": [
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0,
|
|
|
|
|
- "max": 0.05,
|
|
|
|
|
- "deduction": -0.1
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.05,
|
|
|
|
|
- "max": 0.1,
|
|
|
|
|
- "deduction": -0.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.1,
|
|
|
|
|
- "max": 0.25,
|
|
|
|
|
- "deduction": -1.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.25,
|
|
|
|
|
- "max": 0.5,
|
|
|
|
|
- "deduction": -3
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.5,
|
|
|
|
|
- "max": "inf",
|
|
|
|
|
- "deduction": -5
|
|
|
|
|
- }
|
|
|
|
|
- ],
|
|
|
|
|
- "stain_area": [
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0,
|
|
|
|
|
- "max": 0.05,
|
|
|
|
|
- "deduction": -0.1
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.05,
|
|
|
|
|
- "max": 0.1,
|
|
|
|
|
- "deduction": -0.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.1,
|
|
|
|
|
- "max": 0.25,
|
|
|
|
|
- "deduction": -1.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.25,
|
|
|
|
|
- "max": 0.5,
|
|
|
|
|
- "deduction": -3
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0.5,
|
|
|
|
|
- "max": "inf",
|
|
|
|
|
- "deduction": -5
|
|
|
|
|
- }
|
|
|
|
|
- ],
|
|
|
|
|
- "scratch_length": [
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0,
|
|
|
|
|
- "max": 1,
|
|
|
|
|
- "deduction": -0.1
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 1,
|
|
|
|
|
- "max": 2,
|
|
|
|
|
- "deduction": -0.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 2,
|
|
|
|
|
- "max": 5,
|
|
|
|
|
- "deduction": -1
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 5,
|
|
|
|
|
- "max": 10,
|
|
|
|
|
- "deduction": -2
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 10,
|
|
|
|
|
- "max": 20,
|
|
|
|
|
- "deduction": -3
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 20,
|
|
|
|
|
- "max": 50,
|
|
|
|
|
- "deduction": -4
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 50,
|
|
|
|
|
- "max": "inf",
|
|
|
|
|
- "deduction": -5
|
|
|
|
|
- }
|
|
|
|
|
- ]
|
|
|
|
|
- },
|
|
|
|
|
- "coefficients": {
|
|
|
|
|
- "wear_area": 0.25,
|
|
|
|
|
- "scratch_length": 0.25,
|
|
|
|
|
- "dent_area": 0.25,
|
|
|
|
|
- "stain_area": 0.25
|
|
|
|
|
- },
|
|
|
|
|
- "final_weights": {
|
|
|
|
|
- "front": 0.75,
|
|
|
|
|
- "back": 0.25
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- "centering": {
|
|
|
|
|
- "front": {
|
|
|
|
|
- "rules": [
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0,
|
|
|
|
|
- "max": 52,
|
|
|
|
|
- "deduction": 0
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 52,
|
|
|
|
|
- "max": 55,
|
|
|
|
|
- "deduction": -0.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 55,
|
|
|
|
|
- "max": 60,
|
|
|
|
|
- "deduction": -1
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 60,
|
|
|
|
|
- "max": 62.5,
|
|
|
|
|
- "deduction": -1.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 62.5,
|
|
|
|
|
- "max": 65,
|
|
|
|
|
- "deduction": -2
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 65,
|
|
|
|
|
- "max": 67.5,
|
|
|
|
|
- "deduction": -2.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 67.5,
|
|
|
|
|
- "max": 70,
|
|
|
|
|
- "deduction": -3
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 70,
|
|
|
|
|
- "max": 72.5,
|
|
|
|
|
- "deduction": -3.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 72.5,
|
|
|
|
|
- "max": 75,
|
|
|
|
|
- "deduction": -4
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 75,
|
|
|
|
|
- "max": 77.5,
|
|
|
|
|
- "deduction": -4.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 77.5,
|
|
|
|
|
- "max": 80,
|
|
|
|
|
- "deduction": -5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 80,
|
|
|
|
|
- "max": 82.5,
|
|
|
|
|
- "deduction": -5.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 82.5,
|
|
|
|
|
- "max": 85,
|
|
|
|
|
- "deduction": -6
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 85,
|
|
|
|
|
- "max": 87.5,
|
|
|
|
|
- "deduction": -6.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 87.5,
|
|
|
|
|
- "max": 90,
|
|
|
|
|
- "deduction": -7
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 90,
|
|
|
|
|
- "max": 92.5,
|
|
|
|
|
- "deduction": -7.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 92.5,
|
|
|
|
|
- "max": 95,
|
|
|
|
|
- "deduction": -8
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 95,
|
|
|
|
|
- "max": 97.5,
|
|
|
|
|
- "deduction": -8.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 97.5,
|
|
|
|
|
- "max": "inf",
|
|
|
|
|
- "deduction": -9
|
|
|
|
|
- }
|
|
|
|
|
- ],
|
|
|
|
|
- "coefficients": {
|
|
|
|
|
- "horizontal": 1.2,
|
|
|
|
|
- "vertical": 0.9
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- "back": {
|
|
|
|
|
- "rules": [
|
|
|
|
|
- {
|
|
|
|
|
- "min": 0,
|
|
|
|
|
- "max": 60,
|
|
|
|
|
- "deduction": -0.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 60,
|
|
|
|
|
- "max": 70,
|
|
|
|
|
- "deduction": -1
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 70,
|
|
|
|
|
- "max": 75,
|
|
|
|
|
- "deduction": -1.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 75,
|
|
|
|
|
- "max": 85,
|
|
|
|
|
- "deduction": -2
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 85,
|
|
|
|
|
- "max": 95,
|
|
|
|
|
- "deduction": -2.5
|
|
|
|
|
- },
|
|
|
|
|
- {
|
|
|
|
|
- "min": 95,
|
|
|
|
|
- "max": "inf",
|
|
|
|
|
- "deduction": -3
|
|
|
|
|
- }
|
|
|
|
|
- ],
|
|
|
|
|
- "coefficients": {
|
|
|
|
|
- "horizontal": 1.2,
|
|
|
|
|
- "vertical": 0.9
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- "final_weights": {
|
|
|
|
|
- "front": 0.75,
|
|
|
|
|
- "back": 0.25
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- "card": {
|
|
|
|
|
- "PSA": {
|
|
|
|
|
- "face": 0.35,
|
|
|
|
|
- "corner": 0.3,
|
|
|
|
|
- "edge": 0.1,
|
|
|
|
|
- "center": 0.25
|
|
|
|
|
- },
|
|
|
|
|
- "BGS": {
|
|
|
|
|
- "face": 0.3,
|
|
|
|
|
- "corner": 0.25,
|
|
|
|
|
- "edge": 0.1,
|
|
|
|
|
- "center": 0.25
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- is_range_valid, range_reason = validate_rule_ranges(new_config)
|
|
|
|
|
- print(is_range_valid, range_reason)
|
|
|
|
|
|
|
+import cv2
|
|
|
|
|
+import numpy as np
|
|
|
|
|
+
|
|
|
|
|
+data = np.array([
|
|
|
|
|
+ [
|
|
|
|
|
+ 282,
|
|
|
|
|
+ 316
|
|
|
|
|
+ ],
|
|
|
|
|
+ [
|
|
|
|
|
+ 2593,
|
|
|
|
|
+ 316
|
|
|
|
|
+ ],
|
|
|
|
|
+ [
|
|
|
|
|
+ 2593,
|
|
|
|
|
+ 3601
|
|
|
|
|
+ ],
|
|
|
|
|
+ [
|
|
|
|
|
+ 282,
|
|
|
|
|
+ 3601
|
|
|
|
|
+ ]
|
|
|
|
|
+])
|
|
|
|
|
+
|
|
|
|
|
+ix, iy, iw, ih = cv2.boundingRect(data)
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+def get_box_corners(x, y, w, h):
|
|
|
|
|
+ return [[x, y], [x + w, y], [x + w, y + h], [x, y + h]]
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+print(ix, iy, iw, ih)
|
|
|
|
|
+inner_box_corners_int = get_box_corners(ix, iy, iw, ih)
|
|
|
|
|
+print(inner_box_corners_int)
|