img2pose: Face Alignment and Detection via 6DoF, Face Pose Estimation代码理解

2023-05-16

      

import argparse
import os
import sys
import time

import numpy as np
from PIL import Image, ImageOps
from torchvision import transforms
from tqdm import tqdm
import cv2

sys.path.append("./")
from img2pose import img2poseModel
from model_loader import load_model


def init_model(pretrained_path, threed_68_points, pose_stddev, pose_mean, depth):
    img2pose_model = img2poseModel(
            depth,
            200,
            1400,
            pose_mean=np.load(pose_mean),
            pose_stddev=np.load(pose_stddev),
            threed_68_points=np.load(threed_68_points),
        )
    load_model(
            img2pose_model.fpn_model,
            pretrained_path,
            cpu_mode=str(img2pose_model.device) == "cpu",
            model_only=True,
        )
    img2pose_model.evaluate()

    return img2pose_model


def bbox_voting(bboxes, iou_thresh=0.6):
    # bboxes: a numpy array of N*5 size representing N boxes;
    #         for each box, it is represented as [x1, y1, x2, y2, s]
    # iou_thresh: group bounding boxes if their overlap is > threshold.
    bboxes = np.asarray(bboxes)
    order = bboxes[:, 4].ravel().argsort()[::-1]
    bboxes = bboxes[order, :]
    areas = (bboxes[:, 2] - bboxes[:, 0] + 1) * (bboxes[:, 3] - bboxes[:, 1] + 1)
    voted_bboxes = np.zeros([0, 5])
    while bboxes.shape[0] > 0:
        xx1 = np.maximum(bboxes[0, 0], bboxes[:, 0])
        yy1 = np.maximum(bboxes[0, 1], bboxes[:, 1])
        xx2 = np.minimum(bboxes[0, 2], bboxes[:, 2])
        yy2 = np.minimum(bboxes[0, 3], bboxes[:, 3])
        w = np.maximum(0.0, xx2 - xx1 + 1)
        h = np.maximum(0.0, yy2 - yy1 + 1)
        inter = w * h
        overlaps = inter / (areas[0] + areas[:] - inter)
        merge_indexs = np.where(overlaps >= iou_thresh)[0]
        if merge_indexs.shape[0] == 0:
            bboxes = np.delete(bboxes, np.array([0]), 0)
            areas = np.delete(areas, np.array([0]), 0)
            continue
        bboxes_accu = bboxes[merge_indexs, :]
        bboxes = np.delete(bboxes, merge_indexs, 0)
        areas = np.delete(areas, merge_indexs, 0)
        # generate a new box by score voting and box voting
        bbox = np.zeros((1, 5))
        box_weights = (bboxes_accu[:, -1] / max(bboxes_accu[:, -1])) * overlaps[
            merge_indexs
        ]
        bboxes_accu[:, 0:4] = bboxes_accu[:, 0:4] * np.tile(
            box_weights.reshape((-1, 1)), (1, 4)
        )
        bbox[:, 0:4] = np.sum(bboxes_accu[:, 0:4], axis=0) / (np.sum(box_weights))
        bbox[0, 4] = np.sum(bboxes_accu[:, 4] * box_weights)
        voted_bboxes = np.row_stack((voted_bboxes, bbox))

    return voted_bboxes


def get_M_homo(R, t):
    M = [[R[0][0], R[0][1], R[0][2], t[0]],
         [R[1][0], R[1][1], R[1][2], t[1]],
         [R[2][0], R[2][1], R[2][2], t[2]],
         [0,       0,       0,       1]]
    
    M = np.linalg.inv(np.array(M))

    r = M[:3, :3]
    R_1X3 = np.zeros((1, 3))
    cv2.Rodrigues(r, R_1X3)

    t = np.array([M[0][3], M[1][3], M[2][3]])

    return R_1X3, t


