Вопрос или проблема
Я создал модель CNN, используя набор данных MNIST. Я хочу делать предсказания для последовательности чисел, присутствующих на изображениях. Техника включает в себя сегментацию каждого изображения и подачу его в модель, но я сталкиваюсь с трудностями при сегментации чисел из изображений, потому что присутствует два разных типа изображений. Мне нужна надежная техника, которая удаляет все шумы и тени, присутствующие на изображениях, и сегментирует каждое число отдельно. Я также делюсь изображениями здесь. Я ищу надежную технику и код.
Я пытался использовать этот код и технику, но они не работают для прикрепленных изображений
def segment_and_display_digits(image_path):# Считывание изображенияimg = cv2.imread(image_path)gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Получение размеров изображения
height, width = gray.shape
total_area = height * width
# Применение адаптивного порогового значения
thresh = cv2.adaptiveThreshold(
gray,
255,
cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
cv2.THRESH_BINARY_INV,
21, # Размер блока
10 # Константа C
)
# Поиск контуров
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Фильтрация контуров на основе площади
valid_contours = []
min_area = total_area * 0.001 # Минимум 0.1% от площади изображения
max_area = total_area * 0.5 # Максимум 50% от площади изображения
for cnt in contours:
area = cv2.contourArea(cnt)
if min_area < area < max_area:
x, y, w, h = cv2.boundingRect(cnt)
aspect_ratio = w / float(h)
# Проверка, является ли соотношение сторон разумным для цифры (не слишком широкое и не слишком высокое)
if 0.2 < aspect_ratio < 2:
valid_contours.append(cnt)
# Сортировка контуров слева направо
valid_contours = sorted(valid_contours, key=lambda x: cv2.boundingRect(x)[0])
# Извлечение и отображение цифр
digits = []
padding = int(min(height, width) * 0.02) # Адаптивный отступ в зависимости от размера изображения
for cnt in valid_contours:
x, y, w, h = cv2.boundingRect(cnt)
# Добавление отступа, сохраняя его в пределах границ изображения
x1 = max(0, x - padding)
y1 = max(0, y - padding)
x2 = min(width, x + w + padding)
y2 = min(height, y + h + padding)
digit = img[y1:y2, x1:x2]
digits.append(digit)
# Отображение результатов
if digits:
# Создание визуализации оригинального изображения с обнаруженными цифрами
img_with_boxes = img.copy()
for cnt in valid_contours:
x, y, w, h = cv2.boundingRect(cnt)
cv2.rectangle(img_with_boxes, (x, y), (x+w, y+h), (0, 255, 0), 2)
# Построение оригинального изображения с рамками и сегментированными цифрами
plt.figure(figsize=(15, 5))
# Оригинальное изображение с рамками
plt.subplot(2, 1, 1)
plt.imshow(cv2.cvtColor(img_with_boxes, cv2.COLOR_BGR2RGB))
plt.title('Обнаруженные цифры')
plt.axis('off')
# Сегментированные цифры
plt.subplot(2, 1, 2)
for i, digit in enumerate(digits):
plt.subplot(2, len(digits), len(digits) + i + 1)
plt.imshow(cv2.cvtColor(digit, cv2.COLOR_BGR2RGB))
plt.axis('off')
plt.title(f'Цифра {i+1}')
plt.tight_layout()
plt.show()
else:
print("Цифры не найдены на изображении")
Ответ или решение
Эффективная сегментация чисел на изображениях: подробный подход
Для успешной сегментации отдельных цифр из изображений, представленных вами, необходимо учитывать наличие шума и теней, которые могут усложнять процесс. Правильная обработка изображений с использованием методов компьютерного зрения может значительно улучшить результаты. Давайте рассмотрим пошаговый процесс сегментации, используя OpenCV и подходы к предобработке изображений, которые помогут вам решить возникшие трудности.
Шаг 1: Предобработка изображения
Перед началом сегментации важно удалить шум и улучшить контраст изображения. Для этого можно использовать несколько методов:
- Преобразование в оттенки серого: Преобразуйте цветное изображение в оттенки серого для упрощения обработки.
- Устранение шума: Примените фильтр Гаусса для сглаживания изображения и уменьшения шума.
import cv2
import numpy as np
image = cv2.imread('path_to_image.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
smoothed = cv2.GaussianBlur(gray, (5, 5), 0)
Шаг 2: Бинаризация с адаптивным порогом
Использование адаптивного порога поможет выделить цифры на фоне. Данный метод эффективен для изображений с неоднородным освещением.
thresh = cv2.adaptiveThreshold(smoothed, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)
Шаг 3: Поиск контуров и фильтрация
Последний этап – это поиск контуров и их отбор. Примените подходящую фильтрацию, чтобы отобрать контуры, соответствующие цифрам:
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# Настройка параметров для фильтрации контуров
valid_contours = []
for cnt in contours:
area = cv2.contourArea(cnt)
if 100 < area < 5000: # Настройте область в зависимости от размеров ваших цифр
valid_contours.append(cnt)
Шаг 4: Сегментация и отображение цифр
Теперь, когда у нас есть допустимые контуры, мы можем выделить каждую цифру и визуализировать результаты:
digits = []
for cnt in sorted(valid_contours, key=lambda c: cv2.boundingRect(c)[0]):
x, y, w, h = cv2.boundingRect(cnt)
digit = image[y:y+h, x:x+w] # Извлечение цифры по границам контура
digits.append(digit)
# Визуализация результатов
import matplotlib.pyplot as plt
plt.figure(figsize=(10, 5))
for i, digit in enumerate(digits):
plt.subplot(1, len(digits), i + 1)
plt.imshow(cv2.cvtColor(digit, cv2.COLOR_BGR2RGB))
plt.axis('off')
plt.show()
Заключение
Приведенные выше шаги должны помочь вам в сегментации отдельных цифр из ваших изображений с учетом шума и теней. Обратите внимание на настройки параметров фильтрации и область контуров, так как они могут потребовать подбора в зависимости от качества ваших изображений.
Если у вас возникнут дополнительные вопросы или трудности на каком-либо этапе, не стесняйтесь задавать их! Успехов в вашей работе с CNN и MNIST!