Compare commits

..

5 Commits

Author SHA1 Message Date
0d3467c98c Доработки по скрипту для вырезания VIN из СТС.
Some checks failed
Build/Publish Develop Docs / deploy (push) Has been cancelled
Close inactive issues / close-issues (push) Has been cancelled
2025-07-23 09:25:08 +03:00
671c5085e9 refs # Скрипт для вырезания VIN из СТС.
Some checks failed
Build/Publish Develop Docs / deploy (push) Has been cancelled
2025-07-22 19:27:36 +03:00
644c61e9fe Скрипт для вырезания VIN из СТС.
Some checks are pending
Build/Publish Develop Docs / deploy (push) Waiting to run
2025-07-21 19:51:08 +03:00
5a87e37bb2 Сделал отдельный конфиг для Kaggle.
Some checks are pending
Build/Publish Develop Docs / deploy (push) Waiting to run
2025-07-21 19:03:52 +03:00
206c2a6877 Добавил скрипты для валидации. 2025-07-21 19:03:10 +03:00
6 changed files with 244 additions and 9 deletions

1
.gitignore vendored
View File

@@ -13,6 +13,7 @@ output/
train_data/
pretrained_models/
log/
tags
*.DS_Store
*.vs
*.user

View File

@@ -1,11 +1,11 @@
Global:
model_name: PP-OCRv5_server_rec # To use static model for inference.
debug: false
use_gpu: true
use_gpu: false
epoch_num: 75
log_smooth_window: 20
print_batch_step: 10
save_model_dir: /kaggle/output/PP-OCRv5_server_rec
save_model_dir: output/PP-OCRv5_server_rec
save_epoch_step: 1
eval_batch_step: [0, 2000]
cal_metric_during_train: true
@@ -14,13 +14,13 @@ Global:
checkpoints:
save_inference_dir:
use_visualdl: false
infer_img: /kaggle/input/custom-ocr-dataset/images/1C4HJXEN3MW645094.jpg
character_dict_path: /kaggle/input/custom-ocr-dataset/dict.txt
infer_img: train_data/images/1C4HJXEN3MW645094.jpg
character_dict_path: train_data/dict.txt
max_text_length: &max_text_length 19
infer_mode: false
use_space_char: true
distributed: true
save_res_path: /kaggle/output/rec/predicts_ppocrv5.txt
save_res_path: output/rec/predicts_ppocrv5.txt
d2s_train_image_shape: [3, 48, 320]
@@ -78,10 +78,10 @@ Train:
dataset:
name: MultiScaleDataSet
ds_width: false
data_dir: /kaggle/input/custom-ocr-dataset/images
data_dir: train_data/images
ext_op_transform_idx: 1
label_file_list:
- /kaggle/input/custom-ocr-dataset/train.txt
- train_data/train.txt
transforms:
- DecodeImage:
img_mode: BGR
@@ -110,9 +110,9 @@ Train:
Eval:
dataset:
name: SimpleDataSet
data_dir: /kaggle/input/custom-ocr-dataset/images
data_dir: train_data/images
label_file_list:
- /kaggle/input/custom-ocr-dataset/val.txt
- train_data/val.txt
transforms:
- DecodeImage:
img_mode: BGR

View File

