狗种类识别

需要安装anaconda

目的

对100种狗进行识别,本文为简化,只对2种狗进行识别。

数据组织

有100种狗
E:\bd\train\train\train 下面是所有训练集图片
这里写图片描述

E:\bd\train\val\test1 下是所有验证集图片
这里写图片描述

E:\bd\train\data_train_image.txt 中存放训练图片–种类信息(以数字表示),格式为:
图片名 种类 url
这里写图片描述

E:\bd\train\val.txt 中存放验证图片–种类信息,格式与data_train_image.txt相同

将图片按其种类复制到对应文件夹下

将图片按期类别移动到E:\bd\train\train1下的子文件夹下

"""
加载txt文件,生成字典
每行数据格式: 图片名 类型ID 图片url
"""
def loadData(filePath):
    pic = {}
    filePath = unicode(filePath, "utf8")
    f = open(filePath)    
    line = f.readline() 
    while line:
        line = line.split(' ') 
        data.append(line[0])
        label.append(line[1])
        pic[line[0]] = line[1]
        line = f.readline()
return pic

# 批量生成文件夹
def genDir(path):
base = unicode(path, "utf8")
    i = 0
    for j in range(140):
        file_name = base + str(i)
        os.mkdir(file_name)
        i=i+1

"""
将filePath文件下的图片保存在newFilePath文件夹下的相应子文件夹中
pic 是字典,存放每个图片要移到的子文件夹名
"""
def moveImg(filePath, newFilePath, pic):
    filePath = unicode(filePath, "utf8")
    newFilePath = unicode(newFilePath, "utf8")
    for root, dirs, files in os.walk(filePath):
        for f in files:
            if pic.has_key(f[:-4]):
                fl = filePath + '/' + f
                img = Image.open(fl)
                img.save(newFilePath + '/' +  pic[f[:-4]] + '/' + f) 

调用后结果如下:
这里写图片描述

调整图片大小

为了节省内存,缩小图片,统一调整为64*64。
这里只挑选2个文件夹:23, 50,将这2个文件夹复制到E:\bd\train\train2下,调整后保存在E:\bd\train\train3下

#按照指定图像大小调整尺寸
def resize_image(image, height, width):
     top, bottom, left, right = (0, 0, 0, 0)

     #获取图像尺寸
     h, w, _ = image.shape

     #对于长宽不相等的图片,找到最长的一边
     longest_edge = max(h, w)    

     #计算短边需要增加多上像素宽度使其与长边等长
     if h < longest_edge:
         dh = longest_edge - h
         top = dh // 2
         bottom = dh - top
     elif w < longest_edge:
         dw = longest_edge - w
         left = dw // 2
         right = dw - left
     else:
         pass 

     #RGB颜色
     BLACK = [0, 0, 0]

     #给图像增加边界,是图片长、宽等长,cv2.BORDER_CONSTANT指定边界颜色由value指定
     constant = cv2.copyMakeBorder(image, top , bottom, left, right, cv2.BORDER_CONSTANT, value = BLACK)

     #调整图像大小并返回
     return cv2.resize(constant, (height, width))

def read_path(path_name, newpath):    
     for dir_item in os.listdir(path_name):
         #从初始路径开始叠加,合并成可识别的操作路径
         full_path = os.path.abspath(os.path.join(path_name, dir_item))

         if os.path.isdir(full_path):    #如果是文件夹,继续递归调用
             read_path(full_path)
         else:   #文件
             if dir_item.endswith('.jpg'):
                 image = cv2.imread(full_path)                
                 image = resize_image(image, 64, 64)
                 cv2.imwrite(newpath + '/' + dir_item, image)

调用后结果如下:
这里写图片描述

训练模型

由于训练集和测试集的每类各约有100张图片,数量太少,所以采用扩展的数据集训练模型,准确率约为90%

# 搭建模型
def cnn(weights):
    model = Sequential()
    model.add(Convolution2D(32, 3, 3, input_shape=(64, 64, 3)))
    model.add(Activation('relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))

    model.add(Convolution2D(32, 3, 3))
    model.add(Activation('relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))

    model.add(Convolution2D(64, 3, 3))
    model.add(Activation('relu'))
    model.add(MaxPooling2D(pool_size=(2, 2)))

    model.add(Flatten())  # this converts our 3D feature maps to 1D feature vectors
    model.add(Dense(64))
    model.add(Activation('relu'))
    model.add(Dropout(0.5))
    model.add(Dense(1))
    model.add(Activation('sigmoid'))

    if weights:
        model.load_weights(weights)

return model

# 训练模型
def train():
model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])

    # this is the augmentation configuration we will use for training
    train_datagen = ImageDataGenerator(
        rescale=1./255,
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True)

    # this is the augmentation configuration we will use for testing:
    # only rescaling
    test_datagen = ImageDataGenerator(rescale=1./255)

    # this is a generator that will read pictures found in
    # subfolers of 'E:/bd/train/train3', and indefinitely generate
    # batches of augmented image data
    train_generator = train_datagen.flow_from_directory(
        'E:/bd/train/train3',  # this is the target directory
        target_size=(64, 64),  # all images will be resized to 150x150
        batch_size=32,
        class_mode='binary')  # since we use binary_crossentropy loss, we need binary labels

    # this is a similar generator, for validation data
    validation_generator = test_datagen.flow_from_directory(
        'E:/bd/train/val3',
        target_size=(64, 64),
        batch_size=32,
        class_mode='binary')

    model.fit_generator(
        train_generator,
        samples_per_epoch=200,  # 当模型处理的样本数达到200时,开始下一个epoch
        nb_epoch=30,   # epoch总数
        validation_data=validation_generator,   
        nb_val_samples=80)   # 每个epoch所采用的验证集数量

model.save_weights('first_try.h5')  # always save your weights after training or during 

部分结果:
Epoch 27/30
6/6 [==============================] - 13s - loss: 0.1839 - acc: 0.9255 - val_loss: 0.1789 - val_acc: 0.9233
Epoch 28/30
6/6 [==============================] - 14s - loss: 0.2680 - acc: 0.8775 - val_loss: 0.1809 - val_acc: 0.9386
Epoch 29/30
6/6 [==============================] - 14s - loss: 0.1724 - acc: 0.9323 - val_loss: 0.1819 - val_acc: 0.9398
Epoch 30/30
6/6 [==============================] - 14s - loss: 0.2165 - acc: 0.9027 - val_loss: 0.1394 - val_acc: 0.9422

预测

偷懒,采用训练集中的图片作一下预测,结果输出:
[[ 0.]]
是正确的

def predict():
    model = cnn1('first_try.h5')
    img_path = 'E:/bd/train/train3/23/25435079,1084908304.jpg'
    img = image.load_img(img_path, target_size=(64, 64))
    x = image.img_to_array(img)
    x = np.expand_dims(x, axis=0)
    preds = model.predict(x)
    print preds

参考
人脸检测及识别python实现系列(5)——利用keras库训练人脸识别模型http://www.cnblogs.com/neo-T/p/6477378.html

使用Keras面向小数据集进行图像分类
http://blog.csdn.net/yichenmoyan/article/details/51908840

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值