def show_xyz(img, point_3d, rotation_vector, translation_vector, ipm, dpv):
    R_3X3 = np.zeros((3, 3))
    cv2.Rodrigues(rotation_vector, R_3X3)
    rotation_vector, translation_vector = get_M_homo(R_3X3, translation_vector)

    gap = 1
    x_3d = np.array([point_3d[0] + gap, point_3d[1], point_3d[2]], dtype=np.float64)
    y_3d = np.array([point_3d[0], point_3d[1] + gap, point_3d[2]], dtype=np.float64)
    z_3d = np.array([point_3d[0], point_3d[1], point_3d[2] + gap], dtype=np.float64)
    # print(x_3d.dtype)
    # print(rotation_vector.dtype)
    # print(translation_vector.dtype)
    # print(ipm.dtype)
    # print(dpv.dtype)
    (x_3d, jacobian) = cv2.projectPoints(x_3d, rotation_vector, translation_vector, ipm, dpv)
    (y_3d, jacobian) = cv2.projectPoints(y_3d, rotation_vector, translation_vector, ipm, dpv)
    (z_3d, jacobian) = cv2.projectPoints(z_3d, rotation_vector, translation_vector, ipm, dpv)
    (origin_coordinates, jacobian) = cv2.projectPoints(np.array(point_3d, dtype=np.float64), rotation_vector, translation_vector, ipm, dpv)
    x_coordinates = (int(x_3d[0][0][0]), int(x_3d[0][0][1]))
    y_coordinates = (int(y_3d[0][0][0]), int(y_3d[0][0][1]))
    z_coordinates = (int(z_3d[0][0][0]), int(z_3d[0][0][1]))
    origin_coordinates = (int(origin_coordinates[0][0][0]), int(origin_coordinates[0][0][1]))
    # print(origin_coordinates)
    # print(x_coordinates)

    cv2.line(img, origin_coordinates, x_coordinates, (0, 0, 255), 2)
    cv2.putText(img, "X", x_coordinates, cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2)
    cv2.line(img, origin_coordinates, y_coordinates, (0, 255, 0), 2)
    cv2.putText(img, "Y", y_coordinates, cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
    cv2.line(img, origin_coordinates, z_coordinates, (255, 0, 0), 2)
    cv2.putText(img, "Z", z_coordinates, cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 0, 0), 2)


def main():
    cap = cv2.VideoCapture("./datasets/123.avi")  # "./datasets/123.avi"
    model = init_model(pretrained_path, threed_68_points, pose_stddev, pose_mean, depth)

    while 1:
        success, img_bgr = cap.read()
        # img_bgr = cv2.imread("./datasets/112.png")
        if not success:
            break

        count1 = cv2.getTickCount()
        
        img = img_bgr[:, :, ::-1]

        run_img = img.copy()

        transform = transforms.Compose([transforms.ToTensor()])
        res = model.predict([transform(run_img)])
        
        bboxes = []
        poses = []
        # print("src", res[0])
        for i in range(len(res[0]["scores"])):
            bbox = res[0]["boxes"].cpu().numpy()[i].astype("int")
            score = res[0]["scores"].cpu().numpy()[i]
            pose = res[0]["dofs"].cpu().numpy()[i]

            poses.append(pose)
            bboxes.append(np.append(bbox, score))

        if np.ndim(bboxes) == 1 and len(bboxes) > 0:
            bboxes = bboxes[np.newaxis, :]
        # print(bboxes)
        if bboxes == []:
            continue
        # bboxes = bbox_voting(bboxes, 0.6)
        # print("dest", bboxes)
        for i, [x1,y1,x2,y2,s] in enumerate(bboxes):
            if s > 0.6:
                cv2.rectangle(img_bgr, (int(x1), int(y1)), (int(x2), int(y2)), (255, 0, 0))
                cv2.putText(img_bgr, str(int(s*1000)), (int(x1), int(y1)), cv2.FONT_HERSHEY_PLAIN, 2.0, (0, 0, 255))
                show_xyz(img_bgr, (0, 0, 0), np.array([poses[i][0], poses[i][1], poses[i][2]], dtype=np.float64),
                    np.array([poses[i][3], poses[i][4], poses[i][5]], dtype=np.float64), ipm, dpv)
                print(poses[i])

        count2 = cv2.getTickCount()
        fps = cv2.getTickFrequency() / (count2 - count1)
        cv2.putText(img_bgr, str(fps), (20, 20), cv2.FONT_HERSHEY_PLAIN, 2.0, (0, 0, 255))

        cv2.imshow('video', img_bgr)
        # cv2.waitKey(0)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break


