如何在scikit-learn中分类具有各种大小和格式的不同图像?

时间:2019-06-22 20:27:48

标签: image numpy matplotlib scikit-learn classification

我正在尝试使用scikit-learn构建一个简单的图像分类器。我希望避免在训练之前必须调整大小和转换每个图像。

问题

给出两个不同格式和大小的不同图像(1.jpg2.png),如何在拟合模型时避免使用ValueError

  • 我有一个例子,我仅使用1.jpg进行训练,非常适合。
  • 我有另一个示例,其中我同时使用1.jpg2.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中的其他2.png图像。

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 个答案:

答案 0 :(得分:1)

由于幕后的数学运算,这很困难,(如果细节超出了范围),如果您这样做的话,可以说您构建自己的算法,但仍然无法获得理想的结果。 我曾经用不同大小的面孔遇到过这个问题。也许这段代码为您提供了起点。

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

注意:我很久以前写的这也许不是一个好习惯

答案 1 :(得分:1)

为此,我真的建议使用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文档中进行检查(特别是如果您想进行数据扩充)。

注意:这将按照您的要求拍摄任何图像,无论是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分类器中。