1. 程式人生 > >數字識別樹莓派3+python3.5+opencv3.3+tensorflow1.7+keras

數字識別樹莓派3+python3.5+opencv3.3+tensorflow1.7+keras

本文主要介紹如何利用樹莓派3數字識別1-64數字圖片,最近在做一個智慧車的專案,通過識別賽場的數字來完成定位,在這裡寫一下自己的一些經驗。


1.圖片採集和標註

影象採集是通過opencv呼叫攝像頭來採集圖片的資料,場地的背景為藍色,數字為白色。


通過opencv採集到的影象大小為320x240,對影象進行預處理,包括灰度化、平滑濾波、二值化。由於攝像頭拍攝的角度是歪的,所以還做了一些透射變換,採集到的影象經過處理後效果如下:


為了方便資料的採集,這裡寫了一個小程式來採集數字為1-64的影象:

在採集影象之前,先輸入數字號碼,如10,然後調整好圖片的角度,讓數字儘量位於整個圖片的中央,然後按下‘s’鍵採集圖片,採集到的圖片會儲存在‘./num_data’資料夾下。

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
'''

author:Administrator
datetime:2018/5/11/011 19:49
software: PyCharm
'''

import cv2
import numpy as np

cap = cv2.VideoCapture(1)

cap.set(3,320)
cap.set(4,240)

ret, frame = cap.read()
rows, cols, channels = frame.shape
print(cols, rows, channels)

def get_point(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDBLCLK:
        print(x,y)

cv2.namedWindow("image")
cv2.setMouseCallback("image", get_point)

# 影象預處理
def img_p(img):

    # 灰度化
    gray_img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 平滑濾波
    blur = cv2.blur(gray_img, (3,3))

    # 二值化
    ret1, th1 = cv2.threshold(blur, 190, 255, cv2.THRESH_BINARY)

    # 透視變換
    b = 50
    pts1 = np.float32([[b, 0], [cols-b, 0], [0, rows], [cols, rows]])
    pts2 = np.float32([[0, 0], [cols, 0], [0, rows], [cols, rows]])
    M = cv2.getPerspectiveTransform(pts1, pts2)
    dst = cv2.warpPerspective(th1, M, (cols, rows))

    return dst

num = input("num:")
print(num)
while True:
    # 讀取影象
    ret, frame = cap.read()


    dst = img_p(frame)

    k = cv2.waitKey(10)
    if k == ord('q'):
        break
    elif k == ord('s'):
        filename = r'./num_data/' + num + '.jpg'
        cv2.imwrite(filename, dst)
        print(filename)
        num = input("num:")
        print(num)

    cv2.imshow("image", dst)


cap.release()
cv2.destroyAllWindows()

上面就是採集到的1-64的數字圖片。

2.圖片資料的擴增

採集到的資料數量有限,要用卷積神經網路來識別數字圖片需要大量的資料,所以可以利用keras的影象預處理API對資料進行擴增,具體的API介紹可以參考keras中文文件https://keras.io/zh/preprocessing/image/。我寫了一個數據擴增的小程式,每張圖片生成了200張訓練圖片,100張測試圖片,程式碼如下:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
'''
生成多個樣本

author:Administrator
datetime:2018/3/24/024 18:46
software: PyCharm
'''
from keras.preprocessing.image import ImageDataGenerator,array_to_img, img_to_array, load_img
import os


# 生成資料夾
def ensure_dir(dir_path):
    if not os.path.exists(dir_path):
        try:
            os.makedirs(dir_path)
        except OSError:
            pass


# 圖片生成器ImageDataGenerator
pic_gen = ImageDataGenerator(
    rotation_range=5,
    width_shift_range=0.1,
    height_shift_range=0.1,
    shear_range=0.2,
    zoom_range=0.2,
    fill_mode='nearest')

# 生成圖片
def img_create(img_dir, save_dir, img_prefix, num=100):
    img = load_img(img_dir)
    x = img_to_array(img)
    x = x.reshape((1,) + x.shape)
    img_flow = pic_gen.flow(
        x,
        batch_size=1,
        save_to_dir=save_dir,
        save_prefix=img_prefix,
        save_format="jpg"
    )
    i = 0
    for batch in img_flow:
        i += 1
        if i > num:
            break


# 生成訓練集
for i in range(1, 65, 1):
    img_prefix = str(i)
    img_dir = './num_data/' + img_prefix + '.jpg'
    save_dir = './data/train/' + img_prefix
    ensure_dir(save_dir)
    img_create(img_dir, save_dir, img_prefix, num=200)
    print("train: ", i)


# 生成測試集
for i in range(1, 65, 1):
    img_prefix = str(i)
    img_dir = './num_data/' + img_prefix + '.jpg'
    save_dir = './data/validation/' + img_prefix
    ensure_dir(save_dir)
    img_create(img_dir, save_dir, img_prefix, num=100)
    print("validation: ", i)

執行上面的程式碼,在工程目錄下就會生成一些經過旋轉平移縮放的資料圖片

3.搭建神經網路訓練樣本

接下來就是通過keras來搭建一個簡單的卷積神經網路來訓練一個1-64的圖片分類器,採用的tensorflow1.7作為後端,在GPU上訓練,每次訓練都會儲存最佳的訓練權重。程式碼如下:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
'''
訓練資料
author:Administrator
datetime:2018/3/24/024 19:52
software: PyCharm
'''

# 對樣本進行預處理
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Dropout, Flatten, Dense
from keras.callbacks import ModelCheckpoint

# 設定訓練引數
nb_train_samples = 10000 # 訓練樣本數
nb_validation_samples = 1000 # 測試樣本數
nb_epoch = 20 #訓練輪數
batch_size = 32 #批次大小


# 圖片尺寸
img_width, img_height, channels= 160, 120, 1
input_shape = (img_width, img_height, channels)

# 訓練和測試資料路徑
target = './data/'
train_data_dir = target + 'train'
validation_data_dir = target + 'validation'

# 圖片生成器ImageDataGenerator
train_pic_gen = ImageDataGenerator(
    rescale=1. / 255,  # 對輸入圖片進行歸一化到0-1區間
    # 根據需求進行進一步調整
    # rotation_range=5,
    # width_shift_range=0.1,
    # height_shift_range=0.1,
    )

# 測試集不做變形處理,只需歸一化。
validation_pic_gen = ImageDataGenerator(rescale=1. / 255)

# 按資料夾生成訓練集流和標籤,
train_flow = train_pic_gen.flow_from_directory(
    train_data_dir,
    target_size=(img_width, img_height), #調整影象大小
    batch_size=batch_size,
    color_mode='grayscale', #輸入圖片為灰度圖片
    # color_mode='rgb',
    classes=[str(i) for i in range(1,65,1)],
    class_mode='categorical')

# 按資料夾生成測試集流和標籤,
validation_flow = validation_pic_gen.flow_from_directory(
    validation_data_dir,
    target_size=(img_width, img_height), #調整影象大小
    batch_size=batch_size,
    color_mode='grayscale', #輸入圖片為灰度圖片
    # color_mode='rgb',
    classes=[str(i) for i in range(1, 65, 1)], # 標籤
    class_mode='categorical' #多分類
)


# 搭建模型
model = Sequential()

model.add(Conv2D(32, (3, 3), activation='relu', input_shape=input_shape))
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))

