含有五个类,神经网络类、两个类用于实现画板、两个类用于实现计算器。
画板识别需要先训练网络后,导出两权重,才能使用。
import numpy
import scipy.special
import matplotlib.pyplot
import pylab
from tensorflow.examples.tutorials.mnist import input_data
from PIL import Image
class neuralNetwork:
def __init__(self, inputnodes, hiddennodes, outputnodes, learningrate):
# inputnodes输入节点数目,即图像的宽*高=28*28=784
self.inodes = inputnodes
self.hnodes = hiddennodes
self.onodes = outputnodes
# 初始化权重服从正态分布
self.wih = numpy.random.normal(0.0, pow(self.hnodes, -0.5), (self.hnodes, self.inodes))
self.who = numpy.random.normal(0.0, pow(self.onodes, -0.5), (self.onodes, self.hnodes))
self.lr = learningrate;
# 激活函数
self.activation_function = lambda x: scipy.special.expit(x)
pass
def set_wih_who(self):
self.wih = numpy.loadtxt('MNIST_data/wih.txt')
self.who = numpy.loadtxt('MNIST_data/who.txt')
def train(self, inputs_list, targets_list):
inputs = numpy.array(inputs_list, ndmin=2).T
targets = numpy.array(targets_list, ndmin=2).T
# 正向推算
hidden_inputs = numpy.dot(self.wih, inputs)
hidden_outputs = self.activation_function(hidden_inputs)
final_inputs = numpy.dot(self.who, hidden_outputs)
final_outputs = self.activation_function(final_inputs)
# 误差反向推算
output_errors = targets - final_outputs
self.who += self.lr * numpy.dot((output_errors * final_outputs * (1.0 - final_outputs)),
numpy.transpose(hidden_outputs))
hidden_errors = numpy.dot(self.who.T, output_errors)
self.wih += self.lr * numpy.dot((hidden_errors * hidden_outputs * (1.0 - hidden_outputs)),
numpy.transpose(inputs))
pass
def query(self, inputs_list):
inputs = numpy.array(inputs_list, ndmin=2).T
hidden_inputs = numpy.dot(self.wih, inputs)
hidden_outputs = self.activation_function(hidden_inputs)
final_inputs = numpy.dot(self.who, hidden_outputs)
final_outputs = self.activation_function(final_inputs)
return final_outputs
def mytest(self, fname):
im = Image.open(fname).convert('L')
im = im.resize((28, 28))
tmp = numpy.array(im)
vec = tmp.ravel()
for i in range(len(vec)):
if vec[i] == 0:
vec[i] = 255
else:
vec[i] = 0
myinputs = (numpy.asfarray(vec[0:]) / 255.0 * 0.99) + 0.01
# print(myinputs)
myoutputs = self.query(myinputs)
label = numpy.argmax(myoutputs)
print(label)
pass
def mytest_image(self, img):
im = img
im = im.resize((28, 28))
tmp = numpy.array(im)
vec = tmp.ravel()
for i in range(len(vec)):
if vec[i] == 0:
vec[i] = 255
else:
vec[i] = 0
myinputs = (numpy.asfarray(vec[0:]) / 255.0 * 0.99) + 0.01
# print(myinputs)
myoutputs = self.query(myinputs)
label = numpy.argmax(myoutputs)
return label
if __name__ == "__main__":
# 训练神经网络
input_nodes = 784
hidden_nodes = 100
output_nodes = 10
learning_rate = 0.1
n = neuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
mnist = input_data.read_data_sets('MNIST_data/', one_hot=True)
epochs = 20
for e in range(epochs):
for i in range(10000):
inputs = mnist.train.images[i]
targets = numpy.zeros(output_nodes) + 0.01
targets[numpy.argmax(mnist.train.labels[i])] = 0.99
n.train(inputs, targets)
pass
pass
# 测试神经网络
scorecard = []
for i in range(100):
# image_array = numpy.asfarray(record_value[1:]).reshape(28, 28)
# matplotlib.pyplot.imshow(image_array, cmap="Greys", interpolation='None')
# pylab.show()
if i==1:
numpy.savetxt('wih.txt',n.wih)#(100,784)
numpy.savetxt('who.txt',n.who)#(10,100)
inputs = mnist.test.images[i]
correct_label = numpy.argmax(mnist.test.labels[i])
outputs = n.query(inputs)
label = numpy.argmax(outputs)
if (label == correct_label):
print("right:", label)
scorecard.append(1)
else:
print("wrong:", label, "v", correct_label)
scorecard.append(0)
pass
pass
scorecard_array = numpy.asarray(scorecard)
print("performance= ", scorecard_array.sum() / scorecard_array.size)
from PyQt5.Qt import QWidget, QColor, QPixmap, QIcon, QSize, QCheckBox
from PyQt5.QtWidgets import QHBoxLayout, QVBoxLayout, QPushButton, QSplitter,\
QComboBox, QLabel, QSpinBox, QFileDialog
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PaintBoard import PaintBoard
from my_neuralNetwork import *
import os
os.environ["CUDA_VISIBLE_DEVICES"] = "-1"
#画板类
class MainWidget(QWidget):
Signal_parp = pyqtSignal(str)
def __init__(self, Parent=None):
super().__init__(Parent)
self.__InitData() #先初始化数据,再初始化界面
self.__InitView()
def __InitData(self):
'''
初始化成员变量
'''
self.__paintBoard = PaintBoard(self)
#获取颜色列表(字符串类型)
self.__colorList = QColor.colorNames()
def __InitView(self):
'''
初始化界面
'''
self.setFixedSize(740,480)
self.setWindowTitle("PaintBoard Example PyQt5")
#新建一个水平布局作为本窗体的主布局
self.main_layout = QHBoxLayout(self)
#设置主布局内边距以及控件间距为10px
self.main_layout.setSpacing(10)
#在主界面左侧放置画板
self.main_layout.addWidget(self.__paintBoard)
#新建垂直子布局用于放置按键
self.sub_layout = QVBoxLayout()
#设置此子布局和内部控件的间距为10px
self.sub_layout.setContentsMargins(10, 10, 10, 10)
self.__btn_Clear = QPushButton("清空画板")
self.__btn_Clear.setParent(self) #设置父对象为本界面
#将按键按下信号与画板清空函数相关联
self.__btn_Clear.clicked.connect(self.__paintBoard.Clear)
self.sub_layout.addWidget(self.__btn_Clear)
self.__btn_Quit = QPushButton("退出")
self.__btn_Quit.setParent(self) #设置父对象为本界面
self.__btn_Quit.clicked.connect(self.Quit)
self.sub_layout.addWidget(self.__btn_Quit)
self.__btn_Save = QPushButton("保存作品")
self.__btn_Save.setParent(self)
self.__btn_Save.clicked.connect(self.on_btn_Save_Clicked)
self.sub_layout.addWidget(self.__btn_Save)
self.__btn_Test = QPushButton("识别")
self.__btn_Test.setParent(self)
self.__btn_Test.clicked.connect(self.on_btn_Test_Clicked)
self.sub_layout.addWidget(self.__btn_Test)
self.__cbtn_Eraser = QCheckBox(" 使用橡皮擦")
self.__cbtn_Eraser.setParent(self)
self.__cbtn_Eraser.clicked.connect(self.on_cbtn_Eraser_clicked)
self.sub_layout.addWidget(self.__cbtn_Eraser)
self.splitter = QSplitter(self) #占位符
self.sub_layout.addWidget(self.splitter)
self.__label_penThickness = QLabel(self)
self.__label_penThickness.setText("画笔粗细")
self.__label_penThickness.setFixedHeight(30)
self.sub_layout.addWidget(self.__label_penThickness)
self.__spinBox_penThickness = QSpinBox(self)
self.__spinBox_penThickness.setMaximum(20)
self.__spinBox_penThickness.setMinimum(2)
self.__spinBox_penThickness.setValue(20) #默认粗细为10
self.__spinBox_penThickness.setSingleStep(2) #最小变化值为2
self.__spinBox_penThickness.valueChanged.connect(self.on_PenThicknessChange)#关联spinBox值变化信号和函数on_PenThicknessChange
self.sub_layout.addWidget(self.__spinBox_penThickness)
self.__label_penColor = QLabel(self)
self.__label_penColor.setText("画笔颜色")
self.__label_penColor.setFixedHeight(20)
self.sub_layout.addWidget(self.__label_penColor)
self.__comboBox_penColor = QComboBox(self)
self.__fillColorList(self.__comboBox_penColor) #用各种颜色填充下拉列表
self.__comboBox_penColor.currentIndexChanged.connect(self.on_PenColorChange) #关联下拉列表的当前索引变更信号与函数on_PenColorChange
self.sub_layout.addWidget(self.__comboBox_penColor)
self.main_layout.addLayout(self.sub_layout) #将子布局加入主布局
def __fillColorList(self, comboBox):
index_black = 0
index = 0
for color in self.__colorList:
if color == "black":
index_black = index
index += 1
pix = QPixmap(70,20)
pix.fill(QColor(color))
comboBox.addItem(QIcon(pix),None)
comboBox.setIconSize(QSize(70,20))
comboBox.setSizeAdjustPolicy(QComboBox.AdjustToContents)
comboBox.setCurrentIndex(index_black)
def on_PenColorChange(self):
color_index = self.__comboBox_penColor.currentIndex()
color_str = self.__colorList[color_index]
self.__paintBoard.ChangePenColor(color_str)
def on_PenThicknessChange(self):
penThickness = self.__spinBox_penThickness.value()
self.__paintBoard.ChangePenThickness(penThickness)
def on_btn_Save_Clicked(self):
savePath = QFileDialog.getSaveFileName(self, 'Save Your Paint', '.\\', '*.png')
print(savePath)
if savePath[0] == "":
print("Save cancel")
return
image = self.__paintBoard.GetContentAsQImage()
image.save(savePath[0])
def on_btn_Test_Clicked(self):
image = self.__paintBoard.GetContentAsQImage()
image.save("qaq1.png","PNG")
im = Image.open('qaq1.png').convert('L')
input_nodes = 784
hidden_nodes = 100
output_nodes = 10
learning_rate = 0.05
n = neuralNetwork(input_nodes, hidden_nodes, output_nodes, learning_rate)
n.set_wih_who()
data_str = str(n.mytest_image(im))
self.Signal_parp.emit(data_str)
# return data_str
def on_cbtn_Eraser_clicked(self):
if self.__cbtn_Eraser.isChecked():
self.__paintBoard.EraserMode = True #进入橡皮擦模式
else:
self.__paintBoard.EraserMode = False #退出橡皮擦模式
def Quit(self):
self.close()
from PyQt5.QtWidgets import QWidget
from PyQt5.Qt import QPixmap, QPainter, QPoint, QPaintEvent, QMouseEvent, QPen,QColor, QSize
from PyQt5.QtCore import Qt
#画板类
class PaintBoard(QWidget):
def __init__(self, Parent=None):
super().__init__(Parent)
self.__InitData() #先初始化数据,再初始化界面
self.__InitView()
def __InitData(self):
self.__size = QSize(480,460)
#新建QPixmap作为画板,尺寸为__size
self.__board = QPixmap(self.__size)
self.__board.fill(Qt.white) #用白色填充画板
self.__IsEmpty = True #默认为空画板
self.EraserMode = False #默认为禁用橡皮擦模式
self.__lastPos = QPoint(0,0)#上一次鼠标位置
self.__currentPos = QPoint(0,0)#当前的鼠标位置
self.__painter = QPainter()#新建绘图工具
self.__thickness = 20 #默认画笔粗细为10px
self.__penColor = QColor("black")#设置默认画笔颜色为黑色
self.__colorList = QColor.colorNames() #获取颜色列表
def __InitView(self):
#设置界面的尺寸为__size
self.setFixedSize(self.__size)
def Clear(self):
#清空画板
self.__board.fill(Qt.white)
self.update()
self.__IsEmpty = True
def ChangePenColor(self, color="black"):
#改变画笔颜色
self.__penColor = QColor(color)
def ChangePenThickness(self, thickness=20):
#改变画笔粗细
self.__thickness = thickness
def IsEmpty(self):
#返回画板是否为空
return self.__IsEmpty
def GetContentAsQImage(self):
#获取画板内容(返回QImage)
image = self.__board.toImage()
return image
def paintEvent(self, paintEvent):
#绘图事件
#绘图时必须使用QPainter的实例,此处为__painter
#绘图在begin()函数与end()函数间进行
#begin(param)的参数要指定绘图设备,即把图画在哪里
#drawPixmap用于绘制QPixmap类型的对象
self.__painter.begin(self)
# 0,0为绘图的左上角起点的坐标,__board即要绘制的图
self.__painter.drawPixmap(0,0,self.__board)
self.__painter.end()
def mousePressEvent(self, mouseEvent):
#鼠标按下时,获取鼠标的当前位置保存为上一次位置
self.__currentPos = mouseEvent.pos()
self.__lastPos = self.__currentPos
def mouseMoveEvent(self, mouseEvent):
#鼠标移动时,更新当前位置,并在上一个位置和当前位置间画线
self.__currentPos = mouseEvent.pos()
self.__painter.begin(self.__board)
if self.EraserMode == False:
#非橡皮擦模式
self.__painter.setPen(QPen(self.__penColor,self.__thickness)) #设置画笔颜色,粗细
else:
#橡皮擦模式下画笔为纯白色,粗细为10
self.__painter.setPen(QPen(Qt.white,10))
#画线
self.__painter.drawLine(self.__lastPos, self.__currentPos)
self.__painter.end()
self.__lastPos = self.__currentPos
self.update() #更新显示
def mouseReleaseEvent(self, mouseEvent):
self.__IsEmpty = False #画板不再为空
from PyQt5 import QtCore, QtGui, QtWidgets
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(647, 675)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.b_1 = QtWidgets.QPushButton(self.centralwidget)
self.b_1.setGeometry(QtCore.QRect(10, 330, 71, 71))
self.b_1.setObjectName("b_1")
self.b_2 = QtWidgets.QPushButton(self.centralwidget)
self.b_2.setGeometry(QtCore.QRect(80, 330, 71, 71))
self.b_2.setObjectName("b_2")
self.b_3 = QtWidgets.QPushButton(self.centralwidget)
self.b_3.setGeometry(QtCore.QRect(150, 330, 71, 71))
self.b_3.setObjectName("b_3")
self.b_6 = QtWidgets.QPushButton(self.centralwidget)
self.b_6.setGeometry(QtCore.QRect(150, 400, 71, 71))
self.b_6.setObjectName("b_6")
self.b_4 = QtWidgets.QPushButton(self.centralwidget)
self.b_4.setGeometry(QtCore.QRect(10, 400, 71, 71))
self.b_4.setObjectName("b_4")
self.b_5 = QtWidgets.QPushButton(self.centralwidget)
self.b_5.setGeometry(QtCore.QRect(80, 400, 71, 71))
self.b_5.setObjectName("b_5")
self.b_8 = QtWidgets.QPushButton(self.centralwidget)
self.b_8.setGeometry(QtCore.QRect(80, 470, 71, 71))
self.b_8.setObjectName("b_8")
self.b_9 = QtWidgets.QPushButton(self.centralwidget)
self.b_9.setGeometry(QtCore.QRect(150, 470, 71, 71))
self.b_9.setObjectName("b_9")
self.b_7 = QtWidgets.QPushButton(self.centralwidget)
self.b_7.setGeometry(QtCore.QRect(10, 470, 71, 71))
self.b_7.setObjectName("b_7")
self.b_eq = QtWidgets.QPushButton(self.centralwidget)
self.b_eq.setGeometry(QtCore.QRect(220, 540, 141, 71))
self.b_eq.setObjectName("b_eq")
self.b_net = QtWidgets.QPushButton(self.centralwidget)
self.b_net.setGeometry(QtCore.QRect(150, 540, 71, 71))
self.b_net.setObjectName("b_net")
self.b_mod = QtWidgets.QPushButton(self.centralwidget)
self.b_mod.setGeometry(QtCore.QRect(220, 400, 71, 71))
self.b_mod.setObjectName("b_mod")
self.b_bra_l = QtWidgets.QPushButton(self.centralwidget)
self.b_bra_l.setGeometry(QtCore.QRect(220, 330, 71, 71))
self.b_bra_l.setObjectName("b_bra_l")
self.b_div = QtWidgets.QPushButton(self.centralwidget)
self.b_div.setGeometry(QtCore.QRect(220, 260, 71, 71))
self.b_div.setObjectName("b_div")
self.b_add = QtWidgets.QPushButton(self.centralwidget)
self.b_add.setGeometry(QtCore.QRect(10, 260, 71, 71))
self.b_add.setObjectName("b_add")
self.b_sub = QtWidgets.QPushButton(self.centralwidget)
self.b_sub.setGeometry(QtCore.QRect(80, 260, 71, 71))
self.b_sub.setObjectName("b_sub")
self.b_mul = QtWidgets.QPushButton(self.centralwidget)
self.b_mul.setGeometry(QtCore.QRect(150, 260, 71, 71))
self.b_mul.setObjectName("b_mul")
self.b_pow = QtWidgets.QPushButton(self.centralwidget)
self.b_pow.setGeometry(QtCore.QRect(290, 260, 71, 71))
self.b_pow.setObjectName("b_pow")
self.b_pai = QtWidgets.QPushButton(self.centralwidget)
self.b_pai.setGeometry(QtCore.QRect(290, 400, 71, 71))
self.b_pai.setObjectName("b_pai")
self.b_bra_r = QtWidgets.QPushButton(self.centralwidget)
self.b_bra_r.setGeometry(QtCore.QRect(290, 330, 71, 71))
self.b_bra_r.setObjectName("b_bra_r")
self.l_hist = QtWidgets.QListWidget(self.centralwidget)
self.l_hist.setGeometry(QtCore.QRect(380, 10, 256, 601))
self.l_hist.setObjectName("l_hist")
self.e_view = QtWidgets.QTextEdit(self.centralwidget)
self.e_view.setGeometry(QtCore.QRect(10, 10, 351, 231))
font = QtGui.QFont()
font.setFamily("Adobe Caslon Pro Bold")
font.setPointSize(22)
font.setBold(True)
font.setWeight(75)
self.e_view.setFont(font)
self.e_view.setObjectName("e_view")
self.b_0 = QtWidgets.QPushButton(self.centralwidget)
self.b_0.setGeometry(QtCore.QRect(80, 540, 71, 71))
self.b_0.setObjectName("b_0")
self.b_pt = QtWidgets.QPushButton(self.centralwidget)
self.b_pt.setGeometry(QtCore.QRect(10, 540, 71, 71))
self.b_pt.setObjectName("b_pt")
self.b_del = QtWidgets.QPushButton(self.centralwidget)
self.b_del.setGeometry(QtCore.QRect(220, 470, 71, 71))
self.b_del.setObjectName("b_del")
self.b_clc = QtWidgets.QPushButton(self.centralwidget)
self.b_clc.setGeometry(QtCore.QRect(290, 470, 71, 71))
self.b_clc.setObjectName("b_clc")
MainWindow.setCentralWidget(self.centralwidget)
self.menubar = QtWidgets.QMenuBar(MainWindow)
self.menubar.setGeometry(QtCore.QRect(0, 0, 647, 30))
self.menubar.setObjectName("menubar")
MainWindow.setMenuBar(self.menubar)
self.statusbar = QtWidgets.QStatusBar(MainWindow)
self.statusbar.setObjectName("statusbar")
MainWindow.setStatusBar(self.statusbar)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.b_1.setText(_translate("MainWindow", "1"))
self.b_2.setText(_translate("MainWindow", "2"))
self.b_3.setText(_translate("MainWindow", "3"))
self.b_6.setText(_translate("MainWindow", "6"))
self.b_4.setText(_translate("MainWindow", "4"))
self.b_5.setText(_translate("MainWindow", "5"))
self.b_8.setText(_translate("MainWindow", "8"))
self.b_9.setText(_translate("MainWindow", "9"))
self.b_7.setText(_translate("MainWindow", "7"))
self.b_eq.setText(_translate("MainWindow", "="))
self.b_mod.setText(_translate("MainWindow", "%"))
self.b_bra_l.setText(_translate("MainWindow", "("))
self.b_div.setText(_translate("MainWindow", "/"))
self.b_add.setText(_translate("MainWindow", "+"))
self.b_sub.setText(_translate("MainWindow", "-"))
self.b_mul.setText(_translate("MainWindow", "*"))
self.b_pow.setText(_translate("MainWindow", "^"))
self.b_pai.setText(_translate("MainWindow", "π"))
self.b_bra_r.setText(_translate("MainWindow", ")"))
self.b_0.setText(_translate("MainWindow", "0"))
self.b_pt.setText(_translate("MainWindow", "."))
self.b_del.setText(_translate("MainWindow", "删除"))
self.b_clc.setText(_translate("MainWindow", "清空"))
self.b_net.setText(_translate("MainWindow", "识别"))
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from calc_interface import Ui_MainWindow
import os,sys
from MainWidget import *
global e_view
pluginsPath='PyQt5/Qt/plugins'
if os.path.exists(pluginsPath):
QApplication.addLibraryPath(pluginsPath)
class MyMainWindow(QMainWindow, Ui_MainWindow):
def forge_link(self):
self.b_0.clicked.connect(self.button_event(0))
self.b_1.clicked.connect(self.button_event(1))
self.b_2.clicked.connect(self.button_event(2))
self.b_3.clicked.connect(self.button_event(3))
self.b_4.clicked.connect(self.button_event(4))
self.b_5.clicked.connect(self.button_event(5))
self.b_6.clicked.connect(self.button_event(6))
self.b_7.clicked.connect(self.button_event(7))
self.b_8.clicked.connect(self.button_event(8))
self.b_9.clicked.connect(self.button_event(9))
self.b_add.clicked.connect(self.button_event('+'))
self.b_sub.clicked.connect(self.button_event('-'))
self.b_mul.clicked.connect(self.button_event('*'))
self.b_div.clicked.connect(self.button_event('/'))
self.b_pow.clicked.connect(self.button_event('**'))
self.b_bra_l.clicked.connect(self.button_event('('))
self.b_bra_r.clicked.connect(self.button_event(')'))
self.b_mod.clicked.connect(self.button_event('%'))
self.b_pai.clicked.connect(self.button_event('3.1415926'))
self.b_pt.clicked.connect(self.button_event('.'))
self.b_del.clicked.connect(self.delete_event)
self.b_clc.clicked.connect(self.clear_event)
self.b_eq.clicked.connect(self.calc_complish)
self.b_net.clicked.connect(self.net)
def __init__(self, parent=None):
super(MyMainWindow, self).__init__(parent)
self.setupUi(self)
self.forge_link() #连接槽函数
def button_event(self,arg):
# print(dir(self.e_view))
global e_view
e_view=self.e_view
def fun(): #返回一个自定义的槽函数
global e_view
txt = e_view.toPlainText()
e_view.setText(txt + str(arg))
return fun
def calc_complish(self):
txt=self.e_view.toPlainText()
ans=''
try:
ans=str(eval(txt))
except BaseException:
ans='MathError'
# print(ans)
self.clear_event()
self.e_view.setText(ans)
self.l_hist.addItem(txt+'='+ans)
def clear_event(self):
self.e_view.setText('')
def delete_event(self):
txt = self.e_view.toPlainText()
txt=txt[:len(txt)-1]
self.e_view.setText(txt)
def net(self):
# app = QApplication(sys.argv)
# mainWidget = MainWidget() # 新建一个主界面
mainWidget.Signal_parp.connect(self.deal_emit_slot)
mainWidget.show() # 显示主界面
# mainWidget.Signal_OneParameter.connect(self.deal_emit_slot)
# sys.exit(app.exec_()) # 进入消息循环
def deal_emit_slot(self, data_str):
txt = e_view.toPlainText()
e_view.setText(txt + data_str)
if __name__ == '__main__':
app=QApplication(sys.argv)
myWin=MyMainWindow()
mainWidget = MainWidget() # 新建一个主界面
myWin.show()
sys.exit(app.exec())