- (ниже) Ссылка на изображение: EasyOCR не распознает ни одного символа.

- (ниже) ссылка на изображение: результат EasyOCR: 392159.
[

2
- первое изображение должно дать: 0380564.
- второе изображение должно дать: 92159.
Что я пробовал:
Я увеличил насыщенность и резкость, и мне кажется, что текст стал очень читабельным.
Я не знаю, что я делаю не так...?
Вот мой код Python:
import os
import re
from glob import glob
import csv
import torch
import cv2
import argparse
import numpy as np
import easyocr
def _preprocess_image(img: np.ndarray, image_limit: int, frame_name: str = None) -> np.ndarray:
"""Sharpen and increase saturation of image for better OCR."""
# Sharpen using unsharp mask
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
laplacian = cv2.Laplacian(img, cv2.CV_64F)
sharpened = cv2.convertScaleAbs(img - 0.5 * laplacian)
# Convert to HSV to boost saturation
hsv = cv2.cvtColor(sharpened, cv2.COLOR_BGR2HSV).astype(np.float32)
hsv[:, :, 1] = np.clip(hsv[:, :, 1] * 1.5, 0, 255) # Increase saturation by 50%
hsv = hsv.astype(np.uint8)
# Convert back to BGR
result = cv2.cvtColor(hsv, cv2.COLOR_HSV2BGR)
if image_limit and frame_name:
# Create temp directory if it doesn't exist
os.makedirs("temp", exist_ok=True)
# Use frame name for unique filename
stem = os.path.splitext(frame_name)[0]
filename = f"temp/{stem}_preprocessed.png"
cv2.imwrite(filename, result)
print(f" Saved preprocessed image: {filename}")
return result
def _frame_name_to_timestamp(image_name: str, fps: int = 2, startSecond: int = 515) -> str:
"""Convert frame filename like frame_000001.png to HH:MM:SS.mmm timestamp."""
stem = os.path.splitext(image_name)[0]
match = re.search(r"(\d+)$", stem)
if not match:
return image_name
frame_index = int(match.group(1))
total_ms = int(((frame_index - 1 + (startSecond * 2)) / fps) * 1000)
hours = total_ms // 3_600_000
total_ms %= 3_600_000
minutes = total_ms // 60_000
total_ms %= 60_000
seconds = total_ms // 1_000
milliseconds = total_ms % 1_000
return f"{hours:02}:{minutes:02}:{seconds:02}.{milliseconds:03}"
def extract(folder_path: str = "frames_gpu", output_file: str = "numbers.csv", batch_size: int = 16, image_limit: int = None):
reader = easyocr.Reader(["en"], gpu=True)
image_patterns = ("*.png", "*.jpg", "*.jpeg")
print(f"Is CUDA available? {torch.cuda.is_available()}")
print(f"Using device: {reader.device}")
device_name = "GPU (CUDA)" if reader.device == "cuda" else "CPU"
print(f"Using {device_name} for OCR processing.")
image_files = []
for pattern in image_patterns:
image_files.extend(glob(os.path.join(folder_path, pattern)))
image_files = sorted(image_files)
# Limit images for testing
if image_limit:
image_files = image_files[:image_limit]
print(f"Test mode: processing {len(image_files)} images out of {len(sorted(glob(os.path.join(folder_path, '*.png')))) + len(sorted(glob(os.path.join(folder_path, '*.jpg')))) + len(sorted(glob(os.path.join(folder_path, '*.jpeg'))))} available")
results = {}
# Process in batches
for i in range(0, len(image_files), batch_size):
batch_paths = image_files[i : i + batch_size]
batch_images = []
# CPU Pre-processing: Load images and enhance for OCR
for path in batch_paths:
img = cv2.imread(path)
if img is None:
print(f"Warning: Could not read {path}")
continue
# Sharpen and boost saturation for better OCR
frame_name = os.path.basename(path)
img = _preprocess_image(img, image_limit, frame_name)
batch_images.append(img)
# GPU Inference: Process the whole batch
for idx, img_data in enumerate(batch_images):
filename = os.path.basename(batch_paths[idx])
texts = reader.readtext(img_data, detail=0) # detail=0 returns only text
# Concatenate all detected text (handles character-by-character OCR)
all_text = "".join(str(t) for t in texts)
# Extract number sequences (try 7+ digits first, fallback to 5+ digits if none found)
candidates = re.findall(r"\d{7,}", all_text.replace(" ", ""))
if not candidates:
# Fallback: look for 5+ digit sequences (in case 7-digit is too strict)
candidates = re.findall(r"\d{5,}", all_text.replace(" ", ""))
numbers = sorted(set(candidates))
results[filename] = numbers
if i == 0 and idx < 3 and numbers:
print(f" Found numbers: {numbers}")
print(f"Processed {i + len(batch_paths)} / {len(image_files)} images...")
with open(output_file, "w", newline="", encoding="utf-8") as csv_file:
writer = csv.writer(csv_file)
writer.writerow(["timestamp", "numbers"])
for image_name, numbers in results.items():
writer.writerow([_frame_name_to_timestamp(image_name, fps=2), ";".join(numbers)])
return results
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Extract 7-digit numbers from video frames using OCR")
parser.add_argument("--test", type=int, default=None, metavar="COUNT", help="Test mode: process only COUNT images")
args = parser.parse_args()
extract(image_limit=args.test)