计算机视觉保护隐私





预防是我们的一切。防止数据泄漏的有效保护措施将有助于防止可能造成数百万美元损失的负面后果。在现代世界中,每个组织都处理和存储机密信息。对于大型组织,机密信息量巨大。当每个用户遵守所有信息安全规则时,计算机的“安全性”状态是一种理想的概念。



在办公室中,任何员工都会不时离开计算机,然后打开计算机,无人看管,经常打开文件和文件夹以进行访问,因为许多员工只是忘记锁定自己的PC,或者他们故意在相似的短语的引导下不这样做-“我向后移了五米,为什么要挡住它!?”不幸的是,这样的时刻可以由对材料感兴趣的其他员工使用。







在这种情况下如何确保数据安全?一种方法是使用生物特征认证技术通过用户的面部识别用户。



人脸识别不是一个新概念,目前有许多工具可以完成此任务。如果您不熟悉面部识别的方法和工具,那么使用开源计算机视觉库(开源计算机视觉库)和Python编程语言将是一个极好的解决方案,它将使您尽快实现目标。







我们已经决定要使用该软件,我们需要另一个硬件-网络摄像头。您现在如何设置人脸识别?首先,您需要检测框架中的面部。 Viola-Jones方法是检测人脸的方法之一,该方法已在2001年进行了描述。由于我们对实践更感兴趣,因此我们不再赘述理论上的细节,仅提及该方法基于以下基本原理,例如将图像转换为积分表示,扫描窗口方法和Haar特征的使用。您可以阅读该方法的说明,并在官方网站上查看有关安装OpenCV的信息。以下是Python代码,可让我们从网络摄像头视频流中检测人脸:



import cv2 as cv
import numpy as np

face_cascade = 'haarcascade_frontalface_default.xml'
cam = 1

classifier = cv.CascadeClassifier(face_cascade)

video_stream = cv.VideoCapture(cam)
while True:
    retval, frame = video_stream.read()
    gray_frame = cv.cvtColor(frame, cv.COLOR_BGR2GRAY)
    found_faces = classifier.detectMultiScale(gray_frame, 1.2, 5, minSize=(197, 197))

    for x, y, w, h in found_faces:
        cv.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)

    cv.namedWindow('Stream', cv.WINDOW_NORMAL)
    cv.imshow('Stream', frame)

    k = cv.waitKey(30) & 0xFF
    if k == 27:
        break

video_stream.release()
cv.destroyAllWindows()


在上面的代码中,我们首先导入工作所需的两个模块:cv2(计算机视觉)和numpy(使用矩阵)。在变量face_cascade中,使用Haar级联将路径保存到xml文件。该文件以及其他文件(例如用于眼睛检测的文件)可以在github页面上找到



在变量cam中,我们写入网络摄像机的编号,如果连接了多个,默认情况下唯一连接的摄像机的编号为0。接下来,使用CascadeClassifier方法创建一个分类器对象,并且与摄像机的连接为cv.VideoCapture(摄像机)。然后,在循环中,我们使用read()方法将图像逐帧读取到frame变量中。分类器以灰度处理图像,因此,使用cvtColor方法将图像转换为所需的形式。 detectMultiScale方法返回一个列表,其中包含所有检测到的面部的参数,该列表是一个矩形-顶点坐标(x,y)和矩形的宽度和高度(w,h)。以下各行是程序工作的可选行,但对调试很有用-矩形方法在检测到的脸部位置将一帧添加到源帧中,并且imshow-显示带有视频流的窗口。



这里的一切都很简单,但更有趣。现在我们需要识别脸部。怎么做? OpenCV包含多种面部识别方法,其中包括LBPH(局部二进制模式直方图)方法。在这里,我们将更详细地介绍并了解其工作原理。



通常,会获取图像像素的亮度值以及原始像素周围的八个像素的亮度值。原来是一个3x3的表格,其中包含像素亮度值。然后将0或1写入同一表,如果最外面的像素的亮度值超过中央像素的亮度值,则设置为1,否则为-0。在适当位置放入图像大小的矩阵。因此,对于每个像素。







将矩阵分为一定数量的段(默认情况下为8×8网格),为每个段构建一个直方图,最后通过连接直方图获得表征整个图像的结果。在识别期间,将为研究的图像构建相同的直方图,然后将其与训练数据进行比较。







我们将使用此特定方法,但是首先您需要执行另一个重要步骤-创建带有面孔的基础。通常,该库的结构如下所示:



--Storage\\
	--Person_1\\
		--img_1.jpg
		--img_2.jpg
		--img_n.jpg
	--Person_m\\
                --img_1.jpg
		--img_2.jpg
		--img_n.jpg


