物料清單:樹莓派5,usb相機、顯示器
前言:自己項目上需要用到ai識別缺陷,后續(xù)準(zhǔn)備把ai識別移植到現(xiàn)有的程序中,而整個的流程雖然看了不少但是還是不清楚具體該咋做,就想著借此次機會順便把整個流程跑一遍,后續(xù)就是換個識別物體,也大同小異。
選擇樹莓派5的原因:一方面跑ai需要性能比較高,再參考樹莓派5的參數(shù),感覺性能還挺強悍,跟我們現(xiàn)在用的rk3588就差四個小核,就決定在得捷官網(wǎng)買回來一塊跑跑試試。
樹莓派5:是采用Broadcom 新推出的一款四核 64 位 Arm Cortex-A76 處理器:BCM2712 ,主頻為 2.4GHz,每核二級緩存為 512KB,共享三級緩存為 2MB。Cortex-A76 在微體系結(jié)構(gòu)上比 Cortex-A72 進(jìn)步了三代,更好的制造工藝使 Raspberry Pi 5 的速度更快,工作功耗更低(但是看官方數(shù)據(jù),推薦適配器功率從15W變成了27W)。
硬件連接:外接一個顯示屏,因為桌面太亂就不拍顯示屏了
操作流程:
安裝tensorflow
下載tensorflow時發(fā)現(xiàn)樹莓派4/5架構(gòu)都是aarch64了,通過uname -a來查看
樹莓派5python版本:3.11.2
通過鏈接1:https://github.com/PINTO0309/Tensorflow-bin 查看樹莓派5對應(yīng)文件tensorflow-2.15.0.post1-cp311-none-linux_aarch64.whl
下載地址:Release v2.15.0.post1 · PINTO0309/Tensorflow-bin (github.com)
安裝依懶項,這個都可以根據(jù)上面鏈接中的內(nèi)容進(jìn)行配置,這里就不在貼了,字?jǐn)?shù)超限了
安裝OpenCV:
最后想實時檢測就需要用到OpenCV來打開相機
pip install opencv-python
配置好后如下圖:
到這步,運行檢測的環(huán)境基本就配置完成。
pip安裝的時候錯誤警告:
error: externally-managed-environment
This environment is externally managed
To install Python packages system-wide, try apt install
python3-xyz, where xyz is the package you are trying to
install.
大概意思就是:錯誤消息表明您正在嘗試在一個由系統(tǒng)管理的環(huán)境中安裝 Python 包,而不允許直接在系統(tǒng)范圍內(nèi)執(zhí)行此類操作。
可以用個建虛擬環(huán)境進(jìn)行運行:
python3 -m venv myenv #創(chuàng)建虛擬環(huán)境
source myenv/bin/activate # 激活虛擬環(huán)境(在使用虛擬環(huán)境之前,您需要激活它)
pip install tensorflow-2.15.0.post1-cp311-none-linux_aarch64.whl #安裝 TensorFlow cv2
如果你還是想裝在系統(tǒng)環(huán)境,可以直接運行在命令后面加上--break-system-packages 如下:
pip install tensorflow-2.15.0.post1-cp311-none-linux_aarch64.whl --break-system-packages
deactivate #退出虛擬環(huán)境
圖像采集、模型訓(xùn)練
因為樹莓派的存儲空間和性能有限,我訓(xùn)練就在別的機器上訓(xùn)練了。
from keras.preprocessing.image import ImageDataGenerator, img_to_array, load_img
import os
datagen = ImageDataGenerator(
rotation_range=20,
width_shift_range=0.15,
height_shift_range=0.15,
zoom_range=0.15,
shear_range=0.2,
horizontal_flip=True,
fill_mode='nearest')
dirs = os.listdir("../picture")
print(len(dirs))
for filename in dirs:
img = load_img("../picture//{}".format(filename))
x = img_to_array(img)
# print(x.shape)
x = x.reshape((1,) + x.shape) #datagen.flow要求rank為4
# print(x.shape)
datagen.fit(x)
prefix = filename.split('.')[0]
print(prefix)
counter = 0
for batch in datagen.flow(x, batch_size=4 , save_to_dir='../generater_pic', save_prefix=prefix, save_format='jpg'):
counter += 1
if counter > 50:
break
數(shù)據(jù)集的處理
把圖片轉(zhuǎn)成 .h5文件
import os
from PIL import Image
import numpy as np
import h5py
import tensorflow as tf
import time
# 把圖片壓縮成64*64的
def resize_img():
dirs = os.listdir("generater_pic")
for filename in dirs:
# 使用 tf.io.gfile 讀取文件
filepath = os.path.join("generater_pic", filename)
im = tf.io.read_file(filepath)
img_data = tf.image.decode_jpeg(im)
image_float = tf.image.convert_image_dtype(img_data, tf.float32)
resized = tf.image.resize(image_float, [64, 64]) # 使用 tf.image.resize
resized_im = resized.numpy() # 將 Tensor 轉(zhuǎn)換為 NumPy 數(shù)組
# 使用 PIL 保存圖像
Image.fromarray((resized_im * 255).astype(np.uint8)).save(os.path.join("resized_img", filename))
# 圖片轉(zhuǎn) h5 文件
def image_to_h5():
dirs = os.listdir("resized_img")
Y = [] # label
X = [] # data
print(len(dirs))
for filename in dirs:
label = int(filename.split('_')[0])
Y.append(label)
im = Image.open(os.path.join("resized_img", filename)).convert('RGB')
mat = np.asarray(im)
X.append(mat)
file = h5py.File("dataset/data.h5", "w")
file.create_dataset('X', data=np.array(X))
file.create_dataset('Y', data=np.array(Y))
file.close()
if __name__ == "__main__":
print("start.....: " + str((time.strftime('%Y-%m-%d %H:%M:%S'))))
resize_img()
print("end....: " + str((time.strftime('%Y-%m-%d %H:%M:%S'))))
image_to_h5()
訓(xùn)練模型
在后續(xù)貼上,提示字?jǐn)?shù)超限在樹莓派上進(jìn)行測試
import os
import numpy as np
import tensorflow as tf
from PIL import Image
from keras.models import load_model
import cv2
# 加載模型
model = load_model("model_500_200_c3/cnn_model.keras")
# 準(zhǔn)備輸入數(shù)據(jù)
def load_single_image(frame):
# TF讀取和處理圖像
image_tensor = tf.convert_to_tensor(frame) # 將幀轉(zhuǎn)換為 Tensor
image_tensor = tf.image.convert_image_dtype(image_tensor, tf.float32) # 轉(zhuǎn)換為 float32
resized = tf.image.resize(image_tensor, [64, 64]) # 調(diào)整大小
img_array = resized.numpy() # 轉(zhuǎn)換為數(shù)組
img_array = np.expand_dims(img_array, axis=0) # 添加批次維度
return img_array
# 使用模型進(jìn)行預(yù)測
def predict_image(model, frame):
img_array = load_single_image(frame)
predictions = model.predict(img_array)
predicted_class = np.argmax(predictions, axis=1)
return predicted_class[0]
import cv2
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
# 進(jìn)行預(yù)測
predicted_class = predict_image(model, frame)
cv2.putText(frame, f'Predicted class: {predicted_class}', (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 0, 0), 2)
cv2.imshow('Hand Gesture Recognition', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
測試結(jié)果: