牛!Python 也能實現圖像姿態識別溺水行為了!

2020-06-30     AI科技大本營

原標題:牛!Python 也能實現圖像姿態識別溺水行為了!

作者 | 李秋鍵

責編 | Carol

封圖 | CSDN 下載自視覺中國

眾所周知隨著人工智慧智能的發展,人工智慧的落地項目也在變得越來越多,尤其是計算機視覺方面。

首先圖像分類是根據各自在圖像信息中所反映的不同特徵,把不同類別的目標區分開來的圖像處理方法。它是利用計算機對圖像進行定量分析,把圖像或圖像中的每個像元或區域劃歸為若干個類別中的某一種,以代替人的視覺判讀

這裡整體程序的流程如下:

  1. CNN網絡實現圖像分類
  2. 根據分類結果可視化輸出結果

最終輸出的程序效果如下圖:

一、實驗前的準備

首先我們使用的python版本是3.6.5所用到的模塊如下:

configparser :配置文件模塊 讀寫配置文件

keras:用來訓練和調用神經網絡模型

素材準備

首先我們準備不同的圖片放到一個特定文件夾下。圖片分為三個類別,一個是溺水圖片文件夾,一個是正常游泳圖片文件夾,另一個是疑似溺水無法判定的圖片文件夾。在這裡我們把它放到data文件夾下,

其中疑似圖片文件夾,如下圖可見:

人體姿態識別搭建

1、姿態配置文件設定:

在這裡為了足夠的精度和方便調用,我們使用百度提供的人體分析接口。按照官方的規定設定了配置文件。主要就是設定人體各個肢體零件連接配置。

其對應的代碼如下:

def draw_line(self, img):

# nose ---> neck

cv2.line(img, (int(self.dic[ 'nose'][ 'x']), int(self.dic[ 'nose'][ 'y'])),

(int(self.dic[ 'neck'][ 'x']), int(self.dic[ 'neck'][ 'y'])), (0, 255, 0), 2)

# neck --> left_shoulder

cv2.line(img, (int(self.dic[ 'neck'][ 'x']), int(self.dic[ 'neck'][ 'y'])),

(int(self.dic[ 'left_shoulder'][ 'x']), int(self.dic[ 'left_shoulder'][ 'y'])), (0, 255, 0), 2)

# neck --> right_shoulder

cv2.line(img, (int(self.dic[ 'neck'][ 'x']), int(self.dic[ 'neck'][ 'y'])),

(int(self.dic[ 'right_shoulder'][ 'x']), int(self.dic[ 'right_shoulder'][ 'y'])), (0, 255, 0), 2)

# left _shoulder --> left_elbow

cv2.line(img, (int(self.dic[ 'left_shoulder'][ 'x']), int(self.dic[ 'left_shoulder'][ 'y'])),

(int(self.dic[ 'left_elbow'][ 'x']), int(self.dic[ 'left_elbow'][ 'y'])), (0, 255, 0), 2)

# left _elbow --> left_wrist

cv2.line(img, (int(self.dic[ 'left_elbow'][ 'x']), int(self.dic[ 'left_elbow'][ 'y'])),

(int(self.dic[ 'left_wrist'][ 'x']), int(self.dic[ 'left_wrist'][ 'y'])), (0, 255, 0), 2)

# right _shoulder --> right_elbow

cv2.line(img, (int(self.dic[ 'right_shoulder'][ 'x']), int(self.dic[ 'right_shoulder'][ 'y'])),

(int(self.dic[ 'right_elbow'][ 'x']), int(self.dic[ 'right_elbow'][ 'y'])), (0, 255, 0), 2)

# right _elbow --> right_wrist

cv2.line(img, (int(self.dic[ 'right_elbow'][ 'x']), int(self.dic[ 'right_elbow'][ 'y'])),

(int(self.dic[ 'right_wrist'][ 'x']), int(self.dic[ 'right_wrist'][ 'y'])), (0, 255, 0), 2)

# neck --> left_hip

cv2.line(img, (int(self.dic[ 'neck'][ 'x']), int(self.dic[ 'neck'][ 'y'])),

(int(self.dic[ 'left_hip'][ 'x']), int(self.dic[ 'left_hip'][ 'y'])), (0, 255, 0), 2)

# neck --> right_hip

cv2.line(img, (int(self.dic[ 'neck'][ 'x']), int(self.dic[ 'neck'][ 'y'])),

(int(self.dic[ 'right_hip'][ 'x']), int(self.dic[ 'right_hip'][ 'y'])), (0, 255, 0), 2)

# left _hip --> left_knee

cv2.line(img, (int(self.dic[ 'left_hip'][ 'x']), int(self.dic[ 'left_hip'][ 'y'])),

(int(self.dic[ 'left_knee'][ 'x']), int(self.dic[ 'left_knee'][ 'y'])), (0, 255, 0), 2)

# right _hip --> right_knee

