基于人工神经网络识别手写数字

1、隐藏节点:60
训练样本:50000
阶段:10

import gzip
import pickle
import cv2
import numpy as np

2 training_images:numpy 数组,由6000副图像组成,其中每幅图像都是由784个像素值组成的向量(从28×28像素的原始形状展平而来)
像素值:0.0(黑)~1.0(白)的浮点值
3 training_ids:numpy 数组,包含60000个数字ID
4 test_images:1000幅图像组成的numpy数组,每幅图像都是由784个像素值组成的向量(从原始28×28组成)
5 test_ids:numpy 数组 10000个数字ID
6编写辅助函数

def load_data():
    mnist=gzip.open('./digits_data/mnist.pkl.gz','rb')
    training_data,test_data=pickle.load(mnist)
    mnist.close()
    return (training_data,test_data)

7重新格式化原始数据,以匹配opencv所期望的格式
zip:以元组形式遍历输入和输出向量的匹配对

def wrap_data():
    tr_d,te_d=load_data()
    training_inputs=tr_d[0]
    trainging_results=[vectorized_result(y) for y in tr_d[1])
    trainging_data=zip(training_inputs,trainging_results)
    test_data=zip(te_d[0],te_d[1])
    return (trainging_data,test_data)

8将ID转换为一个分类向量

def wrap_data():
    tr_d,te_d=load_data()
    training_inputs=tr_d[0]
    trainging_results=[vectorized_result(y) for y in tr_d[1])
    trainging_data=zip(training_inputs,trainging_results)
    test_data=zip(te_d[0],te_d[1])
    return (trainging_data,test_data)

9、创建未训练的人工神经网络

def create_ann(hidden_nodes=60):
    ann=cv2.m1.ANN_MLP_create()
    ann.setLayerSizes(np.array([784,hidden_nodes,10]))
    ann.setActivationFunction(cv2.m1.ANN_MLP_SIGMOID_SYM,0.6,1.0)
    ann.setTrainMethod(cv2.m1.ANN_MLP_BACKPROP,0.1,0.1)
    ann.setTermCriteria(cv2.TERM_CRITERIA_MAX_ITER| cv2.TERM_CRITERIA_EPS,100,1.0)
    return ann

10、训练函数

def train(ann,samples=50000,epochs=10):
    tr,test=wrap_data()
    tr=list(tr)
    for epoch in range(epochs):
        print("Completed %d/%d epochs" % (epoch,epochs))
        counter=0
        for  img in tr:
            if(counter>samples):
                break;
            if(counter%1000==0):
                print("Epoch %d: Trained on %d/%d samples" %\ (epoch,counter,samples))
                counter+=1
                samples,response=img
                data=cv.m1.ANN_MLP_createTrainData_create(np.array([sample],dtype=np.float32),cv2.ma.ROW_SAMPLE,
                                                          np.array([response],dtype=np.float32))
                if ann.isTrained():
                    ann.train(data,cv2.m1.ANN_MLP_UPDATE_WEIGHTS |
                            cv2.m1.ANN_MLP_NO_INPUT_SCALE|cv2.m1.ANN_MLP_NO_OUTPUT_SCALE)
                else:
                    ann.train(data,cv2.m1.ANN_MLP_NO_OUTPUT_SCALE|
                              cv2.m1.ANN_MLP_NO_INPUT_SCALE)
                    print("Completed all epochs!")
                    
                    return ann,test

11预测

def predict(ann,sample):
    if sample.shape!=(784,):
        if sample.shape !=(28,28):
            sample=cv2.resize(sample,(28,28),interpolation=cv2.INTER_LINEAR)
        sample=sample.reshape(784,)
    return ann.predict(np.array([sample],dtype=np.float32))

12测试
def tedt(ann,test_data): num_tests=0 num_correct=0 for img in test_data: num_tests+=1 sample,correct_digit_class=img digit_class=predict(ann,sample)[0] if digit_class==correct_digit_class: num_correct+=1 print("Accuracy:%.2f%%"%(100.0*num_correct/num_tests))

13、运行脚本

from digits_ann import create_ann,train,test
ann,test_data=train(create_ann())
test(ann,test_data)

实现主模块
1、导包

import cv2
import numpy as np
import digits_ann

2、编写2个辅助函数

def inside(r1,r2):
    x1,y1,w1,h1=r1
    x2,y2,w2,h2=r2
    return (x1>x2)and (y1>y2)and (x1+w1<x2+w2)and \(y1+h1<y2+h2)

选择每个数字最外层的边框
3、修改矩形的较短边(不管是宽还是高),使其等于较长的边,修改矩形的x或y位置,使宗信保持不变

def warp_digit(rect,img_w,img_h):
    x,y,w,h=rect