@@ -0,0 +1,135 @@
Global:
model_name: PP-OCRv5_server_rec # To use static model for inference.
debug: false
use_gpu: true
epoch_num: 75
log_smooth_window: 20
print_batch_step: 10
save_model_dir: /kaggle/output/PP-OCRv5_server_rec
save_epoch_step: 1
eval_batch_step: [0, 2000]
cal_metric_during_train: true
calc_epoch_interval: 1
pretrained_model: https://paddle-model-ecology.bj.bcebos.com/paddlex/official_pretrained_model/PP-OCRv5_server_rec_pretrained.pdparams
checkpoints:
save_inference_dir:
use_visualdl: false
infer_img: /kaggle/input/custom-ocr-dataset/images/1C4HJXEN3MW645094.jpg
character_dict_path: /kaggle/input/custom-ocr-dataset/dict.txt
max_text_length: &max_text_length 19
infer_mode: false
use_space_char: true
distributed: true
save_res_path: /kaggle/output/rec/predicts_ppocrv5.txt
d2s_train_image_shape: [3, 48, 320]
Optimizer:
name: Adam
beta1: 0.9
beta2: 0.999
lr:
name: Cosine
learning_rate: 0.0005
warmup_epoch: 1
regularizer:
name: L2
factor: 3.0e-05
Architecture:
model_type: rec
algorithm: SVTR_HGNet
Transform:
Backbone:
name: PPHGNetV2_B4
text_rec: True
Head:
name: MultiHead
head_list:
- CTCHead:
Neck:
name: svtr
dims: 120
depth: 2
hidden_dims: 120
kernel_size: [1, 3]
use_guide: True
Head:
fc_decay: 0.00001
- NRTRHead:
nrtr_dim: 384
max_text_length: *max_text_length
Loss:
name: MultiLoss
loss_config_list:
- CTCLoss:
- NRTRLoss:
PostProcess:
name: CTCLabelDecode
Metric:
name: RecMetric
main_indicator: acc
Train:
dataset:
name: MultiScaleDataSet
ds_width: false
data_dir: /kaggle/input/custom-ocr-dataset/images
ext_op_transform_idx: 1
label_file_list:
- /kaggle/input/custom-ocr-dataset/train.txt
transforms:
- DecodeImage:
img_mode: BGR
channel_first: false
- MultiLabelEncode:
gtc_encode: NRTRLabelEncode
- KeepKeys:
keep_keys:
- image
- label_ctc
- label_gtc
- length
- valid_ratio
sampler:
name: MultiScaleSampler
scales: [[320, 32], [320, 48], [320, 64]]
first_bs: &bs 128
fix_bs: false
divided_factor: [8, 16] # w, h
is_training: True
loader:
shuffle: true
batch_size_per_card: *bs
drop_last: true
num_workers: 16
Eval:
dataset:
name: SimpleDataSet
data_dir: /kaggle/input/custom-ocr-dataset/images
label_file_list:
- /kaggle/input/custom-ocr-dataset/val.txt
transforms:
- DecodeImage:
img_mode: BGR
channel_first: false
- MultiLabelEncode:
gtc_encode: NRTRLabelEncode
- RecResizeImg:
image_shape: [3, 48, 320]
- KeepKeys:
keep_keys:
- image
- label_ctc
- label_gtc
- length
- valid_ratio
loader:
shuffle: false
drop_last: false
batch_size_per_card: 128
num_workers: 4

45
scripts/detect_vin.py Normal file
View File

@@ -0,0 +1,45 @@
"""
exec(open("scripts/detect_vin.py").read())
"""
from paddleocr import PaddleOCR
import cv2
import re
ocr = PaddleOCR(lang='en', use_textline_orientation=True)
def cut_vin(ocr, input_image, output_image):
"""
Вырезать VIN из изображения.
"""
image = cv2.imread(input_image)
result = ocr.predict(image)
processed_image = result[0]["doc_preprocessor_res"]["output_img"]
vin_pattern = re.compile(r'^[A-HJ-NPR-Z0-9]{17}$')
found_vin = None
for text, bbox in zip(result[0]["rec_texts"], result[0]["rec_boxes"]):
if vin_pattern.match(text):
found_vin = text
break
if found_vin:
x_min, y_min = bbox[0], bbox[1]
x_max, y_max = bbox[2], bbox[3]
vin_region = processed_image[y_min:y_max, x_min:x_max]
cv2.imwrite(output_image, vin_region)
return found_vin
vin = cut_vin(ocr, "input/image.jpg", "output/vin.jpg")
if vin:
print(f"VIN найден: {vin}.")
else:
print("VIN не обнаружен.")

27
scripts/rec_validation.py Normal file
View File

@@ -0,0 +1,27 @@
import os
from paddleocr import TextRecognition
ocr = TextRecognition(
model_name="PP-OCRv5_server_rec"
# model_dir="output/PP-OCRv5_server_rec_vin"
)
with open("train_data/val.txt", "r") as label_file:
lines = label_file.readlines()
total = len(lines)
matches, mismatches = 0, 0
for idx, line in enumerate(lines, start=1):
file_name, label = line.split("\t")
label = label.strip()
path = os.path.join("train_data", os.path.join("images", file_name))
result = ocr.predict(path)
print(f"{idx}/{total} ", end="")
if result[0]["rec_text"] and result[0]["rec_text"] == label:
print(f"match {label}")
matches += 1
else:
print(f"mismatch {label}")
mismatches += 1
print(f"{matches} matches of {total}")
print(f"{mismatches} mismatches of {total}")

View File

@@ -0,0 +1,27 @@
import os
from paddleocr import PaddleOCR
from typing import Optional
ocr = PaddleOCR(rec_model_dir="output/vin_rec_inference")
def get_best_accuracy(ocr: PaddleOCR, file_path: str) -> Optional[tuple[str, float]]:
result = ocr.predict(file_path)
texts_with_scores = [item for item in filter(
lambda x: len(x[0]) == 17,
zip(result[0]["rec_texts"], result[0]["rec_scores"])
)]
if texts_with_scores:
return max(
texts_with_scores,
key=lambda y: y[1]
)
else:
return None
with open("train_data/val.txt", "r") as label_file:
for line in label_file.readlines():
file_name, label = line.split("\t")
path = os.path.join("train_data", os.path.join("images", file_name))
print(file_name)
print(get_best_accuracy(ocr, path))