cv2.line(img, (int(self.dic[ 'right_hip'][ 'x']), int(self.dic[ 'right_hip'][ 'y'])),

(int(self.dic[ 'right_knee'][ 'x']), int(self.dic[ 'right_knee'][ 'y'])), (0, 255, 0), 2)

# left _knee --> left_ankle

cv2.line(img, (int(self.dic[ 'left_knee'][ 'x']), int(self.dic[ 'left_knee'][ 'y'])),

(int(self.dic[ 'left_ankle'][ 'x']), int(self.dic[ 'left_ankle'][ 'y'])), (0, 255, 0), 2)

# right _knee --> right_ankle

cv2.line(img, (int(self.dic[ 'right_knee'][ 'x']), int(self.dic[ 'right_knee'][ 'y'])),

(int(self.dic[ 'right_ankle'][ 'x']), int(self.dic[ 'right_ankle'][ 'y'])), (0, 255, 0), 2)

在設置好基本的配置文件後,我們通過百度申請的帳號密匙等等調用接口即可。這裡實現的效果如下:

對應代碼如下:

classBaiDuAPI(object):

# 特殊 構造函數 初始化函數

def__init__(self):

app_id = "20038443"

api_key = "LhtctcN7hf6VtkHHcUGwXKfw"

secret_key = "wzWACH340kE0FGhvA9CqWsiRwltf5wFE"

self.client = AipBodyAnalysis(app_id, api_key, secret_key)

""" 讀取圖片 """

defget_file_content(self, photoPath):

withopen(photoPath, 'rb') asfp:

returnfp.read

""" 主函數 """

deffile_main(self, photoPath):

img = self.get_file_content( '{}'.format(photoPath))

""" 調用人體關鍵點識別 """

# 此處只能對一個人進行關鍵點識別

# 也就是說一個圖片如果有好多人的話,只能標出一個人的關節特徵

# 此處可以做修改,即進行把一張圖所有人的關節特徵都表達出來

# ------

# print(self.client.bodyAnalysis(img))

result = self.client.bodyAnalysis(img)[ 'person_info'][ 0][ 'body_parts']

jo = joint.Joint(result)

jo.xunhun(photoPath)

# print(result )

1、神經網絡的搭建:

這裡設定的CNN模型挺常見的模型相似,通過設定卷積核、步長、訓練批次等等搭建網絡。

代碼如下:

model = Sequential #創建一個神經網絡對象

#添加一個卷積層,傳入固定寬高三通道的圖片,以32種不同的卷積核構建32張特徵圖,

# 卷積核大小為3*3,構建特徵圖比例和原圖相同,激活函數為relu函數。

model. add(Conv2D(input_shape=(IMG_W,IMG_H, 3),filters= 32,kernel_size= 3,padding= 'same',activation= 'relu'))

#再次構建一個卷積層

model. add(Conv2D(filters= 32,kernel_size= 3,padding= 'same',activation= 'relu'))

#構建一個池化層,提取特徵,池化層的池化窗口為2*2,步長為2。

model. add(MaxPool2D(pool_size= 2,strides= 2))

#繼續構建卷積層和池化層,區別是卷積核數量為64。

model. add(Conv2D(filters= 64,kernel_size= 3,padding= 'same',activation= 'relu'))

model. add(Conv2D(filters= 64,kernel_size= 3,padding= 'same',activation= 'relu'))

model. add(MaxPool2D(pool_size= 2,strides= 2))

#繼續構建卷積層和池化層,區別是卷積核數量為128。

model. add(Conv2D(filters= 128,kernel_size= 3,padding= 'same',activation= 'relu'))

model. add(Conv2D(filters= 128,kernel_size= 3,padding= 'same',activation= 'relu'))

model. add(MaxPool2D(pool_size= 2, strides= 2))

model. add(Flatten) #數據扁平化

model. add(Dense( 128,activation= 'relu')) #構建一個具有128個神經元的全連接層

model. add(Dense( 64,activation= 'relu')) #構建一個具有64個神經元的全連接層

model. add(Dropout(DROPOUT_RATE)) #加入dropout,防止過擬合。

model. add(Dense(CLASS,activation= 'softmax')) #輸出層,一共3個神經元,對應3個分類

adam = Adam(lr=LEARNING_RATE) #創建Adam優化器

model.compile(optimizer=adam,loss= 'categorical_crossentropy',metrics=[ 'accuracy']) #使用交叉熵代價函數,adam優化器優化模型,並提取準確率

train_generator = train_datagen.flow_from_directory( #設置訓練集疊代器

TRAIN_PATH, #訓練集存放路徑

target_size=(IMG_W,IMG_H), #訓練集圖片尺寸

batch_size=BATCH_SIZE #訓練集批次

)

test_generator = test_datagen.flow_from_directory( #設置測試集疊代器

TEST_PATH, #測試集存放路徑

target_size=(IMG_W,IMG_H), #測試集圖片尺寸

batch_size=BATCH_SIZE, #測試集批次

)

print(train_generator.class_indices) #列印疊代器分類

