小火苗 发表于 2024-11-14 16:51

【米尔-全志 T527 开发板-试用评测】-FacenetPytorch人脸识别

<h1>一、facenet_pytorch算法实现人脸识别</h1>

<p><strong>深度神经网络</strong></p>

<ol>
        <li><span style="font-size: 18px;"><strong>简介</strong></span><br />
        Facenet-PyTorch 是一个基于 PyTorch 框架实现的人脸识别库。它提供了 FaceNet 模型的 PyTorch 实现,可以用于训练自己的人脸识别模型。FaceNet 是由 Google 研究人员提出的一种深度学习模型,专门用于人脸识别任务。<br />
        在利用PyTorch神经网络算法进行人脸图像对比的实验设置中,我们专注于对比环节,而不涉及实际项目的完整实现细节。但为了贴近实际应用,我们可以构想以下流程:<br />
        1)捕捉新人脸图像:首先,我们使用摄像头或其他图像采集设备捕捉一张新的人脸照片。<br />
        2)加载存储的人脸图像:接着,从数据库中加载所有已存储的人脸图像。这些图像是之前采集并存储的,用于与新捕捉到的人脸照片进行对比。<br />
        3)构建神经网络模型:为了实现对比功能,我们需要一个预先训练好或自定义的神经网络模型。这个模型能够提取人脸图像中的关键特征,使得相似的图像在特征空间中具有相近的表示。<br />
        4)特征提取:利用神经网络模型,对新捕捉到的人脸照片和存储的每一张人脸图像进行特征提取。这些特征向量将用于后续的对比计算。<br />
        5)计算相似度:采用合适的相似度度量方法(如余弦相似度、欧氏距离等),计算新照片特征向量与存储图像特征向量之间的相似度。<br />
        6)确定匹配图像:根据相似度计算结果,找到与新照片相似度最高的存储图像,即认为这两张图像匹配成功。<br />
        7)输出匹配结果:最后,输出匹配成功的图像信息或相关标识,以完成人脸对比的实验任务。</li>
        <li><span style="font-size: 18px;"><strong>核心组件</strong></span><br />
        MTCNN:Multi-task Cascaded Convolutional Networks,即多任务级联卷积网络,专门设计用于同时进行人脸检测和对齐。它在处理速度和准确性上都有出色的表现,是当前人脸检测领域的主流算法之一。<br />
        FaceNet:由Google研究人员提出的一种深度学习模型,专门用于人脸识别任务。FaceNet通过将人脸图像映射到一个高维空间,使得同一个人的不同图像在这个空间中的距离尽可能小,而不同人的图像距离尽可能大。这种嵌入表示可以直接用于人脸验证、识别和聚类。</li>
        <li><span style="font-size: 18px;"><strong>功能</strong></span></li>
</ol>

<div>&nbsp;&nbsp;&nbsp;&nbsp;支持人脸检测:使用MTCNN算法进行人脸检测,能够准确识别出图像中的人脸位置。</div>

<div>&nbsp;&nbsp;&nbsp;&nbsp;支持人脸识别:使用FaceNet算法进行人脸识别,能够提取人脸特征并进行相似度计算,实现人脸验证和识别功能。</div>

<p><span style="font-size: 24px;"><strong>二、安装facenet_pytorch库</strong></span></p>

<ol>
        <li><span style="font-size: 18px;"><strong>更新系统</strong></span><br />
        更新ubuntu系统,详情查看米尔提供的资料文件</li>
        <li><span style="font-size: 18px;"><strong>更新系统软件</strong></span><br />
        apt-get update<br />
        </li>
        <li><span style="font-size: 18px;"><strong>安装git等支持软件</strong></span><br />
        sudo apt-get install -y python3-dev python3-pip libopenblas-dev libssl-dev libffi-dev git cmake</li>
        <li><span style="font-size: 18px;"><strong>安装Pytorch支持工具</strong></span></li>
</ol>

<div># 克隆 PyTorch 源代码</div>

<div>git clone --recursive https://github.com/pytorch/pytorch</div>

<div># 进入 PyTorch 目录</div>

<div>cd pytorch</div>

<div># 安装 PyTorch (需要根据你的需求选择 CUDA 版本,如果不需要 GPU 支持则不需要 --cuda 参数)</div>

<div>pip3 install --no-cache-dir torch -f https://download.pytorch.org/whl/torch_stable.html</div>

