Как я могу классифицировать различные изображения с различными размерами и форматами в Scikit-Learn? - PullRequest
1 голос
/ 22 июня 2019

Я пытаюсь создать простой классификатор изображений, используя scikit-learn.Я надеюсь избежать изменения размера и преобразования каждого изображения перед тренировкой.

Вопрос

Учитывая два разных изображения разных форматов и размеров (1.jpg и 2.png), какможно ли избежать ValueError при подгонке модели?

  • У меня есть один пример, когда я тренируюсь, используя только 1.jpg, который подходит успешно.
  • У меня есть еще один пример, в котором я тренируюсь с использованием 1.jpg и 2.png, и получается ValueError.

Этот пример будет соответствовать:

import numpy as np
from sklearn import svm 
import matplotlib.image as mpimg

target = [1, 2]
images = np.array([
    # target 1
    [mpimg.imread('./1.jpg'), mpimg.imread('./1.jpg')],
    # target 2
    [mpimg.imread('./1.jpg'), mpimg.imread('./1.jpg')],
])
n_samples = len(images)
data = images.reshape((n_samples, -1))
model = svm.SVC()
model.fit(data, target)

Этот пример вызовет ошибку Value.

Обратите внимание на другое изображение 2.png в цели 2.

import numpy as np
from sklearn import svm 
import matplotlib.image as mpimg

target = [1, 2]
images = np.array([
    # target 1
    [mpimg.imread('./1.jpg'), mpimg.imread('./1.jpg')],
    # target 2
    [mpimg.imread('./2.png'), mpimg.imread('./1.jpg')],
])
n_samples = len(images)
data = images.reshape((n_samples, -1))
model = svm.SVC()
model.fit(data, target)
# ValueError: setting an array element with a sequence.

1.jpg

1.jpg

2.png

2.png

Ответы [ 2 ]

1 голос
/ 30 июня 2019

Для этого я действительно рекомендую использовать инструменты из Keras, специально предназначенные для предварительной обработки изображений с высокой масштабируемостью и эффективностью.

from keras.preprocessing.image import ImageDataGenerator
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np

1 Определите целевой размер ваших новых изображений

h,w = 150,150 # desired height and width
batch_size = 32 
N_images = 100 #total number of images

Keras работает в пакетном режиме, поэтому batch_size просто определяет, сколько снимков будет обработано за один раз (это не влияет на конечный результат, только на скорость).

2 Создайте генератор изображений

train_datagen = ImageDataGenerator(
    rescale=1./255)

train_generator = train_datagen.flow_from_directory(
    'Pictures_dir',
    target_size=(h, w),
    batch_size=batch_size,
    class_mode = 'binary')

Объект, который будет извлекать изображение, - ImageDataGenerator.У него есть метод flow_from_directory, который, я считаю, может быть полезен для вас здесь.Он будет читать содержимое папки Pictures_dir и ожидать, что ваши изображения будут находиться в папках по классам (например: Pictures_dir / class0 и Pictures_dir / class1).Генератор при вызове создаст изображения из этих папок, а также импортирует их метки (в этом примере 'class0' и 'class1').

Существует множество других аргументов для этого генератора, вы можете проверить их в документации Keras (особенно, если вы хотите увеличить данные).

Примечание: для этого потребуется любойimage, будь то PNG или JPG, как вы и просили

Если вы хотите получить отображение имен классов на метки индексов, выполните:

train_generator.class_indices
# {'class0': 0, 'class1': 1}

Вы можете проверить, что происходит

plt.imshow(train_generator[0][0][0])

3 Извлеките все изображения с измененным размером из генератора

Теперь вы готовы извлечь изображения из ImageGenerator:

def extract_images(generator, sample_count):
    images = np.zeros(shape=(sample_count, h, w, 3))
    labels = np.zeros(shape=(sample_count))
    i = 0
    for images_batch, labels_batch in generator: # we are looping over batches
        images[i*batch_size : (i+1)*batch_size] = images_batch
        labels[i*batch_size : (i+1)*batch_size] = labels_batch
        i += 1
        if i*batch_size >= sample_count:
            # we must break after every image has been seen once, because generators yield indifinitely in a loop
            break
    return images, labels

images, labels = extract_images(train_generator, N_images)

print(labels[0])
plt.imshow(images[0])

Теперь у вас естьвсе изображения одного размера в images и соответствующие им метки в labels, которые затем можно передать в любой классификатор scikit-learn по вашему выбору.

1 голос
/ 27 июня 2019

Это сложно из-за математических операций за сценой (детали выходят за рамки), если вам удастся это сделать, скажем, вы построите свой собственный алгоритм, все равно вы не получите желаемого результата. у меня была эта проблема однажды с лицами разных размеров. может быть, этот кусок кода даст вам отправную точку.

from PIL import Image
import face_recognition

def face_detected(file_address = None , prefix = 'detect_'):
    if file_address is None:
        raise FileNotFoundError('File address required')
    image = face_recognition.load_image_file(file_address)
    face_location = face_recognition.face_locations(image)

    if face_location:
        face_location = face_location[0]
        UP = int(face_location[0] - (face_location[2] - face_location[0]) / 2)
        DOWN = int(face_location[2] + (face_location[2] - face_location[0]) / 2)
        LEFT = int(face_location[3] - (face_location[3] - face_location[2]) / 2)
        RIGHT = int(face_location[1] + (face_location[3] - face_location[2]) / 2)

        if UP - DOWN is not LEFT - RIGHT:
            height = UP - DOWN
            width = LEFT - RIGHT
            delta = width - height
            LEFT -= int(delta / 2)
            RIGHT += int(delta / 2)

        pil_image = Image.fromarray(image[UP:DOWN, LEFT:RIGHT, :])
        pil_image.thumbnail((50, 50), Image.ANTIALIAS)
        pil_image.save(prefix + file_address)

        return True

    pil_image = Image.fromarray(image)
    pil_image.thumbnail((200, 200), Image.ANTIALIAS)
    pil_image.save(prefix + file_address)
    return False

Примечание: я написал это давным-давно, может быть, не очень хорошая практика

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...