自制手写数字程序密码锁

好久之前写的,一直没有发,现在整理一下发布了。

这是和我的第一篇MNIST数字手写识别的进阶,其实数字手写密码锁是17年五六月份左右的我们小组应该做的小组任务,但是带我们任务的学长比较忙,也由于其他原因,我们小组内没有人真正完成手写数字密码锁,只是实现了用kNN进行手写数字识别,关键是用kNN还没办法保存参数……后来断断续续开始学习深度学习,走了不少弯路,后来看了一部分吴恩达的视频,至今也就才算是摸到门槛。下面是我用单层的神经网络进行手写数字分类的代码,最近一周写的,快要考试了,越到考试我越浪……

本人是学自动化的,程序主要是面向过程,编写代码的质量也不高,请见谅!大神请另寻他路……

我的程序分为三个文件来写,一个文件是用openCV进行鼠标写数字,只做了一个很小的数据集,600张训练图片,30张测试图片。以下是用openCV进行鼠标写数字的代码,很简单,需要对openCV有一定了解,在此不进行详解。

 

import numpy as np
import cv2
drawing=False
def drawCircle(event,x,y,flags,param):
    global drawing
    if event==cv2.EVENT_LBUTTONDOWN:
        drawing=True
    if event==cv2.EVENT_MOUSEMOVE and flags==cv2.EVENT_FLAG_LBUTTON:
        if drawing == True:
            cv2.circle(img,(x,y),10,(0,0,0),-1)
        elif event==cv2.EVENT_LBUTTONUP:
            drawing=False

img=np.zeros((280,280,3),np.uint8)+255
cv2.namedWindow('Image')
cv2.setMouseCallback('Image',drawCircle)
n=int(input("Input n:"))#因为写图片的时候可能要写好几次,在这里我用n记录应该从第几个图片开始储存,需要手动输入
print("c->clear  s->save  q->quit")
while(True): # 在写数字的时候,我的第一个图片名编号设为了1,从数字0开始写,最好把第一个图片名编号设为0
    cv2.imshow('Image',img)
    # k=cv2.waitKey(1)&0xFF
    key=cv2.waitKey(1)&0xFF
    if key==ord('s'):
        print("Saving...")
        cv2.imwrite(r"E:\WORK\Python3.6Files\openCV_about\pictures2\img"+str(n)+".png",img)
        print("img"+str(n)+" OK!")
        img=np.zeros((280,280,3),np.uint8)+255
        n+=1
    elif key==ord('q'):
        break
    elif key==ord('c'):
        img = np.zeros((280, 280, 3), np.uint8) + 255
    else:
        pass

 

我用这个程序写了630张图片,600张用来训练,太少了,其实可以找人一起写呀~~~

下边是用Softmax激活函数进行分类的一个最简单的神经网络,目的其实就是得到参数。

 

import numpy as np
import cv2,re
from os import listdir
def savePicturesAndLabels(path):
    name_list=listdir(path)#这里我掉进了一个大坑,我以为读进去图片是按照顺序img1,img2,img3...来的,但是,不是……
    i=0                    #导致我一开始训练出来的测试正确率是百分之十左右,跟瞎蒙差不多......
    n=len(name_list)
    LAB=np.zeros([10,n],dtype=np.uint8)
    IMG=np.zeros([1225,n],dtype=np.uint8)
    labs=[]
    i=0
    for name in name_list:
        img_i=int(name[3:-4])#取文件名中的数字标签
        LAB[(img_i-1)%10,i]=1 #第i列(即第i个图片)的j(=(img_i-1)%10)行(j就是对应的数字标签)设置为1
        labs.append((img_i-1)%10)
        img=cv2.imread(path+"\\"+name,0)
        img2=cv2.pyrDown(cv2.pyrDown(cv2.pyrDown(img)))#由于我的图片原大小是280*280,所以我用了3次图像金字塔,把图
        img2[img2<127]=1                               #片大小缩小为35*35
        img2[img2>=127]=0  # one-hot处理
        img2.resize([1225,1])
        IMG[:,i]=img2[:,0]
        i+=1
    np.save("testIMG.npy",IMG)  #储存把图片处理后的矩阵,在分别储存训练集和测试集的矩阵的时候,直接执行两次本
    np.save("testLAB.npy",LAB)  #自定义函数,改一改文件名就可以啦,我是不是很懒…………
    np.save("testLabels.npy",np.array(labs)) #储存测试用的的标签[1,n] n=600