<div># 测试 PyTorch 安装</div>

<div>python3 -c &quot;import torch; print(torch.__version__)&quot;</div>

<div></div>

<h3>5.安装facenet_pytorch</h3>

<div>pip3 install facenet_pytorch</div>

<div></div>

<p><span style="font-size: 24px;"><strong>三、CSDN参考案例</strong></span></p>

<h3><span style="font-size: 18px;">1.代码实现</span></h3>

<div>############face_demo.py#############################</div>

<div>import cv2</div>

<div>import torch</div>

<div>from facenet_pytorch import MTCNN, InceptionResnetV1</div>

<div># 获得人脸特征向量</div>

<div>def load_known_faces(dstImgPath, mtcnn, resnet):</div>

<div>aligned = []</div>

<div>knownImg = cv2.imread(dstImgPath) # 读取图片</div>

<div>face = mtcnn(knownImg) # 使用mtcnn检测人脸,返回人脸数组</div>

<div>if face is not None:</div>

<div>aligned.append(face)</div>

<div>aligned = torch.stack(aligned).to(device)</div>

<div>with torch.no_grad():</div>

<div>known_faces_emb = resnet(aligned).detach().cpu()</div>

<div># 使用ResNet模型获取人脸对应的特征向量</div>

<div>print(&quot;\n人脸对应的特征向量为:\n&quot;, known_faces_emb)</div>

<div>return known_faces_emb, knownImg</div>

<div># 计算人脸特征向量间的欧氏距离,设置阈值,判断是否为同一张人脸</div>

<div>def match_faces(faces_emb, known_faces_emb, threshold):</div>

<div>isExistDst = False</div>

<div>distance = (known_faces_emb - faces_emb).norm().item()</div>

<div>print(&quot;\n两张人脸的欧式距离为:%.2f&quot; % distance)</div>

<div>if (distance &lt; threshold):</div>

<div>isExistDst = True</div>

<div>return isExistDst</div>

<div>if __name__ == &#39;__main__&#39;:</div>

<div># help(MTCNN)</div>

<div># help(InceptionResnetV1)</div>

<div># 获取设备</div>

<div>device = torch.device(&#39;cuda:0&#39; if torch.cuda.is_available() else &#39;cpu&#39;)</div>

<div># mtcnn模型加载设置网络参数,进行人脸检测</div>

<div>mtcnn = MTCNN(min_face_size=12, thresholds=,</div>

<div>keep_all=True, device=device)</div>

<div># InceptionResnetV1模型加载用于获取人脸特征向量</div>

<div>resnet = InceptionResnetV1(pretrained=&#39;vggface2&#39;).eval().to(device)</div>

<div>MatchThreshold = 0.8 # 人脸特征向量匹配阈值设置</div>

<div>known_faces_emb, _ = load_known_faces(&#39;yz.jpg&#39;, mtcnn, resnet) # 已知人物图</div>

<div>faces_emb, img = load_known_faces(&#39;yz1.jpg&#39;, mtcnn, resnet) # 待检测人物图</div>

<div>isExistDst = match_faces(faces_emb, known_faces_emb, MatchThreshold) # 人脸匹配</div>

<div>print(&quot;设置的人脸特征向量匹配阈值为:&quot;, MatchThreshold)</div>

<div>if isExistDst:</div>

<div>boxes, prob, landmarks = mtcnn.detect(img, landmarks=True)</div>

<div>print(&#39;由于欧氏距离小于匹配阈值,故匹配&#39;)</div>

<div>else:</div>

<div>print(&#39;由于欧氏距离大于匹配阈值,故不匹配&#39;)</div>

<div>此代码是使用训练后的模型程序进行使用,在程序中需要标明人脸识别对比的图像。</div>

<p><span style="font-size: 18px;"><strong>2.实践过程</strong></span></p>

<div>第一次运行时系统需要下载预训练的vggface模型,下载过程较长,后面就不需要在下载了运行会很快。如图所示:</div>

<div></div>

<div></div>

<h3><span style="font-size: 18px;">3.程序运行异常呗终止</span></h3>

<div>运行程序,提示killed,系统杀死了本程序的运行,经过多方面的测试,最终发现是识别的图片过大,使得程序对内存消耗过大导致。后将图片缩小可以正常运行了。</div>

<div>以下是对比图像和对比结果。</div>

<div></div>

<div></div>

<div></div>

<div></div>

<p><span style="font-size: 24px;"><strong>四、gitHub开源代码</strong></span></p>

<ol>
        <li><span style="font-size: 18px;"><strong>首先下载代码文件</strong></span><br />
        代码库中,大致的介绍了facenet算法的训练步骤等。<br />
        </li>
        <li><span style="font-size: 18px;"><strong>代码实现</strong></span><br />
        以下是facenet的python代码,注意需要更改下面的一条程序&quot;cuda&quot; False,因为t527使用的是cpu,芯片到时自带gpu但是cuda用不了,因为cuda是英伟达退出的一种计算机架构。<br />
        import matplotlib.pyplot as plt<br />
        import numpy as np<br />
        import torch<br />
        import torch.backends.cudnn as cudnn<br />
        from nets.facenet import Facenet as facenet<br />
        from utils.utils import preprocess_input, resize_image, show_config<br />
        #--------------------------------------------#<br />
        # 使用自己训练好的模型预测需要修改2个参数<br />
        # model_path和backbone需要修改!<br />
        #--------------------------------------------#<br />
        class Facenet(object):<br />
        _defaults = {<br />
        #--------------------------------------------------------------------------#<br />
        # 使用自己训练好的模型进行预测要修改model_path,指向logs文件夹下的权值文件<br />
        # 训练好后logs文件夹下存在多个权值文件,选择验证集损失较低的即可。<br />
        # 验证集损失较低不代表准确度较高,仅代表该权值在验证集上泛化性能较好。<br />
        #--------------------------------------------------------------------------#<br />
        &quot;model_path&quot; : &quot;model_data/facenet_mobilenet.pth&quot;,<br />
        #--------------------------------------------------------------------------#<br />
        # 输入图片的大小。<br />
        #--------------------------------------------------------------------------#<br />
        &quot;input_shape&quot; : ,<br />
        #--------------------------------------------------------------------------#<br />
        # 所使用到的主干特征提取网络<br />
        #--------------------------------------------------------------------------#<br />
        &quot;backbone&quot; : &quot;mobilenet&quot;,<br />
        #-------------------------------------------#<br />
        # 是否进行不失真的resize<br />
        #-------------------------------------------#<br />
        &quot;letterbox_image&quot; : True,<br />
        #-------------------------------------------#<br />
        # 是否使用Cuda<br />
        # 没有GPU可以设置成False<br />
        #-------------------------------------------#<br />
        &quot;cuda&quot; : False,<br />
        }<br />@classmethod <br />
        def get_defaults(cls, n):<br />
        if n in cls._defaults:<br />
        return cls._defaults<br />
        else:<br />
        return &quot;Unrecognized attribute name &#39;&quot; + n + &quot;&#39;&quot;<br />
        #---------------------------------------------------#<br />
        # 初始化Facenet<br />
        #---------------------------------------------------#<br />
        def __init__(self, **kwargs):<br />
        self.__dict__.update(self._defaults)<br />
        for name, value in kwargs.items():<br />
        setattr(self, name, value)<br />
        self.generate()<br />
        show_config(**self._defaults)<br />
        def generate(self):<br />
        #---------------------------------------------------#<br />
        # 载入模型与权值<br />
        #---------------------------------------------------#<br />
        print(&#39;Loading weights into state dict...&#39;)<br />
        device = torch.device(&#39;cuda&#39; if torch.cuda.is_available() else &#39;cpu&#39;)<br />
        self.net = facenet(backbone=self.backbone, mode=&quot;predict&quot;).eval()<br />
        self.net.load_state_dict(torch.load(self.model_path, map_location=device), strict=False)<br />
        print(&#39;{} model loaded.&#39;.format(self.model_path))<br />
        if self.cuda:<br />
        self.net = torch.nn.DataParallel(self.net)<br />
        cudnn.benchmark = True<br />
        self.net = self.net.cuda()<br />
        #---------------------------------------------------#<br />
        # 检测图片<br />
        #---------------------------------------------------#<br />
        def detect_image(self, image_1, image_2):<br />
        #---------------------------------------------------#<br />
        # 图片预处理,归一化<br />
        #---------------------------------------------------#<br />
        with torch.no_grad():<br />
        image_1 = resize_image(image_1, , self.input_shape], letterbox_image=self.letterbox_image)<br />
        image_2 = resize_image(image_2, , self.input_shape], letterbox_image=self.letterbox_image)<br />
        photo_1 = torch.from_numpy(np.expand_dims(np.transpose(preprocess_input(np.array(image_1, np.float32)), (2, 0, 1)), 0))<br />
        photo_2 = torch.from_numpy(np.expand_dims(np.transpose(preprocess_input(np.array(image_2, np.float32)), (2, 0, 1)), 0))<br />
        if self.cuda:<br />
        photo_1 = photo_1.cuda()<br />
        photo_2 = photo_2.cuda()<br />
        #---------------------------------------------------#<br />
        # 图片传入网络进行预测<br />
        #---------------------------------------------------#<br />
        output1 = self.net(photo_1).cpu().numpy()<br />
        output2 = self.net(photo_2).cpu().numpy()<br />
        #---------------------------------------------------#<br />
        # 计算二者之间的距离<br />
        #---------------------------------------------------#<br />
        l1 = np.linalg.norm(output1 - output2, axis=1)<br />
        plt.subplot(1, 2, 1)<br />
        plt.imshow(np.array(image_1))<br />
        plt.subplot(1, 2, 2)<br />
        plt.imshow(np.array(image_2))<br />
        plt.text(-12, -12, &#39;Distance:%.3f&#39; % l1, ha=&#39;center&#39;, va= &#39;bottom&#39;,fontsize=11)<br />
        plt.show()<br />
        return l1</li>
        <li><span style="font-size: 18px;"><strong>代码实现</strong></span><br />
        此代码调用的签名的代码,但其可以直接的去调用图片进行人脸识别。<br />
        from PIL import Image<br />
        from facenet import Facenet<br />
        if __name__ == &quot;__main__&quot;:<br />
        model = Facenet()<br />
        while True:<br />
        image_1 = input(&#39;Input image_1 filename:&#39;)<br />
        try:<br />
        image_1 = Image.open(image_1)<br />
        except:<br />
        print(&#39;Image_1 Open Error! Try again!&#39;)<br />
        continue<br />
        image_2 = input(&#39;Input image_2 filename:&#39;)<br />
        try:<br />
        image_2 = Image.open(image_2)<br />
        except:<br />
        print(&#39;Image_2 Open Error! Try again!&#39;)<br />
        continue<br />
        probability = model.detect_image(image_1,image_2)<br />
        print(probability)</li>
        <li><span style="font-size: 18px;"><strong>程序运行</strong></span></li>
</ol>

<div></div>

<div>运行程序后首先显示的是程序的配置信息,然后可以输入图像对比检测的内容。以下是图像识别的效果和对比的准确率。</div>

<div></div>

<div></div>

<div></div>

<div></div>

<div></div>

<div></div>

<p><span style="font-size: 24px;"><strong>五、参考文献</strong></span></p>

<div>CSDN博客</div>

<div>https://blog.csdn.net/weixin_45939929/article/details/124789487?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-1-124789487-blog-142987324.235^v43^pc_blog_bottom_relevance_base6&amp;spm=1001.2101.3001.4242.2&amp;utm_relevant_index=4</div>

<div>官方源码来源</div>

<div><a href="https://gitcode.com/gh_mirrors/fac/facenet-pytorch/overview">https://gitcode.com/gh_mirrors/fac/facenet-pytorch/overview</a></div>

<p><!--importdoc--></p>

Jacktang 发表于 2024-11-15 07:30

<p>人脸识别的算法还真多</p>

<p>说的安装facenet_pytorch库的步骤还不太明白</p>

小火苗 发表于 2024-11-15 09:04

Jacktang 发表于 2024-11-15 07:30
人脸识别的算法还真多

说的安装facenet_pytorch库的步骤还不太明白

<p>1.GitHub下载程序</p>

<p>2。更改facenet。py程序</p>

<p>3。运行preditct。py</p>

<p>4.输入想要对比图片的文件夹名称和文件名称</p>

<p>5.环境安装 就是缺啥按啥</p>

chejm 发表于 2024-11-15 17:22

<p>感谢楼主分享的技术知识,非常详细易懂,希望能自己实际实测试试</p>
页: [1]
查看完整版本: 【米尔-全志 T527 开发板-试用评测】-FacenetPytorch人脸识别