try:

model = load_model( '{}.h5'.format(SAVE_PATH)) #嘗試讀取訓練好的模型,再次訓練

print( 'model upload,start training!')

except:

print( 'not find model,start training') #如果沒有訓練過的模型,則從頭開始訓練

model.fit_generator( #模型擬合

train_generator, #訓練集疊代器

steps_per_epoch=len(train_generator), #每個周期需要疊代多少步

epochs=EPOCHS, #疊代周期

validation_data=test_generator, #測試集疊代器

validation_steps=len(test_generator) #測試集疊代多少步

)

model.save( '{}.h5'.format(SAVE_PATH)) #保存模型

print( 'finish {} epochs!'.format(EPOCHS))

2、模型的調用:

代碼如下:

# 載入模型

model = load_model( 'model_selector.h5')

label = np.array([ '正常', '疑似', '溺水'])

defimage_change(image):

image = image.resize(( 224, 224))

image = img_to_array(image)

image = image / 255

image = np.expand_dims(image, 0)

returnimage

classBaiDuAPI(object):

# 特殊 構造函數 初始化函數

def__init__(self):

app_id = "20038443"

api_key = "LhtctcN7hf6VtkHHcUGwXKfw"

secret_key = "wzWACH340kE0FGhvA9CqWsiRwltf5wFE"

self.client = AipBodyAnalysis(app_id, api_key, secret_key)

""" 讀取圖片 """

defget_file_content(self, photoPath):

withopen(photoPath, 'rb') asfp:

returnfp.read

""" 主函數 """

deffile_main(self, photoPath):

img = self.get_file_content( '{}'.format(photoPath))

""" 調用人體關鍵點識別 """

# 此處只能對一個人進行關鍵點識別

# 也就是說一個圖片如果有好多人的話,只能標出一個人的關節特徵

# 此處可以做修改,即進行把一張圖所有人的關節特徵都表達出來

# ------

# print(self.client.bodyAnalysis(img))

result = self.client.bodyAnalysis(img)[ 'person_info'][ 0][ 'body_parts']

jo = joint.Joint(result)

jo.xunhun(photoPath)

# print(result )

#預測2.jpg的結果

try:

image = load_img( "2.jpg")

#plt.imshow(image)

image = image_change(image)

baiduapi = BaiDuAPI

baiduapi.file_main( '2.jpg')

img=cv2.imread( "temp.jpg")

img_PIL = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))

myfont = ImageFont.truetype( r'C:/Windows/Fonts/simfang.ttf', 40)

draw = ImageDraw.Draw(img_PIL)

draw.text(( 300, 10), label[model.predict_classes(image)][ 0], font=myfont, fill=( 200, 100, 0))

img_OpenCV = cv2.cvtColor(np.asarray(img_PIL), cv2.COLOR_RGB2BGR)

cv2.imshow( 'frame', img_OpenCV)

cv2.waitKey( 0)

except:

pass

#預測1.jpg的結果

try:

image = load_img( "1.jpg")

#plt.imshow(image)

image = image_change(image)

baiduapi = BaiDuAPI

baiduapi.file_main( '1.jpg')

img=cv2.imread( "temp.jpg")

img_PIL = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))

myfont = ImageFont.truetype( r'C:/Windows/Fonts/simfang.ttf', 40)

draw = ImageDraw.Draw(img_PIL)

draw.text(( 300, 10), label[model.predict_classes(image)][ 0], font=myfont, fill=( 200, 100, 0))

img_OpenCV = cv2.cvtColor(np.asarray(img_PIL), cv2.COLOR_RGB2BGR)

cv2.imshow( 'frame', img_OpenCV)

cv2.waitKey( 0)

except:

pass

#預測3.jpg的結果

try:

image = load_img( "3.jpg")

#plt.imshow(image)

image = image_change(image)

baiduapi = BaiDuAPI

baiduapi.file_main( '3.jpg')

img=cv2.imread( "temp.jpg")

img_PIL = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))

myfont = ImageFont.truetype( r'C:/Windows/Fonts/simfang.ttf', 40)

draw = ImageDraw.Draw(img_PIL)

draw.text(( 300, 10), label[model.predict_classes(image)][ 0], font=myfont, fill=( 200, 100, 0))

img_OpenCV = cv2.cvtColor(np.asarray(img_PIL), cv2.COLOR_RGB2BGR)

cv2.imshow( 'frame', img_OpenCV)

cv2.waitKey( 0)

except:

pass

最終運行程序結果如下:

源碼地址:

https://pan.baidu.com/s/1qMwPCTTyqDWPXoPj1XnKgA

提取碼:us2k

作者簡介:

李秋鍵,CSDN博客專家,CSDN達人課作者。碩士在讀於中國礦業大學,開發有taptap競賽獲獎等等。

文章來源: https://twgreatdaily.com/zh-mo/fGRNBXMBiuFnsJQVQCC9.html










CSDN湘苗培優

2020-12-24