返回列表 发新帖我要提问本帖赏金: 10.00元(功能说明)

连载:一步步实现人脸数据的提取【原创】

[复制链接]
 楼主| keer_zu 发表于 2019-1-15 17:01 | 显示全部楼层 |阅读模式
ce, AC, se, TE, face
本帖最后由 keer_zu 于 2019-1-24 10:00 编辑

要识别人脸,先要录入人脸图片。

录入需要考虑的是怎么能从摄像头得到的数据中得到你需要录入的人脸。
首先,你要从摄像头的流数据(比如rtsp)中得到一个image,
然后从中得到人脸,这个过程还需要排除旁边其他人的人脸。

从rtsp读取的数据如果一直不处理,就会让缓冲崩溃。
所以打算采用每隔若干张image(比如20张),选一张去处理。其余的都交给显示程序播放视频。
被处理的那张虽然是好多张中才选取一张,但是如果要和播放串行处理,仍然会造成播放不畅,缓冲崩掉。所以必须采用并发,先实现并发
(第一步,让python并发起来)


  1. import cv2
  2. import dlib
  3. import os
  4. import sys
  5. #import random
  6. import time
  7. from multiprocessing import Process, JoinableQueue, Queue
  8. from random import random
  9. import time

  10. #tasks_queue = JoinableQueue()
  11. results_queue = Queue()



  12. name = "abc"#input('please input your name:')
  13. window_name = "face picture entry"
  14. output_dir = './' + name + '_faces'
  15. size = 64

  16. if not os.path.exists(output_dir):
  17.     os.makedirs(output_dir)

  18. # 改变图片的亮度与对比度
  19. def relight(img, light=1, bias=0):
  20.     w = img.shape[1]
  21.     h = img.shape[0]
  22.     #image = []
  23.     for i in range(0,w):
  24.         for j in range(0,h):
  25.             for c in range(3):
  26.                 tmp = int(img[j,i,c]*light + bias)
  27.                 if tmp > 255:
  28.                     tmp = 255
  29.                 elif tmp < 0:
  30.                     tmp = 0
  31.                 img[j,i,c] = tmp
  32.     return img

  33. #使用dlib自带的frontal_face_detector作为我们的特征提取器
  34. detector = dlib.get_frontal_face_detector()

  35. #videoName = './' + name + '.avi'
  36. videoName = "rtsp://admin:ABC_123456@172.17.208.150:554/Streaming/Channels/101?transportmode=unicast"
  37. # 打开摄像头 参数为输入流,可以为摄像头或视频文件


  38. def CatchUsbVideo(out_queue):
  39.     process_flag = False
  40.     cv2.namedWindow(window_name)

  41.     #视频来源,可以来自一段已存好的视频,也可以直接来自USB摄像头
  42.     cap = cv2.VideoCapture(videoName)      
  43.     n = 1
  44.     while cap.isOpened():
  45.         ok, frame = cap.read() #读取一帧数据
  46.         if not ok:            
  47.             break                    

  48.         #显示图像并等待10毫秒按键输入,输入‘q’退出程序
  49.         cv2.namedWindow(window_name, cv2.WINDOW_NORMAL) #cv2.WND_PROP_FULLSCREEN)
  50.         #cv2.moveWindow(window_name, screen.x - 1, screen.y - 1)
  51.         cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN,
  52.                           cv2.WINDOW_FULLSCREEN)
  53.         n = n + 1
  54.         if n == 20:
  55.             if process_flag == True:
  56.                 out_queue.put(frame)
  57.             n = 1
  58.             
  59.         else:
  60.             frameresize = cv2.resize(frame,(1280,800))
  61.             cv2.imshow(window_name, frameresize)

  62.         c = cv2.waitKey(10)
  63.         if c & 0xFF == ord('q'):
  64.             break        
  65.         if c & 0xFF == ord('d'):
  66.             process_flag = True

  67.     #释放摄像头并销毁所有窗口
  68.     cap.release()
  69.     cv2.destroyAllWindows()


  70. def FaceDectection(in_queue):
  71.     while 1:
  72.         img = in_queue.get()
  73.         if img is None:
  74.             break
  75.         else:
  76.             print("====== recv pic")


  77. #if __name__ == '__main__':
  78. #    CatchUsbVideo()
  79. processes = []

  80. p = Process(target=CatchUsbVideo, args=(results_queue,))
  81. p.start()
  82. processes.append(p)

  83. p = Process(target=FaceDectection, args=(results_queue,))
  84. p.start()
  85. processes.append(p)


  86. for p in processes:
  87.     p.join()

  88. while 1:
  89.     time.sleep(1)