model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(64, activation='softmax'))

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

model.summary()

# 回撥函式,儲存最佳訓練引數
checkpointer = ModelCheckpoint(filepath="./weights/weights.h5", verbose=1, save_best_only=True)

# 匯入上次訓練的權重
try:
    model.load_weights('./weights/weights.h5')
    print("load weights...")
except:
    print("not weights")
    pass

# 資料流訓練API
model.fit_generator(
    train_flow,
    steps_per_epoch=nb_train_samples/batch_size,
    epochs=nb_epoch,
    validation_data=validation_flow,
    validation_steps=nb_validation_samples/batch_size,
    callbacks=[checkpointer]
    )

經過了大概30分鐘訓練,訓練集達到了96%以上的正確率,測試集達到了99.2%的正確率。


4.測試訓練效果

我寫了一個測試程式,從攝像頭採集一張圖片,經過影象預處理後儲存到本地,然後輸入到之前訓練好的卷積神經網路進行預測,將預測的結果顯示在原圖上,測試的程式碼如下:

#!/usr/bin/env python3
# -*- coding:utf-8 -*-
'''
攝像頭採集圖片驗證
author:Administrator
datetime:2018/3/25/025 9:27
software: PyCharm
'''
import cv2
import matplotlib.pyplot as plt
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras.preprocessing import image
from keras.optimizers import SGD

import numpy as np

# 圖片尺寸
img_width, img_height, channels= 160, 120, 1
input_shape = (img_width, img_height, channels)

# img_path = './prediction/pre0.png'

# 獲取圖片並進行預處理
def img_pre(img_path = './temp.png'):

    img = image.load_img(img_path, grayscale=True, target_size=(img_width, img_height))
    # plt.imshow(img)
    # plt.show()
    x = image.img_to_array(img)
    x = np.expand_dims(x, axis=0)
    x /= 255.0
    # print(x.shape)
    return x