if __name__=="__main__":
    X = np.load("trainIMG.npy")
    Y = np.load("trainLAB.npy")
    k = 10  # 分类数 0~9
    v = 1225 # 维度 35*35
    n = X.shape[1] # 样本数 600
    np.random.seed(13)#生成随机数种子
    w = np.random.random([k, v]) # w[10,1225]
    b = np.random.random([k, 1]) # b[10,1]
    r = 0.1
    #以下注释部分是训练的过程,训练的时候把注释去掉。
    # for t in range(3000):
    #     z = (np.dot(w, X) + b)n # z[10,600]=w[10,1225] x X[1225,600]
    #     sum_a = ((np.exp(z)).sum(axis=0)).reshape([1, n]) # sum_a[1,600]
    #     a = np.exp(z) / sum_a # a[10,600]=z[10,600]/sum_a[1,600]
    #     # print(a[:,0])#这一句话是用来观察训练效果的
    #     w =w+  r * np.dot(Y - a, X.T) / n # 根据反向传播计算出 w 和 b 的参数更新公式,用道一点点简单的高数知识
    #     b =b+  r * ((np.dot(Y - a, np.ones([n, 1]))).reshape(k, 1)) / n # 
    # np.save("IMG_w.npy",w) # 训练完之后保存参数
    # np.save("IMG_b.npy",b)

    # tX=np.load("trainIMG.npy") # 这里后来注释掉了,因为一开始我需要测试训练集的训练效果
    # tY=np.load("trainLabels.npy")
    tX=np.load("testIMG.npy")#加载训练图片
    tY=np.load("testLabels.npy")#加载训练标签
    tn=tX.shape[1]
    W=np.load("IMG_W.npy")
    B=np.load("IMG_B.npy")

    Z = (np.dot(W, tX) + B)
    sum_A = ((np.exp(Z)).sum(axis=0)).reshape([1, tn])
    A = np.exp(Z) / sum_A
    predict = []
    for i in range(tn):
        #print((np.where(A[:, i] == np.amax(A[:, i])))[0][0])
        predict.append((np.where(A[:, i] == np.amax(A[:, i])))[0][0])#找到每一列中最大值所在的位置,这样就能得到每
    # print(predict)                                                 #一个图片的测试结果了,仔细体会......
    errors = tY - np.array(predict) #这一步和下边的一步就是得到与正确标签不相等的错误结果标签
    errors[errors != 0] = 1         #这样就可以统计错误个数了
    print(np.where(errors[:]==1))
    errors_num = errors.sum()
    print("总测试数:", tn)
    print("错误个数:", errors_num)
    print("正确率:{}%".format(100 - 100 * errors_num / tn))

下边是主程序

# 其中一些图标或者矩阵数据文件我没有上传,可以根据自己写的数据制作
import numpy as np
import cv2
import easygui,re
from urllib import request
import urllib
drawing=False
import speech
def drawCircle(event,x,y,flags,param):
    global drawing
    if event==cv2.EVENT_LBUTTONDOWN:
        drawing=True
    if event==cv2.EVENT_MOUSEMOVE and flags==cv2.EVENT_FLAG_LBUTTON:
        if drawing == True:
            cv2.circle(img,(x,y),10,(0,0,0),-1)
        elif event==cv2.EVENT_LBUTTONUP:
            drawing=False

def checkPassword(password):
    if password==[1,2,3,4]:
        return True
    else:
        return False
