python 人脸检测、单目测距以及人脸打码
最近想写博客但是下班后完全提不起兴趣,今天周末刚好闲下心来,想了想把在github发现的一个人脸检测项目调试了下,发现挺不错的,准确率跟速度都挺适合低配版设备使用,所以过几天想自己训练一下检测车牌,试试效果,如果可以的话再进一步考虑下怎么使用。
项目地址:给作者点个star
整个项目已经预训练好了多款模型,我就尝试了下onnx与咖啡的,除了侧脸有时不行,小目标检测还不错,这么小的模型能做到这样确实是个牛人。
废话就不多说了,调用源码项目里也有,我就直接用opencv版的,然后自己尝试了加两个小应用代码,就不造轮子,直接网上拿了,省得装其他库了,一个是单目测距,一个是人脸马赛克处理。代码如下。
测试代码
# %%writefile Face_Distance_Mosaic.py
# coding=utf-8
import argparse
import os
import time
from math import ceilimport cv2
import numpy as np
from cv2 import dnnimage_mean = np.array([127, 127, 127])
image_std = 128.0
iou_threshold = 0.3
center_variance = 0.1
size_variance = 0.2
min_boxes = [[10.0, 16.0, 24.0], [32.0, 48.0], [64.0, 96.0], [128.0, 192.0, 256.0]]
strides = [8.0, 16.0, 32.0, 64.0]# 距离计算函数
def distance_to_camera(knownWidth, focalLength, perWidth): """knownWidth:知道的目标宽度 厘米focalLength:摄像头焦距perWidth:检测框宽度 像素#读入第一张图,通过已知距离计算相机焦距image = cv2.imread(IMAGE_PATHS[0]) marker = find_marker(image) focalLength = (marker[1][0] * KNOWN_DISTANCE) / KNOWN_WIDTH """return (knownWidth * focalLength) / perWidth ##马赛克
def do_mosaic(frame, x, y, w, h, neighbor=9):"""马赛克的实现原理是把图像上某个像素点一定范围邻域内的所有点用邻域内左上像素点的颜色代替,这样可以模糊细节,但是可以保留大体的轮廓。:param frame: opencv frame:param int x : 马赛克左顶点:param int y: 马赛克右顶点:param int w: 马赛克宽:param int h: 马赛克高:param int neighbor: 马赛克每一块的宽"""fh, fw = frame.shape[0], frame.shape[1]if (y + h > fh) or (x + w > fw):returnfor i in range(0, h - neighbor, neighbor): # 关键点0 减去neightbour 防止溢出for j in range(0, w - neighbor, neighbor):rect = [j + x, i + y, neighbor, neighbor]color = frame[i + y][j + x].tolist() # 关键点1 tolistleft_up = (rect[0], rect[1])right_down = (rect[0] + neighbor - 1, rect[1] + neighbor - 1) # 关键点2 减去一个像素cv2.rectangle(frame, left_up, right_down, color, -1)def define_img_size(image_size):shrinkage_list = []feature_map_w_h_list = []for size in image_size:feature_map = [int(ceil(size / stride)) for stride in strides]feature_map_w_h_list.append(feature_map)for i in range(0, len(image_size)):shrinkage_list.append(strides)priors = generate_priors(feature_map_w_h_list, shrinkage_list, image_size, min_boxes)return priorsdef generate_priors(feature_map_list, shrinkage_list, image_size, min_boxes):priors = []for index in range(0, len(feature_map_list[0])):scale_w = image_size[0] / shrinkage_list[0][index]scale_h = image_size[1] / shrinkage_list[1][index]for j in range(0, feature_map_list[1][index]):for i in range(0, feature_map_list[0][index]):x_center = (i + 0.5) / scale_wy_center = (j + 0.5) / scale_hfor min_box in min_boxes[index]:w = min_box / image_size[0]h = min_box / image_size[1]priors.append([x_center,y_center,w,h])print("priors nums:{}".format(len(priors)))return np.clip(priors, 0.0, 1.0)def hard_nms(box_scores, iou_threshold, top_k=-1, candidate_size=200):scores = box_scores[:, -1]boxes = box_scores[:, :-1]picked = []indexes = np.argsort(scores)indexes = indexes[-candidate_size:]while len(indexes) > 0:current = indexes[-1]picked.append(current)if 0 < top_k == len(picked) or len(indexes) == 1:breakcurrent_box = boxes[current, :]indexes = indexes[:-1]rest_boxes = boxes[indexes, :]iou = iou_of(rest_boxes,np.expand_dims(current_box, axis=0),)indexes = indexes[iou <= iou_threshold]return box_scores[picked, :]def area_of(left_top, right_bottom):hw = np.clip(right_bottom - left_top, 0.0, None)return hw[..., 0] * hw[..., 1]def iou_of(boxes0, boxes1, eps=1e-5):overlap_left_top = np.maximum(boxes0[..., :2], boxes1[..., :2])overlap_right_bottom = np.minimum(boxes0[..., 2:], boxes1[..., 2:])overlap_area = area_of(overlap_left_top, overlap_right_bottom)area0 = area_of(boxes0[..., :2], boxes0[..., 2:])area1 = area_of(boxes1[..., :2], boxes1[..., 2:])return overlap_area / (area0 + area1 - overlap_area + eps)def predict(width, height, confidences, boxes, prob_threshold, iou_threshold=0.3, top_k=-1):boxes = boxes[0]confidences = confidences[0]picked_box_probs = []picked_labels = []for class_index in range(1, confidences.shape[1]):probs = confidences[:, class_index]mask = probs > prob_thresholdprobs = probs[mask]if probs.shape[0] == 0:continuesubset_boxes = boxes[mask, :]box_probs = np.concatenate([subset_boxes, probs.reshape(-1, 1)], axis=1)box_probs = hard_nms(box_probs,iou_threshold=iou_threshold,top_k=top_k,)picked_box_probs.append(box_probs)picked_labels.extend([class_index] * box_probs.shape[0])if not picked_box_probs:return np.array([]), np.array([]), np.array([])picked_box_probs = np.concatenate(picked_box_probs)picked_box_probs[:, 0] *= widthpicked_box_probs[:, 1] *= heightpicked_box_probs[:, 2] *= widthpicked_box_probs[:, 3] *= heightreturn picked_box_probs[:, :4].astype(np.int32), np.array(picked_labels), picked_box_probs[:, 4]def convert_locations_to_boxes(locations, priors, center_variance,size_variance):if len(priors.shape) + 1 == len(locations.shape):priors = np.expand_dims(priors, 0)return np.concatenate([locations[..., :2] * center_variance * priors[..., 2:] + priors[..., :2],np.exp(locations[..., 2:] * size_variance) * priors[..., 2:]], axis=len(locations.shape) - 1)def center_form_to_corner_form(locations):return np.concatenate([locations[..., :2] - locations[..., 2:] / 2,locations[..., :2] + locations[..., 2:] / 2], len(locations.shape) - 1)def inference():onnx_path="model/version-RFB-320_simplified.onnx"caffe_prototxt_path="model/RFB-320.prototxt"caffe_model_path="model/RFB-320.caffemodel"threshold=0.7input_size=[320,240]
# net = dnn.readNetFromONNX(onnx_path) # onnx versionnet = dnn.readNetFromCaffe(caffe_prototxt_path, caffe_model_path) # caffe model converted from onnxwitdh = input_size[0]height = input_size[1]priors = define_img_size(input_size)cap = cv2.VideoCapture(0) while(cap.isOpened()):ret, frame = cap.read()if ret==True:img_ori = framerect = cv2.resize(img_ori, (witdh, height))rect = cv2.cvtColor(rect, cv2.COLOR_BGR2RGB)net.setInput(dnn.blobFromImage(rect, 1 / image_std, (witdh, height), 127))time_time = time.time()boxes, scores = net.forward(["boxes", "scores"])
# print("inference time: {} s".format(round(time.time() - time_time, 4)))boxes = np.expand_dims(np.reshape(boxes, (-1, 4)), axis=0)scores = np.expand_dims(np.reshape(scores, (-1, 2)), axis=0)boxes = convert_locations_to_boxes(boxes, priors, center_variance, size_variance)boxes = center_form_to_corner_form(boxes)boxes, labels, probs = predict(img_ori.shape[1], img_ori.shape[0], scores, boxes, threshold)for i in range(boxes.shape[0]):box = boxes[i, :]cv2.rectangle(img_ori, (box[0], box[1]), (box[2], box[3]), (0, 255, 0), 2)cv2.circle(img_ori, (box[0], box[1]), 1, (0,0,255), 4)cv2.circle(img_ori, (box[2], box[3]), 1, (0,0,255), 4)ya_max = box[1] yb_max = box[3]pix_person_height = yb_max - ya_max
# focalLength = ((box[3]-box[1]) * 60) / 15
# print(focalLength)distance = distance_to_camera(15,580, pix_person_height)if distance/100>1.0:cv2.putText(img_ori, "%.2fm" % (distance/100),(box[0], box[1] - 10), cv2.FONT_HERSHEY_SIMPLEX,1, (255,0 , 255), 2)else:cv2.putText(img_ori, "%.2fcm" % (distance),(box[0], box[1] - 10), cv2.FONT_HERSHEY_SIMPLEX,1, (255,0 , 255), 2)
# 人脸马赛克do_mosaic(img_ori, box[0]+5, box[1]+5, box[2]-box[0]-5, box[3]-box[1]-5, neighbor=9)cv2.imshow("Face_Distance_Mosaic", img_ori)if cv2.waitKey(10) & 0xFF == ord('q'):breakelse:breakcap.release()cv2.destroyAllWindows()if __name__ == '__main__':inference()
距离检测
# 距离计算函数
def distance_to_camera(knownWidth, focalLength, perWidth): """knownWidth:知道的目标宽度 厘米focalLength:摄像头焦距perWidth:检测框宽度 像素#读入第一张图,通过已知距离计算相机焦距image = cv2.imread(IMAGE_PATHS[0]) marker = find_marker(image) focalLength = (marker[1][0] * KNOWN_DISTANCE) / KNOWN_WIDTH """return (knownWidth * focalLength) / perWidth
马赛克处理
##马赛克
def do_mosaic(frame, x, y, w, h, neighbor=9):"""马赛克的实现原理是把图像上某个像素点一定范围邻域内的所有点用邻域内左上像素点的颜色代替,这样可以模糊细节,但是可以保留大体的轮廓。:param frame: opencv frame:param int x : 马赛克左顶点:param int y: 马赛克右顶点:param int w: 马赛克宽:param int h: 马赛克高:param int neighbor: 马赛克每一块的宽"""fh, fw = frame.shape[0], frame.shape[1]if (y + h > fh) or (x + w > fw):returnfor i in range(0, h - neighbor, neighbor): # 关键点0 减去neightbour 防止溢出for j in range(0, w - neighbor, neighbor):rect = [j + x, i + y, neighbor, neighbor]color = frame[i + y][j + x].tolist() # 关键点1 tolistleft_up = (rect[0], rect[1])right_down = (rect[0] + neighbor - 1, rect[1] + neighbor - 1) # 关键点2 减去一个像素cv2.rectangle(frame, left_up, right_down, color, -1)
演示
人脸检测
距离
本来是录了个远距离的,但是个人脸没有打码(没脸见人_),就没上传了,两个模块同一张演示图吧。
马赛克
总体来说效果还算不错的,单目测距的效果需要外部参数,要不然效果不好,如果参数设好了,近距离误差还行,远距离误差也不错,人脸打码在这个信息爆炸重要的年代还是很有必要的,相比较与人工手动打码省时又省力,而且还能进一步将打码框替换成其他图片,实现自动添加水印。
项目链接
python 人脸检测、单目测距以及人脸打码相关推荐
- python测量镜头到目标距离_摄像头单目测距原理及实现
摄像头单目测距原理及实现 一.测距原理 空间的深度或距离等数据的摄像头. 人的眼睛长在头部的前方,两只眼的视野范围重叠,两眼同时看某一物体时,产生的视觉称为双眼视觉. 双眼视觉的优点是可以弥补单眼视野 ...
- python opencv单目测距 小孔成像原理
python opencv单目测距 小孔成像原理 小孔成像原理 代码 opencv>3.x 小孔成像原理 一 用相似三角形计算物体或者目标到相机的距离 我们将使用相似三角形来计算相机到一个已知的 ...
- python手机摄像头投测距_python opencv单目测距 小孔成像原理
python opencv单目测距 小孔成像原理 小孔成像原理 一 用相似三角形计算物体或者目标到相机的距离 我们将使用相似三角形来计算相机到一个已知的物体或者目标的距离. 相似三角形就是这么一回事: ...
- 目标检测+目标追踪+单目测距(毕设+代码)
更多视觉额自动驾驶项目请见: 小白学视觉 自动驾驶项目 项目成果图 现推出专栏项目:从图像处理(去雾/去雨)/目标检测/目标跟踪/单目测距/到人体姿态识别等视觉感知项目---------------- ...
- 【自动驾驶】摄像头单目测距原理及实现
原文链接:摄像头单目测距原理及实现 可以观看这个视频,了解针孔相机和透镜. 摄像头单目测距原理及实现 一.测距原理 空间的深度或距离等数据的摄像头. 人的眼睛长在头部的前方,两只眼的视野范围重叠,两眼 ...
- 相机模型、相机标定及基于yolov5的单目测距实现
相机模型.相机标定及基于yolov5的单目测距实现 1 前言 2 相机模型及单目测距原理 3 相机参数标定 3.1 内参矩阵 3.2 内参标定 3.3 外参矩阵 4 基于yolov5的单目测距实现 1 ...
- 单目测距原理与实现(代码可运行)
Opencv3实现单目视觉测距 一.前言 单目视觉测距:网上有很多关于单目测距的文章,主要借鉴的是OpenCV学习笔记(二十一)--简单的单目视觉测距尝试和单目摄像机测距(python+opencv) ...
- yolo 车辆测距+车辆识别+单目测距(双目测距)
基于yolo目标检测算法实现的车前道路中的车辆和行人检测,并且可以估测出目标与本车之间的距离 一.视频展示 yolo车距1 订阅专栏获得源码(提供完整代码,无需看下文) 二.单目测距原理 图中有一个车 ...
- 人脸检测概述(不是人脸识别)
目录 1 引言... 3 2 人脸检测技术的发展与现状... 4 3 人脸检测算法相关工作... 4 3.1 评价指标... 5 3.2 人脸检测常用数据库... 6 3.2.1 FDDB ...
最新文章
- 电脑服务器怎么打开网页,电脑的iis服务器打开网页的方法
- nginx+tomcat+redis实现会话共享
- Android studio 关于SQlite数据库导出,创建数据库、表以及如何查看操作
- JavaScript高级之函数进阶
- 淘宝发布年度十大同款:钟南山哑铃、奥特曼变身器、嫦娥五号暖宝宝入选
- MySql 学习笔记-Mysql架构介绍与查询sql执行流程
- 老年代的更新机制_如何理解Java GC机制
- 2017.5.12PM
- java经典sql笔试题
- matlab 第二版 赵元哲 下载,基于MATLAB的黑盒电路仿真设计及应用
- 并行强化学习算法:A2C/A3C
- c语言中dot作用,Unix中的dot命令详解
- 2018年的总结和2019年的期望
- 北大数学英才班,没有一名新生经历高三
- 为什么令牌不是基于“所知”
- Android中HorizontalScrollView的使用总结
- 怪物猎人ns联机显示与服务器连接发生错误,怪物猎人世界网络连不上怎么办?联机失败问题解决方法...
- 重磅综述:精准精神病学机器学习的现代观点
- 记录repast4py的前两个example——rndWalker和Rumer Agent
- 【计网【题目】一个大公司有一个总部和三个下属部门。公司分配到的网络前缀是192.77.33/24.
热门文章
- Kubernetes Autoscaling是如何工作的?
- 好用的GIF捕捉器——LICEcap
- 文件上传功能测试、性能测试解决方案(含Jmeter配置及加压参数分析)
- Maven工程聚合错误Could not find artifact cn.itcast.parent:itcast-parent:pom:0.0.1-SNAPSHOT and 'parent.rel
- matlab中的round、ceil、floor、fix函数
- Python 爬取朋友圈最新方法
- android app 版本下载,linguee app下载-linguee安卓 安卓版v1.3.0-PC6安卓网
- 想偷窥我 Windows 的隐私?呵呵了~ WPD 这款小工具能把漏洞全封死!
- 眼部识别取代指纹识别还有多远?
- 50 行 Python 代码绘制数据大屏,这个可视化框架真的太神了