# 搭建神經網路
model = Sequential()

model.add(Conv2D(32, (3, 3), activation='relu', input_shape=input_shape))
model.add(Conv2D(32, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))

model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dense(64, activation='softmax'))


# 載入權重
model.load_weights('./weights/weights.h5')

# 影象預處理
def img_p(img):
    rows, cols, channels = img.shape
    # 灰度化
    gray_img = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 平滑濾波
    blur = cv2.blur(gray_img, (3,3))

    # 二值化
    ret1, th1 = cv2.threshold(blur, 190, 255, cv2.THRESH_BINARY)

    # 透視變換
    b = 50
    pts1 = np.float32([[b, 0], [cols-b, 0], [0, rows], [cols, rows]])
    pts2 = np.float32([[0, 0], [cols, 0], [0, rows], [cols, rows]])
    M = cv2.getPerspectiveTransform(pts1, pts2)
    dst = cv2.warpPerspective(th1, M, (cols, rows))

    return dst

cap = cv2.VideoCapture(1)  # 開啟usb攝像頭
cap.set(3, 320)
cap.set(4, 240)
ret, frame = cap.read()  # 讀取一幀圖片
print(frame.shape)
num = ''
while True:
    ret, frame = cap.read()  # 讀取一幀圖片

    # 判斷按鍵按下
    k = cv2.waitKey(1)

    if k == ord('s'):  # 如果‘s’鍵按下,截圖儲存圖片到電腦

        # 圖片預處理
        dst = img_p(frame)

        cv2.imwrite('temp.png', dst)
        cv2.imshow('dst', dst)

        # 讀取歸一化處理過的圖片
        xr = img_pre()

        # 進行預測,返回分類結果
        classes = model.predict_classes(xr)[0]
        num = str(classes + 1)
        print("num:", num) # 列印結果

    elif k == ord('q'):
        break

    font = cv2.FONT_HERSHEY_SIMPLEX
    cv2.putText(frame, num, (10, 50), font, 2, (0, 0, 255), 4, cv2.LINE_AA)  # 在圖片上顯示預測結果
    cv2.imshow('frame', frame)  # 顯示圖片


cv2.destroyAllWindows()
cap.release()



按下鍵盤上的‘s’鍵擷取圖片,測試的效果如上圖所示。

5.在樹莓派3上進行部署

首先要在樹莓派3上搭建opencv3.3,tensorflow1.7和keras環境,可以參考tju_cc的部落格點選開啟連結,有詳細的教程。keras安裝可以參考官方文件,也可以通過sudo pip3 install keras 來安裝。

首先在樹莓派home目錄下 建立一個number的資料夾,通過FTP傳輸工具將權重檔案weights和test.py檔案上傳到樹莓派,,然後可以通過VNC遠端桌面工具來連線樹莓派,執行測試程式。


開啟VNC終端,執行測試程式,載入權重檔案有點慢。。。按下's'鍵截圖儲存,送到神經網路進行預測。(如果感覺樹莓派執行卡的話,可以嘗試將樹莓派CPU超頻到1.4GHz,GPU超頻到500MHz,把視訊記憶體調到256M)。


到此為止,就完成了攝像頭對數字圖片的採集和識別。

相關推薦

數字識別樹莓3+python3.5+opencv3.3+tensorflow1.7+keras

本文主要介紹如何利用樹莓派3數字識別1-64數字圖片,最近在做一個智慧車的專案,通過識別賽場的數字來完成定位,在這裡寫一下自己的一些經驗。1.圖片採集和標註影象採集是通過opencv呼叫攝像頭來採集圖片的資料,場地的背景為藍色,數字為白色。通過opencv採集到的影象大小為3

樹莓3 +python3.5 + 最新版tensorflow

在樹莓派中,用官方提供的tensorflow最高只能在python3.4的環境下安裝到tensorflow-1.1.0。現在樹莓派的系統一般都為python3.5。tensorflow也已經更新到了tensorflow-1.8.0。下面我麼以安裝tensorflow-1.8.

樹莓3b pyhon3.5 安裝opencv3.4

參考了百度文庫、CSDN的各位大佬的安裝教程,重複安裝了好多次都沒有成功。最後在同學的幫助下,在google上找到了解決方法。下面就是所安裝的具體過程。首先要確保有足夠的空間,樹莓派至少要需要16G的SD卡,16G的其實都勉強。 首先安裝依賴包,在進行軟體安裝之前要更新一下現有的軟體包: s

Python3OpenCV3.3 圖像處理(一)--環境搭建與簡單DEMO