x_center=x+w//2
y_center=y+h//2
if(h>w):
    w=h
    x=x_center-(w//2)
else:
    h=w
    y=y_center-(h//2)

4、在四周添加5个像素

padding=5
x-=padding
y-=padding
w+=2*padding
h+=2*padding

此时,修改的矩形可能会延申到图像外部
5、为避免越界问题,裁剪矩形使矩形完全位于图像内,下面是边缘检查和裁剪矩形的代码:

if x<0:
    x=0
elif x>img_w:
    x=img_w
if y<0:
    y=0
elif y>img_h:
    y=img_h
if x+w>img_w:
    w=img_w-x
if y+h>img_h:
    h=img_h-y

6、返回修改后的矩形代码

return x,y,w,h

7、主程序:创建人工神经网络,在MNIST数据集上对其训练

nn,test_data=digits_ann.train(digits_ann.create_ann(60),50000,10)

60隐藏节点,50000训练样本,10阶段
8、加载测试图像

img_path="./digit_images/digits_0.jpg"
img=cv2.imread(img_path,cv2.IMREAD_COLOR)

9、把图像转换为灰度图像并进行模糊,以去噪声,使墨水的颜色均匀一点

gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
cv2.GaussianBlur(gray,(7,7),0,gray)

10、阈值、形态学运算:确保数字从背景中脱颖而出

ret,thresh=cv2.threshold(gray,127,255,cv2.THRESH_BINARY_INV)
erode_kernel=np.ones((2,2),np.uint8)
thresh=cv2.erode(thresh,erode_kernel,thresh,iterations=2)

cv2.THRESH_BINARY_INV:逆二值阈值
数据集是黑底白字
11、形态学运算过后,分别检测图片中的每个数字,首先找到轮廓

contours,hier=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)

12\遍历轮廓找到矩形框。丢弃所有太大或太小而不能视为数字的矩形,同时丢弃所有完全包含在其他矩形中的矩形。
把其他矩形添加到好的矩形列表中

rectangles=[]
img_h,img_w=img.shape[:2]
img_area=img_w*img_h
for c in contours:
    a=cv2.contourArea(c)
    if a>=0.98 *img_area or a<=0.0001*img_area:
        continue
    r=cv2.boundingRect()
    is_inside=False
    for q in rectangles:
        if inside(r,q):
            is_inside=True
            break
    if not is_inside:
        rectangles.append(r)

13、对该列表清理,并对图像数据分类

for r in rectangles:
    x,y,w,h=wrap_digit(r,img_w,img_h)
    roi=thresh[y:y+h,x:x+w]
    digit_class=int(digits_ann.predict(ann,roi)[0])

14、对每个数字分类后,绘制经过清理的矩形框及分类结果

cv2.rectangles(img,(x,y),(x+w,y+h),(0,255,0),2)
cv2.putText(img,"%d"%digit_class,(x,y-5),cv2.FONT_HERSHEY_SIMPLEX,1,(255,0,0),2)

15、保存图像,指导用户按下任意键结束程序

cv2.imwrite("detected_and_classified_digits_thresh.png",thresh)
cv2.imwrite("detected_and_classified_digits.png",img)
cv2.imshow("thresh",thresh)
cv2.imshow("detected_and_classified_digits",img)
cv2.waitKey()

总结:
1、激活函数
cv2.m1.ANN_MLP_SIGMOID_SYM
cv2.m1.ANN_MLP_IDENTITY
cv2.m1.ANN_MLP_GAUSSIAN
cv2.m1.ANN_MLP_RELU
cv2.m1.ANN_MLP_LEAKYRELU
2\训练方法
cv2.m1.ANN_MLP_BACKPROP
cv2.m1.ANN_MLP_RPROP
cv2.ma.ANN_MLP_ANNEAL

从网络摄像头实时捕捉帧,使用深度神经网络检测和分类任何给定帧中存在的20类物体
1导包

import  cv2
import numpy as np

2、加载caffe模型

model=cv2.dnn.readNetFromCaffe('objects_data/MobileNetSSD_deploy.prototxt',
                               "objects_data/MobileNetSSD_deploy.caffemodel")

3、定义预处理参数
期望输入的图像300个像素,希望像素值在-1.0~1.0。即相对于通常从0到255范围内,需要减去127.5,再除以127.5

bold_height=300
color_scale=1.0/127.5
average_color=(127.5,127.5,127.5)

4、定义置信度阈值,表示所需要的最小置信度

confidence_threshold=0.5

5、类的标签:

labels=['airplane','bicycle','bird','boat','bottle','bus','car','cat','chair','cow','dining table',
        'dog','horse','motoebike','person','potted plant','sheep','sofa','train','TV or monitor'
        ]

6、每一帧:计算长宽比,

cap=cv.VideoCapture(0)
success,frame=cap.read()
while success:
    h,w=frame,shape[:2]
    aspect_radio=w/h
    
    bold_width=int(blod__height*aspect_radio)
    bold_size=(bold_width,blod__height)

7、预处理(调整帧的大小,将像素数据转换到-1.0~1.0

blod=cv2.dnn.blodFromImage(frame,scalefactor=color_scale,size=blod_size,mean=average_color)

8、将生成的二进制大对象(blod)送入深度神经网络,并获得模型的输出

model.setInput(blod)
results=model.forward()

9、访问标签,使用id查找之前定义的列表中的标签

for object in results[0,0]:
    confidence=object[2]
    if confidence>confidence_threshold:
        x0,y0,x1,y1=(object[3:7]*[w,h,w,h]).astype(int)
        id=int(object[1])
        label=labels[id-1]

10、访问检测到的物体时:绘制检测矩形以及分类标签和置信度

cv2.rectangle(frame,(x0,y0),(x1,y1),(255,0,0),2)
text='%s(%.1f%%)'%(label,confidence*100.0)
cv2.putText(frame,text,(x0,y0-20),cv2.FONT_HERSHEY_SIMPLEX,1,(255,0,0),2)

11、显示
按下ESc:退出
否则:采集另一帧,继续循环下一次迭代

cv.imshow('Objects',frame)

k=cv2.waitKey(1)
if k==27:#Escape
    break
success,frame=cap.read()

基于第三方深度神经网络的人脸检测和分类

你可能感兴趣的:(python,知识总结,opencv,python,计算机视觉)