Jetson nano实战系列:基于Opencv实现人脸检测(HAARcascades分类器与Caffe模型的使用)

0、序

  OpenCV是什么?引用度娘的介绍就是“其是一个基于BSD许可(开源)发行的跨平台计算机视觉和机器学习软件库,可以运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。”可以说是一个功能强大的用于图像视频等相关处理的一个库。
  查看是否已安装好opencv,check原系统已经安装好opencv,只要是import cv2没问题,那就是安装OK的。
在这里插入图片描述

相关版本details version
CUDA 10.2.89
cuDNN 8.0.0.180
OpenCV 4.4.0
Python 3.6.9
TensorFlow 2.3.1
Jetpack Jetpack 4.4.1
Platform Jetson nano

1、Gsteamer获取camera数据流

  在Jetson 中调用CSI摄像头,需要使用Gsteamer获取数据流,需要先进行gstreamer_pipeline的配置。

def gstreamer_pipeline(
         capture_width=640,
         capture_height=480,
         display_width=640,
         display_height=480,
         framerate=60,
         flip_method=0,
):
return (
         "nvarguscamerasrc ! "
         "video/x-raw(memory:NVMM), "
         "width=(int)%d, height=(int)%d, "
         "format=(string)NV12, framerate=(fraction)%d/1 ! "
         "nvvidconv flip-method=%d ! "
         "video/x-raw, width=(int)%d, height=(int)%d, format=(string)BGRx ! "
         "videoconvert ! "
         "video/x-raw, format=(string)BGR ! appsink"
        % (
                capture_width,
                capture_height,
                framerate,
                flip_method,
                display_width,
                display_height,
        )
)

2、人脸检测的实现

2.1、基于haar cascades分类器实现

  参考opencv官方中face detect的介绍,关于使用基于Haar特征的级联分类器进行对象检测是Paul Viola和Michael Jones在其论文“使用简单特征的增强级联进行快速对象检测”中于2001年提出的一种有效的对象检测方法。
在这里插入图片描述
  在opencv中常用的人脸检测的分类器有:haarcascade_frontalface_default.xml、haarcascade_frontalface_alt2.xml、lbpcascade_frontalface.xml、haarcascade_frontalface_alt_tree.xml等。
在这里插入图片描述
How to use Haar-cascade Detection in OpenCV?
  在opencv中配备了相关的检测器和训练器,可以为你需要检测的对象进行训练,获得自己的适用于特定对象的检测器。使用opencv进行人脸检测,在opencv中已经提供了许多特定对象的分类器,例如说针对人脸的、眼睛等经过预训练的分类器。这些XML分类器文件存储在“你的安装路径/opencv / data / haarcascades /文件夹中。”
  该demo使用的分类器是haarcascade_frontalface_alt2。
在这里插入图片描述

def CatchUsbVideo(window_name, camera_idx):
    cv2.namedWindow(window_name)
 
    #视频来源,可以来自一段已存好的视频,也可以直接来自USB摄像头
    cap = cv2.VideoCapture(gstreamer_pipeline(flip_method=camera_idx), cv2.CAP_GSTREAMER)
 
    #告诉OpenCV使用人脸识别分类器
    classfier = cv2.CascadeClassifier("/usr/share/opencv4/haarcascades/haarcascade_frontalface_alt2.xml")
 
    #识别出人脸后要画的边框的颜色,RGB格式
    color = (0, 255, 0)
 
    while cap.isOpened():
        ok, frame = cap.read() #读取一帧数据
        if not ok:
            break
 
        #将当前帧转换成灰度图像
        grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        cv2.imshow("grey pic", grey)

        #人脸检测,1.2和2分别为图片缩放比例和需要检测的有效点数
        faceRects = classfier.detectMultiScale(grey, scaleFactor = 1.2, minNeighbors = 3, minSize = (32, 32))
        if len(faceRects) > 0:               #大于0则检测到人脸
            pic_time = time.strftime('%Y.%m.%d_%H:%M:%S ',time.localtime(time.time()))
            pic_name = "./works/pic_data/" + pic_time + ".png"
            print(pic_name)
            cv2.imwrite(pic_name, frame)		#保存图片
            
            for faceRect in faceRects:       #单独框出每一张人脸
                x, y, w, h = faceRect
                cv2.rectangle(frame, (x, y), (x+w, y+h), color, 2)

        #显示图像
        cv2.imshow(window_name, frame)
        c = cv2.waitKey(10)
        if c & 0xFF == ord('q'):
            break
 
    #释放摄像头并销毁所有窗口
    cap.release()
    cv2.destroyAllWindows()
 
