python图像分类示例_python +keras实现图像分类(入门级例子讲解)

本文介绍了一个基于Kaggle猫狗大战数据集的图像分类项目,使用了二分类和多分类的交叉熵损失函数。通过OpenCV预处理图像,构建了一个简单的CNN模型,最终达到了0.7072的准确率。此外,还展示了如何用PyQT实现一个简单的猫狗图像预测界面。
摘要由CSDN通过智能技术生成

一.项目描述

数据集来源于kaggle猫狗大战数据集。训练集有25000张,猫狗各占一半。测试集12500张。希望计算机可以从这些训练集图片中学习到猫狗的特征,从而使得计算机可以正确的对未曾见过的猫狗图片进行分类。这就是图像分类问题,计算机视觉研究领域之一,计算机通过学习图像本身的特征将不同类别的图像区分开来。

二.评价指标

二分类评价指标

binary_crossentropy:交叉熵

ŷ i是样本标签,yi样本输出。只有yi和ŷ i是相等时,loss才为0,否则loss就是为一个正数。而且,概率相差越大,loss就越大。这个度量概率距离的方式称为交叉熵。

二分类模型的最后一层的激活函数 是:sigmoid

二分类模型最后输出的是0到1的数。

应该使用numpy的四舍五入求取类别,并转换为整数

pred_y=int(np.round(predict_y))

多分类评价指标

categorical_crossentropy:分类交叉熵函数

ŷ i是样本标签,yi样本输出

多分类模型的最后一层的激活函数 是:softmax

softmax先把输出指数化,再归一化,得到各类概率。

假设一个问题是3分类,一个训练样本进来得到的softmax是[0.5,0.2,0.3]

假设这个正确样本类别为第一个类别。

则该样本分类交叉熵为:

多分类模型输出的是各个类别的概率,如2个样本的预测输出为:ypred=[[0.5,0.2,0.3],[0.4,0.1,0.5]]

应该使用numpy求取最大值索引

pred=np.argmax(ypred,axis=1)

得到[0,2]

三.算例实现

数据集

电脑垃圾啦,无法将全部图片都用上,跑不动。

于是猫和狗都选取原始数据集的一半左右。

猫的图片如下:

狗的图片如下:

各种各样的猫和狗,不容易找到统一的图片预处理方式,如处理成二值图像(但猫狗颜色不一样,二值处理有的把背景提取出来啦,毕竟二值处理需要把前景色处理成白色,为了达到此要求,有的图片得做反二值化处理)

就对图片不做任何处理吧,防止图片失真。

1数据集读取函数

注意:cv2.imread(name) 图片路径不能含有中文。

#个人喜好用OpenCV

需要对图片统一大小: cv2.resize(img, (100, 100))

import os

import numpy as np

import cv2

def ReFileName(dirPath):

"""

:param dirPath: 文件夹路径

:return:

"""

# 对目录下的文件进行遍历

x=[]

for file in os.listdir(dirPath):

# 判断是否是文件

if os.path.isfile(os.path.join(dirPath, file)) == True:

c= os.path.basename(file)

name = dirPath + '\\' + c

img = cv2.imread(name)

img = cv2.resize(img, (100, 100)) # 使尺寸大小一样

x.append(img)

return x

2数据集读取并处理

分别读取猫狗数据集,之前我将猫和狗放在两个文件夹啦。

对数据除以255,cnn模型对数值小的数处理得比较好。

转换数据格式,图像格式为np.uint8, 转换成float型,计算机可以计算。

标签处理,猫处理成1,狗处理成0

dirPathcat = r"catdog\cat"#文件路径

cat=ReFileName(dirPathcat)#调用函数

cat=np.array(cat)/255

cat=cat.astype(np.float64)

print('输入cat.shape',cat.shape)

biaoqiancat=[1 for i in range(len(cat))]#标签处理

biaoqiancat=np.array(biaoqiancat)#标签

dirPathdog = r"catdog\dog"#文件路径

dog=ReFileName(dirPathdog)#调用函数

dog=np.array(dog)/255#数据

dog=dog.astype(np.float64)

biaoqiandog=[0 for i in range(len(dog))]#标签处理

biaoqiandog=np.array(biaoqiandog)#标签

3.数据打乱

首先拼接数据集,然后打乱数据集特征和标签。

如果是多分类问题得在打乱数据前对y进行one-hot化,如:

y=keras.utils.to_categorical(y,4)#四分类

x=np.concatenate((cat,dog),axis=0)

y=np.concatenate((biaoqiancat,biaoqiandog),axis=0)

index = [i for i in range(len(y))] # test_data为测试数据

np.random.seed(1)

np.random.shuffle(index) # 打乱索引

train_data = x[index]

train_label = y[index]

4.定义模型

电脑不行,就用个普通模型跑吧。

如果是多分类问题

最后两行为

model.add(Dense(2, activation='softmax')) # 输出层

model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])

本文模型

from keras.models import Sequential

from keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPooling2D

import keras

import time

def define_model():

model = Sequential()

model.add(Conv2D(filters=16,

kernel_size=(5, 5),

padding='same',

input_shape=(100, 100, 3),

activation='relu')) # 卷积层1