def webSpider():
    url='http://image.baidu.com/search/index?tn=baiduimage&ps=1&ct=201326592&lm=-1&cl=2&nc=1&ie=utf-8&word=tupian'#这里没有写网址链接
    headers={
        'User-Agent': 'Chrome/63.0.3239.84',
        'Connection': 'keep-alive'
    }
    req=request.Request(url=url,headers=headers)
    resp=request.urlopen(req)
    text=(resp.read()).decode('utf-8')
    cmpl=re.compile("http://\S+.jpg")
    jpg_urls=re.findall(cmpl,text)
    # keys_dic={}
    speech.say("即将浏览网站图片,请确保已经连接网络。")
    speech.say("按下 ESC 键退出程序,按下其他任意键浏览下一张图片!")
    speech.say("浏览过程中因网络问题可能会有卡顿,请等待程序响应!")
    for jpg_url in jpg_urls:
        try:
            request.urlretrieve(jpg_url,"E:\\Temp.jpg")
            current_jpg = cv2.imread("E:\\Temp.jpg")
            cv2.namedWindow("Temp.jpg",flags=cv2.WINDOW_AUTOSIZE) # WINDOW_NORMAL
            cv2.imshow("Temp.jpg", cv2.pyrDown(current_jpg))
            # print("+++++++++++++++"+jpg_url)
            w_key=cv2.waitKey(0)
            if w_key==27:
                break
        # except urllib.error.HTTPError:
        except :
            # print("---------------"+jpg_url)
            pass
    cv2.destroyAllWindows()
##    speech.say("浏览结束!")

def customizedFunction():
    # print("Log in!")
    webSpider()


if __name__=="__main__":
    # customizedFunction()
    # easygui.buttonbox(
    #     msg="Press:\nq-->Quit the programme.\ns-->Save the number.\nc-->Clear the image without saving.\nr-->Retype the password.",
    #     title='', choices=["OK!"])
    speech.say("按下“S”键确认当前输入的数字,按下 C 键清除当前画布,按下 R 键重新输入整个密码,按下 Q 键退出程序。")
    img = np.zeros((280, 280, 3), np.uint8) + 255
    cv2.namedWindow('Please input the password')
    cv2.setMouseCallback('Please input the password', drawCircle)
    W = np.load("IMG_W.npy")
    B = np.load("IMG_B.npy")
    # print("Press:\nq->quit the programme\ns->save and predict\nc->clear the image without saving ")
    password=[]
    while(True):
        cv2.imshow("Please input the password",img)
        key=cv2.waitKey(1)&0xFF
        if key==ord('s'):
            tX = cv2.pyrDown(cv2.pyrDown(cv2.pyrDown(cv2.cvtColor(img,cv2.COLOR_BGR2GRAY))))
            tX[tX < 127] = 1
            tX[tX >= 127] = 0
            tX.resize([1225, 1])
            Z = (np.dot(W, tX) + B)
            sum_A = (np.exp(Z)).sum(axis=0)
            A = np.exp(Z) / sum_A
            predict = (np.where(A == np.amax(A)))[0][0]
            # print(predict)
            speech.say(str(predict))
            password.append(predict)
            if len(password)==4:
                if checkPassword(password):
                    cv2.destroyWindow("Please input the password")
                    # easygui.buttonbox(msg="\n\n\t\t\t\t    密码正确!", title="提示", choices=[], image="right.gif")
                    speech.say("密码正确!")
                    break
                else:
                    speech.say("密码错误!")
                    response=easygui.buttonbox(msg="",title='',choices=["重新输入","退出"],)
                    if response=="重新输入":
                        password=[]
                    elif response=="退出" or None:
                        cv2.destroyWindow("Please input the password")
                        exit()
            img = np.zeros((280, 280, 3), np.uint8) + 255
        elif key==ord('q'):
            cv2.destroyWindow("Please input the password")
            exit()
        elif key==ord('c'):
            img = np.zeros((280, 280, 3), np.uint8) + 255
        elif key==ord('r'):
            speech.say("重新输入密码。")
            # easygui.buttonbox(msg="",title='提示',choices='',image='ok.gif')
            img = np.zeros((280, 280, 3), np.uint8) + 255
            password=[]
        else:
            pass
    if checkPassword(password):
        customizedFunction()
    else:
        exit()
    speech.say("感谢使用!")

程序就是这样,小试牛刀,没什么技术含量的东西,大神勿喷。
对于神经网络一点也不懂的同学,建议去看一看吴恩达老师在网易云课堂的视频。

 

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值