在深度学习7日入门-百度PaddlePaddle框架学习小结中,我提到计划通过神经网络实现一个图片分类模型,用于图书馆阅览室场景下座位状态检测。整理数据集阶段我已经通过鱼眼摄像头抓取了近600张图片,每张图片上目前分隔出12个座位图片,现在问题来了,我要将这7000+张图片筛选出来,分成座位上有人和座位上无人的两种情况。
同事帮忙临时安装在天花板上的鱼眼摄像头
昨天,我是将每张图片打开,然后关闭,再分别移动到相应目录下,100张没到已经痛苦不已!
昨晚受到群里有人通过PaddleHub上人体骨骼关键点模块做的一个追踪舞蹈动作那个视频的启发,我也想通过这个来自动筛选图片,比如抬左手完成触发某个动作,抬右手触发另一个动作。但我觉得那个动作太大,我想可以通过判断人脸位置相对移动,比如点头或摇头来实现。我在PaddlePaddle飞桨官网搜寻,没有看到人脸俯仰角、偏航角之类的人脸属性模块,直到看到人脸关键点的模块face_landmark_localization。因此,我的思路是这样的:通过matplotlib展示图片,再通过小本本摄像头抓取人脸,然后获取人脸上关键点,通过多张人脸图片上关键点位置移动判定是点头还是摇头,然后将图片移至相应目录,再继续展示下一张图片。
人脸关键点是下图这样子的,每张人脸有68个关键点(人脸轮廓17个点,左右眉毛各5个点,左右眼睛各6个点,鼻子9个点,嘴巴20个点),我在这里使用的是鼻翼那点即第34个点。
PaddleHub使用也超级简单,先pip安装paddlepaddle和paddlehub,然后安装人脸关键点检测模型face_landmark_localization
!pip install --upgrade paddlepaddle==1.7.1 !pip install --upgrade paddlehub==1.6.2 !hub install face_landmark_localization==1.0.2
然后就可以用了:
import paddlehub as hubimport cv2face_landmark = hub.Module(name="face_landmark_localization")# Replace face detection module to speed up predictions but reduce performance# face_landmark.set_face_detector_module(hub.Module(name="ultra_light_fast_generic_face_detector_1mb_320"))result = face_landmark.keypoint_detection(images=[cv2.imread('/PATH/TO/IMAGE')])# or# result = face_landmark.keypoint_detection(paths=['/PATH/TO/IMAGE'])
先通过摄像头获取人脸图片,然后通过hub获取人脸关键点信息,通过多张图片上关键点位置判断上下移动或左右移动是否超过相应阀值,以此来确定是点头或摇头,将点头或摇头标识在matplotlib图片标题上,再然后将图片移动到指定位置。
以下是运行时的界面:
经过几次调试,后来将计时加入,默认计时到或点头触发一种图片筛选,摇头触发另一种,不用点头直接等几秒超时可以节省一大半头部动作。
本项目已在AiStudio公开:https://aistudio.baidu.com/aistudio/projectdetail/446447
此处附上全部代码:
###import osimport shutilimport paddlehub as hub#from skimage import ioimport matplotlib.pyplot as pltimport matplotlib.image as mpimgfrom PIL import Image,ImageTkimport numpy as npimport timeimport cv2import jsonimport timeimages_path = "./images/"none_path="./none/"someone_path="./someone/"plt.rcParams['font.sans-serif'] = ['SimHei'] #正常显示中文标签plt.rcParams['axes.unicode_minus']=False #正常显示负号cap = Nonecap = cv2.VideoCapture(0) #打开本地摄像头ret, frame = cap.read()height,width,chl = frame.shapeprint('width*height: ',width, height)face_landmark = hub.Module(name="face_landmark_localization")nose_position = 33 #34 for noseposition=[]def getnoseposition(): ret, frame = cap.read() while (ret != True): #print('cap.read ret:', ret) ret, frame = cap.read() results = face_landmark.keypoint_detection(images=[frame]) #print(results) if len(results) != 0: #可能没有抓到人脸 result = results[0] x=int(result['data'][0][nose_position][0]) y=int(result['data'][0][nose_position][1]) #print(x,y) return (x,y) else: return (0,0)def get_offset(): global position a = np.array(position) xmin,ymin = a.min(axis=0) xmax,ymax =a.max(axis=0) xabsoffset = xmax-xmin yabsoffset = ymax-ymin #print('xabsoffset, yabsoffset: ',xabsoffset, yabsoffset) return xabsoffset, yabsoffsetdef shake_nod_head(): global position #print(position) length = len(position) #print('nod_head',length) if length < 8: return 0 #continue if length > 20: del(position[0]) xoffset,yoffset = get_offset() if xoffset <= height*0.10 and yoffset <= height*0.10: return 0 elif xoffset >= yoffset: return 1 #摇头 else: return 2 #点头imgs = os.listdir(images_path)plt.ion()for img in imgs: print(img) if os.path.isdir(images_path + img): continue image = mpimg.imread(images_path+img) plt.imshow(image) plt.title(img) plt.pause(0.2) position=[] #x,y = getnoseposition() #position.append((x,y)) start_time = time.time() while True: plt.pause(0.02) if (time.time() - start_time) > 3: print('计时到--默认有人') plt.title(img + ' 计时到,默认有人') shutil.move(images_path + img, someone_path+img) break x,y = getnoseposition() if x==0 and y==0: continue position.append((x,y)) head = shake_nod_head() if head == 2: print('点头-有人') plt.title(img + ' 有人') shutil.move(images_path + img, someone_path+img) break elif head == 1: plt.title(img + ' 无人') print('摇头-无人') shutil.move(images_path + img, none_path+img) break else: continue plt.pause(0.8) plt.clf() #break #shutil.move(images_path + img, none_path+img)
6000多次的点头或摇头,我的五一节就在颈椎骨质增生康复训练中过去了!
祝大家五一节开心,劳动的人最美丽!
//
完