# ipm:相机内参  dpv:相机畸变参数
ipm = np.array([[738.77113867, 0., 309.55582235], [0., 738.46009689, 220.83418211], [0, 0, 1]])
dpv = np.array([0.0573193604, -0.37914004, -0.00216807948, 0.000132759817, 0.923696829])
depth = 18   # 18, 50, 101
pose_mean = "./models/WIDER_train_pose_mean_v1.npy"
pose_stddev = "./models/WIDER_train_pose_stddev_v1.npy"
threed_68_points = "./pose_references/reference_3d_68_points_trans.npy"
pretrained_path = "models/img2pose_v1.pth"
if __name__ == "__main__":
    main()

        以上面的main.py为运行起点,img2pose代码主要调用逻辑如下所示(可配合这里一起理解)。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

img2pose: Face Alignment and Detection via 6DoF, Face Pose Estimation代码理解 的相关文章

  • 为什么编译器抱怨对齐?

    我想了解更多关于对齐的信息 为什么 Microsoft 编译器 Visual Studio 2012 Express 会抱怨以下代码片段的对齐情况 declspec align 16 class Foo public virtual Foo
  • 如何使用头文件签名(幻数)检查文件类型?

    通过输入文件及其扩展名 我的代码成功地从 幻数 中检测到文件的类型 magic numbers png bytes 0x89 0x50 0x4E 0x47 0x0D 0x0A 0x1A 0x0A jpg bytes 0xFF 0xD8 0x
  • 将 Z 轴与向量对齐的最简单方法是什么?

    给定一个点 如 0 0 0 和一个向量 如 x y z 对齐以 0 0 0 为中心的负 Z 轴以指向该向量的方向的最简单方法是什么 使用 OpenGL 的示例将受到欢迎 但不是必需的 有很多不同的方法可以旋转坐标系以指向给定方向 它们都会使
  • 如何在 Material-UI 中将按钮居中

    我不知道如何在 Material UI 中将按钮居中 这是我的代码 function BigCard props const classes props return div div
  • 如何将文本输入与图像按钮对齐?

    我有一个表单 其中输入字段的最后一行后面跟着 2 个图像按钮 无论我尝试什么 我似乎都无法将按钮与字段水平对齐 这是所有代码 http jsfiddle net h3ZPk http jsfiddle net h3ZPk 添加此规则 but
  • H1 在左边,“按钮”在右边,垂直对齐

    我试图在一行上显示 与包含框左侧对齐的 H1 元素 几个 按钮 此处为 A 元素 与包含框的右侧对齐 都在同一基线上 是否可以用最少的标记 即没有换行元素 来做到这一点 而不必设置精确的高度 行高 边距顶部等 div h1 What a g
  • Apache代理负载均衡后端服务器故障检测

    这是我的场景 由我的前任设计 两台 Apache 服务器为多个混合后端 Web 服务器 Apache IIS Tomcat 等 提供反向代理服务 有些网站我们有多个后端 Web 服务器 在这些情况下 我们会执行以下操作
  • 如何判断 HTML5 音频元素是否正在使用 Javascript 播放

    我有一个audio网页中的元素 我想确保用户在离开页面时不会仍在播放它 我怎样才能确定audio页面卸载时元素未播放 到目前为止 我有以下代码 但它似乎不起作用 卸载报告时弹出的对话框playing is false即使音频正在播放
  • UITableView 的文本右对齐且缩进

    我想做一个UITableView文本右对齐且缩进 如下图所示 不幸的是 我不能通过写来做到这一点 cell textLabel textAlignment UITextAlignmentRight cell indentationLevel
  • 每个请求上的 51Degrees 重新加载会减慢 ASP.NET MVC 的速度

    添加 51Degrees 移动检测库后 我的 ASP NET MVC 3 项目速度慢得像爬行一样 51Degrees 日志文件定义为
  • 是否有一个很好的 emacs 模式来显示和编辑巨大的分隔符分隔的文件?

    我一直在寻找一段时间 但没有找到一种可以轻松编辑大型制表符 逗号 冒号分隔文件的模式 我一直想要一种确保列始终对齐的模式 就像组织模式表一样 我知道我可以轻松地将整个文件转换为组织模式表 然后在完成后将其返回 但是对于大文件来说 这会变得非
  • Horizo​​ntalAlignment=拉伸、最大宽度、左对齐同时?

    这看起来应该很容易 但我很困惑 在 WPF 中 我想要一个 TextBox 拉伸到其父级的宽度 但仅限于最大宽度 问题是我希望它在其父级中保持合理 要使其拉伸 您必须使用 Horizo ntalAlignment Stretch 但结果会居
  • 维奥拉-琼斯算法 - “像素之和”?

    我看过很多关于 Viola Jones 算法如何真正工作的文章和问题的答案 我不断找到答案 说某个区域中的 像素总和 减去相邻区域中的 像素总和 我对 像素总和 的含义感到困惑 其价值依据是什么 是该区域的像素数吗 颜色的强度 提前致谢 这
  • 将 QHBoxLayout 的每个小部件对齐到顶部

    我试图将 QHBoxlayout 中的每个小部件对齐到顶部 但我得到的是每个小部件似乎都居中 我认为这是由于尺寸不同造成的 例如 from PyQt5 QtGui import from PyQt5 QtCore import from P
  • 如何“对齐”2个字符串?

    首先让我解释一下 对齐 的含义 假设我们必须字符串 例如AGBCDEFABCDIEFK 他们的 结盟 是 A G B C D E F A B C D I E F K A B C D E F 另一个 相当简单的 例子 因为我相信我的问题可能与
  • 如何将引导程序形式的输入与输入组插件对齐?

    我有一个非常简单的 Bootstrap 3 表单 当我不使用它时 我可以轻松 自动 对齐input group addons 在我的表单中使用它们后 无法对齐它 由于添加了插件 带有插件的线更宽
  • SSE、内在函数和对齐

    我使用大量 SSE 编译器内在函数编写了一个 3D 矢量类 一切都工作正常 直到我开始使用 new 来实例化具有 3D 向量作为成员的类 我在发布模式下经历了奇怪的崩溃 但在调试模式下却没有 反之亦然 因此 我阅读了一些文章 并认为我需要将
  • Html 表格右对齐

    item a item b item c item d item e item a item b item c item d item e 我的表中有两行 我希望它们每行都有一个左对齐的项目和一些右对齐的项目 如上面的第一个示例所示 然而
  • 隐藏在 C++ 类中嵌入 char 数组中的数据成员的性能、安全性和对齐方式是什么?

    我最近看到一个代码库 我担心它违反了对齐约束 我已经对其进行了擦洗 以生成一个最小的示例 如下所示 简而言之 球员们是 Pool 对于 高效 的某些定义 这是一个有效分配内存的类 Pool保证返回一块与请求大小对齐的内存块 Obj list
  • 如何避免在 Excel 中垂直合并单元格?

    我厌倦了合并单元格 它们就是行不通 因此 当我只需要文本在多列中居中时 我找到了一种避免水平合并单元格的方法 那是 Range A1 C1 HorizontalAlignment xlCenterAcrossSelection 它就像一个魅