好的,我们有一个带有面部图像的基础。现在,您需要以某种方式处理用于训练或训练算法的基础。处理归结为生成所有图像的列表以及每个人的ID或标签的列表。此操作最简单的代码如下所示:



storage = 'storage'
images = []
labels = []
names = {}
id = 0

for subdir in os.scandir(storage):
    names[id] = subdir.name
    subdir_path = os.path.join(storage, subdir.name)

    for file in os.scandir(subdir_path):
        if file.name.split('.')[-1].lower() not in ['png', 'bmp', 'jpeg', 'gif']:
            continue
        file_path = os.path.join(subdir_path, file.name)
        image = cv.imread(file_path, 0)
        label = id
        images.append(image)
        labels.append(label)
    id += 1


在这里,一切都非常简单。存储变量将路径存储到文件夹,该文件夹包含带有个人面部图像的文件夹,然后是图像列表,标签列表和带有名称的字典。工作原理:将某个人的文件夹中的所有图像添加到图像列表中,例如,其中有15张图像。如果这是存储中的第一个文件夹,则标签将等于0,因此,同时将多达15次的0添加到了标签列表中在名称字典中,将创建一个记录,其中的键是标签,值是该人的姓名(带有特定人的图像的文件夹的名称)。因此,对于整个存储。在上面的代码中,请注意使用imread方法的那一行-在此图像被读取并表示为像素亮度矩阵,并写入到image变量中。



现在最有趣的部分是训练算法:



recognizer = cv.face.LBPHFaceRecognizer_create(1, 8, 8, 8, 130) 
recognizer.train(images, np.array(labels))


在代码的第一行中,我们使用LBPHFaceRecognizer_create方法初始化算法。还记得LBPH算法的描述吗?提到的函数的参数仅包含我们所讨论的内容:沿边界取所需像素周围的半径,由半径形成的“圆”中像素的数量,水平和垂直段的数量以及影响识别决策的阈值人员,即要求越严格,门槛越低。接下来,我们调用train方法进行训练,将图像和标签列表作为参数传入。现在,该算法已从数据库中存储了面孔,并将能够识别出它们。事情很小,它仍然需要在循环的第一段代码中添加几行(found_faces中的x,y,w,h):检测到一张脸后,我们需要识别它,如果不识别出该脸,或其他人被识别,请立即锁定计算机!



roi = gray_frame[y:y+h, x:x+w]
name, dist = recognizer.predict(roi)
cv.putText(frame, '%s - %.0f' % (names[name], dist), (x, y), cv.FONT_HERSHEY_DUPLEX, 1, (0, 255, 0), 3)
if names[name] != "Ivan Petrov":
    ctypes.windll.user32.LockWorkStation()


在第一行中,roi(来自感兴趣区域)是一个变量,我们将包含检测到的面部的图像片段写入其中。在下一行中,当调用预报方法时,人脸识别直接发生。该方法返回与识别出的脸部相对应的标签以及表征检测到的脸部与识别出的脸部之间的差异程度的值(该值越小,表示识别出正确脸部的置信度越高)。接下来,再次出于调试目的,使用putText方法将文本添加到具有识别人员名称的框架中。最后,我们检查最简单的条件:如果识别出PC的非所有者(这是需要带有名称的字典的位置),则锁定计算机。如您所见,ctypes.windll.user32.LockWorkStation()行负责阻止。使它起作用除cv2和numpy外,还需要导入ctypes模块。



结果,一旦识别出他人的面孔或原则上不识别该个人计算机,该PC便被锁定。解锁PC后,程序将继续运行。您还可以在员工离开工作场所时添加PC锁。您不必花很长时间就能了解这里有很多细微差别。例如,如果在背景中识别出另一张脸怎么办?在这种情况下,您可以设置看起来像脸的对象的最小尺寸,然后将忽略背景中的脸(为此,detectMultiScale方法中有一个minSize参数)。在其他情况下,如果需要,也可以找到好的解决方案。



阻止正常工作的最重要因素之一是照片数据库中图像的质量。首先,期望对于一个特定的人来说有许多不同的角度和面部表情。其次,照明会自行调整,因此值得考虑这一点并使用在不同照明条件下拍摄的图像。第三,您应该从员工工作场所的网络摄像机记录图像;还有一种在OpenCV中保存图像的方法。至于代码,为确保将其扩展,将添加其他功能,以便可以使用类将其“包装”在函数中。完美无止境!最主要的是要记住程序动作的顺序:用照片处理数据库,训练,检测,识别。



在网络研讨会09/03/2020 10-00莫斯科时间,演讲者将提供一种实用的方法来训练用于目标检测的神经网络,并引用源代码并指明所使用的技术,并回答您的问题。您可以在以下链接进行注册:newtechaudit.ru/vebinar-computer-vision






All Articles