@21ic小管家 @sherwin @海中水 @tyw @yyy71cj @gaoyang9992006

2019年1月15号,增加探测并获取人脸代码:

  1. def FaceDectection(in_queue):
  2.     index = 0
  3.     while 1:
  4.         img = in_queue.get()
  5.         gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  6.         # 使用detector进行人脸检测
  7.         dets = detector(gray_img, 1)

  8.         for i, d in enumerate(dets):
  9.             x1 = d.top() if d.top() > 0 else 0
  10.             y1 = d.bottom() if d.bottom() > 0 else 0
  11.             x2 = d.left() if d.left() > 0 else 0
  12.             y2 = d.right() if d.right() > 0 else 0

  13.             face = img[x1:y1,x2:y2]
  14.             # 调整图片的对比度与亮度, 对比度与亮度值都取随机数,这样能增加样本的多样性
  15.             #face = relight(face, random.uniform(0.5, 1.5), random.randint(-50, 50))

  16.             face = cv2.resize(face, (size,size))

  17.             #cv2.imshow('image', face)

  18.             cv2.imwrite(output_dir+'/'+str(index)+'.jpg', face)

  19.             index += 1

  20.         if index == 5:
  21.                 break

2019-1-16 10:35继续修改FaceDectection(),可以获取镜头中主要人物的人脸,用于人脸采集和识别。
这里,我只是简单做了一下尺寸的筛选。


  1.     def FaceDectection(in_queue):
  2.         index = 0
  3.         while 1:
  4.             img = in_queue.get()
  5.             gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  6.             # 使用detector进行人脸检测
  7.             dets = detector(gray_img, 1)

  8.             for i, d in enumerate(dets):
  9.                 print("----- i:%d\n" % i)
  10.                 x1 = d.top() if d.top() > 0 else 0
  11.                 y1 = d.bottom() if d.bottom() > 0 else 0
  12.                 x2 = d.left() if d.left() > 0 else 0
  13.                 y2 = d.right() if d.right() > 0 else 0

  14.                 face = img[x1:y1,x2:y2]


  15.                 if face.shape[0] > 400 :  # check picture size
  16.                     cv2.imwrite(output_dir+'/'+str(index)+'.jpg', face)

  17.                 index += 1

  18.             if index == 5:
  19.                 break