if __name__ == '__main__':
    CatchUsbVideo("Find face", 0)

  效果就引用OpenCV官网的介绍:

Now we find the faces in the image. If faces are found, it returns the positions of detected faces as Rect(x,y,w,h). Once we get these locations, we can create a ROI for the face and apply eye detection on this ROI (since eyes are always on the face !!! ).

2.2、基于预训练的caffe模型

  该模型是基于SSD和ResNet网络来训练的,实现参考@cv小白_jackko
该博主的《opencv_deeplearning实战1:基于深度学习的opencv人脸检测》,模型和相关权重参数的传送门如下:
模型结构文件:https://github.com/opencv/opencv/tree/master/samples/dnn/face_detector
参数文件:https://github.com/JackKoLing/opencv_deeplearning_practice/blob/master/practice1_face_detection/res10_300x300_ssd_iter_140000.caffemodel
在这里插入图片描述

import numpy as np
import cv2
import os
import time
import pickle

# 定义相关的路径参数
modelPath = "deploy.prototxt.txt"
weightPath = "res10_300x300_ssd_iter_140000.caffemodel"
confidence = 0.5 # 置信度参数,高于此数才认为是人脸,可调

font=cv2.FONT_HERSHEY_SIMPLEX

def resize_auto(height, width):

	image_exchange = cv2.imread("/home/colin/works/face_detect/mark.png")
	
	height_e, width_e = image_exchange.shape[:2]
	h = height/height_e
	if h <= 0:
		h = 1
	
	w = width/width_e
	if w <= 0:
		w = 1

	img_rs = cv2.resize(image_exchange, (int(width_e * h/2), int(width_e * h/2)), interpolation = cv2.INTER_CUBIC)

	return img_rs

	
def image_save(img):
	pic_time = time.strftime('%Y.%m.%d_%H:%M:%S ',time.localtime(time.time()))
	pic_name = "/home/colin/works/pic_data/" + pic_time + ".jpg"
	print(pic_name)
	cv2.imwrite(pic_name, img)

catch_count = 0
def catch_face(startX, endX, startY, endY, image):
	global catch_count
	face_pic = image[startY -50: endY + 50, startX-50 : endX + 50]
	
	if face_pic.size > 0 and catch_count < 50:
		catch_count +=1
		pic_name = "/home/colin/works/pic_data/" + "colin_" + str(catch_count) + ".jpg"
		cv2.imwrite(pic_name, face_pic)
		print("face catch %d\n"%(catch_count))

def face_detector(image, save_switch, catch_switch):
	
	net = cv2.dnn.readNetFromCaffe(modelPath, weightPath)
	net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA)  #使用cuDNN加速
	net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA)	#使用cuDNN加速
	
	# 输入图片并重置大小符合模型的输入要求
	(h, w) = image.shape[:2]  #获取图像的高和宽,用于画图
	blob = cv2.dnn.blobFromImage(cv2.resize(image, (300, 300)), 1.0,
		(300, 300), (104.0, 177.0, 123.0))  
	#blobFromImage
	net.setInput(blob)
	detections = net.forward() # 预测结果

	# 可视化:在原图加上标签和框
	for i in range(0, detections.shape[2]):
		# 获得置信度
		res_confidence = detections[0, 0, i, 2]
		# 过滤掉低置信度的像素
		if res_confidence > confidence :
			#save img
			if save_switch == 1:
				image_save(image)
			
			# 获得框的位置
			box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
			(startX, startY, endX, endY) = box.astype("int")
                        
			#add by colin.tan
			if catch_switch == 1:
				catch_face(startX, endX, startY, endY, image)
				
			# 在图片上写上标签
			text = "{:.2f}%".format(res_confidence * 100)
			# 如果检测脸部在左上角,则把标签放在图片内,否则放在图片上面
			y = startY - 10 if startY - 10 > 10 else startY + 10 
			cv2.rectangle(image, (startX, startY), (endX, endY),(0, 255, 0), 2)
			cv2.putText(image, text, (startX, y),cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 2)
				
	resImage = image
	return resImage 

  在原实现的基础上增加了调用cuda进行图像处理加速,减少了程序对于CPU的占用,一定程度上提升了程序性能。

参考附录

1)opencv_deeplearning实战1:基于深度学习的opencv人脸检测
2)算法优化二——如何提高人脸检测正确率

猜你喜欢

转载自blog.csdn.net/qq_33475105/article/details/111994173
今日推荐