http opencv3 opencv col lan pytho href tar .net https://blog.csdn.net/qq_32811489/article/details/78636049 https://blog.csdn.net/gangzhu

Python3.5開發3 - 基本命令及如何進行讀寫檔案

Python3.5開發3 - 基本命令及如何進行讀寫檔案 知識點: 熟練使用Python的列表,元組,集合與字典 熟練使用Python讀寫檔案 演示: # list a = [1,'yx',['x','y'],6]

【機器學習】Windows +Anaconda3(python3.5)+opencv3.4.1 安裝(2)

                 Windows +Anaconda3(python3.5)+opencv3.4.1 安裝(2)   原文參考:https://www.cnblogs.com/

【機器學習】Windows +Anaconda3(python3.5)+opencv3.4.1 安裝(1)

              Windows +Anaconda3(python3.5)+opencv3.4.1 安裝(1)   1. Anacond的介紹    Anaconda指的是一個

【機器學習】Windows +Anaconda3(python3.5)+opencv3.4.1 安裝(4)

           Windows +Anaconda3(python3.5)+opencv3.4.1 安裝(4)    想解決import cv2問題 ,於是在網上找了一些方法,但是許多是不可行的,後來發現一

IDE相關(六)Ubuntu18.04+Python2/3.6.5+OpenCV3.4.3實現開啟攝像頭

 必要的環境配置見:IDE相關(五)基於ubuntu 18.04 配置opencv 並在Qt上應用(全過程) 一、Ubuntu下執行Python指令碼 新建檔案: touch test.py 或 vim test.py (前提是安裝了vim) vim t

Windows +Anaconda3(python3.5)+opencv3.4.1 安裝(1)

       Windows +Anaconda3(python3.5)+opencv3.4.1 安裝(3)  想解決import cv2問題 ,於是在網上找了一些方法,但是許多是無效的,後來發現一種方法可行的,分享給大家。  1.其他方法:    1. 因為之前在

阿里雲伺服器(Ubuntu)樹莓 安裝python3、ffmpeg命令

安裝python3 sudo apt-get update sudo apt-get install python3 安裝python3的pip sudo apt-get install python3 python3-pip 安裝ffmpeg sudo apt-

Anaconda Python3.6 OpenCV3.3 Ubuntu 16.04原始碼編譯

2018.08.22更新: Mac到手了,環境立馬配起來,先把ffmpeg裝了不然後面讀視訊讀不了。 brew install ffmpeg brew install pkg-config pkg-config這個東西有點噁心,裝了ffmpeg還不行,

機器學習實戰例項之手寫數字識別(KNN、python3

from numpy import * from os import listdir import operator def img2Vector(filename): returnVecter = zeros((1,1024)) fr = open(fil

Python3OpenCV3.3 影象處理(二)--影象基本操作

一、本節簡述          本節主要講解影象的一些基礎知識,以及影象的載入和獲得屬性,最後將會學到 OpenCV 攝像頭的簡單使用。 二、影象基本知識         1、影象是什麼:                     影象是客觀物件的一種相似性的、生動性

caffe安裝(2)python3.5+opencv3.1+caffe

1. OpenCV3 opencv3 與cuda8不相容,不啟動支援cuda 真的是歷經千辛啊 安裝依賴庫 sudo apt-get install cmake git pkg-config libgtk2.0-dev libavcodec-de

Python3OpenCV3.3 影象處理(一)--環境搭建與簡單DEMO

一、所需軟體 本教程需要一下軟體: PyCharm 2017.2.3  (其他版本也可) OpenCV 3.3 Python 3 Windows 7以上版本 二、環境配置        

Python3.5+OpenCV3.2讀取影象問題

由於編碼原因,opencv3.2無法用imread\imwrite直接讀寫含有中文字元的影象路徑,因此讀寫要用以下2個方法: import cv2 as cimport numpy as npimg=

Python3OpenCV3.3 影象處理(十九)--直線檢測

這節課能容不多,基本上是遵循規律編寫程式碼即可 import cv2 as cv import numpy as np def line_detection(img): """方

Python3OpenCV3.3 影象處理(十四)--模板匹配

一、什麼是模板匹配 在整個影象區域發現與給定子影象匹配的區域,模板匹配的工作方式是在待檢測影象上從左到右,從上到下計算模板圖象與重疊子影象的匹配度,匹配度越大,兩者越相同 二、OpenCV中的模

解決樹莓python3無法import模組RPi.GPIO的問題辦法

[email protected]:~ $ python3Python 3.6.4 (default, Apr  8 2018, 18:42:32) [GCC 6.3.0 20170516]