2019.01.23
  1. def ConvertUseTensorflowMtcnn(in_queue,msg_q):
  2.     margin = 32
  3.     index_num = 0
  4.     target_dir = os.path.join(img_dir,"images_data_%d" % target_img_size)
  5.     output_user_dir = os.path.join(target_dir, name)
  6.     if not os.path.exists(output_user_dir):
  7.         os.makedirs(output_user_dir)

  8.     minsize = 30 # minimum size of face
  9.     threshold = [ 0.6, 0.7, 0.7 ]  # three steps's threshold
  10.     factor = 0.709 # scale factor


  11.     with tf.Graph().as_default():
  12.         gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.25)
  13.         sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False))
  14.         with sess.as_default():
  15.             pnet, rnet, onet = detect_face.create_mtcnn(sess, None)
  16.     while 1:
  17.         file_name = in_queue.get()
  18.         print("====== file: %s" % file_name)
  19.         img = cv2.imread(file_name)
  20.         
  21.         bounding_boxes, _ = detect_face.detect_face(img, minsize, pnet, rnet, onet, threshold, factor)
  22.         print(bounding_boxes)
  23.         nrof_faces = bounding_boxes.shape[0]
  24.         print(nrof_faces)
  25.         if nrof_faces>0:
  26.             det = bounding_boxes[:,0:4]
  27.             det_arr = []
  28.             img_size = np.asarray(img.shape)[0:2]
  29.             print("====nrof_face: %d  img size:"  % nrof_faces)
  30.             print(img_size)
  31.             if nrof_faces == 1:
  32.                 bounding_box_size = (det[:,2]-det[:,0])*(det[:,3]-det[:,1])
  33.                 img_center = img_size / 2
  34.                 offsets = np.vstack([ (det[:,0]+det[:,2])/2-img_center[1], (det[:,1]+det[:,3])/2-img_center[0] ])
  35.                 offset_dist_squared = np.sum(np.power(offsets,2.0),0)
  36.                 index = np.argmax(bounding_box_size-offset_dist_squared*2.0) # some extra weight on the centering
  37.                 det_arr.append(det[index,:])
  38.             for i, det in enumerate(det_arr):
  39.                 det = np.squeeze(det)
  40.                 bb = np.zeros(4, dtype=np.int32)
  41.                 bb[0] = np.maximum(det[0]-margin/2, 0)
  42.                 bb[1] = np.maximum(det[1]-margin/2, 0)
  43.                 bb[2] = np.minimum(det[2]+margin/2, img_size[1])
  44.                 bb[3] = np.minimum(det[3]+margin/2, img_size[0])
  45.                 cropped = img[bb[1]:bb[3],bb[0]:bb[2],:]
  46.                 scaled = misc.imresize(cropped, (target_img_size, target_img_size), interp='bilinear')

  47.                 output_filename = os.path.join(output_user_dir, ("%d" % index_num) +'.png')

  48.                 filename_base, file_extension = os.path.splitext(output_filename)

  49.                 output_filename_n = "{}{}".format(filename_base, file_extension)

  50.                 misc.imsave(output_filename_n, scaled)

  51.                 index_num += 1
  52.         #if os.path.exists(file_name):
  53.             #os.remove(file_name)
  54.         if index_num >= 5:
  55.             msg_q.put("complate_msg")
  56.             msg_q.put("complate_msg")
  57.             break


对opencv筛选的人脸图片使用tensorflow实现的mtcnn进行再次确认和校正:



打赏榜单

21ic小喇叭 打赏了 10.00 元 2019-01-21
理由:谢谢分享

评论

[url=home.php?mod=space&uid=544565]@renxiaolin[/url] :多谢鼓励  发表于 2019-1-29 08:36
给力  发表于 2019-1-28 16:57
[url=home.php?mod=space&uid=7589]@tyw[/url] 多谢老T叔鼓励  发表于 2019-1-15 17:09

评分

参与人数 1威望 +15 收起 理由
tyw + 15 很给力!

查看全部评分

 楼主| keer_zu 发表于 2019-1-15 17:04 | 显示全部楼层
本帖最后由 keer_zu 于 2019-1-15 18:19 编辑

github同步更新中。。。。
 楼主| keer_zu 发表于 2019-1-15 18:35 | 显示全部楼层
本帖最后由 keer_zu 于 2019-1-15 18:38 编辑