随机推荐

  • c++中string、char *、char[]相互转换

    一 string转char 主要有三种方法可以将str转换为char 类型 xff0c 分别是 xff1a data c str copy 其中 xff0c copy 可能会报安全性错误 xff0c 自行解决即可 3 1 data 方法 s
  • char数组与char指针

    转载来源 xff1a https www cnblogs com nzbbody p 3553222 html https blog csdn net jack 20 article details 78913202 一 0 的添加 存在的
  • linux下tcpdump的使用

    简介 用简单的话来定义tcpdump xff0c 就是 xff1a dump the traffic on a network xff0c 根据使用者的定义对网络上的数据包进行截获的包分析工具 tcpdump可以将网络中传送的数据包的 头
  • khadas vim3安装ros1

    khadas vim3 按照网上的方法可以正常安装ros2 xff0c 但是按照ros1则可能会有一些奇奇怪怪的问题导致按照失败 xff0c 不过在一位群友的帮助下 xff0c 找到了解决的方法 khadas vim3 将源换为下面 xff
  • 【Android】CMake添加多个c文件

    1 准备工作 先下相关的插件 xff0c 进入setting xff0c 勾选这LLDB NDK CMake三个 xff0c 点击OK后即可下载 2 Native C 43 43 工程 简单总结一下CMake使用的操作步骤 1 新建Nati
  • 什么是字节序(端序、低端字节序、高端字节序、网络字节序)

    前言 一个内容为12 xff08 字符串 xff09 的文本文件 xff0c 它的第一个字节是什么 xff08 小端序 xff09 xff1f 如果你的回答是0x32 xff0c 那你真的应该好好理解下字节序了 如下图所示 xff0c 我这
  • APM中电机输出分析

    一 APM类分析 老规矩 xff0c 先上类图 xff08 1 xff09 如图 xff08 1 xff09 所示 xff0c AP Motors是大部分电机类的父类 xff0c 是AC AttitudeControl姿态控制类的保护型成员
  • 解决安装ROS时出现的sudo rosdep init错误问题

    解决安装ROS时出现的sudo rosdep init错误问题 目前安装ROS时输入sudo rosdep init的命令时 xff0c 可能会出现以下的错误 xff1a ERROR cannot download default sour
  • JS实现HTTP请求头-Basic Authorization

    HTTP协议中的 Authorization 请求消息头含有服务器用于验证用户代理身份的凭证 xff0c 通常会在服务器返回401 Unauthorized 状态码以及WWW Authenticate 消息头之后在后续请求中发送此消息头 A
  • C语言Post和Get方法 ,拿过去直接用

    C语言post 和get 方法的实现 我自己实现的post 和get 请求方法 xff0c 可以直接使用在单片机上 xff0c 比如ESP32 上 xff0c OPl1000 上面 xff0c 下面直接上代码 span class toke
  • QT中图表类QChart系列之(1)-基本用法,画折线图、各个类之间的关系

    参考 xff1a https www cnblogs com yunhaisoft p 5180127 html 首先要注意3点 xff1a xff08 1 xff09 在 pro文件中添加 xff1a QT 43 61 charts xf
  • STM32使用FIFO实现USART串口发送中断

    fifo就不要造轮子了 xff0c 用现成的就行了 linux内核中有目前人类写出的基于c语言的最强FIFO xff0c 请自行搜索学习 巧夺天工的kfifo xff0c kfifo精妙无比 xff0c 实在是高 xff0c 其中用到的环回
  • c++的json读取操作

    使用的开源库是nlohmann json 后续操作也都是基于该开源库操作 本地json文件如下 xff1a 34 model config 34 34 model type 34 34 paddlex 34 34 model cfg fil
  • 三维重建了解

    一 三维重建方法 1 1 传统方法 RGBD D来源结构光或者TOF xff1a 缺点 xff0c 重建范围受限 xff0c 一般不能重建大模型 xff1b 比如 xff0c kinectFusion xff0c DynamicFusion
  • docker容器常用命令

    一 常用命令 显示本地镜像 xff1a docker images 显示已经启动的容器 xff1a docker ps a 从docker hub拉取镜像 reed98 airsim v0是镜像名 xff1a docker pull ree
  • ARM学习随笔(12)定时器查询方式和中断方式

    定时器详细讲解 百度文库 点击打开链接 xff08 一 xff09 查询方式和中断方式的区别在于 xff1a 查询方式不断查询标志位然后进行处理 xff0c 而中断要编写中断服务子程序来处理中断事件 xff08 二 xff09 内部中断是指
  • vgg16网络裁剪并加载模型参数

    主要是测试下模型裁剪后转onnx的问题 删除vgg16网络全连接层 xff0c 加载预训练模型并重新保存模型参数 xff0c 将该参数用于转onnx模型格式 usr bin env python coding utf 8 64 Time 2
  • pth转onnx的三种情况

    usr bin env python coding utf 8 64 Time 2022 8 3 16 19 64 Author weiz 64 ProjectName cbir 64 File pth2onnx py 64 Descrip
  • 以vgg为backbone的简易图像检索系统

    图像检索 xff08 Content based Image Retrieval xff0c 简称CBIR xff09 即以图搜图 xff0c 基于图片语义信息 xff0c 诸如颜色 纹理 布局 CNN based高层语义等特征检索技术 该
  • img2pose: Face Alignment and Detection via 6DoF, Face Pose Estimation代码理解

    import argparse import os import sys import time import numpy as np from PIL import Image ImageOps from torchvision impo