我正在尝试使用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)
观察目标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.
答案 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
h,w = 150,150 # desired height and width
batch_size = 32
N_images = 100 #total number of images
Keras
是批量工作的,因此batch_size
仅确定一次要处理多少张图片(这不会影响最终结果,只会影响速度)。
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])
现在您可以从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
分类器中。