刚刚更新代码,为第二个进程增加人脸获取代码:


  1. import cv2
  2. import dlib
  3. import os
  4. import sys
  5. #import random
  6. import time
  7. from multiprocessing import Process, JoinableQueue, Queue
  8. from random import random
  9. import time

  10. #tasks_queue = JoinableQueue()
  11. results_queue = Queue()



  12. name = input('please input your name:')
  13. window_name = "face picture entry"
  14. output_dir = './' + name + '_t'
  15. size = 64

  16. if not os.path.exists(output_dir):
  17.     os.makedirs(output_dir)

  18. # 改变图片的亮度与对比度
  19. def relight(img, light=1, bias=0):
  20.     w = img.shape[1]
  21.     h = img.shape[0]
  22.     #image = []
  23.     for i in range(0,w):
  24.         for j in range(0,h):
  25.             for c in range(3):
  26.                 tmp = int(img[j,i,c]*light + bias)
  27.                 if tmp > 255:
  28.                     tmp = 255
  29.                 elif tmp < 0:
  30.                     tmp = 0
  31.                 img[j,i,c] = tmp
  32.     return img

  33. #使用dlib自带的frontal_face_detector作为我们的特征提取器
  34. detector = dlib.get_frontal_face_detector()

  35. #videoName = './' + name + '.avi'
  36. videoName = "rtsp://admin:ABC_123456@172.17.208.150:554/Streaming/Channels/101?transportmode=unicast"
  37. # 打开摄像头 参数为输入流,可以为摄像头或视频文件


  38. def CatchUsbVideo(out_queue):
  39.     process_flag = False
  40.     cv2.namedWindow(window_name)

  41.     #视频来源,可以来自一段已存好的视频,也可以直接来自USB摄像头
  42.     cap = cv2.VideoCapture(videoName)      
  43.     n = 1
  44.     while cap.isOpened():
  45.         ok, frame = cap.read() #读取一帧数据
  46.         if not ok:            
  47.             break                    

  48.         #显示图像并等待10毫秒按键输入,输入‘q’退出程序
  49.         cv2.namedWindow(window_name, cv2.WINDOW_NORMAL) #cv2.WND_PROP_FULLSCREEN)
  50.         #cv2.moveWindow(window_name, screen.x - 1, screen.y - 1)
  51.         cv2.setWindowProperty(window_name, cv2.WND_PROP_FULLSCREEN,
  52.                           cv2.WINDOW_FULLSCREEN)
  53.         n = n + 1
  54.         if n == 20:
  55.             if process_flag == True:
  56.                 out_queue.put(frame)
  57.             n = 1
  58.             
  59.         else:
  60.             frameresize = cv2.resize(frame,(1280,800))
  61.             cv2.imshow(window_name, frameresize)

  62.         c = cv2.waitKey(10)
  63.         if c & 0xFF == ord('q'):
  64.             break        
  65.         if c & 0xFF == ord('d'):
  66.             process_flag = True

  67.     #释放摄像头并销毁所有窗口
  68.     cap.release()
  69.     cv2.destroyAllWindows()


  70. def FaceDectection(in_queue):
  71.     index = 0
  72.     while 1:
  73.         img = in_queue.get()
  74.         gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  75.         # 使用detector进行人脸检测
  76.         dets = detector(gray_img, 1)

  77.         for i, d in enumerate(dets):
  78.             x1 = d.top() if d.top() > 0 else 0
  79.             y1 = d.bottom() if d.bottom() > 0 else 0
  80.             x2 = d.left() if d.left() > 0 else 0
  81.             y2 = d.right() if d.right() > 0 else 0

  82.             face = img[x1:y1,x2:y2]
  83.             # 调整图片的对比度与亮度, 对比度与亮度值都取随机数,这样能增加样本的多样性
  84.             #face = relight(face, random.uniform(0.5, 1.5), random.randint(-50, 50))

  85.             face = cv2.resize(face, (size,size))

  86.             #cv2.imshow('image', face)

  87.             cv2.imwrite(output_dir+'/'+str(index)+'.jpg', face)

  88.             index += 1

  89.         if index == 5:
  90.                 break


  91. #if __name__ == '__main__':
  92. #    CatchUsbVideo()
  93. processes = []

  94. p = Process(target=CatchUsbVideo, args=(results_queue,))
  95. p.start()
  96. processes.append(p)

  97. p = Process(target=FaceDectection, args=(results_queue,))
  98. p.start()
  99. processes.append(p)


  100. for p in processes:
  101.     p.join()

  102. while 1:
  103. time.sleep(1)


