EasyOCR не распознает текст на изображенииPython

Программы на Python
Anonymous
EasyOCR не распознает текст на изображении

Сообщение Anonymous »

Я пытаюсь извлечь текст из видео. Я создал обрезанные кадры из видео с помощью ffmpeg и сохранил их в формате PNG. Теперь я использую эти PNG для извлечения текста с помощью EasyOCR. Сначала я пытался сделать это с помощью Tesseract, но это было слишком медленно, поэтому я выбрал EasyOCR, потому что хотел использовать свой графический процессор для более быстрого процесса. Сейчас я приведу два изображения, которые использую в качестве примеров.
  • (ниже) Ссылка на изображение: EasyOCR не распознает ни одного символа.
    Изображение
  • (ниже) ссылка на изображение: результат EasyOCR: 392159.
    [
    Изображение
    2
Ожидается результат:
  • первое изображение должно дать: 0380564.
  • второе изображение должно дать: 92159.
первый, EasyOCR не может распознать текст, второй, он говорит об этом это «392159».
Что я пробовал:
Я увеличил насыщенность и резкость, и мне кажется, что текст стал очень читабельным.
Я не знаю, что я делаю не так...?
Вот мой код 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)

Вернуться в «Python»