文章目录
-
实验目的
-
算法原理概述
-
实验内容
-
结果分析
-
存在不足
-
总代码
-
总结
实验目的
图像处理(image processing),用计算机对图像进行分析,以达到所需结果的技术。图像处理将会是物联网产业发展的重要支柱之一。
本实验旨在让学生加深本课程中图像预处理、人脸检测、后处理等重要的知识点的理解和实践,并实现针对视频中的人脸检测和追逐算法,最终生成标注后的视频/流媒体。
算法原理概述
利用OPENCV中训练好的人脸检测模型haarcascade_frontalface_alt2.xml进行人脸检测,将其获得的第一个人脸方框作为目标跟踪的ROI区域;
将ROI区域转化到HSV空间中,并计算出ROI区域中的直方图;
对视频逐帧进行以下处理:
(1)对图片进行高斯滤波降噪;
(2)将图片转化到HSV空间中;
(3)利用ROI区域的直方图对图片进行反向投影;
(4)利用OPENCV均值迁移meanShift() 计算出目标区域,并在图片中进行标定;
(5)利用OPENCV中训练好的人脸检测模型haarcascade_frontalface_alt2.xml进行人脸检测,并在图中进行标定出人脸方框;
实验内容
一、问题描述
从摄像头中获得视频流,检测出视频中出现的人脸,对其进行追踪,生成追踪轨迹并进行标注输出;
二、算法步骤
目标跟踪ROI区域获取:利用OPENCV中自带的人脸检测器,获得第一个检测出的人脸区域,作为目标ROI区域;
1.while flag:
2. ref, frame = capture.read()
3. gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
4. faceRects = classifier.detectMultiScale(gray)
5. # 读取到的人脸
6. if len(faceRects) > 0:
7. flag = False
8. for faceRect in faceRects:
9. x_roi, y_roi, w_roi, h_roi = faceRect
10. break
高斯滤波:为了减小噪声对于目标追踪与人脸检测影响,在进行追踪与检测前先进行高斯滤波处理,削弱噪声影响;
1. frame = cv.GaussianBlur(frame, (5, 5), 0)
将ROI区域转化到HSV色彩空间中:为了计算出ROI区域的直方图与直方图的反射投影,先得将ROI区域的色彩空间由RGB向HSV进行转化;
1.hsv_roi = cv.cvtColor(roi, cv.COLOR_BGR2HSV)
计算出ROI区域内直方图:获取ROI图像中HSV通道的高低值,通过inRange() 提取出来ROI区域内容作为掩模 mask,利用该掩模计算出ROI的直方图;
1.low = 15
2.high = 255
3.mask = cv.inRange(hsv_roi, (low, low, low), (high, high, high))
4.cv.imshow('b', mask)
5.#cv.waitKey(1000)
6.roi_hist = cv.calcHist([hsv_roi], [0], mask, [180], [0, 180])
7.cv.normalize(roi_hist, roi_hist, 0, 255, cv.NORM_MINMAX)
8.term_crit = (cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1)
利用ROI区域直方图进行反向投影:将图片转化到HSV色彩空间中,利用ROI区域的直方图,对图片进行反向投影;
1.hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
2.# 直方图反向投影
3.dst = cv.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)
均值迁移更新目标区域:利用OPENCV中自带的均值迁移meanShift(),进行目标区域更新;
1.ret, track_window = cv.meanShift(dst, track_window, term_crit)
2.# 绘制窗口
3.x, y, w, h = track_window
4.cv.rectangle(frame, (x, y), (x + w , y + h+100), 255, 2)
人脸检测:利用OPENCV中自带的人脸检测器,将图片中所有人脸检测出来,并在图片中进行标定;
1.faceRects = classifier.detectMultiScale(hsv)
2.f len(faceRects) > 0:
3. for faceRect in faceRects:
4. x, y, w, h = faceRect
5. if w > 100:
6. #标定出人脸方框
7. cv.rectangle(frame, (x, y), (x + w, y + h), color, 2)
结果分析
目标跟踪ROI区域获取:获得第一个检测出来的人脸区域;