这样可以获取到视频中出现的人脸,接下来要根据大小做筛选,每一张image只选一个占据主要位置的人脸。

这一步完成后,在用mtcnn做一次筛选,淘汰掉不被认可的图片。



海中水 发表于 2019-1-15 21:26 | 显示全部楼层
非常棒!
 楼主| keer_zu 发表于 2019-1-16 10:35 | 显示全部楼层
本帖最后由 keer_zu 于 2019-1-16 10:38 编辑

可以获取占主要位置的人脸了:


  1. def FaceDectection(in_queue):
  2.     index = 0
  3.     while 1:
  4.         img = in_queue.get()
  5.         gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  6.         # 使用detector进行人脸检测
  7.         dets = detector(gray_img, 1)

  8.         for i, d in enumerate(dets):
  9.             print("----- i:%d\n" % i)
  10.             x1 = d.top() if d.top() > 0 else 0
  11.             y1 = d.bottom() if d.bottom() > 0 else 0
  12.             x2 = d.left() if d.left() > 0 else 0
  13.             y2 = d.right() if d.right() > 0 else 0

  14.             face = img[x1:y1,x2:y2]


  15.             if face.shape[0] > 400 :  # check picture size
  16.                 cv2.imwrite(output_dir+'/'+str(index)+'.jpg', face)

  17.             index += 1

  18.         if index == 5:
  19. break


这样无论在人脸的录入和识别过程中,这一步是必须的,后续再对数据做些处理。继续。。。。。

其中 i 表示在一个画面中得到几个人脸,因为对录入人脸尺寸的限制,录入画面检测到几张脸最终也只会保留不大于一张人脸。
在检测的设备里面,需要适当放宽对尺寸的要求,这就要对不同尺寸做对比了,只处理距离最近的那张,所以人脸的录入和探测还是有些微不同的。


评论

[url=home.php?mod=space&uid=1748102]@740071911[/url] :是个好主意  发表于 2019-1-18 09:18
[url=home.php?mod=space&uid=472461]@keer_zu[/url] :过程也可以在啊,例如第二天在1楼最后一行插入一个日期,然后接着贴上本楼代码。不然如果评论很多,你这个贴那不要贴到很后面的楼层吗  发表于 2019-1-18 08:50
[url=home.php?mod=space&uid=1748102]@740071911[/url] :主要是看过程啊  发表于 2019-1-17 08:50
大佬,一楼的帖子可以再次编辑的吧,可以把这楼的代码放在1楼  发表于 2019-1-17 08:46
740071911 发表于 2019-1-17 08:44 | 显示全部楼层
这是工控机传数据到后台服务器,服务器人脸识别吗,表示没学过python,真的是一个行业吗
 楼主| keer_zu 发表于 2019-1-17 08:51 | 显示全部楼层
740071911 发表于 2019-1-17 08:44
这是工控机传数据到后台服务器,服务器人脸识别吗,表示没学过python,真的是一个行业吗 ...

和硬件相关就是一个行业
muxb 发表于 2019-1-17 16:58 | 显示全部楼层
请问一堆bmp或者jpeg的数据,你怎么提取这堆数据里面的需要的数据?比如一张合照的数据,提取某一个人的数据。
 楼主| keer_zu 发表于 2019-1-17 17:15 | 显示全部楼层
本帖最后由 keer_zu 于 2019-1-17 17:28 编辑
muxb 发表于 2019-1-17 16:58
请问一堆bmp或者jpeg的数据,你怎么提取这堆数据里面的需要的数据?比如一张合照的数据,提取某一个人的数 ...

