视频流识别与抓拍图片进行识别存在区别,通过视频流识别可实现对摄像头采集到的所有图片进行快速分析,按照设定存储规则存储所需的图片。随着视频摄像头的高清化以及应用场景的海量增长,对监控系统视频信号的存储带来巨大的挑战,存储空间永远都是不够用的,同时对视频信号的利用也带来很大困难,导致大量视频信号存而不用。
随着深度学习等人工智能技术快速发展,通过视频流实时分析视频信号,实时选择需要存在的有效视频信号得到快速发展,避免了大量低价值视频信号的存储问题,同时有利于视频信号的高效利用。特别是,在人脸识别领域已经得到规模化应用,能够通过各种铺设的摄像头识别人群中的多人身份,实现快速定位特定人员、信息匹配的目的。例如公安在处理刑侦案件时最大的痛点,是遇到警情或案件时,需要对20多小时的视频资料逐帧排查。不仅效率低下,还容易错过关键信息。因此公安希望能够通过AI的加持,在特定时间特定区域下对可疑人群做快速识别。公安只需要输入嫌疑人照片,设定时间、地点便能够实现快速识别与定位。目前,实现高效、智能化、自动化的人脸识别、数据处理和分析,已成为大势所趋。
- 对于不具备机器视觉能力的摄像头可以通过人工智能SDK与云端后台管理系统进行连接,获取算法支持,实现对于视频流实时处理。
- 对于具备机器视觉能力的摄像头通过内置视频流智能算法程序实现特定目标的识别,依赖本地硬件资源实现有限目标的识别。
未来人脸识别等智能算法的壁垒将会逐渐消除,越来越多的公司会将注意力放在视频流识别的实际场景的应用中,实际场景的痛点挖掘及细分将成为重点发力领域。随着人脸识别等智能算法模型的日渐成熟,市场容量饱和速度越来越快,已经完成原始积累和市场开拓的公司将会牢牢把持人脸市场,后续公司进入难度越来越大,生存空间持续被挤压。而在工业领域的特定视频流识别会成为新兴发展市场,这需要工业领域知识又需要视频流识别智能算法模型的知识,比如铁轨是否有裂缝等民生场景,通过机器识别的应用将能大大提升工作效率。
程序实例:
1获取视频流
利用OpenCV获取USB摄像头的视频流的程序如下:
#-*- coding: utf-8 -*-
import cv2
import sys
from PIL import Image
def CatchUsbVideo(window_name, camera_idx):
cv2.namedWindow(window_name)
#视频来源,可以来自一段已存好的视频,也可以直接来自USB摄像头
cap = cv2.VideoCapture(camera_idx)
while cap.isOpened():
ok, frame = cap.read() #读取一帧数据
if not ok:
break
#显示图像并等待10毫秒按键输入,输入‘q’退出程序
cv2.imshow(window_name, frame)
c = cv2.waitKey(10)
if c & 0xFF == ord('q'):
break
#释放摄像头并销毁所有窗口
cap.release()
cv2.destroyAllWindows()
__main__':
if len(sys.argv) != 2:
print("Usage:%s camera_id " % (sys.argv[0]))
else:
CatchUsbVideo("截取视频流", int(sys.argv[1]))
2 识别人脸程序
#-*- coding: utf-8 -*-
import cv2
import sys
from PIL import Image
def CatchUsbVideo(window_name, camera_idx):
cv2.namedWindow(window_name)
#视频来源,可以来自一段已存好的视频,也可以直接来自USB摄像头
cap = cv2.VideoCapture(camera_idx)
#告诉OpenCV使用人脸识别分类器
classfier = cv2.CascadeClassifier("/usr/local/share/OpenCV/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)
#人脸检测,1.2和2分别为图片缩放比例和需要检测的有效点数
faceRects = classfier.detectMultiScale(grey, scaleFactor = 1.2, minNeighbors = 3, minSize = (32, 32))
if len(faceRects) > 0: #大于0则检测到人脸
for faceRect in faceRects: #单独框出每一张人脸
x, y, w, h = faceRect
cv2.rectangle(frame, (x - 10, y - 10), (x w 10, y h 10), color, 2)
#显示图像
cv2.imshow(window_name, frame)
c = cv2.waitKey(10)
if c & 0xFF == ord('q'):
break
#释放摄像头并销毁所有窗口
cap.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
if len(sys.argv) != 2:
print("Usage:%s camera_id " % (sys.argv[0]))
else:
CatchUsbVideo("识别人脸区域", int(sys.argv[1]))
3为人脸识别准备数据
#-*- coding: utf-8 -*-
import cv2
import sys
from PIL import Image
def CatchPICFromVideo(window_name, camera_idx, catch_pic_num, path_name):
cv2.namedWindow(window_name)
#视频来源,可以来自一段已存好的视频,也可以直接来自USB摄像头
cap = cv2.VideoCapture(camera_idx)
#告诉OpenCV使用人脸识别分类器
classfier = cv2.CascadeClassifier("/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt2.xml")
#识别出人脸后要画的边框的颜色,RGB格式
color = (0, 255, 0)
num = 0
while cap.isOpened():
ok, frame = cap.read() #读取一帧数据
if not ok:
break
grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) #将当前桢图像转换成灰度图像
#人脸检测,1.2和2分别为图片缩放比例和需要检测的有效点数
faceRects = classfier.detectMultiScale(grey, scaleFactor = 1.2, minNeighbors = 3, minSize = (32, 32))
if len(faceRects) > 0: #大于0则检测到人脸
for faceRect in faceRects: #单独框出每一张人脸
x, y, w, h = faceRect
#将当前帧保存为图片
img_name = '%s/%d.jpg'%(path_name, num)
image = frame[y - 10: y h 10, x - 10: x w 10]
cv2.imwrite(img_name, image)
num = 1
if num > (catch_pic_num): #如果超过指定最大保存数量退出循环
break
#画出矩形框
cv2.rectangle(frame, (x - 10, y - 10), (x w 10, y h 10), color, 2)
#显示当前捕捉到了多少人脸图片了,这样站在那里被拍摄时心里有个数,不用两眼一抹黑傻等着
font = cv2.FONT_HERSHEY_SIMPLEX
cv2.putText(frame,'num:%d' % (num),(x 30, y 30), font, 1, (255,0,255),4)
#超过指定最大保存数量结束程序
if num > (catch_pic_num): break
#显示图像
cv2.imshow(window_name, frame)
c = cv2.waitKey(10)
if c & 0xFF == ord('q'):
break
#释放摄像头并销毁所有窗口
cap.release()
cv2.destroyAllWindows()
if __name__ == '__main__':
if len(sys.argv) != 4:
print("Usage:%s camera_id face_num_max path_name " % (sys.argv[0]))
else:
CatchPICFromVideo("截取人脸", int(sys.argv[1]), int(sys.argv[2]), sys.argv[3])
4利用Keras训练人脸识别模型
# -*- coding: utf-8 -*-
import os
import sys
import numpy as np
import cv2
IMAGE_SIZE = 64
#按照指定图像大小调整尺寸
def resize_image(image, height = IMAGE_SIZE, width = IMAGE_SIZE):
top, bottom, left, right = (0, 0, 0, 0)
#获取图像尺寸
h, w, _ = image.shape
#对于长宽不相等的图片,找到最长的一边
longest_edge = max(h, w)
#计算短边需要增加多上像素宽度使其与长边等长
if h < longest_edge:
dh = longest_edge - h
top = dh // 2
bottom = dh - top
elif w < longest_edge:
dw = longest_edge - w
left = dw // 2
right = dw - left
else:
pass
#RGB颜色
BLACK = [0, 0, 0]
#给图像增加边界,是图片长、宽等长,cv2.BORDER_CONSTANT指定边界颜色由value指定
constant = cv2.copyMakeBorder(image, top , bottom, left, right, cv2.BORDER_CONSTANT, value = BLACK)
#调整图像大小并返回
return cv2.resize(constant, (height, width))
#读取训练数据
images = []
labels = []
def read_path(path_name):
for dir_item in os.listdir(path_name):
#从初始路径开始叠加,合并成可识别的操作路径
full_path = os.path.abspath(os.path.join(path_name, dir_item))
if os.path.isdir(full_path): #如果是文件夹,继续递归调用
read_path(full_path)
else: #文件
if dir_item.endswith('.jpg'):
image = cv2.imread(full_path)
image = resize_image(image, IMAGE_SIZE, IMAGE_SIZE)
#放开这个代码,可以看到resize_image()函数的实际调用效果
#cv2.imwrite('1.jpg', image)
images.append(image)
labels.append(path_name)
return images,labels
#从指定路径读取训练数据
def load_dataset(path_name):
images,labels = read_path(path_name)
#将输入的所有图片转成四维数组,尺寸为(图片数量*IMAGE_SIZE*IMAGE_SIZE*3)
#我和闺女两个人共1200张图片,IMAGE_SIZE为64,故对我来说尺寸为1200 * 64 * 64 * 3
#图片为64 * 64像素,一个像素3个颜色值(RGB)
images = np.array(images)
print(images.shape)
#标注数据,'me'文件夹下都是我的脸部图像,全部指定为0,另外一个文件夹下是闺女的,全部指定为1
labels = np.array([0 if label.endswith('me') else 1 for label in labels])
return images, labels
if __name__ == '__main__':
if len(sys.argv) != 2:
print("Usage:%s path_name " % (sys.argv[0]))
else:
images, labels = load_dataset(sys.argv[1])
5视频流识别特定目标
#识别人脸
def face_predict(self, image):
#依然是根据后端系统确定维度顺序
if K.image_dim_ordering() == 'th' and image.shape != (1, 3, IMAGE_SIZE, IMAGE_SIZE):
image = resize_image(image) #尺寸必须与训练集一致都应该是IMAGE_SIZE x IMAGE_SIZE
image = image.reshape((1, 3, IMAGE_SIZE, IMAGE_SIZE)) #与模型训练不同,这次只是针对1张图片进行预测
elif K.image_dim_ordering() == 'tf' and image.shape != (1, IMAGE_SIZE, IMAGE_SIZE, 3):
image = resize_image(image)
image = image.reshape((1, IMAGE_SIZE, IMAGE_SIZE, 3))
#浮点并归一化
image = image.astype('float32')
image /= 255
#给出输入属于各个类别的概率,我们是二值类别,则该函数会给出输入图像属于0和1的概率各为多少
result = self.model.predict_proba(image)
print('result:', result)
#给出类别预测:0或者1
result = self.model.predict_classes(image)
#返回类别预测结果
return result[0]
#-*- coding: utf-8 -*-
import cv2
import sys
import gc
from face_train_use_keras import Model
if __name__ == '__main__':
if len(sys.argv) != 2:
print("Usage:%s camera_id " % (sys.argv[0]))
sys.exit(0)
#加载模型
model = Model()
model.load_model(file_path = './model/me.face.model.h5')
#框住人脸的矩形边框颜色
color = (0, 255, 0)
#捕获指定摄像头的实时视频流
cap = cv2.VideoCapture(int(sys.argv[1]))
#人脸识别分类器本地存储路径
cascade_path = "/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt2.xml"
#循环检测识别人脸
while True:
_, frame = cap.read() #读取一帧视频
#图像灰化,降低计算复杂度
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
#使用人脸识别分类器,读入分类器
cascade = cv2.CascadeClassifier(cascade_path)
#利用分类器识别出哪个区域为人脸
faceRects = cascade.detectMultiScale(frame_gray, scaleFactor = 1.2, minNeighbors = 3, minSize = (32, 32))
if len(faceRects) > 0:
for faceRect in faceRects:
x, y, w, h = faceRect
#截取脸部图像提交给模型识别这是谁
image = frame[y - 10: y h 10, x - 10: x w 10]
faceID = model.face_predict(image)
#如果是“我”
if faceID == 0:
cv2.rectangle(frame, (x - 10, y - 10), (x w 10, y h 10), color, thickness = 2)
#文字提示是谁
cv2.putText(frame,'Dady',
(x 30, y 30), #坐标
cv2.FONT_HERSHEY_SIMPLEX, #字体
1, #字号
(255,0,255), #颜色
2) #字的线宽
else:
pass
cv2.imshow("识别朕", frame)
#等待10毫秒看是否有按键输入
k = cv2.waitKey(10)
#如果输入q则退出循环
if k & 0xFF == ord('q'):
break
#释放摄像头并销毁所有窗口
cap.release()
cv2.destroyAllWindows()
参考资料:
http://www.cnblogs.com/neo-T/p/6426029.html