得到ROI区域掩模并计算出掩模内的直方图:设定阈值low、high,对ROI区域内进行二值化处理,在low与high之间的像素设置为255,不在之间的设为0;并计算出掩模内的直方图;


利用均值移动进行目标跟踪:将图片转移到HSV空间中,利用ROI区域内直方图,对图片进行反向投影,并利用OPENCV中自带的meanShift()进行目标区域更新;

人脸检测:利用OPENCV中自带人脸检测器进行图片人脸检测;
存在不足
当存在一些干扰时,如戴上口罩,或者存在一些非人物体时,会导致人脸检测失效,这是由于OPENCV自带的人脸检测精度不高,因此我们可以训练一个精度更高的人脸检测模型;

均值迁移对于目标跟踪也存在着一些问题:一旦目标脱离出目标框,只有当目标重新出现在框内目标框才会重新跟踪,运动过快的目标也会导致目标框脱离;



目标检测的关键在于: ROI区域内对于目标物体特征提取的效果;在本实验体现为掩模的制定,这个二值化处理的双阈值的设定,容易受到环境亮度的影响,因此可以寻找一种更好的特征提取的办法进行改进;
总代码
import cv2 as cv
CADES_PATH = 'D:/computer_view_exercise1/venv\Lib/site-packages/cv2/data/haarcascade_frontalface_alt2.xml'
'''
face_test:将摄像头人脸检测,并进行标注
'''
def face_test():
color = (0, 255, 0)
capture = cv.VideoCapture(0, cv.CAP_DSHOW)
classifier = cv.CascadeClassifier(CADES_PATH)
flag = True
#存检测点的列表,大小为M
points = []
M = 15
# 读取ROI区域的坐标
while flag:
ref, frame = capture.read()
gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
faceRects = classifier.detectMultiScale(gray)
# 读取到的人脸
if len(faceRects) > 0:
flag = False
for faceRect in faceRects:
x_roi, y_roi, w_roi, h_roi = faceRect
break
roi = frame[y_roi:y_roi+h_roi, x_roi:x_roi+w_roi]
#cv.imshow('a', roi)
#cv.waitKey(1000)
hsv_roi = cv.cvtColor(roi, cv.COLOR_BGR2HSV)
cv.imshow('m', hsv_roi)
track_window = (x_roi, y_roi, w_roi, h_roi)
#设置阈值
low = 16
high = 95
mask = cv.inRange(hsv_roi, (low, low, low), (high, high, high))
cv.imshow('b', mask)
#cv.waitKey(1000)
roi_hist = cv.calcHist([hsv_roi], [0], mask, [180], [0, 180])
cv.normalize(roi_hist, roi_hist, 0, 255, cv.NORM_MINMAX)
term_crit = (cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, 10, 1)
# 目标跟踪
while True:
ret, frame = capture.read()
#frame = cv.GaussianBlur(frame, (5, 5), 0)
if ret is False:
break;
hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
cv.imshow('hsv', hsv)
# 直方图反向投影
dst = cv.calcBackProject([hsv], [0], roi_hist, [0, 180], 1)
# 均值迁移,搜索更新roi区域
ret, track_window = cv.meanShift(dst, track_window, term_crit)
# 绘制窗口
x, y, w, h = track_window
cv.rectangle(frame, (x, y), (x + w , y + h+100), 255, 2)
x_center = int(x+w/2)
y_center = int(y+h/2+50)
if len(points) < M:
points.append((x_center, y_center))
else:
for i in range(M-1):
points[i] = points[i+1]
points[-1] = (x_center, y_center)
radius = 10
points_color = (0, 0, 255)
#绘制点轨迹
if len(points) == M:
for point in points:
cv.circle(frame, point, radius, points_color, -4)
#检测人脸
faceRects = classifier.detectMultiScale(hsv)
if len(faceRects) > 0:
for faceRect in faceRects:
x, y, w, h = faceRect
if w > 100:
#标定出人脸方框
cv.rectangle(frame, (x, y), (x + w, y + h), color, 2)
cv.imshow('picture', cv.flip(frame, 1))
cv.waitKey(60)
cv.destroyAllWindows()
if __name__ == '__main__':
face_test()
总结
无

2万+

被折叠的 条评论
为什么被折叠?