先检测人脸,就是把人脸部分全部提取出来,然后识别,识别有很多方式,上面提到的facenet采用的是计算欧氏距离来判断是否是同一个人。
 楼主| keer_zu 发表于 2019-1-24 10:01 | 显示全部楼层
  1. def ConvertUseTensorflowMtcnn(in_queue,msg_q):
  2.     margin = 32
  3.     index_num = 0
  4.     target_dir = os.path.join(img_dir,"images_data_%d" % target_img_size)
  5.     output_user_dir = os.path.join(target_dir, name)
  6.     if not os.path.exists(output_user_dir):
  7.         os.makedirs(output_user_dir)

  8.     minsize = 30 # minimum size of face
  9.     threshold = [ 0.6, 0.7, 0.7 ]  # three steps's threshold
  10.     factor = 0.709 # scale factor


  11.     with tf.Graph().as_default():
  12.         gpu_options = tf.GPUOptions(per_process_gpu_memory_fraction=0.25)
  13.         sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options, log_device_placement=False))
  14.         with sess.as_default():
  15.             pnet, rnet, onet = detect_face.create_mtcnn(sess, None)
  16.     while 1:
  17.         file_name = in_queue.get()
  18.         print("====== file: %s" % file_name)
  19.         img = cv2.imread(file_name)
  20.         
  21.         bounding_boxes, _ = detect_face.detect_face(img, minsize, pnet, rnet, onet, threshold, factor)
  22.         print(bounding_boxes)
  23.         nrof_faces = bounding_boxes.shape[0]
  24.         print(nrof_faces)
  25.         if nrof_faces>0:
  26.             det = bounding_boxes[:,0:4]
  27.             det_arr = []
  28.             img_size = np.asarray(img.shape)[0:2]
  29.             print("====nrof_face: %d  img size:"  % nrof_faces)
  30.             print(img_size)
  31.             if nrof_faces == 1:
  32.                 bounding_box_size = (det[:,2]-det[:,0])*(det[:,3]-det[:,1])
  33.                 img_center = img_size / 2
  34.                 offsets = np.vstack([ (det[:,0]+det[:,2])/2-img_center[1], (det[:,1]+det[:,3])/2-img_center[0] ])
  35.                 offset_dist_squared = np.sum(np.power(offsets,2.0),0)
  36.                 index = np.argmax(bounding_box_size-offset_dist_squared*2.0) # some extra weight on the centering
  37.                 det_arr.append(det[index,:])
  38.             for i, det in enumerate(det_arr):
  39.                 det = np.squeeze(det)
  40.                 bb = np.zeros(4, dtype=np.int32)
  41.                 bb[0] = np.maximum(det[0]-margin/2, 0)
  42.                 bb[1] = np.maximum(det[1]-margin/2, 0)
  43.                 bb[2] = np.minimum(det[2]+margin/2, img_size[1])
  44.                 bb[3] = np.minimum(det[3]+margin/2, img_size[0])
  45.                 cropped = img[bb[1]:bb[3],bb[0]:bb[2],:]
  46.                 scaled = misc.imresize(cropped, (target_img_size, target_img_size), interp='bilinear')

  47.                 output_filename = os.path.join(output_user_dir, ("%d" % index_num) +'.png')

  48.                 filename_base, file_extension = os.path.splitext(output_filename)

  49.                 output_filename_n = "{}{}".format(filename_base, file_extension)

  50.                 misc.imsave(output_filename_n, scaled)

  51.                 index_num += 1
  52.         #if os.path.exists(file_name):
  53.             #os.remove(file_name)
  54.         if index_num >= 5:
  55.             msg_q.put("complate_msg")
  56.             msg_q.put("complate_msg")
  57.             break
renxiaolin 发表于 2019-1-28 16:57 | 显示全部楼层
给力呀
yaneda 发表于 2019-2-16 10:36 | 显示全部楼层
谢谢分享,很不错的内容
 楼主| keer_zu 发表于 2020-3-25 18:01 | 显示全部楼层
好久没有碰tensorflow了,好久没有碰python了@yyy71cj
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:qq群:49734243 Email:zukeqiang@gmail.com

1478

主题

12912

帖子

55

粉丝
快速回复 在线客服 返回列表 返回顶部
个人签名:qq群:49734243 Email:zukeqiang@gmail.com

1478

主题

12912

帖子

55

粉丝
快速回复 在线客服 返回列表 返回顶部