├── README.md
├── classification
├── README.md
├── __pycache__
│ ├── classification.cpython-37.pyc
│ ├── classification.cpython-38.pyc
│ ├── classification_copy.cpython-37.pyc
│ ├── classification_copy.cpython-38.pyc
│ └── classification_pose.cpython-37.pyc
├── classification.py
├── classification_pose.py
├── cls_test.txt
├── cls_train.txt
├── eval_top1.py
├── eval_top5.py
├── img
│ ├── cat.jpg
│ └── dog.jpg
├── logs
│ ├── Epoch50-Total_Loss0.0870-Val_Loss0.0343.pth
│ └── README.md
├── nets
│ ├── __pycache__
│ │ ├── mobilenet.cpython-37.pyc
│ │ ├── resnet50.cpython-37.pyc
│ │ └── vgg16.cpython-37.pyc
│ ├── mobilenet.py
│ ├── resnet50.py
│ └── vgg16.py
├── predict.py
├── requirements.txt
├── test.py
├── train.py
├── txt_annotation.py
└── utils
│ ├── __pycache__
│ ├── dataloader.cpython-37.pyc
│ └── utils.cpython-37.pyc
│ ├── dataloader.py
│ └── utils.py
├── examples
├── media
│ ├── COCO_val2014_000000000192.jpg
│ ├── COCO_val2014_000000000241.jpg
│ ├── COCO_val2014_000000000257.jpg
│ ├── COCO_val2014_000000000294.jpg
│ ├── COCO_val2014_000000000328.jpg
│ ├── COCO_val2014_000000000338.jpg
│ ├── COCO_val2014_000000000357.jpg
│ ├── COCO_val2014_000000000360.jpg
│ ├── COCO_val2014_000000000395.jpg
│ ├── COCO_val2014_000000000415.jpg
│ ├── COCO_val2014_000000000428.jpg
│ ├── COCO_val2014_000000000459.jpg
│ ├── COCO_val2014_000000000474.jpg
│ ├── COCO_val2014_000000000488.jpg
│ ├── COCO_val2014_000000000536.jpg
│ ├── COCO_val2014_000000000544.jpg
│ ├── COCO_val2014_000000000564.jpg
│ ├── COCO_val2014_000000000569.jpg
│ ├── COCO_val2014_000000000589.jpg
│ ├── COCO_val2014_000000000623.jpg
│ ├── test3.mp4
│ ├── test4.mp4
│ ├── test4_60fps.mp4
│ ├── test5.mp4
│ └── video.avi
├── tutorial_api_cpp
│ ├── 01_body_from_image_default.cpp
│ ├── 02_whole_body_from_image_default.cpp
│ ├── 03_keypoints_from_image.cpp
│ ├── 04_keypoints_from_images.cpp
│ ├── 05_keypoints_from_images_multi_gpu.cpp
│ ├── 06_face_from_image.cpp
│ ├── 07_hand_from_image.cpp
│ ├── 08_heatmaps_from_image.cpp
│ ├── 09_keypoints_from_heatmaps.cpp
│ ├── 10_asynchronous_custom_input.cpp
│ ├── 11_asynchronous_custom_input_multi_camera.cpp
│ ├── 12_asynchronous_custom_output.cpp
│ ├── 13_asynchronous_custom_input_output_and_datum.cpp
│ ├── 14_synchronous_custom_input.cpp
│ ├── 15_synchronous_custom_preprocessing.cpp
│ ├── 16_synchronous_custom_postprocessing.cpp
│ ├── 17_synchronous_custom_output.cpp
│ ├── 18_synchronous_custom_all_and_datum.cpp
│ ├── CMakeLists.txt
│ └── README.md
└── tutorial_api_python
│ ├── 01_body_from_image.py
│ ├── 02_whole_body_from_image.py
│ ├── 04_keypoints_from_images.py
│ ├── 05_keypoints_from_images_multi_gpu.py
│ ├── 06_face_from_image.py
│ ├── 07_hand_from_image.py
│ ├── 08_heatmaps_from_image.py
│ ├── 09_keypoints_from_heatmaps.py
│ ├── 12_asynchronous_custom_output.py
│ ├── CMakeLists.txt
│ ├── README.md
│ └── openpose_python.py
├── keypoints_hand.png
├── keypoints_pose_25.png
├── models
├── cameraParameters
│ └── flir
│ │ └── 17012332.xml.example
├── face
│ ├── haarcascade_frontalface_alt.xml
│ └── pose_deploy.prototxt
├── getModels.bat
├── getModels.sh
├── hand
│ └── pose_deploy.prototxt
└── pose
│ ├── body_25
│ └── pose_deploy.prototxt
│ ├── coco
│ └── pose_deploy_linevec.prototxt
│ └── mpi
│ ├── pose_deploy_linevec.prototxt
│ └── pose_deploy_linevec_faster_4_stages.prototxt
├── requirements.txt
├── test.py
├── test_video.py
├── test_video_track_point.py
├── track_of_point.jpg
└── 文本材料
├── 1.作品简介.doc
├── 2.引用说明.docx
└── 3.安装说明.docx
/README.md:
--------------------------------------------------------------------------------
1 | # 手语识别
2 | ---
3 | ## 0、使用到的模型
4 | (1). openpose,作者:CMU-Perceptual-Computing-Lab
5 | ```
6 | https://github.com/CMU-Perceptual-Computing-Lab/openpose
7 | ```
8 | (2). 图像分类classification,作者:Bubbliiiing
9 | ```
10 | https://github.com/bubbliiiing/classification-pytorch
11 |
12 | B站对应视频:https://www.bilibili.com/video/BV143411B7wg
13 | ```
14 | (3). 手语教学视频,作者:二碳碳
15 | ```
16 | https://www.bilibili.com/video/BV1XE41137LV
17 | ```
18 | (感谢大佬们的开源项目和教程,都已star加三连)
19 |
20 |
21 |
22 |
23 | ---
24 |
25 | ## 1、大致思路
26 | 方法一: 将视频输入到openpose中,检测出关节点的变化轨迹,将轨迹绘制在一张图片上,把这张图片传到图像分类网络中检测属于哪个动作
27 | ```
28 | 视频 -----> | openpose |-----> 关节点运动轨迹图-------> | 图像分类模型 | ----------> 单词分类
29 | ```
30 | 方法二: 将视频输入到openpose中,检测出每一帧中关节点的位置,将多帧进行堆叠,形成一个三维张量,其中两个维度是图片的宽和高,一个维度是时间,然后对这个三维张量使用三维卷积进行训练和预测
31 | ```
32 | 视频 -----> | openpose |-----> 多张关节点位置图 ---------> | 堆叠 | --------> 三维张量 -------> | 三维卷积网络 | ----------> 单词分类
33 | ```
34 |
35 |
36 |
37 |
38 | ---
39 |
40 | ## 2、环境配置
41 | python:3.7(其他版本会导致openpose无法运行,建议使用anaconda的python环境)
42 | cuda:10
43 | cudnn:7或8应该都行
44 | (配置cuda和cudnn会比较麻烦,如果实在不想配,你可以去openpose的github网站下载使用cpu的版本,这里这个版本应该不支持cpu)
45 |
46 |
47 |
48 | 具体的配置环境方式:
49 | ### (0).python和cuda和cudnn自己装
50 |
51 |
52 | ### (1).下载文件
53 | 下载代码文件后,再从网盘下载模型和数据文件(没有这些跑不起来),网盘链接:
54 | ```
55 | 链接:https://pan.baidu.com/s/1Q2aVVhMhSfWL4qKS9QslkQ
56 | 提取码:abcd
57 | ```
58 | 将从github下载的文件夹和网盘下载的文件夹合并,然后就可以下一步了。
59 | (当然你大可直接找我要u盘拿完整的文件)
60 |
61 |
62 |
63 | ### (2).安装requirements.txt中的库
64 | cmd进入环境后,cd到项目文件夹下,执行指令:
65 | ```
66 | pip install -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple
67 | ```
68 |
69 |
70 | ### (3).安装torch和torchvision
71 | 先下载好torch(1.2.0)和torchvision(0.4.0)的whl文件,下载地址:
72 | ```
73 | 链接:https://pan.baidu.com/s/1QIuJfEE5qQFpXY8ZlHeLNQ
74 | 提取码:abcd
75 |
76 | (当然你依旧可直接找我拿u盘)
77 | ```
78 | 下载好torch和torchvision的whl文件后,cmd进入环境,cd到下载文件夹下,执行指令:
79 | ```
80 | pip install [torch或torchvision的whl文件的文件名]
81 |
82 | (先装torch再装torchvision,不然有可能会报错)
83 | ```
84 |
85 |
86 |
87 |
88 | ---
89 |
90 | ## 3、测试运行openpose
91 | 项目文件夹下有三个文件:
92 | ```
93 | test.py
94 | test_video.py
95 | test_video_track_point.py
96 | ```
97 | 分别对应openpose的功能:检测图片、检测视频、检测视频并绘制关节点轨迹
98 | 具体的使用方法可以看文件中的注释部分
99 |
100 |
101 |
102 | 在test_video_track_point.py中,取消掉最后几行的注释,就可以将绘制的轨迹图送到classification中去做分类检测
103 | (不过现阶段分类器尚未做好)
104 |
105 |
106 |
107 |
108 | ---
109 |
110 | ## 4、classification的训练和使用
111 | 可以看下classification文件夹中的README.md文件,大佬已经在里边讲得很详细了
112 |
113 |
--------------------------------------------------------------------------------
/classification/README.md:
--------------------------------------------------------------------------------
1 | ## Classification:分类模型在Pytorch当中的实现
2 | ---
3 |
4 | ## 目录
5 | 1. [所需环境 Environment](#所需环境)
6 | 2. [文件下载 Download](#文件下载)
7 | 3. [预测步骤 How2predict](#预测步骤)
8 | 4. [训练步骤 How2train](#训练步骤)
9 | 5. [评估步骤 How2eval](#评估步骤)
10 | 6. [参考资料 Reference](#Reference)
11 |
12 | ## 所需环境
13 | pytorch == 1.2.0
14 |
15 | ## 文件下载
16 | 训练所需的预训练权重都可以在百度云下载。
17 | 链接: https://pan.baidu.com/s/1KwH-O7EafSpfPXnCyX_DVw
18 | 提取码: 2g5y
19 |
20 | 训练所用的示例猫狗数据集也可以在百度云下载。
21 | 链接: https://pan.baidu.com/s/1Jz1nafsrRcw2Hqso4c8i0g
22 | 提取码: hmmx
23 |
24 | ## 预测步骤
25 | ### a、使用预训练权重
26 | 1. 下载完库后解压,model_data已经存在一个训练好的猫狗模型mobilenet025_catvsdog.h5,运行predict.py,输入
27 | ```python
28 | img/cat.jpg
29 | ```
30 | ### b、使用自己训练的权重
31 | 1. 按照训练步骤训练。
32 | 2. 在classification.py文件里面,在如下部分修改model_path、classes_path、backbone和alpha使其对应训练好的文件;**model_path对应logs文件夹下面的权值文件,classes_path是model_path对应分的类,backbone对应使用的主干特征提取网络,alpha是当使用mobilenet的alpha值**。
33 | ```python
34 | _defaults = {
35 | "model_path" : 'model_data/mobilenet_catvsdog.pth',
36 | "classes_path" : 'model_data/cls_classes.txt',
37 | "input_shape" : [224,224,3],
38 | "backbone" : 'mobilenet',
39 | "cuda" : True
40 | }
41 | ```
42 | 3. 运行predict.py,输入
43 | ```python
44 | img/cat.jpg
45 | ```
46 |
47 | ## 训练步骤
48 | 1. datasets文件夹下存放的图片分为两部分,train里面是训练图片,test里面是测试图片。
49 | 2. 在训练之前需要首先准备好数据集,在train或者test文件里里面创建不同的文件夹,每个文件夹的名称为对应的类别名称,文件夹下面的图片为这个类的图片。文件格式可参考如下:
50 | ```
51 | |-datasets
52 | |-train
53 | |-cat
54 | |-123.jpg
55 | |-234.jpg
56 | |-dog
57 | |-345.jpg
58 | |-456.jpg
59 | |-...
60 | |-test
61 | |-cat
62 | |-567.jpg
63 | |-678.jpg
64 | |-dog
65 | |-789.jpg
66 | |-890.jpg
67 | |-...
68 | ```
69 | 3. 在准备好数据集后,需要在根目录运行txt_annotation.py生成训练所需的cls_train.txt,运行前需要修改其中的classes,将其修改成自己需要分的类。
70 | 4. 之后修改model_data文件夹下的cls_classes.txt,使其也对应自己需要分的类。
71 | 5. 在train.py里面调整自己要选择的网络和权重后,就可以开始训练了!
72 |
73 | ## 评估步骤
74 | 1. datasets文件夹下存放的图片分为两部分,train里面是训练图片,test里面是测试图片,在评估的时候,我们使用的是test文件夹里面的图片。
75 | 2. 在评估之前需要首先准备好数据集,在train或者test文件里里面创建不同的文件夹,每个文件夹的名称为对应的类别名称,文件夹下面的图片为这个类的图片。文件格式可参考如下:
76 | ```
77 | |-datasets
78 | |-train
79 | |-cat
80 | |-123.jpg
81 | |-234.jpg
82 | |-dog
83 | |-345.jpg
84 | |-456.jpg
85 | |-...
86 | |-test
87 | |-cat
88 | |-567.jpg
89 | |-678.jpg
90 | |-dog
91 | |-789.jpg
92 | |-890.jpg
93 | |-...
94 | ```
95 | 3. 在准备好数据集后,需要在根目录运行txt_annotation.py生成评估所需的cls_test.txt,运行前需要修改其中的classes,将其修改成自己需要分的类。
96 | 4. 之后在classification.py文件里面修改如下部分model_path、classes_path、backbone和alpha使其对应训练好的文件;**model_path对应logs文件夹下面的权值文件,classes_path是model_path对应分的类,backbone对应使用的主干特征提取网络,alpha是当使用mobilenet的alpha值**。
97 | ```python
98 | _defaults = {
99 | "model_path" : 'model_data/mobilenet_catvsdog.pth',
100 | "classes_path" : 'model_data/cls_classes.txt',
101 | "input_shape" : [224,224,3],
102 | "backbone" : 'mobilenet',
103 | "cuda" : True
104 | }
105 | ```
106 | 5. 运行eval_top1.py和eval_top5.py来进行模型准确率评估。
107 |
108 | ## Reference
109 | https://github.com/keras-team/keras-applications
110 |
111 |
--------------------------------------------------------------------------------
/classification/__pycache__/classification.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/classification/__pycache__/classification.cpython-37.pyc
--------------------------------------------------------------------------------
/classification/__pycache__/classification.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/classification/__pycache__/classification.cpython-38.pyc
--------------------------------------------------------------------------------
/classification/__pycache__/classification_copy.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/classification/__pycache__/classification_copy.cpython-37.pyc
--------------------------------------------------------------------------------
/classification/__pycache__/classification_copy.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/classification/__pycache__/classification_copy.cpython-38.pyc
--------------------------------------------------------------------------------
/classification/__pycache__/classification_pose.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/classification/__pycache__/classification_pose.cpython-37.pyc
--------------------------------------------------------------------------------
/classification/classification.py:
--------------------------------------------------------------------------------
1 | import copy
2 | import os
3 |
4 | import matplotlib.pyplot as plt
5 | import numpy as np
6 | import torch
7 | from torch import nn
8 | from torch.autograd import Variable
9 |
10 | from nets.mobilenet import mobilenet_v2
11 | from nets.resnet50 import resnet50
12 | from nets.vgg16 import vgg16
13 | from utils.utils import letterbox_image
14 |
15 | get_model_from_name = {
16 | "mobilenet":mobilenet_v2,
17 | "resnet50":resnet50,
18 | "vgg16":vgg16,
19 | }
20 |
21 | #----------------------------------------#
22 | # 预处理训练图片
23 | #----------------------------------------#
24 | def _preprocess_input(x,):
25 | x /= 127.5
26 | x -= 1.
27 | return x
28 |
29 | #--------------------------------------------#
30 | # 使用自己训练好的模型预测需要修改3个参数
31 | # model_path和classes_path和backbone都需要修改!
32 | #--------------------------------------------#
33 | class Classification(object):
34 | _defaults = {
35 | "model_path" : 'classification/logs/Epoch50-Total_Loss0.0870-Val_Loss0.0343.pth',
36 | "classes_path" : 'classification/model_data/cls_classes.txt',
37 | "input_shape" : [224,224,3],
38 | "backbone" : 'mobilenet',
39 | "cuda" : True
40 | }
41 |
42 | @classmethod
43 | def get_defaults(cls, n):
44 | if n in cls._defaults:
45 | return cls._defaults[n]
46 | else:
47 | return "Unrecognized attribute name '" + n + "'"
48 |
49 | #---------------------------------------------------#
50 | # 初始化classification
51 | #---------------------------------------------------#
52 | def __init__(self, **kwargs):
53 | self.__dict__.update(self._defaults)
54 | self.class_names = self._get_class()
55 | self.generate()
56 |
57 | #---------------------------------------------------#
58 | # 获得所有的分类
59 | #---------------------------------------------------#
60 | def _get_class(self):
61 | classes_path = os.path.expanduser(self.classes_path)
62 | with open(classes_path) as f:
63 | class_names = f.readlines()
64 | class_names = [c.strip() for c in class_names]
65 | return class_names
66 |
67 | #---------------------------------------------------#
68 | # 获得所有的分类
69 | #---------------------------------------------------#
70 | def generate(self):
71 | model_path = os.path.expanduser(self.model_path)
72 |
73 | # 计算总的种类
74 | self.num_classes = len(self.class_names)
75 |
76 | assert self.backbone in ["mobilenet", "resnet50", "vgg16"]
77 |
78 | self.model = get_model_from_name[self.backbone](num_classes=self.num_classes, pretrained=False)
79 |
80 | self.model = self.model.eval()
81 | state_dict = torch.load(self.model_path)
82 | self.model.load_state_dict(state_dict)
83 | if self.cuda:
84 | self.model = nn.DataParallel(self.model)
85 | self.model = self.model.cuda()
86 | print('{} model, and classes loaded.'.format(model_path))
87 |
88 | #---------------------------------------------------#
89 | # 检测图片
90 | #---------------------------------------------------#
91 | def detect_image(self, image):
92 | old_image = copy.deepcopy(image)
93 |
94 | crop_img = letterbox_image(image, [self.input_shape[0],self.input_shape[1]])
95 | photo = np.array(crop_img,dtype = np.float32)
96 |
97 | # 图片预处理,归一化
98 | photo = np.reshape(_preprocess_input(photo),[1,self.input_shape[0],self.input_shape[1],self.input_shape[2]])
99 | photo = np.transpose(photo,(0,3,1,2))
100 |
101 | with torch.no_grad():
102 | photo = Variable(torch.from_numpy(photo).type(torch.FloatTensor))
103 | if self.cuda:
104 | photo = photo.cuda()
105 | preds = torch.softmax(self.model(photo)[0], dim=-1).cpu().numpy()
106 |
107 | class_name = self.class_names[np.argmax(preds)]
108 | probability = np.max(preds)
109 |
110 | # 显示图片
111 | plt.subplot(1, 1, 1)
112 | plt.imshow(np.array(old_image))
113 | plt.title('Class:%s Probability:%.3f' %(class_name, probability))
114 | plt.show()
115 | return class_name
116 |
117 | def close_session(self):
118 | self.sess.close()
119 |
--------------------------------------------------------------------------------
/classification/classification_pose.py:
--------------------------------------------------------------------------------
1 | import copy
2 | import os
3 |
4 | import matplotlib.pyplot as plt
5 | import numpy as np
6 | import torch
7 | from torch import nn
8 | from torch.autograd import Variable
9 |
10 | from classification.nets.mobilenet import mobilenet_v2
11 | from classification.nets.resnet50 import resnet50
12 | from classification.nets.vgg16 import vgg16
13 | from classification.utils.utils import letterbox_image
14 |
15 | get_model_from_name = {
16 | "mobilenet":mobilenet_v2,
17 | "resnet50":resnet50,
18 | "vgg16":vgg16,
19 | }
20 |
21 | #----------------------------------------#
22 | # 预处理训练图片
23 | #----------------------------------------#
24 | def _preprocess_input(x,):
25 | x /= 127.5
26 | x -= 1.
27 | return x
28 |
29 | #--------------------------------------------#
30 | # 使用自己训练好的模型预测需要修改3个参数
31 | # model_path和classes_path和backbone都需要修改!
32 | #--------------------------------------------#
33 | class Classification(object):
34 | _defaults = {
35 | "model_path" : 'classification/logs/Epoch50-Total_Loss0.0870-Val_Loss0.0343.pth',
36 | "classes_path" : 'classification/model_data/cls_classes.txt',
37 | "input_shape" : [224,224,3],
38 | "backbone" : 'mobilenet',
39 | "cuda" : True
40 | }
41 |
42 | @classmethod
43 | def get_defaults(cls, n):
44 | if n in cls._defaults:
45 | return cls._defaults[n]
46 | else:
47 | return "Unrecognized attribute name '" + n + "'"
48 |
49 | #---------------------------------------------------#
50 | # 初始化classification
51 | #---------------------------------------------------#
52 | def __init__(self, **kwargs):
53 | self.__dict__.update(self._defaults)
54 | self.class_names = self._get_class()
55 | self.generate()
56 |
57 | #---------------------------------------------------#
58 | # 获得所有的分类
59 | #---------------------------------------------------#
60 | def _get_class(self):
61 | classes_path = os.path.expanduser(self.classes_path)
62 | with open(classes_path) as f:
63 | class_names = f.readlines()
64 | class_names = [c.strip() for c in class_names]
65 | return class_names
66 |
67 | #---------------------------------------------------#
68 | # 获得所有的分类
69 | #---------------------------------------------------#
70 | def generate(self):
71 | model_path = os.path.expanduser(self.model_path)
72 |
73 | # 计算总的种类
74 | self.num_classes = len(self.class_names)
75 |
76 | assert self.backbone in ["mobilenet", "resnet50", "vgg16"]
77 |
78 | self.model = get_model_from_name[self.backbone](num_classes=self.num_classes, pretrained=False)
79 |
80 | self.model = self.model.eval()
81 | state_dict = torch.load(self.model_path)
82 | self.model.load_state_dict(state_dict)
83 | if self.cuda:
84 | self.model = nn.DataParallel(self.model)
85 | self.model = self.model.cuda()
86 | print('{} model, and classes loaded.'.format(model_path))
87 |
88 | #---------------------------------------------------#
89 | # 检测图片
90 | #---------------------------------------------------#
91 | def detect_image(self, image):
92 | old_image = copy.deepcopy(image)
93 |
94 | crop_img = letterbox_image(image, [self.input_shape[0],self.input_shape[1]])
95 | photo = np.array(crop_img,dtype = np.float32)
96 |
97 | # 图片预处理,归一化
98 | photo = np.reshape(_preprocess_input(photo),[1,self.input_shape[0],self.input_shape[1],self.input_shape[2]])
99 | photo = np.transpose(photo,(0,3,1,2))
100 |
101 | with torch.no_grad():
102 | photo = Variable(torch.from_numpy(photo).type(torch.FloatTensor))
103 | if self.cuda:
104 | photo = photo.cuda()
105 | preds = torch.softmax(self.model(photo)[0], dim=-1).cpu().numpy()
106 |
107 | class_name = self.class_names[np.argmax(preds)]
108 | probability = np.max(preds)
109 |
110 | # 显示图片
111 | plt.subplot(1, 1, 1)
112 | plt.imshow(np.array(old_image))
113 | plt.title('Class:%s Probability:%.3f' %(class_name, probability))
114 | plt.show()
115 | return class_name
116 |
117 | def close_session(self):
118 | self.sess.close()
119 |
--------------------------------------------------------------------------------
/classification/eval_top1.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import torch
3 | from PIL import Image
4 | from torch.autograd import Variable
5 |
6 | from classification import Classification, _preprocess_input
7 | from utils.utils import letterbox_image
8 |
9 |
10 | class top1_Classification(Classification):
11 | def detect_image(self, image):
12 | crop_img = letterbox_image(image, [self.input_shape[0],self.input_shape[1]])
13 | photo = np.array(crop_img,dtype = np.float32)
14 |
15 | # 图片预处理,归一化
16 | photo = np.reshape(_preprocess_input(photo),[1,self.input_shape[0],self.input_shape[1],self.input_shape[2]])
17 | photo = np.transpose(photo,(0,3,1,2))
18 |
19 | with torch.no_grad():
20 | photo = Variable(torch.from_numpy(photo).type(torch.FloatTensor))
21 | if self.cuda:
22 | photo = photo.cuda()
23 | preds = torch.softmax(self.model(photo)[0], dim=-1).cpu().numpy()
24 |
25 | arg_pred = np.argmax(preds)
26 | return arg_pred
27 |
28 | def evaluteTop1(classfication, lines):
29 | correct = 0
30 | total = len(lines)
31 | for index, line in enumerate(lines):
32 | annotation_path = line.split(';')[1].split()[0]
33 | x = Image.open(annotation_path)
34 | y = int(line.split(';')[0])
35 |
36 | pred = classfication.detect_image(x)
37 | correct += pred == y
38 | if index % 100 == 0:
39 | print("[%d/%d]"%(index,total))
40 | return correct / total
41 |
42 | classfication = top1_Classification()
43 | with open(r"classification/cls_test.txt","r") as f:
44 | lines = f.readlines()
45 | top1 = evaluteTop1(classfication, lines)
46 | print("top-1 accuracy = %.2f%%" % (top1*100))
47 |
--------------------------------------------------------------------------------
/classification/eval_top5.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import torch
3 | from PIL import Image
4 | from torch.autograd import Variable
5 |
6 | from classification import Classification, _preprocess_input
7 | from utils.utils import letterbox_image
8 |
9 |
10 | class top5_Classification(Classification):
11 | def detect_image(self, image):
12 | crop_img = letterbox_image(image, [self.input_shape[0],self.input_shape[1]])
13 | photo = np.array(crop_img,dtype = np.float32)
14 |
15 | # 图片预处理,归一化
16 | photo = np.reshape(_preprocess_input(photo),[1,self.input_shape[0],self.input_shape[1],self.input_shape[2]])
17 | photo = np.transpose(photo,(0,3,1,2))
18 |
19 | with torch.no_grad():
20 | photo = Variable(torch.from_numpy(photo).type(torch.FloatTensor))
21 | if self.cuda:
22 | photo = photo.cuda()
23 | preds = torch.softmax(self.model(photo)[0], dim=-1).cpu().numpy()
24 |
25 | arg_pred = np.argsort(preds)[::-1]
26 | arg_pred_top5 = arg_pred[:5]
27 | return arg_pred_top5
28 |
29 | def evaluteTop5(classfication, lines):
30 | correct = 0
31 | total = len(lines)
32 | for index, line in enumerate(lines):
33 | annotation_path = line.split(';')[1].split()[0]
34 | x = Image.open(annotation_path)
35 | y = int(line.split(';')[0])
36 |
37 | pred = classfication.detect_image(x)
38 | correct += y in pred
39 | if index % 100 == 0:
40 | print("[%d/%d]"%(index,total))
41 | return correct / total
42 |
43 | classfication = top5_Classification()
44 | with open(r"classification/cls_test.txt","r") as f:
45 | lines = f.readlines()
46 | top5 = evaluteTop5(classfication, lines)
47 | print("top-5 accuracy = %.2f%%" % (top5*100))
48 |
49 |
--------------------------------------------------------------------------------
/classification/img/cat.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/classification/img/cat.jpg
--------------------------------------------------------------------------------
/classification/img/dog.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/classification/img/dog.jpg
--------------------------------------------------------------------------------
/classification/logs/Epoch50-Total_Loss0.0870-Val_Loss0.0343.pth:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/classification/logs/Epoch50-Total_Loss0.0870-Val_Loss0.0343.pth
--------------------------------------------------------------------------------
/classification/logs/README.md:
--------------------------------------------------------------------------------
1 | 存放训练后的模型
--------------------------------------------------------------------------------
/classification/nets/__pycache__/mobilenet.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/classification/nets/__pycache__/mobilenet.cpython-37.pyc
--------------------------------------------------------------------------------
/classification/nets/__pycache__/resnet50.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/classification/nets/__pycache__/resnet50.cpython-37.pyc
--------------------------------------------------------------------------------
/classification/nets/__pycache__/vgg16.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/classification/nets/__pycache__/vgg16.cpython-37.pyc
--------------------------------------------------------------------------------
/classification/nets/mobilenet.py:
--------------------------------------------------------------------------------
1 | from torch import nn
2 | from torchvision.models.utils import load_state_dict_from_url
3 |
4 |
5 | __all__ = ['MobileNetV2', 'mobilenet_v2']
6 |
7 |
8 | model_urls = {
9 | 'mobilenet_v2': 'https://download.pytorch.org/models/mobilenet_v2-b0353104.pth',
10 | }
11 |
12 |
13 | def _make_divisible(v, divisor, min_value=None):
14 | if min_value is None:
15 | min_value = divisor
16 | new_v = max(min_value, int(v + divisor / 2) // divisor * divisor)
17 | if new_v < 0.9 * v:
18 | new_v += divisor
19 | return new_v
20 |
21 | class ConvBNReLU(nn.Sequential):
22 | def __init__(self, in_planes, out_planes, kernel_size=3, stride=1, groups=1):
23 | padding = (kernel_size - 1) // 2
24 | super(ConvBNReLU, self).__init__(
25 | nn.Conv2d(in_planes, out_planes, kernel_size, stride, padding, groups=groups, bias=False),
26 | nn.BatchNorm2d(out_planes),
27 | nn.ReLU6(inplace=True)
28 | )
29 |
30 | class InvertedResidual(nn.Module):
31 | def __init__(self, inp, oup, stride, expand_ratio):
32 | super(InvertedResidual, self).__init__()
33 | self.stride = stride
34 | assert stride in [1, 2]
35 |
36 | hidden_dim = int(round(inp * expand_ratio))
37 | self.use_res_connect = self.stride == 1 and inp == oup
38 |
39 | layers = []
40 | if expand_ratio != 1:
41 | layers.append(ConvBNReLU(inp, hidden_dim, kernel_size=1))
42 | layers.extend([
43 | ConvBNReLU(hidden_dim, hidden_dim, stride=stride, groups=hidden_dim),
44 | nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),
45 | nn.BatchNorm2d(oup),
46 | ])
47 | self.conv = nn.Sequential(*layers)
48 |
49 | def forward(self, x):
50 | if self.use_res_connect:
51 | return x + self.conv(x)
52 | else:
53 | return self.conv(x)
54 |
55 |
56 | class MobileNetV2(nn.Module):
57 | def __init__(self, num_classes=1000, width_mult=1.0, inverted_residual_setting=None, round_nearest=8):
58 | super(MobileNetV2, self).__init__()
59 | block = InvertedResidual
60 | input_channel = 32
61 | last_channel = 1280
62 |
63 | if inverted_residual_setting is None:
64 | inverted_residual_setting = [
65 | # t, c, n, s
66 | # 112, 112, 32 -> 112, 112, 16
67 | [1, 16, 1, 1],
68 | # 112, 112, 16 -> 56, 56, 24
69 | [6, 24, 2, 2],
70 | # 56, 56, 24 -> 28, 28, 32
71 | [6, 32, 3, 2],
72 | # 28, 28, 32 -> 14, 14, 64
73 | [6, 64, 4, 2],
74 | # 14, 14, 64 -> 14, 14, 96
75 | [6, 96, 3, 1],
76 | # 14, 14, 96 -> 7, 7, 160
77 | [6, 160, 3, 2],
78 | # 7, 7, 160 -> 7, 7, 320
79 | [6, 320, 1, 1],
80 | ]
81 |
82 | if len(inverted_residual_setting) == 0 or len(inverted_residual_setting[0]) != 4:
83 | raise ValueError("inverted_residual_setting should be non-empty "
84 | "or a 4-element list, got {}".format(inverted_residual_setting))
85 |
86 | input_channel = _make_divisible(input_channel * width_mult, round_nearest)
87 | self.last_channel = _make_divisible(last_channel * max(1.0, width_mult), round_nearest)
88 |
89 | # 224, 224, 3 -> 112, 112, 32
90 | features = [ConvBNReLU(3, input_channel, stride=2)]
91 |
92 | for t, c, n, s in inverted_residual_setting:
93 | output_channel = _make_divisible(c * width_mult, round_nearest)
94 | for i in range(n):
95 | stride = s if i == 0 else 1
96 | features.append(block(input_channel, output_channel, stride, expand_ratio=t))
97 | input_channel = output_channel
98 |
99 | # 7, 7, 320 -> 7,7,1280
100 | features.append(ConvBNReLU(input_channel, self.last_channel, kernel_size=1))
101 | self.features = nn.Sequential(*features)
102 |
103 | self.classifier = nn.Sequential(
104 | nn.Dropout(0.2),
105 | nn.Linear(self.last_channel, num_classes),
106 | )
107 |
108 | for m in self.modules():
109 | if isinstance(m, nn.Conv2d):
110 | nn.init.kaiming_normal_(m.weight, mode='fan_out')
111 | if m.bias is not None:
112 | nn.init.zeros_(m.bias)
113 | elif isinstance(m, nn.BatchNorm2d):
114 | nn.init.ones_(m.weight)
115 | nn.init.zeros_(m.bias)
116 | elif isinstance(m, nn.Linear):
117 | nn.init.normal_(m.weight, 0, 0.01)
118 | nn.init.zeros_(m.bias)
119 |
120 | def forward(self, x):
121 | x = self.features(x)
122 | # 1280
123 | x = x.mean([2, 3])
124 | x = self.classifier(x)
125 | return x
126 |
127 | def freeze_backbone(self):
128 | for param in self.features.parameters():
129 | param.requires_grad = False
130 |
131 | def Unfreeze_backbone(self):
132 | for param in self.features.parameters():
133 | param.requires_grad = True
134 |
135 |
136 | def mobilenet_v2(pretrained=False, progress=True, num_classes=1000):
137 | model = MobileNetV2()
138 | if pretrained:
139 | state_dict = load_state_dict_from_url(model_urls['mobilenet_v2'], model_dir='./model_data',
140 | progress=progress)
141 | model.load_state_dict(state_dict)
142 |
143 | if num_classes!=1000:
144 | model.classifier = nn.Sequential(
145 | nn.Dropout(0.2),
146 | nn.Linear(model.last_channel, num_classes),
147 | )
148 | return model
149 |
--------------------------------------------------------------------------------
/classification/nets/resnet50.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import torch.nn as nn
3 | from torchvision.models.utils import load_state_dict_from_url
4 |
5 | model_urls = {
6 | 'resnet50': 'https://download.pytorch.org/models/resnet50-19c8e357.pth',
7 | }
8 |
9 |
10 | def conv3x3(in_planes, out_planes, stride=1, groups=1, dilation=1):
11 | return nn.Conv2d(in_planes, out_planes, kernel_size=3, stride=stride,
12 | padding=dilation, groups=groups, bias=False, dilation=dilation)
13 |
14 |
15 | def conv1x1(in_planes, out_planes, stride=1):
16 | return nn.Conv2d(in_planes, out_planes, kernel_size=1, stride=stride, bias=False)
17 |
18 |
19 |
20 | class Bottleneck(nn.Module):
21 | expansion = 4
22 | def __init__(self, inplanes, planes, stride=1, downsample=None, groups=1,
23 | base_width=64, dilation=1, norm_layer=None):
24 | super(Bottleneck, self).__init__()
25 | if norm_layer is None:
26 | norm_layer = nn.BatchNorm2d
27 | width = int(planes * (base_width / 64.)) * groups
28 | # Both self.conv2 and self.downsample layers downsample the input when stride != 1
29 | self.conv1 = conv1x1(inplanes, width)
30 | self.bn1 = norm_layer(width)
31 |
32 | self.conv2 = conv3x3(width, width, stride, groups, dilation)
33 | self.bn2 = norm_layer(width)
34 |
35 | self.conv3 = conv1x1(width, planes * self.expansion)
36 | self.bn3 = norm_layer(planes * self.expansion)
37 | self.relu = nn.ReLU(inplace=True)
38 | self.downsample = downsample
39 | self.stride = stride
40 |
41 | def forward(self, x):
42 | identity = x
43 |
44 | out = self.conv1(x)
45 | out = self.bn1(out)
46 | out = self.relu(out)
47 |
48 | out = self.conv2(out)
49 | out = self.bn2(out)
50 | out = self.relu(out)
51 |
52 | out = self.conv3(out)
53 | out = self.bn3(out)
54 |
55 | if self.downsample is not None:
56 | identity = self.downsample(x)
57 |
58 | out += identity
59 | out = self.relu(out)
60 |
61 | return out
62 |
63 |
64 | class ResNet(nn.Module):
65 |
66 | def __init__(self, block, layers, num_classes=1000, zero_init_residual=False,
67 | groups=1, width_per_group=64, replace_stride_with_dilation=None,
68 | norm_layer=None):
69 | super(ResNet, self).__init__()
70 | if norm_layer is None:
71 | norm_layer = nn.BatchNorm2d
72 | self._norm_layer = norm_layer
73 |
74 | self.inplanes = 64
75 | self.dilation = 1
76 | if replace_stride_with_dilation is None:
77 | replace_stride_with_dilation = [False, False, False]
78 |
79 | if len(replace_stride_with_dilation) != 3:
80 | raise ValueError("replace_stride_with_dilation should be None "
81 | "or a 3-element tuple, got {}".format(replace_stride_with_dilation))
82 |
83 | self.block = block
84 | self.groups = groups
85 | self.base_width = width_per_group
86 |
87 | # 224,224,3 -> 112,112,64
88 | self.conv1 = nn.Conv2d(3, self.inplanes, kernel_size=7, stride=2, padding=3,
89 | bias=False)
90 | self.bn1 = norm_layer(self.inplanes)
91 | self.relu = nn.ReLU(inplace=True)
92 |
93 | # 112,112,64 -> 56,56,64
94 | self.maxpool = nn.MaxPool2d(kernel_size=3, stride=2, padding=1)
95 |
96 | # 56,56,64 -> 56,56,256
97 | self.layer1 = self._make_layer(block, 64, layers[0])
98 |
99 | # 56,56,256 -> 28,28,512
100 | self.layer2 = self._make_layer(block, 128, layers[1], stride=2,
101 | dilate=replace_stride_with_dilation[0])
102 |
103 | # 28,28,512 -> 14,14,1024
104 | self.layer3 = self._make_layer(block, 256, layers[2], stride=2,
105 | dilate=replace_stride_with_dilation[1])
106 |
107 | # 14,14,1024 -> 7,7,2048
108 | self.layer4 = self._make_layer(block, 512, layers[3], stride=2,
109 | dilate=replace_stride_with_dilation[2])
110 |
111 | # 7,7,2048 -> 2048
112 | self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
113 |
114 | # 2048 -> num_classes
115 | self.fc = nn.Linear(512 * block.expansion, num_classes)
116 |
117 | for m in self.modules():
118 | if isinstance(m, nn.Conv2d):
119 | nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
120 | elif isinstance(m, (nn.BatchNorm2d, nn.GroupNorm)):
121 | nn.init.constant_(m.weight, 1)
122 | nn.init.constant_(m.bias, 0)
123 |
124 | if zero_init_residual:
125 | for m in self.modules():
126 | if isinstance(m, Bottleneck):
127 | nn.init.constant_(m.bn3.weight, 0)
128 |
129 | def _make_layer(self, block, planes, blocks, stride=1, dilate=False):
130 | norm_layer = self._norm_layer
131 | downsample = None
132 | previous_dilation = self.dilation
133 | if dilate:
134 | self.dilation *= stride
135 | stride = 1
136 | if stride != 1 or self.inplanes != planes * block.expansion:
137 | downsample = nn.Sequential(
138 | conv1x1(self.inplanes, planes * block.expansion, stride),
139 | norm_layer(planes * block.expansion),
140 | )
141 |
142 | layers = []
143 | # Conv_block
144 | layers.append(block(self.inplanes, planes, stride, downsample, self.groups,
145 | self.base_width, previous_dilation, norm_layer))
146 | self.inplanes = planes * block.expansion
147 | for _ in range(1, blocks):
148 | # identity_block
149 | layers.append(block(self.inplanes, planes, groups=self.groups,
150 | base_width=self.base_width, dilation=self.dilation,
151 | norm_layer=norm_layer))
152 |
153 | return nn.Sequential(*layers)
154 |
155 | def forward(self, x):
156 | x = self.conv1(x)
157 | x = self.bn1(x)
158 | x = self.relu(x)
159 | x = self.maxpool(x)
160 |
161 | x = self.layer1(x)
162 | x = self.layer2(x)
163 | x = self.layer3(x)
164 | x = self.layer4(x)
165 |
166 | x = self.avgpool(x)
167 | x = torch.flatten(x, 1)
168 | x = self.fc(x)
169 |
170 | return x
171 |
172 | def freeze_backbone(self):
173 | backbone = [self.conv1, self.bn1, self.layer1, self.layer2, self.layer3, self.layer4]
174 | for module in backbone:
175 | for param in module.parameters():
176 | param.requires_grad = False
177 |
178 | def Unfreeze_backbone(self):
179 | backbone = [self.conv1, self.bn1, self.layer1, self.layer2, self.layer3, self.layer4]
180 | for module in backbone:
181 | for param in module.parameters():
182 | param.requires_grad = True
183 |
184 |
185 | def resnet50(pretrained=False, progress=True, num_classes=1000):
186 | model = ResNet(Bottleneck, [3, 4, 6, 3])
187 | if pretrained:
188 | state_dict = load_state_dict_from_url(model_urls['resnet50'], model_dir='./model_data',
189 | progress=progress)
190 | model.load_state_dict(state_dict)
191 |
192 | if num_classes!=1000:
193 | model.fc = nn.Linear(512 * model.block.expansion, num_classes)
194 | return model
195 |
--------------------------------------------------------------------------------
/classification/nets/vgg16.py:
--------------------------------------------------------------------------------
1 | import torch
2 | import torch.nn as nn
3 | from torchvision.models.utils import load_state_dict_from_url
4 |
5 | model_urls = {
6 | 'vgg16': 'https://download.pytorch.org/models/vgg16-397923af.pth',
7 | }
8 |
9 |
10 | class VGG(nn.Module):
11 | def __init__(self, features, num_classes=1000, init_weights=True):
12 | super(VGG, self).__init__()
13 | self.features = features
14 | self.avgpool = nn.AdaptiveAvgPool2d((7, 7))
15 | self.classifier = nn.Sequential(
16 | nn.Linear(512 * 7 * 7, 4096),
17 | nn.ReLU(True),
18 | nn.Dropout(),
19 | nn.Linear(4096, 4096),
20 | nn.ReLU(True),
21 | nn.Dropout(),
22 | nn.Linear(4096, num_classes),
23 | )
24 | if init_weights:
25 | self._initialize_weights()
26 |
27 | def forward(self, x):
28 | x = self.features(x)
29 | x = self.avgpool(x)
30 | x = torch.flatten(x, 1)
31 | x = self.classifier(x)
32 | return x
33 |
34 | def _initialize_weights(self):
35 | for m in self.modules():
36 | if isinstance(m, nn.Conv2d):
37 | nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
38 | if m.bias is not None:
39 | nn.init.constant_(m.bias, 0)
40 | elif isinstance(m, nn.BatchNorm2d):
41 | nn.init.constant_(m.weight, 1)
42 | nn.init.constant_(m.bias, 0)
43 | elif isinstance(m, nn.Linear):
44 | nn.init.normal_(m.weight, 0, 0.01)
45 | nn.init.constant_(m.bias, 0)
46 |
47 | def freeze_backbone(self):
48 | for param in self.features.parameters():
49 | param.requires_grad = False
50 |
51 | def Unfreeze_backbone(self):
52 | for param in self.features.parameters():
53 | param.requires_grad = True
54 |
55 |
56 | def make_layers(cfg, batch_norm=False):
57 | layers = []
58 | in_channels = 3
59 | for v in cfg:
60 | if v == 'M':
61 | layers += [nn.MaxPool2d(kernel_size=2, stride=2)]
62 | else:
63 | conv2d = nn.Conv2d(in_channels, v, kernel_size=3, padding=1)
64 | if batch_norm:
65 | layers += [conv2d, nn.BatchNorm2d(v), nn.ReLU(inplace=True)]
66 | else:
67 | layers += [conv2d, nn.ReLU(inplace=True)]
68 | in_channels = v
69 | return nn.Sequential(*layers)
70 |
71 | # 224,224,3 -> 224,224,64 -> 112,112,64 -> 112,112,128 -> 56,56,128 -> 56,56,256 -> 28,28,256 -> 28,28,512
72 | # 14,14,512 -> 14,14,512 -> 7,7,512
73 | cfgs = {
74 | 'D': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'],
75 | }
76 |
77 | def vgg16(pretrained=False, progress=True, num_classes=1000):
78 | model = VGG(make_layers(cfgs['D']))
79 | if pretrained:
80 | state_dict = load_state_dict_from_url(model_urls['vgg16'], model_dir='./model_data',
81 | progress=progress)
82 | model.load_state_dict(state_dict,strict=False)
83 |
84 | if num_classes!=1000:
85 | model.classifier = nn.Sequential(
86 | nn.Linear(512 * 7 * 7, 4096),
87 | nn.ReLU(True),
88 | nn.Dropout(),
89 | nn.Linear(4096, 4096),
90 | nn.ReLU(True),
91 | nn.Dropout(),
92 | nn.Linear(4096, num_classes),
93 | )
94 | return model
95 |
--------------------------------------------------------------------------------
/classification/predict.py:
--------------------------------------------------------------------------------
1 | from PIL import Image
2 |
3 | from classification import Classification
4 |
5 | classfication = Classification()
6 |
7 | while True:
8 | img = input('Input image filename:')
9 | try:
10 | image = Image.open(img)
11 | except:
12 | print('Open Error! Try again!')
13 | continue
14 | else:
15 | class_name = classfication.detect_image(image)
16 | print(class_name)
17 |
--------------------------------------------------------------------------------
/classification/requirements.txt:
--------------------------------------------------------------------------------
1 | scipy==1.2.1
2 | numpy==1.17.0
3 | matplotlib==3.1.2
4 | opencv_python==4.1.2.30
5 | # torch==1.2.0
6 | # torchvision==0.4.0
7 | tqdm==4.60.0
8 | Pillow==8.2.0
9 | h5py==2.10.0
10 |
--------------------------------------------------------------------------------
/classification/test.py:
--------------------------------------------------------------------------------
1 | from torchsummary import summary
2 |
3 | from nets.mobilenet import mobilenet_v2
4 | from nets.resnet50 import resnet50
5 | from nets.vgg16 import vgg16
6 |
7 | if __name__ == "__main__":
8 | model = vgg16(num_classes=1000, pretrained=False).train().cuda()
9 | summary(model,(3,473,473))
10 |
--------------------------------------------------------------------------------
/classification/train.py:
--------------------------------------------------------------------------------
1 | import time
2 |
3 | import numpy as np
4 | import torch
5 | import torch.backends.cudnn as cudnn
6 | import torch.nn.functional as F
7 | import torch.optim as optim
8 | from torch import nn
9 | from torch.utils.data import DataLoader
10 | from tqdm import tqdm
11 |
12 | from nets.mobilenet import mobilenet_v2
13 | from nets.resnet50 import resnet50
14 | from nets.vgg16 import vgg16
15 | from utils.utils import weights_init
16 | from utils.dataloader import DataGenerator, detection_collate
17 |
18 | get_model_from_name = {
19 | "mobilenet" : mobilenet_v2,
20 | "resnet50" : resnet50,
21 | "vgg16" : vgg16,
22 | }
23 |
24 | freeze_layers = {
25 | "mobilenet" :81,
26 | "resnet50" :173,
27 | "vgg16" :19,
28 | }
29 |
30 | def get_lr(optimizer):
31 | for param_group in optimizer.param_groups:
32 | return param_group['lr']
33 |
34 | def fit_one_epoch(net,epoch,epoch_size,epoch_size_val,gen,genval,Epoch,cuda):
35 | total_loss = 0
36 | total_accuracy = 0
37 |
38 | val_toal_loss = 0
39 | with tqdm(total=epoch_size,desc=f'Epoch {epoch + 1}/{Epoch}',postfix=dict,mininterval=0.3) as pbar:
40 | for iteration, batch in enumerate(gen):
41 | if iteration >= epoch_size:
42 | break
43 | images, targets = batch
44 | with torch.no_grad():
45 | images = torch.from_numpy(images).type(torch.FloatTensor)
46 | targets = torch.from_numpy(targets).type(torch.FloatTensor).long()
47 | if cuda:
48 | images = images.cuda()
49 | targets = targets.cuda()
50 |
51 | optimizer.zero_grad()
52 |
53 | outputs = net(images)
54 | loss = nn.CrossEntropyLoss()(outputs, targets)
55 | loss.backward()
56 | optimizer.step()
57 |
58 | total_loss += loss.item()
59 | with torch.no_grad():
60 | accuracy = torch.mean((torch.argmax(F.softmax(outputs, dim=-1), dim=-1) == targets).type(torch.FloatTensor))
61 | total_accuracy += accuracy.item()
62 |
63 |
64 | pbar.set_postfix(**{'total_loss': total_loss / (iteration + 1),
65 | 'accuracy' : total_accuracy / (iteration + 1),
66 | 'lr' : get_lr(optimizer)})
67 | pbar.update(1)
68 |
69 | print('Start Validation')
70 | with tqdm(total=epoch_size_val, desc=f'Epoch {epoch + 1}/{Epoch}',postfix=dict,mininterval=0.3) as pbar:
71 | for iteration, batch in enumerate(genval):
72 | if iteration >= epoch_size_val:
73 | break
74 | images, targets = batch
75 | with torch.no_grad():
76 | images = torch.from_numpy(images).type(torch.FloatTensor)
77 | targets = torch.from_numpy(targets).type(torch.FloatTensor).long()
78 | if cuda:
79 | images = images.cuda()
80 | targets = targets.cuda()
81 |
82 | optimizer.zero_grad()
83 |
84 | outputs = net(images)
85 | val_loss = nn.CrossEntropyLoss()(outputs, targets)
86 |
87 | val_toal_loss += val_loss.item()
88 |
89 | pbar.set_postfix(**{'total_loss': val_toal_loss / (iteration + 1),
90 | 'lr' : get_lr(optimizer)})
91 | pbar.update(1)
92 |
93 | print('Finish Validation')
94 | print('Epoch:'+ str(epoch+1) + '/' + str(Epoch))
95 | print('Total Loss: %.4f || Val Loss: %.4f ' % (total_loss/(epoch_size+1),val_toal_loss/(epoch_size_val+1)))
96 |
97 | print('Saving state, iter:', str(epoch+1))
98 | torch.save(model.state_dict(), 'classification/logs/Epoch%d-Total_Loss%.4f-Val_Loss%.4f.pth'%((epoch+1),total_loss/(epoch_size+1),val_toal_loss/(epoch_size_val+1)))
99 |
100 | #---------------------------------------------------#
101 | # 获得类
102 | #---------------------------------------------------#
103 | def get_classes(classes_path):
104 | '''loads the classes'''
105 | with open(classes_path) as f:
106 | class_names = f.readlines()
107 | class_names = [c.strip() for c in class_names]
108 | return class_names
109 |
110 | #----------------------------------------#
111 | # 主函数
112 | #----------------------------------------#
113 | if __name__ == "__main__":
114 | log_dir = "classification/logs/"
115 | #---------------------#
116 | # 所用模型种类
117 | #---------------------#
118 | backbone = "mobilenet"
119 | #---------------------#
120 | # 输入的图片大小
121 | #---------------------#
122 | input_shape = [224,224,3]
123 | #-------------------------------#
124 | # Cuda的使用
125 | #-------------------------------#
126 | Cuda = True
127 |
128 | #-------------------------------#
129 | # 是否使用网络的imagenet
130 | # 预训练权重
131 | #-------------------------------#
132 | pretrained = True
133 |
134 | classes_path = 'classification/model_data/cls_classes.txt'
135 | class_names = get_classes(classes_path)
136 | num_classes = len(class_names)
137 |
138 | assert backbone in ["mobilenet", "resnet50", "vgg16"]
139 |
140 | model = get_model_from_name[backbone](num_classes=num_classes,pretrained=pretrained)
141 | if not pretrained:
142 | weights_init(model)
143 |
144 | #------------------------------------------#
145 | # 注释部分可用于断点续练
146 | # 将训练好的模型重新载入
147 | #------------------------------------------#
148 | # # 加快模型训练的效率
149 | # model_path = "model_data/Omniglot_vgg.pth"
150 | # print('Loading weights into state dict...')
151 | # device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
152 | # model_dict = model.state_dict()
153 | # pretrained_dict = torch.load(model_path, map_location=device)
154 | # pretrained_dict = {k: v for k, v in pretrained_dict.items() if np.shape(model_dict[k]) == np.shape(v)}
155 | # model_dict.update(pretrained_dict)
156 | # model.load_state_dict(model_dict)
157 |
158 | with open(r"classification/cls_train.txt","r") as f:
159 | lines = f.readlines()
160 |
161 | np.random.seed(10101)
162 | np.random.shuffle(lines)
163 | np.random.seed(None)
164 | num_val = int(len(lines)*0.1)
165 | num_train = len(lines) - num_val
166 |
167 | net = model.train()
168 | if Cuda:
169 | net = torch.nn.DataParallel(model)
170 | cudnn.benchmark = True
171 | net = net.cuda()
172 |
173 | #------------------------------------------------------#
174 | # 主干特征提取网络特征通用,冻结训练可以加快训练速度
175 | # 也可以在训练初期防止权值被破坏。
176 | # Init_Epoch为起始世代
177 | # Freeze_Epoch为冻结训练的世代
178 | # Epoch总训练世代
179 | # 提示OOM或者显存不足请调小Batch_size
180 | #------------------------------------------------------#
181 | if True:
182 | #--------------------------------------------#
183 | # BATCH_SIZE不要太小,不然训练效果很差
184 | #--------------------------------------------#
185 | lr = 1e-3
186 | Batch_size = 32
187 | Init_Epoch = 0
188 | Freeze_Epoch = 50
189 |
190 | optimizer = optim.Adam(net.parameters(),lr,weight_decay=5e-4)
191 | lr_scheduler = optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.9)
192 |
193 | train_dataset = DataGenerator(input_shape,lines[:num_train])
194 | val_dataset = DataGenerator(input_shape,lines[num_train:], False)
195 | gen = DataLoader(train_dataset, batch_size=Batch_size, num_workers=4, pin_memory=True,
196 | drop_last=True, collate_fn=detection_collate)
197 | gen_val = DataLoader(val_dataset, batch_size=Batch_size, num_workers=4, pin_memory=True,
198 | drop_last=True, collate_fn=detection_collate)
199 |
200 | epoch_size = train_dataset.get_len()//Batch_size
201 | epoch_size_val = val_dataset.get_len()//Batch_size
202 |
203 | print(train_dataset.get_len(), val_dataset.get_len())
204 |
205 | if epoch_size == 0 or epoch_size_val == 0:
206 | raise ValueError("数据集过小,无法进行训练,请扩充数据集。")
207 | #------------------------------------#
208 | # 冻结一定部分训练
209 | #------------------------------------#
210 | model.freeze_backbone()
211 |
212 | for epoch in range(Init_Epoch,Freeze_Epoch):
213 | fit_one_epoch(model,epoch,epoch_size,epoch_size_val,gen,gen_val,Freeze_Epoch,Cuda)
214 | lr_scheduler.step()
215 |
216 | if True:
217 | #--------------------------------------------#
218 | # BATCH_SIZE不要太小,不然训练效果很差
219 | #--------------------------------------------#
220 | lr = 1e-4
221 | Batch_size = 16
222 | Freeze_Epoch = 50
223 | Epoch = 100
224 |
225 | optimizer = optim.Adam(net.parameters(),lr,weight_decay=5e-4)
226 | lr_scheduler = optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.9)
227 |
228 | train_dataset = DataGenerator(input_shape,lines[:num_train])
229 | val_dataset = DataGenerator(input_shape,lines[num_train:], False)
230 | gen = DataLoader(train_dataset, batch_size=Batch_size, num_workers=2, pin_memory=True,
231 | drop_last=True, collate_fn=detection_collate)
232 | gen_val = DataLoader(val_dataset, batch_size=Batch_size, num_workers=2, pin_memory=True,
233 | drop_last=True, collate_fn=detection_collate)
234 |
235 | epoch_size = train_dataset.get_len()//Batch_size
236 | epoch_size_val = val_dataset.get_len()//Batch_size
237 |
238 | if epoch_size == 0 or epoch_size_val == 0:
239 | raise ValueError("数据集过小,无法进行训练,请扩充数据集。")
240 | #------------------------------------#
241 | # 解冻后训练
242 | #------------------------------------#
243 | model.Unfreeze_backbone()
244 |
245 | for epoch in range(Freeze_Epoch,Epoch):
246 | fit_one_epoch(model,epoch,epoch_size,epoch_size_val,gen,gen_val,Epoch,Cuda)
247 | lr_scheduler.step()
248 |
--------------------------------------------------------------------------------
/classification/txt_annotation.py:
--------------------------------------------------------------------------------
1 | import os
2 | from os import getcwd
3 |
4 | #---------------------------------------------#
5 | # 训练前一定要注意修改classes
6 | # 种类顺序需要和model_data下的txt一样
7 | #---------------------------------------------#
8 | classes = ["camera", "chair", "cup", "schooner"]
9 | sets = ["train", "test"]
10 |
11 | wd = getcwd()
12 | for se in sets:
13 | list_file = open('classification/cls_' + se + '.txt', 'w')
14 |
15 | datasets_path = "classification/datasets/" + se
16 | types_name = os.listdir(datasets_path)
17 | for type_name in types_name:
18 | if type_name not in classes:
19 | continue
20 | cls_id = classes.index(type_name)
21 |
22 | photos_path = os.path.join(datasets_path, type_name)
23 | photos_name = os.listdir(photos_path)
24 | for photo_name in photos_name:
25 | _, postfix = os.path.splitext(photo_name)
26 | if postfix not in ['.jpg', '.png', '.jpeg']:
27 | continue
28 | list_file.write(str(cls_id) + ";" + '%s/%s'%(wd, os.path.join(photos_path, photo_name)))
29 | list_file.write('\n')
30 | list_file.close()
31 |
32 |
--------------------------------------------------------------------------------
/classification/utils/__pycache__/dataloader.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/classification/utils/__pycache__/dataloader.cpython-37.pyc
--------------------------------------------------------------------------------
/classification/utils/__pycache__/utils.cpython-37.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/classification/utils/__pycache__/utils.cpython-37.pyc
--------------------------------------------------------------------------------
/classification/utils/dataloader.py:
--------------------------------------------------------------------------------
1 | from random import shuffle
2 |
3 | import cv2
4 | import numpy as np
5 | import torch.utils.data as data
6 | from PIL import Image
7 |
8 | from utils.utils import letterbox_image
9 |
10 |
11 | #----------------------------------------#
12 | # 预处理训练图片
13 | #----------------------------------------#
14 | def _preprocess_input(x,):
15 | x /= 127.5
16 | x -= 1.
17 | return x
18 |
19 | def rand(a=0, b=1):
20 | return np.random.rand()*(b-a) + a
21 |
22 | def get_random_data(image, input_shape, jitter=.3, hue=.1, sat=1.5, val=1.5):
23 | image = image.convert("RGB")
24 | h, w = input_shape
25 |
26 | # 对图像进行缩放并且进行长和宽的扭曲
27 | new_ar = w/h * rand(1-jitter,1+jitter)/rand(1-jitter,1+jitter)
28 | scale = rand(.75, 1.25)
29 | if new_ar < 1:
30 | nh = int(scale*h)
31 | nw = int(nh*new_ar)
32 | else:
33 | nw = int(scale*w)
34 | nh = int(nw/new_ar)
35 | image = image.resize((nw,nh), Image.BICUBIC)
36 |
37 | # 将图像多余的部分加上灰条
38 | dx = int(rand(0, w-nw))
39 | dy = int(rand(0, h-nh))
40 | new_image = Image.new('RGB', (w,h), (128,128,128))
41 | new_image.paste(image, (dx, dy))
42 | image = new_image
43 |
44 | # 翻转图像
45 | flip = rand()<.5
46 | if flip: image = image.transpose(Image.FLIP_LEFT_RIGHT)
47 |
48 | rotate = rand()<.5
49 | if rotate:
50 | angle=np.random.randint(-15,15)
51 | a,b=w/2,h/2
52 | M=cv2.getRotationMatrix2D((a,b),angle,1)
53 | image=cv2.warpAffine(np.array(image),M,(w,h),borderValue=[128,128,128])
54 |
55 | # 色域扭曲
56 | hue = rand(-hue, hue)
57 | sat = rand(1, sat) if rand()<.5 else 1/rand(1, sat)
58 | val = rand(1, val) if rand()<.5 else 1/rand(1, val)
59 | x = cv2.cvtColor(np.array(image,np.float32)/255, cv2.COLOR_RGB2HSV)
60 | x[..., 1] *= sat
61 | x[..., 2] *= val
62 | x[x[:,:, 0]>360, 0] = 360
63 | x[:, :, 1:][x[:, :, 1:]>1] = 1
64 | x[x<0] = 0
65 | image_data = cv2.cvtColor(x, cv2.COLOR_HSV2RGB)*255
66 | return image_data
67 |
68 | class DataGenerator(data.Dataset):
69 | def __init__(self, input_shape, lines, random=True):
70 | self.input_shape = input_shape
71 | self.lines = lines
72 | self.random = random
73 |
74 | def __len__(self):
75 | return len(self.lines)
76 |
77 | def get_len(self):
78 | return len(self.lines)
79 |
80 | def __getitem__(self, index):
81 | if index == 0:
82 | shuffle(self.lines)
83 |
84 | annotation_path = self.lines[index].split(';')[1].split()[0]
85 | img = Image.open(annotation_path)
86 |
87 | if self.random:
88 | img = get_random_data(img, [self.input_shape[0],self.input_shape[1]])
89 | else:
90 | img = letterbox_image(img, [self.input_shape[0],self.input_shape[1]])
91 |
92 | img = np.array(img).astype(np.float32)
93 | img = _preprocess_input(img)
94 | img = np.transpose(img,[2,0,1])
95 |
96 | y = int(self.lines[index].split(';')[0])
97 | return img, y
98 |
99 | def detection_collate(batch):
100 | images = []
101 | targets = []
102 | for img, y in batch:
103 | images.append(img)
104 | targets.append(y)
105 | images = np.array(images)
106 | targets = np.array(targets)
107 | return images, targets
108 |
--------------------------------------------------------------------------------
/classification/utils/utils.py:
--------------------------------------------------------------------------------
1 | import torch
2 | from PIL import Image
3 |
4 |
5 | def letterbox_image(image, size):
6 | '''resize image with unchanged aspect ratio using padding'''
7 | iw, ih = image.size
8 | h, w = size
9 | scale = min(w/iw, h/ih)
10 | nw = int(iw*scale)
11 | nh = int(ih*scale)
12 |
13 | image = image.resize((nw,nh), Image.BICUBIC)
14 | new_image = Image.new('RGB', size, (128,128,128))
15 | new_image.paste(image, ((w-nw)//2, (h-nh)//2))
16 | return new_image
17 |
18 | def weights_init(net, init_type='normal', init_gain=0.02):
19 | def init_func(m):
20 | classname = m.__class__.__name__
21 | if hasattr(m, 'weight') and classname.find('Conv') != -1:
22 | if init_type == 'normal':
23 | torch.nn.init.normal_(m.weight.data, 0.0, init_gain)
24 | elif init_type == 'xavier':
25 | torch.nn.init.xavier_normal_(m.weight.data, gain=init_gain)
26 | elif init_type == 'kaiming':
27 | torch.nn.init.kaiming_normal_(m.weight.data, a=0, mode='fan_in')
28 | elif init_type == 'orthogonal':
29 | torch.nn.init.orthogonal_(m.weight.data, gain=init_gain)
30 | else:
31 | raise NotImplementedError('initialization method [%s] is not implemented' % init_type)
32 | elif classname.find('BatchNorm2d') != -1:
33 | torch.nn.init.normal_(m.weight.data, 1.0, 0.02)
34 | torch.nn.init.constant_(m.bias.data, 0.0)
35 | print('initialize network with %s type' % init_type)
36 | net.apply(init_func)
37 |
--------------------------------------------------------------------------------
/examples/media/COCO_val2014_000000000192.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/COCO_val2014_000000000192.jpg
--------------------------------------------------------------------------------
/examples/media/COCO_val2014_000000000241.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/COCO_val2014_000000000241.jpg
--------------------------------------------------------------------------------
/examples/media/COCO_val2014_000000000257.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/COCO_val2014_000000000257.jpg
--------------------------------------------------------------------------------
/examples/media/COCO_val2014_000000000294.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/COCO_val2014_000000000294.jpg
--------------------------------------------------------------------------------
/examples/media/COCO_val2014_000000000328.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/COCO_val2014_000000000328.jpg
--------------------------------------------------------------------------------
/examples/media/COCO_val2014_000000000338.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/COCO_val2014_000000000338.jpg
--------------------------------------------------------------------------------
/examples/media/COCO_val2014_000000000357.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/COCO_val2014_000000000357.jpg
--------------------------------------------------------------------------------
/examples/media/COCO_val2014_000000000360.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/COCO_val2014_000000000360.jpg
--------------------------------------------------------------------------------
/examples/media/COCO_val2014_000000000395.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/COCO_val2014_000000000395.jpg
--------------------------------------------------------------------------------
/examples/media/COCO_val2014_000000000415.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/COCO_val2014_000000000415.jpg
--------------------------------------------------------------------------------
/examples/media/COCO_val2014_000000000428.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/COCO_val2014_000000000428.jpg
--------------------------------------------------------------------------------
/examples/media/COCO_val2014_000000000459.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/COCO_val2014_000000000459.jpg
--------------------------------------------------------------------------------
/examples/media/COCO_val2014_000000000474.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/COCO_val2014_000000000474.jpg
--------------------------------------------------------------------------------
/examples/media/COCO_val2014_000000000488.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/COCO_val2014_000000000488.jpg
--------------------------------------------------------------------------------
/examples/media/COCO_val2014_000000000536.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/COCO_val2014_000000000536.jpg
--------------------------------------------------------------------------------
/examples/media/COCO_val2014_000000000544.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/COCO_val2014_000000000544.jpg
--------------------------------------------------------------------------------
/examples/media/COCO_val2014_000000000564.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/COCO_val2014_000000000564.jpg
--------------------------------------------------------------------------------
/examples/media/COCO_val2014_000000000569.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/COCO_val2014_000000000569.jpg
--------------------------------------------------------------------------------
/examples/media/COCO_val2014_000000000589.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/COCO_val2014_000000000589.jpg
--------------------------------------------------------------------------------
/examples/media/COCO_val2014_000000000623.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/COCO_val2014_000000000623.jpg
--------------------------------------------------------------------------------
/examples/media/test3.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/test3.mp4
--------------------------------------------------------------------------------
/examples/media/test4.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/test4.mp4
--------------------------------------------------------------------------------
/examples/media/test4_60fps.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/test4_60fps.mp4
--------------------------------------------------------------------------------
/examples/media/test5.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/test5.mp4
--------------------------------------------------------------------------------
/examples/media/video.avi:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/examples/media/video.avi
--------------------------------------------------------------------------------
/examples/tutorial_api_cpp/01_body_from_image_default.cpp:
--------------------------------------------------------------------------------
1 | // ----------------------------- OpenPose C++ API Tutorial - Example 1 - Body from image -----------------------------
2 | // It reads an image, process it, and displays it with the pose keypoints.
3 |
4 | // Third-party dependencies
5 | #include
6 | // Command-line user interface
7 | #define OPENPOSE_FLAGS_DISABLE_POSE
8 | #include
9 | // OpenPose dependencies
10 | #include
11 |
12 | // Custom OpenPose flags
13 | // Producer
14 | DEFINE_string(image_path, "examples/media/COCO_val2014_000000000192.jpg",
15 | "Process an image. Read all standard formats (jpg, png, bmp, etc.).");
16 | // Display
17 | DEFINE_bool(no_display, false,
18 | "Enable to disable the visual display.");
19 |
20 | // This worker will just read and return all the jpg files in a directory
21 | void display(const std::shared_ptr>>& datumsPtr)
22 | {
23 | try
24 | {
25 | // User's displaying/saving/other processing here
26 | // datum.cvOutputData: rendered frame with pose or heatmaps
27 | // datum.poseKeypoints: Array with the estimated pose
28 | if (datumsPtr != nullptr && !datumsPtr->empty())
29 | {
30 | // Display image
31 | const cv::Mat cvMat = OP_OP2CVCONSTMAT(datumsPtr->at(0)->cvOutputData);
32 | if (!cvMat.empty())
33 | {
34 | cv::imshow(OPEN_POSE_NAME_AND_VERSION + " - Tutorial C++ API", cvMat);
35 | cv::waitKey(0);
36 | }
37 | else
38 | op::opLog("Empty cv::Mat as output.", op::Priority::High, __LINE__, __FUNCTION__, __FILE__);
39 | }
40 | else
41 | op::opLog("Nullptr or empty datumsPtr found.", op::Priority::High);
42 | }
43 | catch (const std::exception& e)
44 | {
45 | op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
46 | }
47 | }
48 |
49 | void printKeypoints(const std::shared_ptr>>& datumsPtr)
50 | {
51 | try
52 | {
53 | // Example: How to use the pose keypoints
54 | if (datumsPtr != nullptr && !datumsPtr->empty())
55 | {
56 | // Alternative 1
57 | op::opLog("Body keypoints: " + datumsPtr->at(0)->poseKeypoints.toString(), op::Priority::High);
58 |
59 | // // Alternative 2
60 | // op::opLog(datumsPtr->at(0)->poseKeypoints, op::Priority::High);
61 |
62 | // // Alternative 3
63 | // std::cout << datumsPtr->at(0)->poseKeypoints << std::endl;
64 |
65 | // // Alternative 4 - Accesing each element of the keypoints
66 | // op::opLog("\nKeypoints:", op::Priority::High);
67 | // const auto& poseKeypoints = datumsPtr->at(0)->poseKeypoints;
68 | // op::opLog("Person pose keypoints:", op::Priority::High);
69 | // for (auto person = 0 ; person < poseKeypoints.getSize(0) ; person++)
70 | // {
71 | // op::opLog("Person " + std::to_string(person) + " (x, y, score):", op::Priority::High);
72 | // for (auto bodyPart = 0 ; bodyPart < poseKeypoints.getSize(1) ; bodyPart++)
73 | // {
74 | // std::string valueToPrint;
75 | // for (auto xyscore = 0 ; xyscore < poseKeypoints.getSize(2) ; xyscore++)
76 | // valueToPrint += std::to_string( poseKeypoints[{person, bodyPart, xyscore}] ) + " ";
77 | // op::opLog(valueToPrint, op::Priority::High);
78 | // }
79 | // }
80 | // op::opLog(" ", op::Priority::High);
81 | }
82 | else
83 | op::opLog("Nullptr or empty datumsPtr found.", op::Priority::High);
84 | }
85 | catch (const std::exception& e)
86 | {
87 | op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
88 | }
89 | }
90 |
91 | int tutorialApiCpp()
92 | {
93 | try
94 | {
95 | op::opLog("Starting OpenPose demo...", op::Priority::High);
96 | const auto opTimer = op::getTimerInit();
97 |
98 | // Configuring OpenPose
99 | op::opLog("Configuring OpenPose...", op::Priority::High);
100 | op::Wrapper opWrapper{op::ThreadManagerMode::Asynchronous};
101 | // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)
102 | if (FLAGS_disable_multi_thread)
103 | opWrapper.disableMultiThreading();
104 |
105 | // Starting OpenPose
106 | op::opLog("Starting thread(s)...", op::Priority::High);
107 | opWrapper.start();
108 |
109 | // Process and display image
110 | const cv::Mat cvImageToProcess = cv::imread(FLAGS_image_path);
111 | const op::Matrix imageToProcess = OP_CV2OPCONSTMAT(cvImageToProcess);
112 | auto datumProcessed = opWrapper.emplaceAndPop(imageToProcess);
113 | if (datumProcessed != nullptr)
114 | {
115 | printKeypoints(datumProcessed);
116 | if (!FLAGS_no_display)
117 | display(datumProcessed);
118 | }
119 | else
120 | op::opLog("Image could not be processed.", op::Priority::High);
121 |
122 | // Measuring total time
123 | op::printTime(opTimer, "OpenPose demo successfully finished. Total time: ", " seconds.", op::Priority::High);
124 |
125 | // Return
126 | return 0;
127 | }
128 | catch (const std::exception&)
129 | {
130 | return -1;
131 | }
132 | }
133 |
134 | int main(int argc, char *argv[])
135 | {
136 | // Parsing command line flags
137 | gflags::ParseCommandLineFlags(&argc, &argv, true);
138 |
139 | // Running tutorialApiCpp
140 | return tutorialApiCpp();
141 | }
142 |
--------------------------------------------------------------------------------
/examples/tutorial_api_cpp/02_whole_body_from_image_default.cpp:
--------------------------------------------------------------------------------
1 | // -------------------------- OpenPose C++ API Tutorial - Example 2 - Whole body from image --------------------------
2 | // It reads an image, process it, and displays it with the pose, hand, and face keypoints.
3 |
4 | // Third-party dependencies
5 | #include
6 | // Command-line user interface
7 | #define OPENPOSE_FLAGS_DISABLE_POSE
8 | #include
9 | // OpenPose dependencies
10 | #include
11 |
12 | // Custom OpenPose flags
13 | // Producer
14 | DEFINE_string(image_path, "examples/media/COCO_val2014_000000000241.jpg",
15 | "Process an image. Read all standard formats (jpg, png, bmp, etc.).");
16 | // Display
17 | DEFINE_bool(no_display, false,
18 | "Enable to disable the visual display.");
19 |
20 | // This worker will just read and return all the jpg files in a directory
21 | void display(const std::shared_ptr>>& datumsPtr)
22 | {
23 | try
24 | {
25 | // User's displaying/saving/other processing here
26 | // datum.cvOutputData: rendered frame with pose or heatmaps
27 | // datum.poseKeypoints: Array with the estimated pose
28 | if (datumsPtr != nullptr && !datumsPtr->empty())
29 | {
30 | // Display image
31 | const cv::Mat cvMat = OP_OP2CVCONSTMAT(datumsPtr->at(0)->cvOutputData);
32 | if (!cvMat.empty())
33 | {
34 | cv::imshow(OPEN_POSE_NAME_AND_VERSION + " - Tutorial C++ API", cvMat);
35 | cv::waitKey(0);
36 | }
37 | else
38 | op::opLog("Empty cv::Mat as output.", op::Priority::High, __LINE__, __FUNCTION__, __FILE__);
39 | }
40 | else
41 | op::opLog("Nullptr or empty datumsPtr found.", op::Priority::High);
42 | }
43 | catch (const std::exception& e)
44 | {
45 | op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
46 | }
47 | }
48 |
49 | void printKeypoints(const std::shared_ptr>>& datumsPtr)
50 | {
51 | try
52 | {
53 | // Example: How to use the pose keypoints
54 | if (datumsPtr != nullptr && !datumsPtr->empty())
55 | {
56 | op::opLog("Body keypoints: " + datumsPtr->at(0)->poseKeypoints.toString(), op::Priority::High);
57 | op::opLog("Face keypoints: " + datumsPtr->at(0)->faceKeypoints.toString(), op::Priority::High);
58 | op::opLog("Left hand keypoints: " + datumsPtr->at(0)->handKeypoints[0].toString(), op::Priority::High);
59 | op::opLog("Right hand keypoints: " + datumsPtr->at(0)->handKeypoints[1].toString(), op::Priority::High);
60 | }
61 | else
62 | op::opLog("Nullptr or empty datumsPtr found.", op::Priority::High);
63 | }
64 | catch (const std::exception& e)
65 | {
66 | op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
67 | }
68 | }
69 |
70 | int tutorialApiCpp()
71 | {
72 | try
73 | {
74 | op::opLog("Starting OpenPose demo...", op::Priority::High);
75 | const auto opTimer = op::getTimerInit();
76 |
77 | // Configuring OpenPose
78 | op::opLog("Configuring OpenPose...", op::Priority::High);
79 | op::Wrapper opWrapper{op::ThreadManagerMode::Asynchronous};
80 | // Add hand and face
81 | opWrapper.configure(op::WrapperStructFace{true});
82 | opWrapper.configure(op::WrapperStructHand{true});
83 | // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)
84 | if (FLAGS_disable_multi_thread)
85 | opWrapper.disableMultiThreading();
86 |
87 | // Starting OpenPose
88 | op::opLog("Starting thread(s)...", op::Priority::High);
89 | opWrapper.start();
90 |
91 | // Process and display image
92 | const cv::Mat cvImageToProcess = cv::imread(FLAGS_image_path);
93 | const op::Matrix imageToProcess = OP_CV2OPCONSTMAT(cvImageToProcess);
94 | auto datumProcessed = opWrapper.emplaceAndPop(imageToProcess);
95 | if (datumProcessed != nullptr)
96 | {
97 | printKeypoints(datumProcessed);
98 | if (!FLAGS_no_display)
99 | display(datumProcessed);
100 | }
101 | else
102 | op::opLog("Image could not be processed.", op::Priority::High);
103 |
104 | // Measuring total time
105 | op::printTime(opTimer, "OpenPose demo successfully finished. Total time: ", " seconds.", op::Priority::High);
106 |
107 | // Return
108 | return 0;
109 | }
110 | catch (const std::exception&)
111 | {
112 | return -1;
113 | }
114 | }
115 |
116 | int main(int argc, char *argv[])
117 | {
118 | // Parsing command line flags
119 | gflags::ParseCommandLineFlags(&argc, &argv, true);
120 |
121 | // Running tutorialApiCpp
122 | return tutorialApiCpp();
123 | }
124 |
--------------------------------------------------------------------------------
/examples/tutorial_api_cpp/03_keypoints_from_image.cpp:
--------------------------------------------------------------------------------
1 | // ----------------------- OpenPose C++ API Tutorial - Example 3 - Body from image -----------------------
2 | // It reads an image, process it, and displays it with the pose (and optionally hand and face) keypoints. In addition,
3 | // it includes all the OpenPose configuration flags (enable/disable hand, face, output saving, etc.).
4 |
5 | // Third-party dependencies
6 | #include
7 | // Command-line user interface
8 | #define OPENPOSE_FLAGS_DISABLE_PRODUCER
9 | #define OPENPOSE_FLAGS_DISABLE_DISPLAY
10 | #include
11 | // OpenPose dependencies
12 | #include
13 |
14 | // Custom OpenPose flags
15 | // Producer
16 | DEFINE_string(image_path, "examples/media/COCO_val2014_000000000294.jpg",
17 | "Process an image. Read all standard formats (jpg, png, bmp, etc.).");
18 | // Display
19 | DEFINE_bool(no_display, false,
20 | "Enable to disable the visual display.");
21 |
22 | // This worker will just read and return all the jpg files in a directory
23 | void display(const std::shared_ptr>>& datumsPtr)
24 | {
25 | try
26 | {
27 | // User's displaying/saving/other processing here
28 | // datum.cvOutputData: rendered frame with pose or heatmaps
29 | // datum.poseKeypoints: Array with the estimated pose
30 | if (datumsPtr != nullptr && !datumsPtr->empty())
31 | {
32 | // Display image
33 | const cv::Mat cvMat = OP_OP2CVCONSTMAT(datumsPtr->at(0)->cvOutputData);
34 | if (!cvMat.empty())
35 | {
36 | cv::imshow(OPEN_POSE_NAME_AND_VERSION + " - Tutorial C++ API", cvMat);
37 | cv::waitKey(0);
38 | }
39 | else
40 | op::opLog("Empty cv::Mat as output.", op::Priority::High, __LINE__, __FUNCTION__, __FILE__);
41 | }
42 | else
43 | op::opLog("Nullptr or empty datumsPtr found.", op::Priority::High);
44 | }
45 | catch (const std::exception& e)
46 | {
47 | op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
48 | }
49 | }
50 |
51 | void printKeypoints(const std::shared_ptr>>& datumsPtr)
52 | {
53 | try
54 | {
55 | // Example: How to use the pose keypoints
56 | if (datumsPtr != nullptr && !datumsPtr->empty())
57 | {
58 | op::opLog("Body keypoints: " + datumsPtr->at(0)->poseKeypoints.toString(), op::Priority::High);
59 | op::opLog("Face keypoints: " + datumsPtr->at(0)->faceKeypoints.toString(), op::Priority::High);
60 | op::opLog("Left hand keypoints: " + datumsPtr->at(0)->handKeypoints[0].toString(), op::Priority::High);
61 | op::opLog("Right hand keypoints: " + datumsPtr->at(0)->handKeypoints[1].toString(), op::Priority::High);
62 | }
63 | else
64 | op::opLog("Nullptr or empty datumsPtr found.", op::Priority::High);
65 | }
66 | catch (const std::exception& e)
67 | {
68 | op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
69 | }
70 | }
71 |
72 | void configureWrapper(op::Wrapper& opWrapper)
73 | {
74 | try
75 | {
76 | // Configuring OpenPose
77 |
78 | // logging_level
79 | op::checkBool(
80 | 0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.",
81 | __LINE__, __FUNCTION__, __FILE__);
82 | op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);
83 | op::Profiler::setDefaultX(FLAGS_profile_speed);
84 |
85 | // Applying user defined configuration - GFlags to program variables
86 | // outputSize
87 | const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), "-1x-1");
88 | // netInputSize
89 | const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), "-1x368");
90 | // faceNetInputSize
91 | const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), "368x368 (multiples of 16)");
92 | // handNetInputSize
93 | const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), "368x368 (multiples of 16)");
94 | // poseMode
95 | const auto poseMode = op::flagsToPoseMode(FLAGS_body);
96 | // poseModel
97 | const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));
98 | // JSON saving
99 | if (!FLAGS_write_keypoint.empty())
100 | op::opLog(
101 | "Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`"
102 | " instead.", op::Priority::Max);
103 | // keypointScaleMode
104 | const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);
105 | // heatmaps to add
106 | const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,
107 | FLAGS_heatmaps_add_PAFs);
108 | const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);
109 | // >1 camera view?
110 | const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1);
111 | // Face and hand detectors
112 | const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);
113 | const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);
114 | // Enabling Google Logging
115 | const bool enableGoogleLogging = true;
116 |
117 | // Pose configuration (use WrapperStructPose{} for default and recommended configuration)
118 | const op::WrapperStructPose wrapperStructPose{
119 | poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,
120 | FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,
121 | op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,
122 | (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),
123 | heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,
124 | FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),
125 | op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};
126 | opWrapper.configure(wrapperStructPose);
127 | // Face configuration (use op::WrapperStructFace{} to disable it)
128 | const op::WrapperStructFace wrapperStructFace{
129 | FLAGS_face, faceDetector, faceNetInputSize,
130 | op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),
131 | (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};
132 | opWrapper.configure(wrapperStructFace);
133 | // Hand configuration (use op::WrapperStructHand{} to disable it)
134 | const op::WrapperStructHand wrapperStructHand{
135 | FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,
136 | op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,
137 | (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};
138 | opWrapper.configure(wrapperStructHand);
139 | // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)
140 | const op::WrapperStructExtra wrapperStructExtra{
141 | FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};
142 | opWrapper.configure(wrapperStructExtra);
143 | // Output (comment or use default argument to disable any output)
144 | const op::WrapperStructOutput wrapperStructOutput{
145 | FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),
146 | op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,
147 | FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),
148 | op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,
149 | op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),
150 | op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),
151 | op::String(FLAGS_udp_port)};
152 | opWrapper.configure(wrapperStructOutput);
153 | // No GUI. Equivalent to: opWrapper.configure(op::WrapperStructGui{});
154 | // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)
155 | if (FLAGS_disable_multi_thread)
156 | opWrapper.disableMultiThreading();
157 | }
158 | catch (const std::exception& e)
159 | {
160 | op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
161 | }
162 | }
163 |
164 | int tutorialApiCpp()
165 | {
166 | try
167 | {
168 | op::opLog("Starting OpenPose demo...", op::Priority::High);
169 | const auto opTimer = op::getTimerInit();
170 |
171 | // Configuring OpenPose
172 | op::opLog("Configuring OpenPose...", op::Priority::High);
173 | op::Wrapper opWrapper{op::ThreadManagerMode::Asynchronous};
174 | configureWrapper(opWrapper);
175 |
176 | // Starting OpenPose
177 | op::opLog("Starting thread(s)...", op::Priority::High);
178 | opWrapper.start();
179 |
180 | // Process and display image
181 | const cv::Mat cvImageToProcess = cv::imread(FLAGS_image_path);
182 | const op::Matrix imageToProcess = OP_CV2OPCONSTMAT(cvImageToProcess);
183 | auto datumProcessed = opWrapper.emplaceAndPop(imageToProcess);
184 | if (datumProcessed != nullptr)
185 | {
186 | printKeypoints(datumProcessed);
187 | if (!FLAGS_no_display)
188 | display(datumProcessed);
189 | }
190 | else
191 | op::opLog("Image could not be processed.", op::Priority::High);
192 |
193 | // Measuring total time
194 | op::printTime(opTimer, "OpenPose demo successfully finished. Total time: ", " seconds.", op::Priority::High);
195 |
196 | // Return
197 | return 0;
198 | }
199 | catch (const std::exception&)
200 | {
201 | return -1;
202 | }
203 | }
204 |
205 | int main(int argc, char *argv[])
206 | {
207 | // Parsing command line flags
208 | gflags::ParseCommandLineFlags(&argc, &argv, true);
209 |
210 | // Running tutorialApiCpp
211 | return tutorialApiCpp();
212 | }
213 |
--------------------------------------------------------------------------------
/examples/tutorial_api_cpp/04_keypoints_from_images.cpp:
--------------------------------------------------------------------------------
1 | // ----------------------- OpenPose C++ API Tutorial - Example 4 - Body from images ----------------------
2 | // It reads images, process them, and display them with the pose (and optionally hand and face) keypoints. In addition,
3 | // it includes all the OpenPose configuration flags (enable/disable hand, face, output saving, etc.).
4 |
5 | // Third-party dependencies
6 | #include
7 | // Command-line user interface
8 | #define OPENPOSE_FLAGS_DISABLE_PRODUCER
9 | #define OPENPOSE_FLAGS_DISABLE_DISPLAY
10 | #include
11 | // OpenPose dependencies
12 | #include
13 |
14 | // Custom OpenPose flags
15 | // Producer
16 | DEFINE_string(image_dir, "examples/media/",
17 | "Process a directory of images. Read all standard formats (jpg, png, bmp, etc.).");
18 | // Display
19 | DEFINE_bool(no_display, false,
20 | "Enable to disable the visual display.");
21 |
22 | // This worker will just read and return all the jpg files in a directory
23 | bool display(const std::shared_ptr>>& datumsPtr)
24 | {
25 | try
26 | {
27 | // User's displaying/saving/other processing here
28 | // datum.cvOutputData: rendered frame with pose or heatmaps
29 | // datum.poseKeypoints: Array with the estimated pose
30 | if (datumsPtr != nullptr && !datumsPtr->empty())
31 | {
32 | // Display image and sleeps at least 1 ms (it usually sleeps ~5-10 msec to display the image)
33 | const cv::Mat cvMat = OP_OP2CVCONSTMAT(datumsPtr->at(0)->cvOutputData);
34 | if (!cvMat.empty())
35 | cv::imshow(OPEN_POSE_NAME_AND_VERSION + " - Tutorial C++ API", cvMat);
36 | else
37 | op::opLog("Empty cv::Mat as output.", op::Priority::High, __LINE__, __FUNCTION__, __FILE__);
38 | }
39 | else
40 | op::opLog("Nullptr or empty datumsPtr found.", op::Priority::High);
41 | const auto key = (char)cv::waitKey(1);
42 | return (key == 27);
43 | }
44 | catch (const std::exception& e)
45 | {
46 | op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
47 | return true;
48 | }
49 | }
50 |
51 | void printKeypoints(const std::shared_ptr>>& datumsPtr)
52 | {
53 | try
54 | {
55 | // Example: How to use the pose keypoints
56 | if (datumsPtr != nullptr && !datumsPtr->empty())
57 | {
58 | op::opLog("Body keypoints: " + datumsPtr->at(0)->poseKeypoints.toString(), op::Priority::High);
59 | op::opLog("Face keypoints: " + datumsPtr->at(0)->faceKeypoints.toString(), op::Priority::High);
60 | op::opLog("Left hand keypoints: " + datumsPtr->at(0)->handKeypoints[0].toString(), op::Priority::High);
61 | op::opLog("Right hand keypoints: " + datumsPtr->at(0)->handKeypoints[1].toString(), op::Priority::High);
62 | }
63 | else
64 | op::opLog("Nullptr or empty datumsPtr found.", op::Priority::High);
65 | }
66 | catch (const std::exception& e)
67 | {
68 | op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
69 | }
70 | }
71 |
72 | void configureWrapper(op::Wrapper& opWrapper)
73 | {
74 | try
75 | {
76 | // Configuring OpenPose
77 |
78 | // logging_level
79 | op::checkBool(
80 | 0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.",
81 | __LINE__, __FUNCTION__, __FILE__);
82 | op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);
83 | op::Profiler::setDefaultX(FLAGS_profile_speed);
84 |
85 | // Applying user defined configuration - GFlags to program variables
86 | // outputSize
87 | const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), "-1x-1");
88 | // netInputSize
89 | const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), "-1x368");
90 | // faceNetInputSize
91 | const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), "368x368 (multiples of 16)");
92 | // handNetInputSize
93 | const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), "368x368 (multiples of 16)");
94 | // poseMode
95 | const auto poseMode = op::flagsToPoseMode(FLAGS_body);
96 | // poseModel
97 | const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));
98 | // JSON saving
99 | if (!FLAGS_write_keypoint.empty())
100 | op::opLog(
101 | "Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`"
102 | " instead.", op::Priority::Max);
103 | // keypointScaleMode
104 | const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);
105 | // heatmaps to add
106 | const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,
107 | FLAGS_heatmaps_add_PAFs);
108 | const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);
109 | // >1 camera view?
110 | const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1);
111 | // Face and hand detectors
112 | const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);
113 | const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);
114 | // Enabling Google Logging
115 | const bool enableGoogleLogging = true;
116 |
117 | // Pose configuration (use WrapperStructPose{} for default and recommended configuration)
118 | const op::WrapperStructPose wrapperStructPose{
119 | poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,
120 | FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,
121 | op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,
122 | (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),
123 | heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,
124 | FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),
125 | op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};
126 | opWrapper.configure(wrapperStructPose);
127 | // Face configuration (use op::WrapperStructFace{} to disable it)
128 | const op::WrapperStructFace wrapperStructFace{
129 | FLAGS_face, faceDetector, faceNetInputSize,
130 | op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),
131 | (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};
132 | opWrapper.configure(wrapperStructFace);
133 | // Hand configuration (use op::WrapperStructHand{} to disable it)
134 | const op::WrapperStructHand wrapperStructHand{
135 | FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,
136 | op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,
137 | (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};
138 | opWrapper.configure(wrapperStructHand);
139 | // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)
140 | const op::WrapperStructExtra wrapperStructExtra{
141 | FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};
142 | opWrapper.configure(wrapperStructExtra);
143 | // Output (comment or use default argument to disable any output)
144 | const op::WrapperStructOutput wrapperStructOutput{
145 | FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),
146 | op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,
147 | FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),
148 | op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,
149 | op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),
150 | op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),
151 | op::String(FLAGS_udp_port)};
152 | opWrapper.configure(wrapperStructOutput);
153 | // No GUI. Equivalent to: opWrapper.configure(op::WrapperStructGui{});
154 | // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)
155 | if (FLAGS_disable_multi_thread)
156 | opWrapper.disableMultiThreading();
157 | }
158 | catch (const std::exception& e)
159 | {
160 | op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
161 | }
162 | }
163 |
164 | int tutorialApiCpp()
165 | {
166 | try
167 | {
168 | op::opLog("Starting OpenPose demo...", op::Priority::High);
169 | const auto opTimer = op::getTimerInit();
170 |
171 | // Configuring OpenPose
172 | op::opLog("Configuring OpenPose...", op::Priority::High);
173 | op::Wrapper opWrapper{op::ThreadManagerMode::Asynchronous};
174 | configureWrapper(opWrapper);
175 |
176 | // Starting OpenPose
177 | op::opLog("Starting thread(s)...", op::Priority::High);
178 | opWrapper.start();
179 |
180 | // Read frames on directory
181 | const auto imagePaths = op::getFilesOnDirectory(FLAGS_image_dir, op::Extensions::Images);
182 |
183 | // Process and display images
184 | for (const auto& imagePath : imagePaths)
185 | {
186 | const cv::Mat cvImageToProcess = cv::imread(imagePath);
187 | const op::Matrix imageToProcess = OP_CV2OPCONSTMAT(cvImageToProcess);
188 | auto datumProcessed = opWrapper.emplaceAndPop(imageToProcess);
189 | if (datumProcessed != nullptr)
190 | {
191 | printKeypoints(datumProcessed);
192 | if (!FLAGS_no_display)
193 | {
194 | const auto userWantsToExit = display(datumProcessed);
195 | if (userWantsToExit)
196 | {
197 | op::opLog("User pressed Esc to exit demo.", op::Priority::High);
198 | break;
199 | }
200 | }
201 | }
202 | else
203 | op::opLog("Image " + imagePath + " could not be processed.", op::Priority::High);
204 | }
205 |
206 | // Measuring total time
207 | op::printTime(opTimer, "OpenPose demo successfully finished. Total time: ", " seconds.", op::Priority::High);
208 |
209 | // Return
210 | return 0;
211 | }
212 | catch (const std::exception&)
213 | {
214 | return -1;
215 | }
216 | }
217 |
218 | int main(int argc, char *argv[])
219 | {
220 | // Parsing command line flags
221 | gflags::ParseCommandLineFlags(&argc, &argv, true);
222 |
223 | // Running tutorialApiCpp
224 | return tutorialApiCpp();
225 | }
226 |
--------------------------------------------------------------------------------
/examples/tutorial_api_cpp/06_face_from_image.cpp:
--------------------------------------------------------------------------------
1 | // ----------------------------- OpenPose C++ API Tutorial - Example 6 - Face from Image -----------------------------
2 | // It reads an image and the face location, process it, and displays the face keypoints. In addition,
3 | // it includes all the OpenPose configuration flags.
4 | // Input: An image and the face rectangle locations.
5 | // Output: OpenPose face keypoint detection.
6 | // NOTE: This demo is auto-selecting the following flags: `--body 0 --face --face_detector 2`
7 |
8 | // Third-party dependencies
9 | #include
10 | // Command-line user interface
11 | #define OPENPOSE_FLAGS_DISABLE_PRODUCER
12 | #define OPENPOSE_FLAGS_DISABLE_DISPLAY
13 | #include
14 | // OpenPose dependencies
15 | #include
16 |
17 | // Custom OpenPose flags
18 | // Producer
19 | DEFINE_string(image_path, "examples/media/COCO_val2014_000000000241.jpg",
20 | "Process an image. Read all standard formats (jpg, png, bmp, etc.).");
21 | // Display
22 | DEFINE_bool(no_display, false,
23 | "Enable to disable the visual display.");
24 |
25 | // This worker will just read and return all the jpg files in a directory
26 | void display(const std::shared_ptr>>& datumsPtr)
27 | {
28 | try
29 | {
30 | // User's displaying/saving/other processing here
31 | // datum.cvOutputData: rendered frame with pose or heatmaps
32 | // datum.poseKeypoints: Array with the estimated pose
33 | if (datumsPtr != nullptr && !datumsPtr->empty())
34 | {
35 | // Display image
36 | const cv::Mat cvMat = OP_OP2CVCONSTMAT(datumsPtr->at(0)->cvOutputData);
37 | if (!cvMat.empty())
38 | {
39 | cv::imshow(OPEN_POSE_NAME_AND_VERSION + " - Tutorial C++ API", cvMat);
40 | cv::waitKey(0);
41 | }
42 | else
43 | op::opLog("Empty cv::Mat as output.", op::Priority::High, __LINE__, __FUNCTION__, __FILE__);
44 | }
45 | else
46 | op::opLog("Nullptr or empty datumsPtr found.", op::Priority::High);
47 | }
48 | catch (const std::exception& e)
49 | {
50 | op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
51 | }
52 | }
53 |
54 | void printKeypoints(const std::shared_ptr>>& datumsPtr)
55 | {
56 | try
57 | {
58 | // Example: How to use the pose keypoints
59 | if (datumsPtr != nullptr && !datumsPtr->empty())
60 | {
61 | op::opLog("Body keypoints: " + datumsPtr->at(0)->poseKeypoints.toString(), op::Priority::High);
62 | op::opLog("Face keypoints: " + datumsPtr->at(0)->faceKeypoints.toString(), op::Priority::High);
63 | op::opLog("Left hand keypoints: " + datumsPtr->at(0)->handKeypoints[0].toString(), op::Priority::High);
64 | op::opLog("Right hand keypoints: " + datumsPtr->at(0)->handKeypoints[1].toString(), op::Priority::High);
65 | }
66 | else
67 | op::opLog("Nullptr or empty datumsPtr found.", op::Priority::High);
68 | }
69 | catch (const std::exception& e)
70 | {
71 | op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
72 | }
73 | }
74 |
75 | void configureWrapper(op::Wrapper& opWrapper)
76 | {
77 | try
78 | {
79 | // Configuring OpenPose
80 |
81 | // logging_level
82 | op::checkBool(
83 | 0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.",
84 | __LINE__, __FUNCTION__, __FILE__);
85 | op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);
86 | op::Profiler::setDefaultX(FLAGS_profile_speed);
87 |
88 | // Applying user defined configuration - GFlags to program variables
89 | // outputSize
90 | const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), "-1x-1");
91 | // netInputSize
92 | const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), "-1x368");
93 | // faceNetInputSize
94 | const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), "368x368 (multiples of 16)");
95 | // handNetInputSize
96 | const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), "368x368 (multiples of 16)");
97 | // poseMode
98 | const auto poseMode = op::flagsToPoseMode(FLAGS_body);
99 | // poseModel
100 | const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));
101 | // JSON saving
102 | if (!FLAGS_write_keypoint.empty())
103 | op::opLog(
104 | "Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`"
105 | " instead.", op::Priority::Max);
106 | // keypointScaleMode
107 | const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);
108 | // heatmaps to add
109 | const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,
110 | FLAGS_heatmaps_add_PAFs);
111 | const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);
112 | // >1 camera view?
113 | const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1);
114 | // Face and hand detectors
115 | const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);
116 | const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);
117 | // Enabling Google Logging
118 | const bool enableGoogleLogging = true;
119 |
120 | // Pose configuration (use WrapperStructPose{} for default and recommended configuration)
121 | const op::WrapperStructPose wrapperStructPose{
122 | poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,
123 | FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,
124 | op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,
125 | (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),
126 | heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,
127 | FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),
128 | op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};
129 | opWrapper.configure(wrapperStructPose);
130 | // Face configuration (use op::WrapperStructFace{} to disable it)
131 | const op::WrapperStructFace wrapperStructFace{
132 | FLAGS_face, faceDetector, faceNetInputSize,
133 | op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),
134 | (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};
135 | opWrapper.configure(wrapperStructFace);
136 | // Hand configuration (use op::WrapperStructHand{} to disable it)
137 | const op::WrapperStructHand wrapperStructHand{
138 | FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,
139 | op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,
140 | (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};
141 | opWrapper.configure(wrapperStructHand);
142 | // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)
143 | const op::WrapperStructExtra wrapperStructExtra{
144 | FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};
145 | opWrapper.configure(wrapperStructExtra);
146 | // Output (comment or use default argument to disable any output)
147 | const op::WrapperStructOutput wrapperStructOutput{
148 | FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),
149 | op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,
150 | FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),
151 | op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,
152 | op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),
153 | op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),
154 | op::String(FLAGS_udp_port)};
155 | opWrapper.configure(wrapperStructOutput);
156 | // No GUI. Equivalent to: opWrapper.configure(op::WrapperStructGui{});
157 | // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)
158 | if (FLAGS_disable_multi_thread)
159 | opWrapper.disableMultiThreading();
160 | }
161 | catch (const std::exception& e)
162 | {
163 | op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
164 | }
165 | }
166 |
167 | int tutorialApiCpp()
168 | {
169 | try
170 | {
171 | op::opLog("Starting OpenPose demo...", op::Priority::High);
172 | const auto opTimer = op::getTimerInit();
173 |
174 | // Required flags to enable heatmaps
175 | FLAGS_body = 0;
176 | FLAGS_face = true;
177 | FLAGS_face_detector = 2;
178 |
179 | // Configuring OpenPose
180 | op::opLog("Configuring OpenPose...", op::Priority::High);
181 | op::Wrapper opWrapper{op::ThreadManagerMode::Asynchronous};
182 | configureWrapper(opWrapper);
183 |
184 | // Starting OpenPose
185 | op::opLog("Starting thread(s)...", op::Priority::High);
186 | opWrapper.start();
187 |
188 | // Read image and face rectangle locations
189 | const cv::Mat cvImageToProcess = cv::imread(FLAGS_image_path);
190 | const op::Matrix imageToProcess = OP_CV2OPCONSTMAT(cvImageToProcess);
191 | const std::vector> faceRectangles{
192 | op::Rectangle{330.119385f, 277.532715f, 48.717274f, 48.717274f}, // Face of person 0
193 | op::Rectangle{24.036991f, 267.918793f, 65.175171f, 65.175171f}, // Face of person 1
194 | op::Rectangle{151.803436f, 32.477852f, 108.295761f, 108.295761f} // Face of person 2
195 | };
196 |
197 | // Create new datum
198 | auto datumsPtr = std::make_shared>>();
199 | datumsPtr->emplace_back();
200 | auto& datumPtr = datumsPtr->at(0);
201 | datumPtr = std::make_shared();
202 | // Fill datum with image and faceRectangles
203 | datumPtr->cvInputData = imageToProcess;
204 | datumPtr->faceRectangles = faceRectangles;
205 |
206 | // Process and display image
207 | opWrapper.emplaceAndPop(datumsPtr);
208 | if (datumsPtr != nullptr)
209 | {
210 | printKeypoints(datumsPtr);
211 | if (!FLAGS_no_display)
212 | display(datumsPtr);
213 | }
214 | else
215 | op::opLog("Image could not be processed.", op::Priority::High);
216 |
217 | // Info
218 | op::opLog("NOTE: In addition with the user flags, this demo has auto-selected the following flags:\n"
219 | "\t`--body 0 --face --face_detector 2`", op::Priority::High);
220 |
221 | // Measuring total time
222 | op::printTime(opTimer, "OpenPose demo successfully finished. Total time: ", " seconds.", op::Priority::High);
223 |
224 | // Return
225 | return 0;
226 | }
227 | catch (const std::exception&)
228 | {
229 | return -1;
230 | }
231 | }
232 |
233 | int main(int argc, char *argv[])
234 | {
235 | // Parsing command line flags
236 | gflags::ParseCommandLineFlags(&argc, &argv, true);
237 |
238 | // Running tutorialApiCpp
239 | return tutorialApiCpp();
240 | }
241 |
--------------------------------------------------------------------------------
/examples/tutorial_api_cpp/10_asynchronous_custom_input.cpp:
--------------------------------------------------------------------------------
1 | // ------------------------- OpenPose C++ API Tutorial - Example 10 - Custom Input -------------------------
2 | // Asynchronous mode: ideal for fast prototyping when performance is not an issue.
3 | // In this function, the user can implement its own way to create frames (e.g., reading his own folder of images)
4 | // and emplaces/pushes the frames to OpenPose.
5 |
6 | // Third-party dependencies
7 | #include
8 | // Command-line user interface
9 | #define OPENPOSE_FLAGS_DISABLE_PRODUCER
10 | #include
11 | // OpenPose dependencies
12 | #include
13 |
14 | // Custom OpenPose flags
15 | // Producer
16 | DEFINE_string(image_dir, "examples/media/",
17 | "Process a directory of images. Read all standard formats (jpg, png, bmp, etc.).");
18 |
19 | // This worker will just read and return all the basic image file formats in a directory
20 | class UserInputClass
21 | {
22 | public:
23 | UserInputClass(const std::string& directoryPath) :
24 | mImageFiles{op::getFilesOnDirectory(directoryPath, op::Extensions::Images)}, // For all basic image formats
25 | // If we want only e.g., "jpg" + "png" images
26 | // mImageFiles{op::getFilesOnDirectory(directoryPath, std::vector{"jpg", "png"})},
27 | mCounter{0},
28 | mClosed{false}
29 | {
30 | if (mImageFiles.empty())
31 | op::error("No images found on: " + directoryPath, __LINE__, __FUNCTION__, __FILE__);
32 | }
33 |
34 | std::shared_ptr>> createDatum()
35 | {
36 | // Close program when empty frame
37 | if (mClosed || mImageFiles.size() <= mCounter)
38 | {
39 | op::opLog("Last frame read and added to queue. Closing program after it is processed.", op::Priority::High);
40 | // This function stops this worker, which will eventually stop the whole thread system once all the frames
41 | // have been processed
42 | mClosed = true;
43 | return nullptr;
44 | }
45 | else // if (!mClosed)
46 | {
47 | // Create new datum
48 | auto datumsPtr = std::make_shared>>();
49 | datumsPtr->emplace_back();
50 | auto& datumPtr = datumsPtr->at(0);
51 | datumPtr = std::make_shared();
52 |
53 | // Fill datum
54 | const cv::Mat cvInputData = cv::imread(mImageFiles.at(mCounter++));
55 | datumPtr->cvInputData = OP_CV2OPCONSTMAT(cvInputData);
56 |
57 | // If empty frame -> return nullptr
58 | if (datumPtr->cvInputData.empty())
59 | {
60 | op::opLog("Empty frame detected on path: " + mImageFiles.at(mCounter-1) + ". Closing program.",
61 | op::Priority::High);
62 | mClosed = true;
63 | datumsPtr = nullptr;
64 | }
65 |
66 | return datumsPtr;
67 | }
68 | }
69 |
70 | bool isFinished() const
71 | {
72 | return mClosed;
73 | }
74 |
75 | private:
76 | const std::vector mImageFiles;
77 | unsigned long long mCounter;
78 | bool mClosed;
79 | };
80 |
81 | void configureWrapper(op::Wrapper& opWrapper)
82 | {
83 | try
84 | {
85 | // Configuring OpenPose
86 |
87 | // logging_level
88 | op::checkBool(
89 | 0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.",
90 | __LINE__, __FUNCTION__, __FILE__);
91 | op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);
92 | op::Profiler::setDefaultX(FLAGS_profile_speed);
93 |
94 | // Applying user defined configuration - GFlags to program variables
95 | // outputSize
96 | const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), "-1x-1");
97 | // netInputSize
98 | const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), "-1x368");
99 | // faceNetInputSize
100 | const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), "368x368 (multiples of 16)");
101 | // handNetInputSize
102 | const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), "368x368 (multiples of 16)");
103 | // poseMode
104 | const auto poseMode = op::flagsToPoseMode(FLAGS_body);
105 | // poseModel
106 | const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));
107 | // JSON saving
108 | if (!FLAGS_write_keypoint.empty())
109 | op::opLog(
110 | "Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`"
111 | " instead.", op::Priority::Max);
112 | // keypointScaleMode
113 | const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);
114 | // heatmaps to add
115 | const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,
116 | FLAGS_heatmaps_add_PAFs);
117 | const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);
118 | // >1 camera view?
119 | const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1);
120 | // Face and hand detectors
121 | const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);
122 | const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);
123 | // Enabling Google Logging
124 | const bool enableGoogleLogging = true;
125 |
126 | // Pose configuration (use WrapperStructPose{} for default and recommended configuration)
127 | const op::WrapperStructPose wrapperStructPose{
128 | poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,
129 | FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,
130 | op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,
131 | (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),
132 | heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,
133 | FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),
134 | op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};
135 | opWrapper.configure(wrapperStructPose);
136 | // Face configuration (use op::WrapperStructFace{} to disable it)
137 | const op::WrapperStructFace wrapperStructFace{
138 | FLAGS_face, faceDetector, faceNetInputSize,
139 | op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),
140 | (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};
141 | opWrapper.configure(wrapperStructFace);
142 | // Hand configuration (use op::WrapperStructHand{} to disable it)
143 | const op::WrapperStructHand wrapperStructHand{
144 | FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,
145 | op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,
146 | (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};
147 | opWrapper.configure(wrapperStructHand);
148 | // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)
149 | const op::WrapperStructExtra wrapperStructExtra{
150 | FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};
151 | opWrapper.configure(wrapperStructExtra);
152 | // Output (comment or use default argument to disable any output)
153 | const op::WrapperStructOutput wrapperStructOutput{
154 | FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),
155 | op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,
156 | FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),
157 | op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,
158 | op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),
159 | op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),
160 | op::String(FLAGS_udp_port)};
161 | opWrapper.configure(wrapperStructOutput);
162 | // GUI (comment or use default argument to disable any visual output)
163 | const op::WrapperStructGui wrapperStructGui{
164 | op::flagsToDisplayMode(FLAGS_display, FLAGS_3d), !FLAGS_no_gui_verbose, FLAGS_fullscreen};
165 | opWrapper.configure(wrapperStructGui);
166 | // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)
167 | if (FLAGS_disable_multi_thread)
168 | opWrapper.disableMultiThreading();
169 | }
170 | catch (const std::exception& e)
171 | {
172 | op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
173 | }
174 | }
175 |
176 | int tutorialApiCpp()
177 | {
178 | try
179 | {
180 | op::opLog("Starting OpenPose demo...", op::Priority::High);
181 | const auto opTimer = op::getTimerInit();
182 |
183 | // Configuring OpenPose
184 | op::opLog("Configuring OpenPose...", op::Priority::High);
185 | op::Wrapper opWrapper{op::ThreadManagerMode::AsynchronousIn};
186 | configureWrapper(opWrapper);
187 |
188 | // Start, run, and stop processing - exec() blocks this thread until OpenPose wrapper has finished
189 | op::opLog("Starting thread(s)...", op::Priority::High);
190 | opWrapper.start();
191 |
192 | // User processing
193 | UserInputClass userInputClass(FLAGS_image_dir);
194 | bool userWantsToExit = false;
195 | while (!userWantsToExit && !userInputClass.isFinished())
196 | {
197 | // Push frame
198 | auto datumToProcess = userInputClass.createDatum();
199 | if (datumToProcess != nullptr)
200 | {
201 | auto successfullyEmplaced = opWrapper.waitAndEmplace(datumToProcess);
202 | if (!successfullyEmplaced)
203 | op::opLog("Processed datum could not be emplaced.", op::Priority::High);
204 | }
205 | }
206 |
207 | op::opLog("Stopping thread(s)", op::Priority::High);
208 | opWrapper.stop();
209 |
210 | // Measuring total time
211 | op::printTime(opTimer, "OpenPose demo successfully finished. Total time: ", " seconds.", op::Priority::High);
212 |
213 | // Return
214 | return 0;
215 | }
216 | catch (const std::exception&)
217 | {
218 | return -1;
219 | }
220 | }
221 |
222 | int main(int argc, char *argv[])
223 | {
224 | // Parsing command line flags
225 | gflags::ParseCommandLineFlags(&argc, &argv, true);
226 |
227 | // Running tutorialApiCpp
228 | return tutorialApiCpp();
229 | }
230 |
--------------------------------------------------------------------------------
/examples/tutorial_api_cpp/11_asynchronous_custom_input_multi_camera.cpp:
--------------------------------------------------------------------------------
1 | // ------------------------- OpenPose C++ API Tutorial - Example 10 - Custom Input -------------------------
2 | // Asynchronous mode: ideal for fast prototyping when performance is not an issue.
3 | // In this function, the user can implement its own way to create frames (e.g., reading his own folder of images)
4 | // and emplaces/pushes the frames to OpenPose.
5 |
6 | // Third-party dependencies
7 | #include
8 | // Command-line user interface
9 | #define OPENPOSE_FLAGS_DISABLE_PRODUCER
10 | #include
11 | // OpenPose dependencies
12 | #include
13 |
14 | // Custom OpenPose flags
15 | // Producer
16 | DEFINE_string(video, "3d_4camera_video.avi",
17 | "Use a video file instead of the camera. Use `examples/media/video.avi` for our default example video.");
18 | DEFINE_string(camera_parameter_path, "models/cameraParameters/flir/",
19 | "String with the folder where the camera parameters are located. If there is only 1 XML file (for single"
20 | " video, webcam, or images from the same camera), you must specify the whole XML file path (ending in .xml).");
21 |
22 | // This worker will just read and return all the basic image file formats in a directory
23 | class UserInputClass
24 | {
25 | public:
26 | UserInputClass(const std::string& videoPath, const std::string& cameraParameterPath) :
27 | mClosed{false},
28 | mFrameCounter{0ull},
29 | mVideoCapture{videoPath}
30 | {
31 | if (!mVideoCapture.isOpened())
32 | {
33 | mClosed = true;
34 | op::error("No video " + videoPath + " opened.", __LINE__, __FUNCTION__, __FILE__);
35 | }
36 |
37 | // Create CameraParameterReader
38 | mCameraParameterReader.readParameters(cameraParameterPath);
39 | }
40 |
41 | std::shared_ptr>> createDatum()
42 | {
43 | if (mClosed)
44 | {
45 | op::opLog("Video already closed, nullptr returned.", op::Priority::High);
46 | return nullptr;
47 | }
48 |
49 | // Read cv::Mat
50 | cv::Mat cvInputData;
51 | mVideoCapture >> cvInputData;
52 | // If empty frame -> return nullptr
53 | if (cvInputData.empty())
54 | {
55 | // Close program when empty frame
56 | op::opLog("Empty frame detected, closing program.", op::Priority::High);
57 | mClosed = true;
58 | return nullptr;
59 | }
60 |
61 | // Create new datum and add 3D information (cv::Mat splitted and camera parameters)
62 | auto datumsPtr = std::make_shared>>();
63 | op::createMultiviewTDatum(datumsPtr, mFrameCounter, mCameraParameterReader, (void*)&cvInputData);
64 |
65 | return datumsPtr;
66 | }
67 |
68 | bool isFinished() const
69 | {
70 | return mClosed;
71 | }
72 |
73 | private:
74 | bool mClosed;
75 | unsigned long long mFrameCounter;
76 | cv::VideoCapture mVideoCapture;
77 | op::CameraParameterReader mCameraParameterReader;
78 | };
79 |
80 | void configureWrapper(op::Wrapper& opWrapper)
81 | {
82 | try
83 | {
84 | // Configuring OpenPose
85 |
86 | // logging_level
87 | op::checkBool(
88 | 0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.",
89 | __LINE__, __FUNCTION__, __FILE__);
90 | op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);
91 | op::Profiler::setDefaultX(FLAGS_profile_speed);
92 |
93 | // Applying user defined configuration - GFlags to program variables
94 | // outputSize
95 | const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), "-1x-1");
96 | // netInputSize
97 | const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), "-1x368");
98 | // faceNetInputSize
99 | const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), "368x368 (multiples of 16)");
100 | // handNetInputSize
101 | const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), "368x368 (multiples of 16)");
102 | // poseMode
103 | const auto poseMode = op::flagsToPoseMode(FLAGS_body);
104 | // poseModel
105 | const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));
106 | // JSON saving
107 | if (!FLAGS_write_keypoint.empty())
108 | op::opLog(
109 | "Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`"
110 | " instead.", op::Priority::Max);
111 | // keypointScaleMode
112 | const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);
113 | // heatmaps to add
114 | const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,
115 | FLAGS_heatmaps_add_PAFs);
116 | const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);
117 | // >1 camera view?
118 | const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1);
119 | // Face and hand detectors
120 | const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);
121 | const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);
122 | // Enabling Google Logging
123 | const bool enableGoogleLogging = true;
124 |
125 | // Pose configuration (use WrapperStructPose{} for default and recommended configuration)
126 | const op::WrapperStructPose wrapperStructPose{
127 | poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,
128 | FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,
129 | op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,
130 | (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),
131 | heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,
132 | FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),
133 | op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};
134 | opWrapper.configure(wrapperStructPose);
135 | // Face configuration (use op::WrapperStructFace{} to disable it)
136 | const op::WrapperStructFace wrapperStructFace{
137 | FLAGS_face, faceDetector, faceNetInputSize,
138 | op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),
139 | (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};
140 | opWrapper.configure(wrapperStructFace);
141 | // Hand configuration (use op::WrapperStructHand{} to disable it)
142 | const op::WrapperStructHand wrapperStructHand{
143 | FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,
144 | op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,
145 | (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};
146 | opWrapper.configure(wrapperStructHand);
147 | // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)
148 | const op::WrapperStructExtra wrapperStructExtra{
149 | FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};
150 | opWrapper.configure(wrapperStructExtra);
151 | // Output (comment or use default argument to disable any output)
152 | const op::WrapperStructOutput wrapperStructOutput{
153 | FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),
154 | op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,
155 | FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),
156 | op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,
157 | op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),
158 | op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),
159 | op::String(FLAGS_udp_port)};
160 | opWrapper.configure(wrapperStructOutput);
161 | // GUI (comment or use default argument to disable any visual output)
162 | const op::WrapperStructGui wrapperStructGui{
163 | op::flagsToDisplayMode(FLAGS_display, FLAGS_3d), !FLAGS_no_gui_verbose, FLAGS_fullscreen};
164 | opWrapper.configure(wrapperStructGui);
165 | // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)
166 | if (FLAGS_disable_multi_thread)
167 | opWrapper.disableMultiThreading();
168 | }
169 | catch (const std::exception& e)
170 | {
171 | op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
172 | }
173 | }
174 |
175 | int tutorialApiCpp()
176 | {
177 | try
178 | {
179 | op::opLog("Starting OpenPose demo...", op::Priority::High);
180 | const auto opTimer = op::getTimerInit();
181 |
182 | // Required flags to enable 3-D
183 | FLAGS_3d = true;
184 | FLAGS_number_people_max = 1;
185 | FLAGS_3d_min_views = 3;
186 | FLAGS_output_resolution = "320x256"; // Optional, but otherwise it gets too big to render in real time
187 | // FLAGS_3d_views = X; // Not required because it only affects OpenPose producers (rather than custom ones)
188 |
189 | // Configuring OpenPose
190 | op::opLog("Configuring OpenPose...", op::Priority::High);
191 | op::Wrapper opWrapper{op::ThreadManagerMode::AsynchronousIn};
192 | configureWrapper(opWrapper);
193 |
194 | // Start, run, and stop processing - exec() blocks this thread until OpenPose wrapper has finished
195 | op::opLog("Starting thread(s)...", op::Priority::High);
196 | opWrapper.start();
197 |
198 | // User processing
199 | UserInputClass userInputClass(FLAGS_video, FLAGS_camera_parameter_path);
200 | bool userWantsToExit = false;
201 | while (!userWantsToExit && !userInputClass.isFinished())
202 | {
203 | if (!opWrapper.isRunning())
204 | {
205 | op::opLog("OpenPose wrapper is no longer running, exiting video.", op::Priority::High);
206 | break;
207 | }
208 | // Push frame
209 | auto datumToProcess = userInputClass.createDatum();
210 | if (datumToProcess != nullptr)
211 | {
212 | auto successfullyEmplaced = opWrapper.waitAndEmplace(datumToProcess);
213 | if (!successfullyEmplaced)
214 | op::opLog("Processed datum could not be emplaced.", op::Priority::High);
215 | }
216 | }
217 |
218 | op::opLog("Stopping thread(s)", op::Priority::High);
219 | opWrapper.stop();
220 |
221 | // Measuring total time
222 | op::printTime(opTimer, "OpenPose demo successfully finished. Total time: ", " seconds.", op::Priority::High);
223 |
224 | // Return
225 | return 0;
226 | }
227 | catch (const std::exception&)
228 | {
229 | return -1;
230 | }
231 | }
232 |
233 | int main(int argc, char *argv[])
234 | {
235 | // Parsing command line flags
236 | gflags::ParseCommandLineFlags(&argc, &argv, true);
237 |
238 | // Running tutorialApiCpp
239 | return tutorialApiCpp();
240 | }
241 |
--------------------------------------------------------------------------------
/examples/tutorial_api_cpp/14_synchronous_custom_input.cpp:
--------------------------------------------------------------------------------
1 | // ------------------------- OpenPose C++ API Tutorial - Example 13 - Custom Input -------------------------
2 | // Synchronous mode: ideal for production integration. It provides the fastest results with respect to runtime
3 | // performance.
4 | // In this function, the user can implement its own way to create frames (e.g., reading his own folder of images).
5 |
6 | // Third-party dependencies
7 | #include
8 | // Command-line user interface
9 | #define OPENPOSE_FLAGS_DISABLE_PRODUCER
10 | #include
11 | // OpenPose dependencies
12 | #include
13 |
14 | // Custom OpenPose flags
15 | // Producer
16 | DEFINE_string(image_dir, "examples/media/",
17 | "Process a directory of images. Read all standard formats (jpg, png, bmp, etc.).");
18 |
19 | // This worker will just read and return all the basic image file formats in a directory
20 | class WUserInput : public op::WorkerProducer>>>
21 | {
22 | public:
23 | WUserInput(const std::string& directoryPath) :
24 | mImageFiles{op::getFilesOnDirectory(directoryPath, op::Extensions::Images)}, // For all basic image formats
25 | // If we want only e.g., "jpg" + "png" images
26 | // mImageFiles{op::getFilesOnDirectory(directoryPath, std::vector{"jpg", "png"})},
27 | mCounter{0}
28 | {
29 | if (mImageFiles.empty())
30 | op::error("No images found on: " + directoryPath, __LINE__, __FUNCTION__, __FILE__);
31 | }
32 |
33 | void initializationOnThread() {}
34 |
35 | std::shared_ptr>> workProducer()
36 | {
37 | try
38 | {
39 | // Close program when empty frame
40 | if (mImageFiles.size() <= mCounter)
41 | {
42 | op::opLog("Last frame read and added to queue. Closing program after it is processed.",
43 | op::Priority::High);
44 | // This funtion stops this worker, which will eventually stop the whole thread system once all the
45 | // frames have been processed
46 | this->stop();
47 | return nullptr;
48 | }
49 | else
50 | {
51 | // Create new datum
52 | auto datumsPtr = std::make_shared>>();
53 | datumsPtr->emplace_back();
54 | auto& datumPtr = datumsPtr->at(0);
55 | datumPtr = std::make_shared();
56 |
57 | // Fill datum
58 | const cv::Mat cvInputData = cv::imread(mImageFiles.at(mCounter++));
59 | datumPtr->cvInputData = OP_CV2OPCONSTMAT(cvInputData);
60 |
61 | // If empty frame -> return nullptr
62 | if (datumPtr->cvInputData.empty())
63 | {
64 | op::opLog("Empty frame detected on path: " + mImageFiles.at(mCounter-1) + ". Closing program.",
65 | op::Priority::High);
66 | this->stop();
67 | datumsPtr = nullptr;
68 | }
69 |
70 | return datumsPtr;
71 | }
72 | }
73 | catch (const std::exception& e)
74 | {
75 | this->stop();
76 | op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
77 | return nullptr;
78 | }
79 | }
80 |
81 | private:
82 | const std::vector mImageFiles;
83 | unsigned long long mCounter;
84 | };
85 |
86 | void configureWrapper(op::Wrapper& opWrapper)
87 | {
88 | try
89 | {
90 | // Configuring OpenPose
91 |
92 | // logging_level
93 | op::checkBool(
94 | 0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.",
95 | __LINE__, __FUNCTION__, __FILE__);
96 | op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);
97 | op::Profiler::setDefaultX(FLAGS_profile_speed);
98 |
99 | // Applying user defined configuration - GFlags to program variables
100 | // outputSize
101 | const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), "-1x-1");
102 | // netInputSize
103 | const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), "-1x368");
104 | // faceNetInputSize
105 | const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), "368x368 (multiples of 16)");
106 | // handNetInputSize
107 | const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), "368x368 (multiples of 16)");
108 | // poseMode
109 | const auto poseMode = op::flagsToPoseMode(FLAGS_body);
110 | // poseModel
111 | const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));
112 | // JSON saving
113 | if (!FLAGS_write_keypoint.empty())
114 | op::opLog(
115 | "Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`"
116 | " instead.", op::Priority::Max);
117 | // keypointScaleMode
118 | const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);
119 | // heatmaps to add
120 | const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,
121 | FLAGS_heatmaps_add_PAFs);
122 | const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);
123 | // >1 camera view?
124 | // const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1 || FLAGS_flir_camera);
125 | const auto multipleView = false;
126 | // Face and hand detectors
127 | const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);
128 | const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);
129 | // Enabling Google Logging
130 | const bool enableGoogleLogging = true;
131 |
132 | // Initializing the user custom classes
133 | // Frames producer (e.g., video, webcam, ...)
134 | auto wUserInput = std::make_shared(FLAGS_image_dir);
135 | // Add custom processing
136 | const auto workerInputOnNewThread = true;
137 | opWrapper.setWorker(op::WorkerType::Input, wUserInput, workerInputOnNewThread);
138 |
139 | // Pose configuration (use WrapperStructPose{} for default and recommended configuration)
140 | const op::WrapperStructPose wrapperStructPose{
141 | poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,
142 | FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,
143 | op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,
144 | (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),
145 | heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,
146 | FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),
147 | op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};
148 | opWrapper.configure(wrapperStructPose);
149 | // Face configuration (use op::WrapperStructFace{} to disable it)
150 | const op::WrapperStructFace wrapperStructFace{
151 | FLAGS_face, faceDetector, faceNetInputSize,
152 | op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),
153 | (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};
154 | opWrapper.configure(wrapperStructFace);
155 | // Hand configuration (use op::WrapperStructHand{} to disable it)
156 | const op::WrapperStructHand wrapperStructHand{
157 | FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,
158 | op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,
159 | (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};
160 | opWrapper.configure(wrapperStructHand);
161 | // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)
162 | const op::WrapperStructExtra wrapperStructExtra{
163 | FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};
164 | opWrapper.configure(wrapperStructExtra);
165 | // Output (comment or use default argument to disable any output)
166 | const op::WrapperStructOutput wrapperStructOutput{
167 | FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),
168 | op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,
169 | FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),
170 | op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,
171 | op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),
172 | op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),
173 | op::String(FLAGS_udp_port)};
174 | opWrapper.configure(wrapperStructOutput);
175 | // GUI (comment or use default argument to disable any visual output)
176 | const op::WrapperStructGui wrapperStructGui{
177 | op::flagsToDisplayMode(FLAGS_display, FLAGS_3d), !FLAGS_no_gui_verbose, FLAGS_fullscreen};
178 | opWrapper.configure(wrapperStructGui);
179 | // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)
180 | if (FLAGS_disable_multi_thread)
181 | opWrapper.disableMultiThreading();
182 | }
183 | catch (const std::exception& e)
184 | {
185 | op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
186 | }
187 | }
188 |
189 | int tutorialApiCpp()
190 | {
191 | try
192 | {
193 | op::opLog("Starting OpenPose demo...", op::Priority::High);
194 | const auto opTimer = op::getTimerInit();
195 |
196 | // OpenPose wrapper
197 | op::opLog("Configuring OpenPose...", op::Priority::High);
198 | op::Wrapper opWrapper;
199 | configureWrapper(opWrapper);
200 |
201 | // Start, run, and stop processing - exec() blocks this thread until OpenPose wrapper has finished
202 | op::opLog("Starting thread(s)...", op::Priority::High);
203 | opWrapper.exec();
204 |
205 | // Measuring total time
206 | op::printTime(opTimer, "OpenPose demo successfully finished. Total time: ", " seconds.", op::Priority::High);
207 |
208 | // Return
209 | return 0;
210 | }
211 | catch (const std::exception&)
212 | {
213 | return -1;
214 | }
215 | }
216 |
217 | int main(int argc, char *argv[])
218 | {
219 | // Parsing command line flags
220 | gflags::ParseCommandLineFlags(&argc, &argv, true);
221 |
222 | // Running tutorialApiCpp
223 | return tutorialApiCpp();
224 | }
225 |
--------------------------------------------------------------------------------
/examples/tutorial_api_cpp/15_synchronous_custom_preprocessing.cpp:
--------------------------------------------------------------------------------
1 | // ------------------------- OpenPose C++ API Tutorial - Example 14 - Custom Pre-processing -------------------------
2 | // Synchronous mode: ideal for production integration. It provides the fastest results with respect to runtime
3 | // performance.
4 | // In this function, the user can implement its own pre-processing, i.e., his function will be called after the image
5 | // has been read by OpenPose but before OpenPose processes the frames.
6 |
7 | // Third-party dependencies
8 | #include
9 | // Command-line user interface
10 | #include
11 | // OpenPose dependencies
12 | #include
13 |
14 | // This worker will just invert the image
15 | class WUserPreProcessing : public op::Worker>>>
16 | {
17 | public:
18 | WUserPreProcessing()
19 | {
20 | // User's constructor here
21 | }
22 |
23 | void initializationOnThread() {}
24 |
25 | void work(std::shared_ptr>>& datumsPtr)
26 | {
27 | try
28 | {
29 | // User's pre-processing (after OpenPose read the input image & before OpenPose processing) here
30 | // datumPtr->cvInputData: input frame
31 | if (datumsPtr != nullptr && !datumsPtr->empty())
32 | {
33 | for (auto& datumPtr : *datumsPtr)
34 | {
35 | cv::Mat cvOutputData = OP_OP2CVMAT(datumPtr->cvOutputData);
36 | cv::bitwise_not(cvOutputData, cvOutputData);
37 | }
38 | }
39 | }
40 | catch (const std::exception& e)
41 | {
42 | this->stop();
43 | op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
44 | }
45 | }
46 | };
47 |
48 | void configureWrapper(op::Wrapper& opWrapper)
49 | {
50 | try
51 | {
52 | // Configuring OpenPose
53 |
54 | // logging_level
55 | op::checkBool(
56 | 0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.",
57 | __LINE__, __FUNCTION__, __FILE__);
58 | op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);
59 | op::Profiler::setDefaultX(FLAGS_profile_speed);
60 |
61 | // Applying user defined configuration - GFlags to program variables
62 | // producerType
63 | op::ProducerType producerType;
64 | op::String producerString;
65 | std::tie(producerType, producerString) = op::flagsToProducer(
66 | op::String(FLAGS_image_dir), op::String(FLAGS_video), op::String(FLAGS_ip_camera), FLAGS_camera,
67 | FLAGS_flir_camera, FLAGS_flir_camera_index);
68 | // cameraSize
69 | const auto cameraSize = op::flagsToPoint(op::String(FLAGS_camera_resolution), "-1x-1");
70 | // outputSize
71 | const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), "-1x-1");
72 | // netInputSize
73 | const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), "-1x368");
74 | // faceNetInputSize
75 | const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), "368x368 (multiples of 16)");
76 | // handNetInputSize
77 | const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), "368x368 (multiples of 16)");
78 | // poseMode
79 | const auto poseMode = op::flagsToPoseMode(FLAGS_body);
80 | // poseModel
81 | const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));
82 | // JSON saving
83 | if (!FLAGS_write_keypoint.empty())
84 | op::opLog(
85 | "Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`"
86 | " instead.", op::Priority::Max);
87 | // keypointScaleMode
88 | const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);
89 | // heatmaps to add
90 | const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,
91 | FLAGS_heatmaps_add_PAFs);
92 | const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);
93 | // >1 camera view?
94 | const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1 || FLAGS_flir_camera);
95 | // Face and hand detectors
96 | const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);
97 | const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);
98 | // Enabling Google Logging
99 | const bool enableGoogleLogging = true;
100 |
101 | // Initializing the user custom classes
102 | // Processing
103 | auto wUserPreProcessing = std::make_shared();
104 | // Add custom processing
105 | const auto workerProcessingOnNewThread = true;
106 | opWrapper.setWorker(op::WorkerType::PreProcessing, wUserPreProcessing, workerProcessingOnNewThread);
107 |
108 | // Pose configuration (use WrapperStructPose{} for default and recommended configuration)
109 | const op::WrapperStructPose wrapperStructPose{
110 | poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,
111 | FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,
112 | op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,
113 | (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),
114 | heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,
115 | FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),
116 | op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};
117 | opWrapper.configure(wrapperStructPose);
118 | // Face configuration (use op::WrapperStructFace{} to disable it)
119 | const op::WrapperStructFace wrapperStructFace{
120 | FLAGS_face, faceDetector, faceNetInputSize,
121 | op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),
122 | (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};
123 | opWrapper.configure(wrapperStructFace);
124 | // Hand configuration (use op::WrapperStructHand{} to disable it)
125 | const op::WrapperStructHand wrapperStructHand{
126 | FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,
127 | op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,
128 | (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};
129 | opWrapper.configure(wrapperStructHand);
130 | // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)
131 | const op::WrapperStructExtra wrapperStructExtra{
132 | FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};
133 | opWrapper.configure(wrapperStructExtra);
134 | // Producer (use default to disable any input)
135 | const op::WrapperStructInput wrapperStructInput{
136 | producerType, producerString, FLAGS_frame_first, FLAGS_frame_step, FLAGS_frame_last,
137 | FLAGS_process_real_time, FLAGS_frame_flip, FLAGS_frame_rotate, FLAGS_frames_repeat,
138 | cameraSize, op::String(FLAGS_camera_parameter_path), FLAGS_frame_undistort, FLAGS_3d_views};
139 | opWrapper.configure(wrapperStructInput);
140 | // Output (comment or use default argument to disable any output)
141 | const op::WrapperStructOutput wrapperStructOutput{
142 | FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),
143 | op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,
144 | FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),
145 | op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,
146 | op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),
147 | op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),
148 | op::String(FLAGS_udp_port)};
149 | opWrapper.configure(wrapperStructOutput);
150 | // GUI (comment or use default argument to disable any visual output)
151 | const op::WrapperStructGui wrapperStructGui{
152 | op::flagsToDisplayMode(FLAGS_display, FLAGS_3d), !FLAGS_no_gui_verbose, FLAGS_fullscreen};
153 | opWrapper.configure(wrapperStructGui);
154 | // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)
155 | if (FLAGS_disable_multi_thread)
156 | opWrapper.disableMultiThreading();
157 | }
158 | catch (const std::exception& e)
159 | {
160 | op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
161 | }
162 | }
163 |
164 | int tutorialApiCpp()
165 | {
166 | try
167 | {
168 | op::opLog("Starting OpenPose demo...", op::Priority::High);
169 | const auto opTimer = op::getTimerInit();
170 |
171 | // OpenPose wrapper
172 | op::opLog("Configuring OpenPose...", op::Priority::High);
173 | op::Wrapper opWrapper;
174 | configureWrapper(opWrapper);
175 |
176 | // Start, run, and stop processing - exec() blocks this thread until OpenPose wrapper has finished
177 | op::opLog("Starting thread(s)...", op::Priority::High);
178 | opWrapper.exec();
179 |
180 | // Measuring total time
181 | op::printTime(opTimer, "OpenPose demo successfully finished. Total time: ", " seconds.", op::Priority::High);
182 |
183 | // Return
184 | return 0;
185 | }
186 | catch (const std::exception&)
187 | {
188 | return -1;
189 | }
190 | }
191 |
192 | int main(int argc, char *argv[])
193 | {
194 | // Parsing command line flags
195 | gflags::ParseCommandLineFlags(&argc, &argv, true);
196 |
197 | // Running tutorialApiCpp
198 | return tutorialApiCpp();
199 | }
200 |
--------------------------------------------------------------------------------
/examples/tutorial_api_cpp/16_synchronous_custom_postprocessing.cpp:
--------------------------------------------------------------------------------
1 | // ------------------------- OpenPose C++ API Tutorial - Example 15 - Custom Post-processing -------------------------
2 | // Synchronous mode: ideal for production integration. It provides the fastest results with respect to runtime
3 | // performance.
4 | // In this function, the user can implement its own post-processing, i.e., his function will be called after OpenPose
5 | // has processed the frames but before saving or visualizing any result.
6 |
7 | // Third-party dependencies
8 | #include
9 | // Command-line user interface
10 | #include
11 | // OpenPose dependencies
12 | #include
13 |
14 | // This worker will just invert the image
15 | class WUserPostProcessing : public op::Worker>>>
16 | {
17 | public:
18 | WUserPostProcessing()
19 | {
20 | // User's constructor here
21 | }
22 |
23 | void initializationOnThread() {}
24 |
25 | void work(std::shared_ptr>>& datumsPtr)
26 | {
27 | try
28 | {
29 | // User's post-processing (after OpenPose processing & before OpenPose outputs) here
30 | // datumPtr->cvOutputData: rendered frame with pose or heatmaps
31 | // datumPtr->poseKeypoints: Array with the estimated pose
32 | if (datumsPtr != nullptr && !datumsPtr->empty())
33 | {
34 | for (auto& datumPtr : *datumsPtr)
35 | {
36 | cv::Mat cvOutputData = OP_OP2CVMAT(datumPtr->cvOutputData);
37 | cv::bitwise_not(cvOutputData, cvOutputData);
38 | }
39 | }
40 | }
41 | catch (const std::exception& e)
42 | {
43 | this->stop();
44 | op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
45 | }
46 | }
47 | };
48 |
49 | void configureWrapper(op::Wrapper& opWrapper)
50 | {
51 | try
52 | {
53 | // Configuring OpenPose
54 |
55 | // logging_level
56 | op::checkBool(
57 | 0 <= FLAGS_logging_level && FLAGS_logging_level <= 255, "Wrong logging_level value.",
58 | __LINE__, __FUNCTION__, __FILE__);
59 | op::ConfigureLog::setPriorityThreshold((op::Priority)FLAGS_logging_level);
60 | op::Profiler::setDefaultX(FLAGS_profile_speed);
61 |
62 | // Applying user defined configuration - GFlags to program variables
63 | // producerType
64 | op::ProducerType producerType;
65 | op::String producerString;
66 | std::tie(producerType, producerString) = op::flagsToProducer(
67 | op::String(FLAGS_image_dir), op::String(FLAGS_video), op::String(FLAGS_ip_camera), FLAGS_camera,
68 | FLAGS_flir_camera, FLAGS_flir_camera_index);
69 | // cameraSize
70 | const auto cameraSize = op::flagsToPoint(op::String(FLAGS_camera_resolution), "-1x-1");
71 | // outputSize
72 | const auto outputSize = op::flagsToPoint(op::String(FLAGS_output_resolution), "-1x-1");
73 | // netInputSize
74 | const auto netInputSize = op::flagsToPoint(op::String(FLAGS_net_resolution), "-1x368");
75 | // faceNetInputSize
76 | const auto faceNetInputSize = op::flagsToPoint(op::String(FLAGS_face_net_resolution), "368x368 (multiples of 16)");
77 | // handNetInputSize
78 | const auto handNetInputSize = op::flagsToPoint(op::String(FLAGS_hand_net_resolution), "368x368 (multiples of 16)");
79 | // poseMode
80 | const auto poseMode = op::flagsToPoseMode(FLAGS_body);
81 | // poseModel
82 | const auto poseModel = op::flagsToPoseModel(op::String(FLAGS_model_pose));
83 | // JSON saving
84 | if (!FLAGS_write_keypoint.empty())
85 | op::opLog(
86 | "Flag `write_keypoint` is deprecated and will eventually be removed. Please, use `write_json`"
87 | " instead.", op::Priority::Max);
88 | // keypointScaleMode
89 | const auto keypointScaleMode = op::flagsToScaleMode(FLAGS_keypoint_scale);
90 | // heatmaps to add
91 | const auto heatMapTypes = op::flagsToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg,
92 | FLAGS_heatmaps_add_PAFs);
93 | const auto heatMapScaleMode = op::flagsToHeatMapScaleMode(FLAGS_heatmaps_scale);
94 | // >1 camera view?
95 | const auto multipleView = (FLAGS_3d || FLAGS_3d_views > 1 || FLAGS_flir_camera);
96 | // Face and hand detectors
97 | const auto faceDetector = op::flagsToDetector(FLAGS_face_detector);
98 | const auto handDetector = op::flagsToDetector(FLAGS_hand_detector);
99 | // Enabling Google Logging
100 | const bool enableGoogleLogging = true;
101 |
102 | // Initializing the user custom classes
103 | // Processing
104 | auto wUserPostProcessing = std::make_shared();
105 | // Add custom processing
106 | const auto workerProcessingOnNewThread = true;
107 | opWrapper.setWorker(op::WorkerType::PostProcessing, wUserPostProcessing, workerProcessingOnNewThread);
108 |
109 | // Pose configuration (use WrapperStructPose{} for default and recommended configuration)
110 | const op::WrapperStructPose wrapperStructPose{
111 | poseMode, netInputSize, FLAGS_net_resolution_dynamic, outputSize, keypointScaleMode, FLAGS_num_gpu,
112 | FLAGS_num_gpu_start, FLAGS_scale_number, (float)FLAGS_scale_gap,
113 | op::flagsToRenderMode(FLAGS_render_pose, multipleView), poseModel, !FLAGS_disable_blending,
114 | (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, op::String(FLAGS_model_folder),
115 | heatMapTypes, heatMapScaleMode, FLAGS_part_candidates, (float)FLAGS_render_threshold,
116 | FLAGS_number_people_max, FLAGS_maximize_positives, FLAGS_fps_max, op::String(FLAGS_prototxt_path),
117 | op::String(FLAGS_caffemodel_path), (float)FLAGS_upsampling_ratio, enableGoogleLogging};
118 | opWrapper.configure(wrapperStructPose);
119 | // Face configuration (use op::WrapperStructFace{} to disable it)
120 | const op::WrapperStructFace wrapperStructFace{
121 | FLAGS_face, faceDetector, faceNetInputSize,
122 | op::flagsToRenderMode(FLAGS_face_render, multipleView, FLAGS_render_pose),
123 | (float)FLAGS_face_alpha_pose, (float)FLAGS_face_alpha_heatmap, (float)FLAGS_face_render_threshold};
124 | opWrapper.configure(wrapperStructFace);
125 | // Hand configuration (use op::WrapperStructHand{} to disable it)
126 | const op::WrapperStructHand wrapperStructHand{
127 | FLAGS_hand, handDetector, handNetInputSize, FLAGS_hand_scale_number, (float)FLAGS_hand_scale_range,
128 | op::flagsToRenderMode(FLAGS_hand_render, multipleView, FLAGS_render_pose), (float)FLAGS_hand_alpha_pose,
129 | (float)FLAGS_hand_alpha_heatmap, (float)FLAGS_hand_render_threshold};
130 | opWrapper.configure(wrapperStructHand);
131 | // Extra functionality configuration (use op::WrapperStructExtra{} to disable it)
132 | const op::WrapperStructExtra wrapperStructExtra{
133 | FLAGS_3d, FLAGS_3d_min_views, FLAGS_identification, FLAGS_tracking, FLAGS_ik_threads};
134 | opWrapper.configure(wrapperStructExtra);
135 | // Producer (use default to disable any input)
136 | const op::WrapperStructInput wrapperStructInput{
137 | producerType, producerString, FLAGS_frame_first, FLAGS_frame_step, FLAGS_frame_last,
138 | FLAGS_process_real_time, FLAGS_frame_flip, FLAGS_frame_rotate, FLAGS_frames_repeat,
139 | cameraSize, op::String(FLAGS_camera_parameter_path), FLAGS_frame_undistort, FLAGS_3d_views};
140 | opWrapper.configure(wrapperStructInput);
141 | // Output (comment or use default argument to disable any output)
142 | const op::WrapperStructOutput wrapperStructOutput{
143 | FLAGS_cli_verbose, op::String(FLAGS_write_keypoint), op::stringToDataFormat(FLAGS_write_keypoint_format),
144 | op::String(FLAGS_write_json), op::String(FLAGS_write_coco_json), FLAGS_write_coco_json_variants,
145 | FLAGS_write_coco_json_variant, op::String(FLAGS_write_images), op::String(FLAGS_write_images_format),
146 | op::String(FLAGS_write_video), FLAGS_write_video_fps, FLAGS_write_video_with_audio,
147 | op::String(FLAGS_write_heatmaps), op::String(FLAGS_write_heatmaps_format), op::String(FLAGS_write_video_3d),
148 | op::String(FLAGS_write_video_adam), op::String(FLAGS_write_bvh), op::String(FLAGS_udp_host),
149 | op::String(FLAGS_udp_port)};
150 | opWrapper.configure(wrapperStructOutput);
151 | // GUI (comment or use default argument to disable any visual output)
152 | const op::WrapperStructGui wrapperStructGui{
153 | op::flagsToDisplayMode(FLAGS_display, FLAGS_3d), !FLAGS_no_gui_verbose, FLAGS_fullscreen};
154 | opWrapper.configure(wrapperStructGui);
155 | // Set to single-thread (for sequential processing and/or debugging and/or reducing latency)
156 | if (FLAGS_disable_multi_thread)
157 | opWrapper.disableMultiThreading();
158 | }
159 | catch (const std::exception& e)
160 | {
161 | op::error(e.what(), __LINE__, __FUNCTION__, __FILE__);
162 | }
163 | }
164 |
165 | int tutorialApiCpp()
166 | {
167 | try
168 | {
169 | op::opLog("Starting OpenPose demo...", op::Priority::High);
170 | const auto opTimer = op::getTimerInit();
171 |
172 | // OpenPose wrapper
173 | op::opLog("Configuring OpenPose...", op::Priority::High);
174 | op::Wrapper opWrapper;
175 | configureWrapper(opWrapper);
176 |
177 | // Start, run, and stop processing - exec() blocks this thread until OpenPose wrapper has finished
178 | op::opLog("Starting thread(s)...", op::Priority::High);
179 | opWrapper.exec();
180 |
181 | // Measuring total time
182 | op::printTime(opTimer, "OpenPose demo successfully finished. Total time: ", " seconds.", op::Priority::High);
183 |
184 | // Return
185 | return 0;
186 | }
187 | catch (const std::exception&)
188 | {
189 | return -1;
190 | }
191 | }
192 |
193 | int main(int argc, char *argv[])
194 | {
195 | // Parsing command line flags
196 | gflags::ParseCommandLineFlags(&argc, &argv, true);
197 |
198 | // Running tutorialApiCpp
199 | return tutorialApiCpp();
200 | }
201 |
--------------------------------------------------------------------------------
/examples/tutorial_api_cpp/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | set(EXAMPLE_FILES
2 | 01_body_from_image_default.cpp
3 | 02_whole_body_from_image_default.cpp
4 | 03_keypoints_from_image.cpp
5 | 04_keypoints_from_images.cpp
6 | 05_keypoints_from_images_multi_gpu.cpp
7 | 06_face_from_image.cpp
8 | 07_hand_from_image.cpp
9 | 08_heatmaps_from_image.cpp
10 | 09_keypoints_from_heatmaps.cpp
11 | 10_asynchronous_custom_input.cpp
12 | 11_asynchronous_custom_input_multi_camera.cpp
13 | 12_asynchronous_custom_output.cpp
14 | 13_asynchronous_custom_input_output_and_datum.cpp
15 | 14_synchronous_custom_input.cpp
16 | 15_synchronous_custom_preprocessing.cpp
17 | 16_synchronous_custom_postprocessing.cpp
18 | 17_synchronous_custom_output.cpp
19 | 18_synchronous_custom_all_and_datum.cpp)
20 |
21 | include(${CMAKE_SOURCE_DIR}/cmake/Utils.cmake)
22 |
23 | foreach(EXAMPLE_FILE ${EXAMPLE_FILES})
24 |
25 | get_filename_component(SOURCE_NAME ${EXAMPLE_FILE} NAME_WE)
26 |
27 | if (UNIX OR APPLE)
28 | set(EXE_NAME "${SOURCE_NAME}.bin")
29 | elseif (WIN32)
30 | set(EXE_NAME "${SOURCE_NAME}")
31 | endif ()
32 |
33 | message(STATUS "Adding Example ${EXE_NAME}")
34 | add_executable(${EXE_NAME} ${EXAMPLE_FILE})
35 | target_link_libraries(${EXE_NAME} openpose ${examples_3rdparty_libraries})
36 |
37 | if (WIN32)
38 | set_property(TARGET ${EXE_NAME} PROPERTY FOLDER "Examples/Tutorial/C++ API")
39 | configure_file(${CMAKE_SOURCE_DIR}/cmake/OpenPose${VCXPROJ_FILE_GPU_MODE}.vcxproj.user
40 | ${CMAKE_CURRENT_BINARY_DIR}/${EXE_NAME}.vcxproj.user @ONLY)
41 | # Properties->General->Output Directory
42 | set_property(TARGET ${EXE_NAME} PROPERTY RUNTIME_OUTPUT_DIRECTORY_RELEASE ${PROJECT_BINARY_DIR}/$(Platform)/$(Configuration))
43 | set_property(TARGET ${EXE_NAME} PROPERTY RUNTIME_OUTPUT_DIRECTORY_DEBUG ${PROJECT_BINARY_DIR}/$(Platform)/$(Configuration))
44 | endif (WIN32)
45 |
46 | endforeach()
47 |
--------------------------------------------------------------------------------
/examples/tutorial_api_cpp/README.md:
--------------------------------------------------------------------------------
1 | # C++ API Examples
2 | See the [OpenPose C++ API doc](../../doc/04_cpp_api.md) for more details on this folder.
3 |
4 | This folder provides examples to the basic OpenPose C++ API. The analogous Python API is exposed in [examples/tutorial_api_python/](../tutorial_api_python/).
5 |
--------------------------------------------------------------------------------
/examples/tutorial_api_python/01_body_from_image.py:
--------------------------------------------------------------------------------
1 | # From Python
2 | # It requires OpenCV installed for Python
3 | import sys
4 | import cv2
5 | import os
6 | from sys import platform
7 | import argparse
8 |
9 | try:
10 | # Import Openpose (Windows/Ubuntu/OSX)
11 | dir_path = os.path.dirname(os.path.realpath(__file__))
12 | try:
13 | # Windows Import
14 | if platform == "win32":
15 | # Change these variables to point to the correct folder (Release/x64 etc.)
16 | sys.path.append(dir_path + '/../../python/openpose/Release');
17 | os.environ['PATH'] = os.environ['PATH'] + ';' + dir_path + '/../../x64/Release;' + dir_path + '/../../bin;'
18 | import pyopenpose as op
19 | else:
20 | # Change these variables to point to the correct folder (Release/x64 etc.)
21 | sys.path.append('../../python');
22 | # If you run `make install` (default path is `/usr/local/python` for Ubuntu), you can also access the OpenPose/python module from there. This will install OpenPose and the python library at your desired installation path. Ensure that this is in your python path in order to use it.
23 | # sys.path.append('/usr/local/python')
24 | from openpose import pyopenpose as op
25 | except ImportError as e:
26 | print('Error: OpenPose library could not be found. Did you enable `BUILD_PYTHON` in CMake and have this Python script in the right folder?')
27 | raise e
28 |
29 | # Flags
30 | parser = argparse.ArgumentParser()
31 | parser.add_argument("--image_path", default="../../../examples/media/COCO_val2014_000000000192.jpg", help="Process an image. Read all standard formats (jpg, png, bmp, etc.).")
32 | args = parser.parse_known_args()
33 |
34 | # Custom Params (refer to include/openpose/flags.hpp for more parameters)
35 | params = dict()
36 | params["model_folder"] = "../../../models/"
37 |
38 | # Add others in path?
39 | for i in range(0, len(args[1])):
40 | curr_item = args[1][i]
41 | if i != len(args[1])-1: next_item = args[1][i+1]
42 | else: next_item = "1"
43 | if "--" in curr_item and "--" in next_item:
44 | key = curr_item.replace('-','')
45 | if key not in params: params[key] = "1"
46 | elif "--" in curr_item and "--" not in next_item:
47 | key = curr_item.replace('-','')
48 | if key not in params: params[key] = next_item
49 |
50 | # Construct it from system arguments
51 | # op.init_argv(args[1])
52 | # oppython = op.OpenposePython()
53 |
54 | # Starting OpenPose
55 | opWrapper = op.WrapperPython()
56 | opWrapper.configure(params)
57 | opWrapper.start()
58 |
59 | # Process Image
60 | datum = op.Datum()
61 | imageToProcess = cv2.imread(args[0].image_path)
62 | datum.cvInputData = imageToProcess
63 | opWrapper.emplaceAndPop(op.VectorDatum([datum]))
64 |
65 | # Display Image
66 | print("Body keypoints: \n" + str(datum.poseKeypoints))
67 | cv2.imshow("OpenPose 1.7.0 - Tutorial Python API", datum.cvOutputData)
68 | cv2.waitKey(0)
69 | except Exception as e:
70 | print(e)
71 | sys.exit(-1)
72 |
--------------------------------------------------------------------------------
/examples/tutorial_api_python/02_whole_body_from_image.py:
--------------------------------------------------------------------------------
1 | # From Python
2 | # It requires OpenCV installed for Python
3 | import sys
4 | import cv2
5 | import os
6 | from sys import platform
7 | import argparse
8 |
9 | try:
10 | # Import Openpose (Windows/Ubuntu/OSX)
11 | dir_path = os.path.dirname(os.path.realpath(__file__))
12 | try:
13 | # Windows Import
14 | if platform == "win32":
15 | # Change these variables to point to the correct folder (Release/x64 etc.)
16 | sys.path.append(dir_path + '/../../python/openpose/Release');
17 | os.environ['PATH'] = os.environ['PATH'] + ';' + dir_path + '/../../x64/Release;' + dir_path + '/../../bin;'
18 | import pyopenpose as op
19 | else:
20 | # Change these variables to point to the correct folder (Release/x64 etc.)
21 | sys.path.append('../../python');
22 | # If you run `make install` (default path is `/usr/local/python` for Ubuntu), you can also access the OpenPose/python module from there. This will install OpenPose and the python library at your desired installation path. Ensure that this is in your python path in order to use it.
23 | # sys.path.append('/usr/local/python')
24 | from openpose import pyopenpose as op
25 | except ImportError as e:
26 | print('Error: OpenPose library could not be found. Did you enable `BUILD_PYTHON` in CMake and have this Python script in the right folder?')
27 | raise e
28 |
29 | # Flags
30 | parser = argparse.ArgumentParser()
31 | parser.add_argument("--image_path", default="../../../examples/media/COCO_val2014_000000000241.jpg", help="Process an image. Read all standard formats (jpg, png, bmp, etc.).")
32 | args = parser.parse_known_args()
33 |
34 | # Custom Params (refer to include/openpose/flags.hpp for more parameters)
35 | params = dict()
36 | params["model_folder"] = "../../../models/"
37 | params["face"] = True
38 | params["hand"] = True
39 |
40 | # Add others in path?
41 | for i in range(0, len(args[1])):
42 | curr_item = args[1][i]
43 | if i != len(args[1])-1: next_item = args[1][i+1]
44 | else: next_item = "1"
45 | if "--" in curr_item and "--" in next_item:
46 | key = curr_item.replace('-','')
47 | if key not in params: params[key] = "1"
48 | elif "--" in curr_item and "--" not in next_item:
49 | key = curr_item.replace('-','')
50 | if key not in params: params[key] = next_item
51 |
52 | # Construct it from system arguments
53 | # op.init_argv(args[1])
54 | # oppython = op.OpenposePython()
55 |
56 | # Starting OpenPose
57 | opWrapper = op.WrapperPython()
58 | opWrapper.configure(params)
59 | opWrapper.start()
60 |
61 | # Process Image
62 | datum = op.Datum()
63 | imageToProcess = cv2.imread(args[0].image_path)
64 | datum.cvInputData = imageToProcess
65 | opWrapper.emplaceAndPop(op.VectorDatum([datum]))
66 |
67 | # Display Image
68 | print("Body keypoints: \n" + str(datum.poseKeypoints))
69 | print("Face keypoints: \n" + str(datum.faceKeypoints))
70 | print("Left hand keypoints: \n" + str(datum.handKeypoints[0]))
71 | print("Right hand keypoints: \n" + str(datum.handKeypoints[1]))
72 | cv2.imshow("OpenPose 1.7.0 - Tutorial Python API", datum.cvOutputData)
73 | cv2.waitKey(0)
74 | except Exception as e:
75 | print(e)
76 | sys.exit(-1)
77 |
--------------------------------------------------------------------------------
/examples/tutorial_api_python/04_keypoints_from_images.py:
--------------------------------------------------------------------------------
1 | # From Python
2 | # It requires OpenCV installed for Python
3 | import sys
4 | import cv2
5 | import os
6 | from sys import platform
7 | import argparse
8 | import time
9 |
10 | try:
11 | # Import Openpose (Windows/Ubuntu/OSX)
12 | dir_path = os.path.dirname(os.path.realpath(__file__))
13 | try:
14 | # Windows Import
15 | if platform == "win32":
16 | # Change these variables to point to the correct folder (Release/x64 etc.)
17 | sys.path.append(dir_path + '/../../python/openpose/Release');
18 | os.environ['PATH'] = os.environ['PATH'] + ';' + dir_path + '/../../x64/Release;' + dir_path + '/../../bin;'
19 | import pyopenpose as op
20 | else:
21 | # Change these variables to point to the correct folder (Release/x64 etc.)
22 | sys.path.append('../../python');
23 | # If you run `make install` (default path is `/usr/local/python` for Ubuntu), you can also access the OpenPose/python module from there. This will install OpenPose and the python library at your desired installation path. Ensure that this is in your python path in order to use it.
24 | # sys.path.append('/usr/local/python')
25 | from openpose import pyopenpose as op
26 | except ImportError as e:
27 | print('Error: OpenPose library could not be found. Did you enable `BUILD_PYTHON` in CMake and have this Python script in the right folder?')
28 | raise e
29 |
30 | # Flags
31 | parser = argparse.ArgumentParser()
32 | parser.add_argument("--image_dir", default="../../../examples/media/", help="Process a directory of images. Read all standard formats (jpg, png, bmp, etc.).")
33 | parser.add_argument("--no_display", default=False, help="Enable to disable the visual display.")
34 | args = parser.parse_known_args()
35 |
36 | # Custom Params (refer to include/openpose/flags.hpp for more parameters)
37 | params = dict()
38 | params["model_folder"] = "../../../models/"
39 |
40 | # Add others in path?
41 | for i in range(0, len(args[1])):
42 | curr_item = args[1][i]
43 | if i != len(args[1])-1: next_item = args[1][i+1]
44 | else: next_item = "1"
45 | if "--" in curr_item and "--" in next_item:
46 | key = curr_item.replace('-','')
47 | if key not in params: params[key] = "1"
48 | elif "--" in curr_item and "--" not in next_item:
49 | key = curr_item.replace('-','')
50 | if key not in params: params[key] = next_item
51 |
52 | # Construct it from system arguments
53 | # op.init_argv(args[1])
54 | # oppython = op.OpenposePython()
55 |
56 | # Starting OpenPose
57 | opWrapper = op.WrapperPython()
58 | opWrapper.configure(params)
59 | opWrapper.start()
60 |
61 | # Read frames on directory
62 | imagePaths = op.get_images_on_directory(args[0].image_dir);
63 | start = time.time()
64 |
65 | # Process and display images
66 | for imagePath in imagePaths:
67 | datum = op.Datum()
68 | imageToProcess = cv2.imread(imagePath)
69 | datum.cvInputData = imageToProcess
70 | opWrapper.emplaceAndPop(op.VectorDatum([datum]))
71 |
72 | print("Body keypoints: \n" + str(datum.poseKeypoints))
73 |
74 | if not args[0].no_display:
75 | cv2.imshow("OpenPose 1.7.0 - Tutorial Python API", datum.cvOutputData)
76 | key = cv2.waitKey(15)
77 | if key == 27: break
78 |
79 | end = time.time()
80 | print("OpenPose demo successfully finished. Total time: " + str(end - start) + " seconds")
81 | except Exception as e:
82 | print(e)
83 | sys.exit(-1)
84 |
--------------------------------------------------------------------------------
/examples/tutorial_api_python/05_keypoints_from_images_multi_gpu.py:
--------------------------------------------------------------------------------
1 | # From Python
2 | # It requires OpenCV installed for Python
3 | import sys
4 | import cv2
5 | import os
6 | from sys import platform
7 | import argparse
8 | import time
9 |
10 | try:
11 | # Import Openpose (Windows/Ubuntu/OSX)
12 | dir_path = os.path.dirname(os.path.realpath(__file__))
13 | try:
14 | # Windows Import
15 | if platform == "win32":
16 | # Change these variables to point to the correct folder (Release/x64 etc.)
17 | sys.path.append(dir_path + '/../../python/openpose/Release');
18 | os.environ['PATH'] = os.environ['PATH'] + ';' + dir_path + '/../../x64/Release;' + dir_path + '/../../bin;'
19 | import pyopenpose as op
20 | else:
21 | # Change these variables to point to the correct folder (Release/x64 etc.)
22 | sys.path.append('../../python');
23 | # If you run `make install` (default path is `/usr/local/python` for Ubuntu), you can also access the OpenPose/python module from there. This will install OpenPose and the python library at your desired installation path. Ensure that this is in your python path in order to use it.
24 | # sys.path.append('/usr/local/python')
25 | from openpose import pyopenpose as op
26 | except ImportError as e:
27 | print('Error: OpenPose library could not be found. Did you enable `BUILD_PYTHON` in CMake and have this Python script in the right folder?')
28 | raise e
29 |
30 | # Flags
31 | parser = argparse.ArgumentParser()
32 | parser.add_argument("--image_dir", default="../../../examples/media/", help="Process a directory of images. Read all standard formats (jpg, png, bmp, etc.).")
33 | parser.add_argument("--no_display", default=False, help="Enable to disable the visual display.")
34 | parser.add_argument("--num_gpu", default=op.get_gpu_number(), help="Number of GPUs.")
35 | args = parser.parse_known_args()
36 |
37 | # Custom Params (refer to include/openpose/flags.hpp for more parameters)
38 | params = dict()
39 | params["model_folder"] = "../../../models/"
40 | params["num_gpu"] = int(vars(args[0])["num_gpu"])
41 | numberGPUs = int(params["num_gpu"])
42 |
43 | # Add others in path?
44 | for i in range(0, len(args[1])):
45 | curr_item = args[1][i]
46 | if i != len(args[1])-1: next_item = args[1][i+1]
47 | else: next_item = "1"
48 | if "--" in curr_item and "--" in next_item:
49 | key = curr_item.replace('-','')
50 | if key not in params: params[key] = "1"
51 | elif "--" in curr_item and "--" not in next_item:
52 | key = curr_item.replace('-','')
53 | if key not in params: params[key] = next_item
54 |
55 | # Construct it from system arguments
56 | # op.init_argv(args[1])
57 | # oppython = op.OpenposePython()
58 |
59 | # Starting OpenPose
60 | opWrapper = op.WrapperPython()
61 | opWrapper.configure(params)
62 | opWrapper.start()
63 |
64 | # Read frames on directory
65 | imagePaths = op.get_images_on_directory(args[0].image_dir);
66 |
67 | # Read number of GPUs in your system
68 | start = time.time()
69 |
70 | # Process and display images
71 | for imageBaseId in range(0, len(imagePaths), numberGPUs):
72 |
73 | # Create datums
74 | images = []
75 |
76 | # Read and push images into OpenPose wrapper
77 | for gpuId in range(0, numberGPUs):
78 |
79 | imageId = imageBaseId+gpuId
80 | if imageId < len(imagePaths):
81 |
82 | imagePath = imagePaths[imageBaseId+gpuId]
83 | datum = op.Datum()
84 | images.append(cv2.imread(imagePath))
85 | datum.cvInputData = images[-1]
86 | opWrapper.waitAndEmplace(op.VectorDatum([datum]))
87 |
88 | # Retrieve processed results from OpenPose wrapper
89 | for gpuId in range(0, numberGPUs):
90 |
91 | imageId = imageBaseId+gpuId
92 | if imageId < len(imagePaths):
93 |
94 | datums = op.VectorDatum()
95 | opWrapper.waitAndPop(datums)
96 | datum = datums[0]
97 |
98 | print("Body keypoints: \n" + str(datum.poseKeypoints))
99 |
100 | if not args[0].no_display:
101 | cv2.imshow("OpenPose 1.7.0 - Tutorial Python API", datum.cvOutputData)
102 | key = cv2.waitKey(15)
103 | if key == 27: break
104 |
105 | end = time.time()
106 | print("OpenPose demo successfully finished. Total time: " + str(end - start) + " seconds")
107 | except Exception as e:
108 | print(e)
109 | sys.exit(-1)
110 |
--------------------------------------------------------------------------------
/examples/tutorial_api_python/06_face_from_image.py:
--------------------------------------------------------------------------------
1 | # From Python
2 | # It requires OpenCV installed for Python
3 | import sys
4 | import cv2
5 | import os
6 | from sys import platform
7 | import argparse
8 | import time
9 |
10 | try:
11 | # Import Openpose (Windows/Ubuntu/OSX)
12 | dir_path = os.path.dirname(os.path.realpath(__file__))
13 | try:
14 | # Windows Import
15 | if platform == "win32":
16 | # Change these variables to point to the correct folder (Release/x64 etc.)
17 | sys.path.append(dir_path + '/../../python/openpose/Release');
18 | os.environ['PATH'] = os.environ['PATH'] + ';' + dir_path + '/../../x64/Release;' + dir_path + '/../../bin;'
19 | import pyopenpose as op
20 | else:
21 | # Change these variables to point to the correct folder (Release/x64 etc.)
22 | sys.path.append('../../python');
23 | # If you run `make install` (default path is `/usr/local/python` for Ubuntu), you can also access the OpenPose/python module from there. This will install OpenPose and the python library at your desired installation path. Ensure that this is in your python path in order to use it.
24 | # sys.path.append('/usr/local/python')
25 | from openpose import pyopenpose as op
26 | except ImportError as e:
27 | print('Error: OpenPose library could not be found. Did you enable `BUILD_PYTHON` in CMake and have this Python script in the right folder?')
28 | raise e
29 |
30 | # Flags
31 | parser = argparse.ArgumentParser()
32 | parser.add_argument("--image_path", default="../../../examples/media/COCO_val2014_000000000241.jpg", help="Process an image. Read all standard formats (jpg, png, bmp, etc.).")
33 | args = parser.parse_known_args()
34 |
35 | # Custom Params (refer to include/openpose/flags.hpp for more parameters)
36 | params = dict()
37 | params["model_folder"] = "../../../models/"
38 | params["face"] = True
39 | params["face_detector"] = 2
40 | params["body"] = 0
41 |
42 | # Add others in path?
43 | for i in range(0, len(args[1])):
44 | curr_item = args[1][i]
45 | if i != len(args[1])-1: next_item = args[1][i+1]
46 | else: next_item = "1"
47 | if "--" in curr_item and "--" in next_item:
48 | key = curr_item.replace('-','')
49 | if key not in params: params[key] = "1"
50 | elif "--" in curr_item and "--" not in next_item:
51 | key = curr_item.replace('-','')
52 | if key not in params: params[key] = next_item
53 |
54 | # Construct it from system arguments
55 | # op.init_argv(args[1])
56 | # oppython = op.OpenposePython()
57 |
58 | # Starting OpenPose
59 | opWrapper = op.WrapperPython()
60 | opWrapper.configure(params)
61 | opWrapper.start()
62 |
63 | # Read image and face rectangle locations
64 | imageToProcess = cv2.imread(args[0].image_path)
65 | faceRectangles = [
66 | op.Rectangle(330.119385, 277.532715, 48.717274, 48.717274),
67 | op.Rectangle(24.036991, 267.918793, 65.175171, 65.175171),
68 | op.Rectangle(151.803436, 32.477852, 108.295761, 108.295761),
69 | ]
70 |
71 | # Create new datum
72 | datum = op.Datum()
73 | datum.cvInputData = imageToProcess
74 | datum.faceRectangles = faceRectangles
75 |
76 | # Process and display image
77 | opWrapper.emplaceAndPop(op.VectorDatum([datum]))
78 | print("Face keypoints: \n" + str(datum.faceKeypoints))
79 | cv2.imshow("OpenPose 1.7.0 - Tutorial Python API", datum.cvOutputData)
80 | cv2.waitKey(0)
81 | except Exception as e:
82 | print(e)
83 | sys.exit(-1)
84 |
--------------------------------------------------------------------------------
/examples/tutorial_api_python/07_hand_from_image.py:
--------------------------------------------------------------------------------
1 | # From Python
2 | # It requires OpenCV installed for Python
3 | import sys
4 | import cv2
5 | import os
6 | from sys import platform
7 | import argparse
8 | import time
9 |
10 | try:
11 | # Import Openpose (Windows/Ubuntu/OSX)
12 | dir_path = os.path.dirname(os.path.realpath(__file__))
13 | try:
14 | # Windows Import
15 | if platform == "win32":
16 | # Change these variables to point to the correct folder (Release/x64 etc.)
17 | sys.path.append(dir_path + '/../../python/openpose/Release');
18 | os.environ['PATH'] = os.environ['PATH'] + ';' + dir_path + '/../../x64/Release;' + dir_path + '/../../bin;'
19 | import pyopenpose as op
20 | else:
21 | # Change these variables to point to the correct folder (Release/x64 etc.)
22 | sys.path.append('../../python');
23 | # If you run `make install` (default path is `/usr/local/python` for Ubuntu), you can also access the OpenPose/python module from there. This will install OpenPose and the python library at your desired installation path. Ensure that this is in your python path in order to use it.
24 | # sys.path.append('/usr/local/python')
25 | from openpose import pyopenpose as op
26 | except ImportError as e:
27 | print('Error: OpenPose library could not be found. Did you enable `BUILD_PYTHON` in CMake and have this Python script in the right folder?')
28 | raise e
29 |
30 | # Flags
31 | parser = argparse.ArgumentParser()
32 | parser.add_argument("--image_path", default="../../../examples/media/COCO_val2014_000000000241.jpg", help="Process an image. Read all standard formats (jpg, png, bmp, etc.).")
33 | args = parser.parse_known_args()
34 |
35 | # Custom Params (refer to include/openpose/flags.hpp for more parameters)
36 | params = dict()
37 | params["model_folder"] = "../../../models/"
38 | params["hand"] = True
39 | params["hand_detector"] = 2
40 | params["body"] = 0
41 |
42 | # Add others in path?
43 | for i in range(0, len(args[1])):
44 | curr_item = args[1][i]
45 | if i != len(args[1])-1: next_item = args[1][i+1]
46 | else: next_item = "1"
47 | if "--" in curr_item and "--" in next_item:
48 | key = curr_item.replace('-','')
49 | if key not in params: params[key] = "1"
50 | elif "--" in curr_item and "--" not in next_item:
51 | key = curr_item.replace('-','')
52 | if key not in params: params[key] = next_item
53 |
54 | # Construct it from system arguments
55 | # op.init_argv(args[1])
56 | # oppython = op.OpenposePython()
57 |
58 | # Starting OpenPose
59 | opWrapper = op.WrapperPython()
60 | opWrapper.configure(params)
61 | opWrapper.start()
62 |
63 | # Read image and face rectangle locations
64 | imageToProcess = cv2.imread(args[0].image_path)
65 | handRectangles = [
66 | # Left/Right hands person 0
67 | [
68 | op.Rectangle(320.035889, 377.675049, 69.300949, 69.300949),
69 | op.Rectangle(0., 0., 0., 0.),
70 | ],
71 | # Left/Right hands person 1
72 | [
73 | op.Rectangle(80.155792, 407.673492, 80.812706, 80.812706),
74 | op.Rectangle(46.449715, 404.559753, 98.898178, 98.898178),
75 | ],
76 | # Left/Right hands person 2
77 | [
78 | op.Rectangle(185.692673, 303.112244, 157.587555, 157.587555),
79 | op.Rectangle(88.984360, 268.866547, 117.818230, 117.818230),
80 | ]
81 | ]
82 |
83 | # Create new datum
84 | datum = op.Datum()
85 | datum.cvInputData = imageToProcess
86 | datum.handRectangles = handRectangles
87 |
88 | # Process and display image
89 | opWrapper.emplaceAndPop(op.VectorDatum([datum]))
90 | print("Left hand keypoints: \n" + str(datum.handKeypoints[0]))
91 | print("Right hand keypoints: \n" + str(datum.handKeypoints[1]))
92 | cv2.imshow("OpenPose 1.7.0 - Tutorial Python API", datum.cvOutputData)
93 | cv2.waitKey(0)
94 | except Exception as e:
95 | print(e)
96 | sys.exit(-1)
97 |
--------------------------------------------------------------------------------
/examples/tutorial_api_python/08_heatmaps_from_image.py:
--------------------------------------------------------------------------------
1 | # From Python
2 | # It requires OpenCV installed for Python
3 | import sys
4 | import cv2
5 | import os
6 | from sys import platform
7 | import argparse
8 |
9 | try:
10 | # Import Openpose (Windows/Ubuntu/OSX)
11 | dir_path = os.path.dirname(os.path.realpath(__file__))
12 | try:
13 | # Windows Import
14 | if platform == "win32":
15 | # Change these variables to point to the correct folder (Release/x64 etc.)
16 | sys.path.append(dir_path + '/../../python/openpose/Release');
17 | os.environ['PATH'] = os.environ['PATH'] + ';' + dir_path + '/../../x64/Release;' + dir_path + '/../../bin;'
18 | import pyopenpose as op
19 | else:
20 | # Change these variables to point to the correct folder (Release/x64 etc.)
21 | sys.path.append('../../python');
22 | # If you run `make install` (default path is `/usr/local/python` for Ubuntu), you can also access the OpenPose/python module from there. This will install OpenPose and the python library at your desired installation path. Ensure that this is in your python path in order to use it.
23 | # sys.path.append('/usr/local/python')
24 | from openpose import pyopenpose as op
25 | except ImportError as e:
26 | print('Error: OpenPose library could not be found. Did you enable `BUILD_PYTHON` in CMake and have this Python script in the right folder?')
27 | raise e
28 |
29 | # Flags
30 | parser = argparse.ArgumentParser()
31 | parser.add_argument("--image_path", default="../../../examples/media/COCO_val2014_000000000192.jpg", help="Process an image. Read all standard formats (jpg, png, bmp, etc.).")
32 | args = parser.parse_known_args()
33 |
34 | # Custom Params (refer to include/openpose/flags.hpp for more parameters)
35 | params = dict()
36 | params["model_folder"] = "../../../models/"
37 | params["heatmaps_add_parts"] = True
38 | params["heatmaps_add_bkg"] = True
39 | params["heatmaps_add_PAFs"] = True
40 | params["heatmaps_scale"] = 2
41 |
42 | # Add others in path?
43 | for i in range(0, len(args[1])):
44 | curr_item = args[1][i]
45 | if i != len(args[1])-1: next_item = args[1][i+1]
46 | else: next_item = "1"
47 | if "--" in curr_item and "--" in next_item:
48 | key = curr_item.replace('-','')
49 | if key not in params: params[key] = "1"
50 | elif "--" in curr_item and "--" not in next_item:
51 | key = curr_item.replace('-','')
52 | if key not in params: params[key] = next_item
53 |
54 | # Construct it from system arguments
55 | # op.init_argv(args[1])
56 | # oppython = op.OpenposePython()
57 |
58 | # Starting OpenPose
59 | opWrapper = op.WrapperPython()
60 | opWrapper.configure(params)
61 | opWrapper.start()
62 |
63 | # Process Image
64 | datum = op.Datum()
65 | imageToProcess = cv2.imread(args[0].image_path)
66 | datum.cvInputData = imageToProcess
67 | opWrapper.emplaceAndPop(op.VectorDatum([datum]))
68 |
69 | # Process outputs
70 | outputImageF = (datum.inputNetData[0].copy())[0,:,:,:] + 0.5
71 | outputImageF = cv2.merge([outputImageF[0,:,:], outputImageF[1,:,:], outputImageF[2,:,:]])
72 | outputImageF = (outputImageF*255.).astype(dtype='uint8')
73 | heatmaps = datum.poseHeatMaps.copy()
74 | heatmaps = (heatmaps).astype(dtype='uint8')
75 |
76 | # Display Image
77 | counter = 0
78 | while 1:
79 | num_maps = heatmaps.shape[0]
80 | heatmap = heatmaps[counter, :, :].copy()
81 | heatmap = cv2.applyColorMap(heatmap, cv2.COLORMAP_JET)
82 | combined = cv2.addWeighted(outputImageF, 0.5, heatmap, 0.5, 0)
83 | cv2.imshow("OpenPose 1.7.0 - Tutorial Python API", combined)
84 | key = cv2.waitKey(-1)
85 | if key == 27:
86 | break
87 | counter += 1
88 | counter = counter % num_maps
89 | except Exception as e:
90 | print(e)
91 | sys.exit(-1)
92 |
--------------------------------------------------------------------------------
/examples/tutorial_api_python/09_keypoints_from_heatmaps.py:
--------------------------------------------------------------------------------
1 | # From Python
2 | # It requires OpenCV installed for Python
3 | import sys
4 | import cv2
5 | import os
6 | from sys import platform
7 | import argparse
8 | import numpy as np
9 |
10 | try:
11 | # Import Openpose (Windows/Ubuntu/OSX)
12 | dir_path = os.path.dirname(os.path.realpath(__file__))
13 | try:
14 | # Windows Import
15 | if platform == "win32":
16 | # Change these variables to point to the correct folder (Release/x64 etc.)
17 | sys.path.append(dir_path + '/../../python/openpose/Release');
18 | os.environ['PATH'] = os.environ['PATH'] + ';' + dir_path + '/../../x64/Release;' + dir_path + '/../../bin;'
19 | import pyopenpose as op
20 | else:
21 | # Change these variables to point to the correct folder (Release/x64 etc.)
22 | sys.path.append('../../python');
23 | # If you run `make install` (default path is `/usr/local/python` for Ubuntu), you can also access the OpenPose/python module from there. This will install OpenPose and the python library at your desired installation path. Ensure that this is in your python path in order to use it.
24 | # sys.path.append('/usr/local/python')
25 | from openpose import pyopenpose as op
26 | except ImportError as e:
27 | print('Error: OpenPose library could not be found. Did you enable `BUILD_PYTHON` in CMake and have this Python script in the right folder?')
28 | raise e
29 |
30 | # Flags
31 | parser = argparse.ArgumentParser()
32 | parser.add_argument("--image_path", default="../../../examples/media/COCO_val2014_000000000294.jpg", help="Process an image. Read all standard formats (jpg, png, bmp, etc.).")
33 | args = parser.parse_known_args()
34 |
35 | # Load image
36 | imageToProcess = cv2.imread(args[0].image_path)
37 |
38 | def get_sample_heatmaps():
39 | # These parameters are globally set. You need to unset variables set here if you have a new OpenPose object. See *
40 | params = dict()
41 | params["model_folder"] = "../../../models/"
42 | params["heatmaps_add_parts"] = True
43 | params["heatmaps_add_bkg"] = True
44 | params["heatmaps_add_PAFs"] = True
45 | params["heatmaps_scale"] = 3
46 | params["upsampling_ratio"] = 1
47 | params["body"] = 1
48 |
49 | # Starting OpenPose
50 | opWrapper = op.WrapperPython()
51 | opWrapper.configure(params)
52 | opWrapper.start()
53 |
54 | # Process Image and get heatmap
55 | datum = op.Datum()
56 | imageToProcess = cv2.imread(args[0].image_path)
57 | datum.cvInputData = imageToProcess
58 | opWrapper.emplaceAndPop(op.VectorDatum([datum]))
59 | poseHeatMaps = datum.poseHeatMaps.copy()
60 | opWrapper.stop()
61 |
62 | return poseHeatMaps
63 |
64 | # Get Heatmap
65 | poseHeatMaps = get_sample_heatmaps()
66 |
67 | # Starting OpenPose
68 | params = dict()
69 | params["model_folder"] = "../../../models/"
70 | params["body"] = 2 # Disable OP Network
71 | params["upsampling_ratio"] = 0 # * Unset this variable
72 | opWrapper = op.WrapperPython()
73 | opWrapper.configure(params)
74 | opWrapper.start()
75 |
76 | # Pass Heatmap and Run OP
77 | datum = op.Datum()
78 | datum.cvInputData = imageToProcess
79 | datum.poseNetOutput = poseHeatMaps
80 | opWrapper.emplaceAndPop(op.VectorDatum([datum]))
81 |
82 | # Display Image
83 | print("Body keypoints: \n" + str(datum.poseKeypoints))
84 | cv2.imshow("OpenPose 1.7.0 - Tutorial Python API", datum.cvOutputData)
85 | cv2.waitKey(0)
86 | except Exception as e:
87 | print(e)
88 | sys.exit(-1)
89 |
--------------------------------------------------------------------------------
/examples/tutorial_api_python/12_asynchronous_custom_output.py:
--------------------------------------------------------------------------------
1 | # From Python
2 | # It requires OpenCV installed for Python
3 | import sys
4 | import cv2
5 | import os
6 | from sys import platform
7 | import argparse
8 |
9 |
10 | def display(datums):
11 | datum = datums[0]
12 | cv2.imshow("OpenPose 1.7.0 - Tutorial Python API", datum.cvOutputData)
13 | key = cv2.waitKey(1)
14 | return (key == 27)
15 |
16 |
17 | def printKeypoints(datums):
18 | datum = datums[0]
19 | print("Body keypoints: \n" + str(datum.poseKeypoints))
20 | print("Face keypoints: \n" + str(datum.faceKeypoints))
21 | print("Left hand keypoints: \n" + str(datum.handKeypoints[0]))
22 | print("Right hand keypoints: \n" + str(datum.handKeypoints[1]))
23 |
24 |
25 | try:
26 | # Import Openpose (Windows/Ubuntu/OSX)
27 | dir_path = os.path.dirname(os.path.realpath(__file__))
28 | try:
29 | # Windows Import
30 | if platform == "win32":
31 | # Change these variables to point to the correct folder (Release/x64 etc.)
32 | sys.path.append(dir_path + '/../../python/openpose/Release');
33 | os.environ['PATH'] = os.environ['PATH'] + ';' + dir_path + '/../../x64/Release;' + dir_path + '/../../bin;'
34 | import pyopenpose as op
35 | else:
36 | # Change these variables to point to the correct folder (Release/x64 etc.)
37 | sys.path.append('../../python');
38 | # If you run `make install` (default path is `/usr/local/python` for Ubuntu), you can also access the OpenPose/python module from there. This will install OpenPose and the python library at your desired installation path. Ensure that this is in your python path in order to use it.
39 | # sys.path.append('/usr/local/python')
40 | from openpose import pyopenpose as op
41 | except ImportError as e:
42 | print('Error: OpenPose library could not be found. Did you enable `BUILD_PYTHON` in CMake and have this Python script in the right folder?')
43 | raise e
44 |
45 | # Flags
46 | parser = argparse.ArgumentParser()
47 | parser.add_argument("--no-display", action="store_true", help="Disable display.")
48 | args = parser.parse_known_args()
49 |
50 | # Custom Params (refer to include/openpose/flags.hpp for more parameters)
51 | params = dict()
52 | params["model_folder"] = "../../../models/"
53 |
54 | # Add others in path?
55 | for i in range(0, len(args[1])):
56 | curr_item = args[1][i]
57 | if i != len(args[1])-1: next_item = args[1][i+1]
58 | else: next_item = "1"
59 | if "--" in curr_item and "--" in next_item:
60 | key = curr_item.replace('-','')
61 | if key not in params: params[key] = "1"
62 | elif "--" in curr_item and "--" not in next_item:
63 | key = curr_item.replace('-','')
64 | if key not in params: params[key] = next_item
65 |
66 | # Construct it from system arguments
67 | # op.init_argv(args[1])
68 | # oppython = op.OpenposePython()
69 |
70 | # Starting OpenPose
71 | opWrapper = op.WrapperPython(op.ThreadManagerMode.AsynchronousOut)
72 | opWrapper.configure(params)
73 | opWrapper.start()
74 |
75 | # Main loop
76 | userWantsToExit = False
77 | while not userWantsToExit:
78 | # Pop frame
79 | datumProcessed = op.VectorDatum()
80 | if opWrapper.waitAndPop(datumProcessed):
81 | if not args[0].no_display:
82 | # Display image
83 | userWantsToExit = display(datumProcessed)
84 | printKeypoints(datumProcessed)
85 | else:
86 | break
87 | except Exception as e:
88 | print(e)
89 | sys.exit(-1)
90 |
--------------------------------------------------------------------------------
/examples/tutorial_api_python/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | ### Add Python Test
2 | configure_file(01_body_from_image.py 01_body_from_image.py)
3 | configure_file(02_whole_body_from_image.py 02_whole_body_from_image.py)
4 | configure_file(04_keypoints_from_images.py 04_keypoints_from_images.py)
5 | configure_file(05_keypoints_from_images_multi_gpu.py 05_keypoints_from_images_multi_gpu.py)
6 | configure_file(06_face_from_image.py 06_face_from_image.py)
7 | configure_file(07_hand_from_image.py 07_hand_from_image.py)
8 | configure_file(08_heatmaps_from_image.py 08_heatmaps_from_image.py)
9 | configure_file(09_keypoints_from_heatmaps.py 09_keypoints_from_heatmaps.py)
10 | configure_file(openpose_python.py openpose_python.py)
11 |
--------------------------------------------------------------------------------
/examples/tutorial_api_python/README.md:
--------------------------------------------------------------------------------
1 | # Python API Examples
2 | See the [OpenPose Python API doc](../../doc/03_python_api.md) for more details on this folder.
3 |
4 | This folder provides examples to the basic OpenPose Python API. The analogous C++ API is exposed in [examples/tutorial_api_cpp/](../tutorial_api_cpp/).
5 |
--------------------------------------------------------------------------------
/examples/tutorial_api_python/openpose_python.py:
--------------------------------------------------------------------------------
1 | # From Python
2 | # It requires OpenCV installed for Python
3 | import sys
4 | import cv2
5 | import os
6 | from sys import platform
7 | import argparse
8 |
9 | try:
10 | # Import Openpose (Windows/Ubuntu/OSX)
11 | dir_path = os.path.dirname(os.path.realpath(__file__))
12 | try:
13 | # Windows Import
14 | if platform == "win32":
15 | # Change these variables to point to the correct folder (Release/x64 etc.)
16 | sys.path.append(dir_path + '/../../python/openpose/Release');
17 | os.environ['PATH'] = os.environ['PATH'] + ';' + dir_path + '/../../x64/Release;' + dir_path + '/../../bin;'
18 | import pyopenpose as op
19 | else:
20 | # Change these variables to point to the correct folder (Release/x64 etc.)
21 | sys.path.append('../../python');
22 | # If you run `make install` (default path is `/usr/local/python` for Ubuntu), you can also access the OpenPose/python module from there. This will install OpenPose and the python library at your desired installation path. Ensure that this is in your python path in order to use it.
23 | # sys.path.append('/usr/local/python')
24 | from openpose import pyopenpose as op
25 | except ImportError as e:
26 | print('Error: OpenPose library could not be found. Did you enable `BUILD_PYTHON` in CMake and have this Python script in the right folder?')
27 | raise e
28 |
29 | # Flags
30 | parser = argparse.ArgumentParser()
31 | parser.add_argument("--image_path", default="../../../examples/media/COCO_val2014_000000000192.jpg", help="Process an image. Read all standard formats (jpg, png, bmp, etc.).")
32 | args = parser.parse_known_args()
33 |
34 | # Custom Params (refer to include/openpose/flags.hpp for more parameters)
35 | params = dict()
36 | params["model_folder"] = "../../../models/"
37 |
38 | # Add others in path?
39 | for i in range(0, len(args[1])):
40 | curr_item = args[1][i]
41 | if i != len(args[1])-1: next_item = args[1][i+1]
42 | else: next_item = "1"
43 | if "--" in curr_item and "--" in next_item:
44 | key = curr_item.replace('-','')
45 | if key not in params: params[key] = "1"
46 | elif "--" in curr_item and "--" not in next_item:
47 | key = curr_item.replace('-','')
48 | if key not in params: params[key] = next_item
49 |
50 | # Construct it from system arguments
51 | # op.init_argv(args[1])
52 | # oppython = op.OpenposePython()
53 |
54 | # Starting OpenPose
55 | opWrapper = op.WrapperPython(op.ThreadManagerMode.Synchronous)
56 | opWrapper.configure(params)
57 | opWrapper.execute()
58 | except Exception as e:
59 | print(e)
60 | sys.exit(-1)
61 |
--------------------------------------------------------------------------------
/keypoints_hand.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/keypoints_hand.png
--------------------------------------------------------------------------------
/keypoints_pose_25.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/keypoints_pose_25.png
--------------------------------------------------------------------------------
/models/cameraParameters/flir/17012332.xml.example:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | 3
6 | 4
7 | d
8 |
9 | 1. 0. 0. 0.
10 | 0. 1. 0. 0.
11 | 0. 0. 1. 0.
12 |
13 | 3
14 | 3
15 | d
16 |
17 | 8.1793481631740565e+02 0. 6.0070689997785121e+02 0.
18 | 8.1651774059837908e+02 5.1784529566329593e+02 0. 0. 1.
19 |
20 | 8
21 | 1
22 | d
23 |
24 | -1.8102158829399091e+00 9.1966147162623262e+00
25 | -4.4293900343777355e-04 1.3638377686816653e-03
26 | 1.3303863414979364e+00 -1.4189051636354870e+00
27 | 8.4725535468475819e+00 4.7911023525901033e+00
28 |
29 |
--------------------------------------------------------------------------------
/models/getModels.bat:
--------------------------------------------------------------------------------
1 | :: Avoid printing all the comments in the Windows cmd
2 | @echo off
3 |
4 | echo ------------------------- BODY, FOOT, FACE, AND HAND MODELS -------------------------
5 | echo ----- Downloading body pose (COCO and MPI), face and hand models -----
6 | SET WGET_EXE=..\3rdparty\windows\wget\wget.exe
7 | SET OPENPOSE_URL=http://posefs1.perception.cs.cmu.edu/OpenPose/models/
8 | SET POSE_FOLDER=pose/
9 | SET FACE_FOLDER=face/
10 | SET HAND_FOLDER=hand/
11 |
12 | echo:
13 | echo ------------------------- POSE (BODY+FOOT) MODELS -------------------------
14 | echo Body (BODY_25)
15 | set BODY_25_FOLDER=%POSE_FOLDER%body_25/
16 | set BODY_25_MODEL=%BODY_25_FOLDER%pose_iter_584000.caffemodel
17 | %WGET_EXE% -c %OPENPOSE_URL%%BODY_25_MODEL% -P %BODY_25_FOLDER%
18 |
19 | echo Body (COCO)
20 | SET COCO_FOLDER=%POSE_FOLDER%coco/
21 | SET COCO_MODEL=%COCO_FOLDER%pose_iter_440000.caffemodel
22 | %WGET_EXE% -c %OPENPOSE_URL%%COCO_MODEL% -P %COCO_FOLDER%
23 |
24 | echo:
25 | echo Body (MPI)
26 | SET MPI_FOLDER=%POSE_FOLDER%mpi/
27 | SET MPI_MODEL=%MPI_FOLDER%pose_iter_160000.caffemodel
28 | %WGET_EXE% -c %OPENPOSE_URL%%MPI_MODEL% -P %MPI_FOLDER%
29 | echo ----------------------- POSE DOWNLOADED -----------------------
30 |
31 | echo:
32 | echo ------------------------- FACE MODELS -------------------------
33 | echo Face
34 | SET FACE_MODEL=%FACE_FOLDER%pose_iter_116000.caffemodel
35 | %WGET_EXE% -c %OPENPOSE_URL%%FACE_MODEL% -P %FACE_FOLDER%
36 | echo ----------------------- FACE DOWNLOADED -----------------------
37 |
38 | echo:
39 | echo ------------------------- HAND MODELS -------------------------
40 | echo Hand
41 | SET HAND_MODEL=%HAND_FOLDER%pose_iter_102000.caffemodel
42 | %WGET_EXE% -c %OPENPOSE_URL%%HAND_MODEL% -P %HAND_FOLDER%
43 | echo ----------------------- HAND DOWNLOADED -----------------------
44 |
--------------------------------------------------------------------------------
/models/getModels.sh:
--------------------------------------------------------------------------------
1 | # ------------------------- BODY, FOOT, FACE, AND HAND MODELS -------------------------
2 | # Downloading body pose (COCO and MPI), face and hand models
3 | OPENPOSE_URL="http://posefs1.perception.cs.cmu.edu/OpenPose/models/"
4 | POSE_FOLDER="pose/"
5 | FACE_FOLDER="face/"
6 | HAND_FOLDER="hand/"
7 |
8 | # ------------------------- POSE (BODY+FOOT) MODELS -------------------------
9 | # Body (BODY_25)
10 | BODY_25_FOLDER=${POSE_FOLDER}"body_25/"
11 | BODY_25_MODEL=${BODY_25_FOLDER}"pose_iter_584000.caffemodel"
12 | wget -c ${OPENPOSE_URL}${BODY_25_MODEL} -P ${BODY_25_FOLDER}
13 |
14 | # Body (COCO)
15 | COCO_FOLDER=${POSE_FOLDER}"coco/"
16 | COCO_MODEL=${COCO_FOLDER}"pose_iter_440000.caffemodel"
17 | wget -c ${OPENPOSE_URL}${COCO_MODEL} -P ${COCO_FOLDER}
18 | # Alternative: it will not check whether file was fully downloaded
19 | # if [ ! -f $COCO_MODEL ]; then
20 | # wget ${OPENPOSE_URL}$COCO_MODEL -P $COCO_FOLDER
21 | # fi
22 |
23 | # Body (MPI)
24 | MPI_FOLDER=${POSE_FOLDER}"mpi/"
25 | MPI_MODEL=${MPI_FOLDER}"pose_iter_160000.caffemodel"
26 | wget -c ${OPENPOSE_URL}${MPI_MODEL} -P ${MPI_FOLDER}
27 |
28 | # "------------------------- FACE MODELS -------------------------"
29 | # Face
30 | FACE_MODEL=${FACE_FOLDER}"pose_iter_116000.caffemodel"
31 | wget -c ${OPENPOSE_URL}${FACE_MODEL} -P ${FACE_FOLDER}
32 |
33 | # "------------------------- HAND MODELS -------------------------"
34 | # Hand
35 | HAND_MODEL=$HAND_FOLDER"pose_iter_102000.caffemodel"
36 | wget -c ${OPENPOSE_URL}${HAND_MODEL} -P ${HAND_FOLDER}
37 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | # torch and torchvision can only be installed with .whl, otherwise it will not install correctly
2 | # torch==1.2.0
3 | # torchvision==0.4.0
4 | opencv_python==4.1.2.30
5 | numpy==1.17.0
6 | matplotlib==3.1.2
7 | tqdm==4.60.0
8 | Pillow==8.3.2
9 | torchsummary==1.5.1
10 | scipy==1.2.1
11 | h5py==2.10.0
12 |
--------------------------------------------------------------------------------
/test.py:
--------------------------------------------------------------------------------
1 | # 此文件用来进行图片骨架检测的测试
2 |
3 | import bin.pyopenpose as op # 注意要3.7才能正确import
4 | import matplotlib.pyplot as plt
5 | import cv2
6 | import numpy as np
7 |
8 | filePath = 'examples/media/COCO_val2014_000000000395.jpg'
9 |
10 | # 找到模型文件
11 | params = dict()
12 | params["model_folder"] = "models/"
13 | params["net_resolution"] = "256x256" # 大小要设置成1:1的,且是2的倍数,1660ti超过256就爆显存了
14 | params["hand"] = True
15 |
16 | # opWrapper用来启动openpose
17 | opWrapper = op.WrapperPython()
18 | opWrapper.configure(params)
19 | opWrapper.start()
20 |
21 | # 加载图片到openpose的运行时里
22 | imageToProcess = cv2.imread(filePath)
23 | datum = op.Datum()
24 | datum.cvInputData = imageToProcess
25 | opWrapper.emplaceAndPop(op.VectorDatum([datum]))
26 |
27 | # 打印出点的位置
28 | # datum.poseKeypoints的类型是ndarray
29 | print("Body keypoints: \n" + str(datum.poseKeypoints))
30 | print("Left hand keypoints: \n" + str(datum.handKeypoints[0]))
31 | print("Right hand keypoints: \n" + str(datum.handKeypoints[1]))
32 |
33 | # 显示图片
34 | cv2.imshow("OpenPose 1.7.0 - Tutorial Python API", datum.cvOutputData)
35 | cv2.waitKey(0)
36 |
--------------------------------------------------------------------------------
/test_video.py:
--------------------------------------------------------------------------------
1 | # 此文件用来进行视频骨架检测的测试
2 |
3 |
4 | import bin.pyopenpose as op # 注意要3.7才能正确import,版本与文件名对应
5 | import matplotlib.pyplot as plt
6 | import cv2
7 | import time
8 |
9 | # 视频路径,若要打开摄像头,设为0
10 | filePath = 'examples/media/test.mp4'
11 |
12 | # 找到模型文件
13 | params = dict()
14 | params["model_folder"] = "models/"
15 | params["net_resolution"] = "256x256" # 大小要设置成1:1的,且是2的倍数,1660ti超过256就爆显存了
16 | params["hand"] = True
17 |
18 | # opWrapper用来启动openpose
19 | opWrapper = op.WrapperPython()
20 | opWrapper.configure(params)
21 | opWrapper.start()
22 |
23 |
24 | # 打开视频
25 | cap = cv2.VideoCapture(filePath)
26 |
27 | fps = 0
28 | while True:
29 | t0 = time.time()
30 | # 截取一帧图片
31 | flag, frame = cap.read()
32 | if flag == False:
33 | break
34 | # 将图片到加载openpose的运行时里
35 | datum = op.Datum()
36 | datum.cvInputData = frame
37 | opWrapper.emplaceAndPop(op.VectorDatum([datum]))
38 |
39 | # 打印出点的位置
40 | # datum.poseKeypoints的类型是ndarray
41 | # print("Body keypoints: \n" + str(datum.poseKeypoints))
42 |
43 |
44 | # 显示图片
45 | cv2.imshow('', datum.cvOutputData)
46 | if cv2.waitKey(10) & 0xFF == 27:
47 | break
48 |
49 | # 计算并打印fps
50 | t1 = time.time()
51 | fps = 1/(t1 - t0)
52 | print('fps = {:.3f}'.format(fps))
53 |
--------------------------------------------------------------------------------
/test_video_track_point.py:
--------------------------------------------------------------------------------
1 | import bin.pyopenpose as op # 注意要3.7才能正确import,版本与文件名对应
2 |
3 | import matplotlib.pyplot as plt
4 | import numpy as np
5 | import cv2
6 | import time
7 | from PIL import Image
8 |
9 | # 视频路径,若要打开摄像头,设为0
10 | filePath = 'examples/media/test4.mp4'
11 |
12 | # 要追踪的关节点,点的定义在kepoints_hand.png和kepoints_pose_25.png里
13 | body_point_list = [1, 2, 3, 4, 5, 6, 7] # 7个
14 | left_hand_point_lsit = [0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17, 20] # 16个
15 | right_hand_point_list = [0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, 17, 20] # 16个
16 | # left_hand_point_lsit = [0] # 1
17 | # right_hand_point_list = [0] # 1
18 |
19 |
20 | # 身体和手部的颜色定义
21 | body_color = [int(36.4*(i+1)) for i in range(7)]
22 | hand_color = [int(15.9*(i+1)) for i in range(16)]
23 | # print(body_color)
24 | # print(hand_color)
25 |
26 | # 找到模型文件
27 | params = dict()
28 | params["model_folder"] = "models/"
29 | params["net_resolution"] = "256x256" # 大小要设置成1:1的,且是2的倍数,1660ti超过256就爆显存了
30 | params["hand"] = True
31 |
32 | # opWrapper用来启动openpose
33 | opWrapper = op.WrapperPython()
34 | opWrapper.configure(params)
35 | opWrapper.start()
36 |
37 |
38 | # 打开视频
39 | cap = cv2.VideoCapture(filePath)
40 |
41 | # 轨迹图
42 | track_img = np.zeros(shape=(1080, 1920, 3), dtype=np.int8)
43 |
44 | fps = 0
45 | while True:
46 | t0 = time.time()
47 | # 截取一帧图片
48 | flag, frame = cap.read()
49 | if flag == False:
50 | break
51 | # 将图片到加载openpose的运行时里做检测
52 | datum = op.Datum()
53 | datum.cvInputData = frame
54 | opWrapper.emplaceAndPop(op.VectorDatum([datum]))
55 |
56 | # 打印出点的位置
57 | # datum.poseKeypoints的类型是ndarray
58 | # print("Body keypoints: \n" + str(datum.poseKeypoints))
59 |
60 | # 获取关节点
61 | body_point = datum.poseKeypoints
62 | left_hand_point = datum.handKeypoints[0]
63 | right_hand_point = datum.handKeypoints[1]
64 |
65 |
66 | # 绘制点轨迹图
67 | color_idx = 0
68 | for idx in body_point_list:
69 | cv2.circle(track_img, (int(body_point[0][idx][0]),int(body_point[0][idx][1])), 1, (0, 0, body_color[color_idx]), 5)
70 | color_idx += 1
71 |
72 | color_idx = 0
73 | for idx in left_hand_point_lsit:
74 | cv2.circle(track_img, (int(left_hand_point[0][idx][0]),int(left_hand_point[0][idx][1])), 1, (0, hand_color[color_idx], 0), 5)
75 | color_idx += 1
76 |
77 | color_idx = 0
78 | for idx in right_hand_point_list:
79 | cv2.circle(track_img, (int(right_hand_point[0][idx][0]),int(right_hand_point[0][idx][1])), 1, (hand_color[color_idx], 0, 0), 5)
80 | color_idx += 1
81 |
82 |
83 | # 显示图片
84 | cv2.imshow('', datum.cvOutputData)
85 | if cv2.waitKey(10) & 0xFF == 27:
86 | break
87 |
88 | # 计算并打印fps
89 | t1 = time.time()
90 | # fps = 1/(t1 - t0)
91 | # print('fps = {:.3f}'.format(fps))
92 |
93 | # 保存图片
94 | track_img = np.uint8(track_img)
95 | cv2.imwrite('track_of_point.jpg', track_img)
96 |
97 |
98 |
99 | ################################################################################
100 | ################################################################################
101 |
102 | # 取消注释下面这几行,就可以把图片送到classification中去做分类
103 |
104 | # from classification.classification_pose import Classification
105 |
106 | # # 将BGR转成RGB
107 | # track_img = cv2.cvtColor(track_img, cv2.COLOR_BGR2RGB)
108 |
109 | # # 分类器
110 | # classification = Classification()
111 |
112 | # # 传到classification中去分类
113 | # track_img = Image.fromarray(track_img)
114 | # class_name = classification.detect_image(track_img)
115 | # print(class_name)
--------------------------------------------------------------------------------
/track_of_point.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/track_of_point.jpg
--------------------------------------------------------------------------------
/文本材料/1.作品简介.doc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/文本材料/1.作品简介.doc
--------------------------------------------------------------------------------
/文本材料/2.引用说明.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/文本材料/2.引用说明.docx
--------------------------------------------------------------------------------
/文本材料/3.安装说明.docx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/owo12321/Sign-Language-Recognition/e54c8a777b7ba64ecabde5ff219a5dec35e0d776/文本材料/3.安装说明.docx
--------------------------------------------------------------------------------