问题描述
我正在尝试使用scikit-learn构建一个简单的图像分类器.我希望避免在训练之前必须调整大小和转换每个图像.
I'm trying to build a simple image classifier using scikit-learn. I'm hoping to avoid having to resize and convert each image before training.
给出两个具有不同格式和大小(1.jpg
和2.png
)的不同图像,如何在拟合模型时避免使用ValueError
?
Given two different images that are different formats and sizes (1.jpg
and 2.png
), how can I avoid a ValueError
while fitting the model?
- 我有一个例子,我仅使用
1.jpg
进行训练,非常适合. - 还有另一个示例,其中我同时使用
1.jpg
和2.png
进行训练,并且生成了ValueError
.
- I have one example where I train using only
1.jpg
, which fits successfully. - I have another example where I train using both
1.jpg
and2.png
and aValueError
is produced.
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图像.
This example will raise a Value error.
Observe the different 2.png image in target 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
推荐答案
为此,我真的建议使用Keras
中的工具,这些工具专门用于以高度可扩展和高效的方式预处理图像.
For this, I would really recommend using the tools in Keras
that are specifically designed to preprocess images in a highly scalable and efficient way.
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
只是确定一次要处理多少张图片(这不会影响最终结果,只会影响速度).
Keras
works in batches, so batch_size
just determines how many pictures at once will be processed (this does not impact your end result, just the speed).
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").
The object that is going to do the image extraction is ImageDataGenerator
. It has the method flow_from_directory
which I believe might be useful for you here. It will read the content of the folder Pictures_dir
and expect your images to be in folders by class (eg: Pictures_dir/class0 and Pictures_dir/class1). The generator, when called, will then create images from these folders and also import their label (in this example, 'class0' and 'class1').
此生成器还有很多其他参数,您可以在Keras
文档中进行检查(特别是如果您想进行数据扩充).
There are plenty of other arguments to this generator, you can check them out in the Keras
documentation (especially if you want to do data augmentation).
注意:这将按照您的要求拍摄任何图像,无论是PNG还是JPG
Note: this will take any image, be it PNG or JPG, as you requested
如果要获取从类名到标签索引的映射,请执行以下操作:
If you want to get the mapping from class names to label indices, do:
train_generator.class_indices
# {'class0': 0, 'class1': 1}
您可以检查
plt.imshow(train_generator[0][0][0])
3从生成器中提取所有调整大小的图像
现在您可以从ImageGenerator
中提取图像了:
3 Extract all resized images from the Generator
Now you are ready to extract the images from the 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
分类器中.
Now you have your images all at the same size in images
, and their corresponding labels in labels
, which you can then feed into any scikit-learn
classifier of your choice.
这篇关于如何在scikit-learn中分类具有各种大小和格式的不同图像?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!