Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Tetragramm
GitHub Repository: Tetragramm/opencv
Path: blob/master/samples/dnn/openpose.cpp
16337 views
1
//
2
// this sample demonstrates the use of pretrained openpose networks with opencv's dnn module.
3
//
4
// it can be used for body pose detection, using either the COCO model(18 parts):
5
// http://posefs1.perception.cs.cmu.edu/OpenPose/models/pose/coco/pose_iter_440000.caffemodel
6
// https://raw.githubusercontent.com/opencv/opencv_extra/master/testdata/dnn/openpose_pose_coco.prototxt
7
//
8
// or the MPI model(16 parts):
9
// http://posefs1.perception.cs.cmu.edu/OpenPose/models/pose/mpi/pose_iter_160000.caffemodel
10
// https://raw.githubusercontent.com/opencv/opencv_extra/master/testdata/dnn/openpose_pose_mpi_faster_4_stages.prototxt
11
//
12
// (to simplify this sample, the body models are restricted to a single person.)
13
//
14
//
15
// you can also try the hand pose model:
16
// http://posefs1.perception.cs.cmu.edu/OpenPose/models/hand/pose_iter_102000.caffemodel
17
// https://raw.githubusercontent.com/CMU-Perceptual-Computing-Lab/openpose/master/models/hand/pose_deploy.prototxt
18
//
19
20
#include <opencv2/dnn.hpp>
21
#include <opencv2/imgproc.hpp>
22
#include <opencv2/highgui.hpp>
23
using namespace cv;
24
using namespace cv::dnn;
25
26
#include <iostream>
27
using namespace std;
28
29
30
// connection table, in the format [model_id][pair_id][from/to]
31
// please look at the nice explanation at the bottom of:
32
// https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/doc/output.md
33
//
34
const int POSE_PAIRS[3][20][2] = {
35
{ // COCO body
36
{1,2}, {1,5}, {2,3},
37
{3,4}, {5,6}, {6,7},
38
{1,8}, {8,9}, {9,10},
39
{1,11}, {11,12}, {12,13},
40
{1,0}, {0,14},
41
{14,16}, {0,15}, {15,17}
42
},
43
{ // MPI body
44
{0,1}, {1,2}, {2,3},
45
{3,4}, {1,5}, {5,6},
46
{6,7}, {1,14}, {14,8}, {8,9},
47
{9,10}, {14,11}, {11,12}, {12,13}
48
},
49
{ // hand
50
{0,1}, {1,2}, {2,3}, {3,4}, // thumb
51
{0,5}, {5,6}, {6,7}, {7,8}, // pinkie
52
{0,9}, {9,10}, {10,11}, {11,12}, // middle
53
{0,13}, {13,14}, {14,15}, {15,16}, // ring
54
{0,17}, {17,18}, {18,19}, {19,20} // small
55
}};
56
57
int main(int argc, char **argv)
58
{
59
CommandLineParser parser(argc, argv,
60
"{ h help | false | print this help message }"
61
"{ p proto | | (required) model configuration, e.g. hand/pose.prototxt }"
62
"{ m model | | (required) model weights, e.g. hand/pose_iter_102000.caffemodel }"
63
"{ i image | | (required) path to image file (containing a single person, or hand) }"
64
"{ width | 368 | Preprocess input image by resizing to a specific width. }"
65
"{ height | 368 | Preprocess input image by resizing to a specific height. }"
66
"{ t threshold | 0.1 | threshold or confidence value for the heatmap }"
67
);
68
69
String modelTxt = parser.get<string>("proto");
70
String modelBin = parser.get<string>("model");
71
String imageFile = parser.get<String>("image");
72
int W_in = parser.get<int>("width");
73
int H_in = parser.get<int>("height");
74
float thresh = parser.get<float>("threshold");
75
if (parser.get<bool>("help") || modelTxt.empty() || modelBin.empty() || imageFile.empty())
76
{
77
cout << "A sample app to demonstrate human or hand pose detection with a pretrained OpenPose dnn." << endl;
78
parser.printMessage();
79
return 0;
80
}
81
82
// read the network model
83
Net net = readNetFromCaffe(modelTxt, modelBin);
84
85
// and the image
86
Mat img = imread(imageFile);
87
if (img.empty())
88
{
89
std::cerr << "Can't read image from the file: " << imageFile << std::endl;
90
exit(-1);
91
}
92
93
// send it through the network
94
Mat inputBlob = blobFromImage(img, 1.0 / 255, Size(W_in, H_in), Scalar(0, 0, 0), false, false);
95
net.setInput(inputBlob);
96
Mat result = net.forward();
97
// the result is an array of "heatmaps", the probability of a body part being in location x,y
98
99
int midx, npairs;
100
int nparts = result.size[1];
101
int H = result.size[2];
102
int W = result.size[3];
103
104
// find out, which model we have
105
if (nparts == 19)
106
{ // COCO body
107
midx = 0;
108
npairs = 17;
109
nparts = 18; // skip background
110
}
111
else if (nparts == 16)
112
{ // MPI body
113
midx = 1;
114
npairs = 14;
115
}
116
else if (nparts == 22)
117
{ // hand
118
midx = 2;
119
npairs = 20;
120
}
121
else
122
{
123
cerr << "there should be 19 parts for the COCO model, 16 for MPI, or 22 for the hand one, but this model has " << nparts << " parts." << endl;
124
return (0);
125
}
126
127
// find the position of the body parts
128
vector<Point> points(22);
129
for (int n=0; n<nparts; n++)
130
{
131
// Slice heatmap of corresponding body's part.
132
Mat heatMap(H, W, CV_32F, result.ptr(0,n));
133
// 1 maximum per heatmap
134
Point p(-1,-1),pm;
135
double conf;
136
minMaxLoc(heatMap, 0, &conf, 0, &pm);
137
if (conf > thresh)
138
p = pm;
139
points[n] = p;
140
}
141
142
// connect body parts and draw it !
143
float SX = float(img.cols) / W;
144
float SY = float(img.rows) / H;
145
for (int n=0; n<npairs; n++)
146
{
147
// lookup 2 connected body/hand parts
148
Point2f a = points[POSE_PAIRS[midx][n][0]];
149
Point2f b = points[POSE_PAIRS[midx][n][1]];
150
151
// we did not find enough confidence before
152
if (a.x<=0 || a.y<=0 || b.x<=0 || b.y<=0)
153
continue;
154
155
// scale to image size
156
a.x*=SX; a.y*=SY;
157
b.x*=SX; b.y*=SY;
158
159
line(img, a, b, Scalar(0,200,0), 2);
160
circle(img, a, 3, Scalar(0,0,200), -1);
161
circle(img, b, 3, Scalar(0,0,200), -1);
162
}
163
164
imshow("OpenPose", img);
165
waitKey();
166
167
return 0;
168
}
169
170