model.add(MaxPooling2D(pool_size=(2, 2))) # 池化层2

model.add(Dropout(0.25))

model.add(Flatten()) # 平坦层

model.add(Dense(10,activation='relu')) # 隐藏层

model.add(Dense(1, activation='sigmoid')) # 输出层

model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

model.summary()

return model

5.模型训练并保持

准确率0.7072,之前使用的是猫狗各3000多张,准确率为0.5。

现在使用的是各6000多张,准确率0.7。

原始数据集有各12000多张,原谅我,使用全部数据集电脑太卡,没服务器,学生党。

start_time = time.time()

model = define_model()

model.fit(train_data, train_label, epochs=2)

model.save('猫狗分类.h5')

end_time = time.time()

run_time = (end_time - start_time) / 60

print(run_time) #3.931485986709595

print('训练结束')

#0.7072

四.pyqt可视化结果

建立个简单版的qt猫狗预测系统吧。

#!/usr/bin/env python3

# -*- coding: utf-8 -*-

# @Author: yudengwu

# @Date : 2020/7/18

import sys

from PyQt5 import QtWidgets, QtCore, QtGui

from PyQt5.QtGui import *

from PyQt5.QtWidgets import *

from PyQt5.QtCore import *

import cv2

import keras

from keras .models import load_model

import numpy as np

import re

class picture(QWidget):

def __init__(self):

super(picture, self).__init__()

self.resize(600, 400)

self.setWindowTitle("猫狗分类")

self.btn = QPushButton()

self.btn.setText("打开图片")

self.btn.clicked.connect(self.openimage)

self.label = QLabel()

self.label.setText('图片路径')

self.labelimage = QLabel()

self.labelimage.setText("显示图片")

#self.labelimage.setFixedSize(500, 400)#设置尺寸

self.labelimage.setStyleSheet("QLabel{background:white;}"

"QLabel{color:rgb(300,300,300,120);font-size:10px;font-weight:bold;font-family:宋体;}"

)

#预测按钮

self.btnclass=QPushButton()

self.btnclass.setText('点击预测分类')

self.btnclass.clicked.connect(self.fenlei)

self.labelclass=QLabel()

self.labelclass.setText('预测类别')

self.labelclass.setStyleSheet("font:16pt '楷体';border-width:2px;border-style: inset;border-color:gray")

layout1=QVBoxLayout()

layout1.addWidget(self.btn)

layout1.addWidget(self.label)

layout1.addWidget(self.labelimage)

layout2 = QVBoxLayout()

layout2.addWidget(self.btnclass)

layout2.addWidget(self.labelclass)

layout=QVBoxLayout()

layout.addLayout(layout1)

layout.addLayout(layout2)

self.setLayout(layout)

def openimage(self):

imgName, imgType = QFileDialog.getOpenFileName(self, "打开图片", "", "*.jpg;;*.png;;All Files(*)")

#jpg = QtGui.QPixmap(imgName).scaled(self.labelimage.width(), self.label.height())#适应labelimage尺寸,前提是label设置了尺寸

jpg = QtGui.QPixmap(imgName)

self.labelimage.setPixmap(jpg)

self.label.setText(str(imgName))

def fenlei(self):

biaoqian = {'1': '猫', '0': '狗'}

path=self.label.text()

newName = re.sub('(D:/机器学习/学习草稿/)','', path)

print(newName)

img = cv2.imread(str(newName))

img = cv2.resize(img, (100, 100)) # 使尺寸大小一样

img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

img = np.array(img) / 255

img = img.astype(np.float64)

img = img.reshape(-1, 100, 100, 1)

model = load_model('猫狗分类.h5')

predict_y = model.predict(img)

pred_y = int(np.round(predict_y))

print(pred_y)

self.labelclass.setText(biaoqian[str(pred_y)])

if __name__ == "__main__":

app = QtWidgets.QApplication(sys.argv)

my = picture()

my.show()

sys.exit(app.exec_())

说明:

newName = re.sub(’(D:/机器学习/学习草稿/)’,’’, path)

这是因为我图片放在了当前项目文件夹里,导致图片绝对路径含有中文,cv.imread()会出错,我去除掉中文部分,使模型读取相对路径

如果你要读取任意文件夹里的图片,要使图片绝对路径无中文。

可以固定图片显示尺寸;

#self.labelimage.setFixedSize(500, 400)#设置尺寸

#jpg = QtGui.QPixmap(imgName).scaled(self.labelimage.width(), self.label.height())#适应labelimage尺寸,前提是label设置了尺寸

结果

预测界面:

识别cat

识别dog

这个结果还不能让我满意,等我多学习下知识再来吧。

当然也可以调用摄像头,实现对摄像头下的猫狗进行实时识别。

可以参考博文然后自己修改程序。就是一个定时器作用,每隔多少时间识别下摄像头下的物体。

opencv进阶学习笔记1: 调用摄像头用法大全(打开摄像头,打开摄像头并实时不断截屏,读取视频并截图)

送上其他资源:

计算机视觉:图像特征与描述大全 (一篇博文带你简单了解完图像特征提取技术)

电气专业的计算机萌新,写博文不容易。如果你觉得本文对你有用,请点个赞再走,谢谢。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值