openpose.cpp 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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/4.x/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/4.x/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. #include <opencv2/dnn.hpp>
  20. #include <opencv2/imgproc.hpp>
  21. #include <opencv2/highgui.hpp>
  22. using namespace cv;
  23. using namespace cv::dnn;
  24. #include <iostream>
  25. using namespace std;
  26. // connection table, in the format [model_id][pair_id][from/to]
  27. // please look at the nice explanation at the bottom of:
  28. // https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/doc/output.md
  29. //
  30. const int POSE_PAIRS[3][20][2] = {
  31. { // COCO body
  32. {1,2}, {1,5}, {2,3},
  33. {3,4}, {5,6}, {6,7},
  34. {1,8}, {8,9}, {9,10},
  35. {1,11}, {11,12}, {12,13},
  36. {1,0}, {0,14},
  37. {14,16}, {0,15}, {15,17}
  38. },
  39. { // MPI body
  40. {0,1}, {1,2}, {2,3},
  41. {3,4}, {1,5}, {5,6},
  42. {6,7}, {1,14}, {14,8}, {8,9},
  43. {9,10}, {14,11}, {11,12}, {12,13}
  44. },
  45. { // hand
  46. {0,1}, {1,2}, {2,3}, {3,4}, // thumb
  47. {0,5}, {5,6}, {6,7}, {7,8}, // pinkie
  48. {0,9}, {9,10}, {10,11}, {11,12}, // middle
  49. {0,13}, {13,14}, {14,15}, {15,16}, // ring
  50. {0,17}, {17,18}, {18,19}, {19,20} // small
  51. }};
  52. int main(int argc, char **argv)
  53. {
  54. CommandLineParser parser(argc, argv,
  55. "{ h help | false | print this help message }"
  56. "{ p proto | | (required) model configuration, e.g. hand/pose.prototxt }"
  57. "{ m model | | (required) model weights, e.g. hand/pose_iter_102000.caffemodel }"
  58. "{ i image | | (required) path to image file (containing a single person, or hand) }"
  59. "{ d dataset | | specify what kind of model was trained. It could be (COCO, MPI, HAND) depends on dataset. }"
  60. "{ width | 368 | Preprocess input image by resizing to a specific width. }"
  61. "{ height | 368 | Preprocess input image by resizing to a specific height. }"
  62. "{ t threshold | 0.1 | threshold or confidence value for the heatmap }"
  63. "{ s scale | 0.003922 | scale for blob }"
  64. );
  65. String modelTxt = samples::findFile(parser.get<string>("proto"));
  66. String modelBin = samples::findFile(parser.get<string>("model"));
  67. String imageFile = samples::findFile(parser.get<String>("image"));
  68. String dataset = parser.get<String>("dataset");
  69. int W_in = parser.get<int>("width");
  70. int H_in = parser.get<int>("height");
  71. float thresh = parser.get<float>("threshold");
  72. float scale = parser.get<float>("scale");
  73. if (parser.get<bool>("help") || modelTxt.empty() || modelBin.empty() || imageFile.empty())
  74. {
  75. cout << "A sample app to demonstrate human or hand pose detection with a pretrained OpenPose dnn." << endl;
  76. parser.printMessage();
  77. return 0;
  78. }
  79. int midx, npairs, nparts;
  80. if (!dataset.compare("COCO")) { midx = 0; npairs = 17; nparts = 18; }
  81. else if (!dataset.compare("MPI")) { midx = 1; npairs = 14; nparts = 16; }
  82. else if (!dataset.compare("HAND")) { midx = 2; npairs = 20; nparts = 22; }
  83. else
  84. {
  85. std::cerr << "Can't interpret dataset parameter: " << dataset << std::endl;
  86. exit(-1);
  87. }
  88. // read the network model
  89. Net net = readNet(modelBin, modelTxt);
  90. // and the image
  91. Mat img = imread(imageFile);
  92. if (img.empty())
  93. {
  94. std::cerr << "Can't read image from the file: " << imageFile << std::endl;
  95. exit(-1);
  96. }
  97. // send it through the network
  98. Mat inputBlob = blobFromImage(img, scale, Size(W_in, H_in), Scalar(0, 0, 0), false, false);
  99. net.setInput(inputBlob);
  100. Mat result = net.forward();
  101. // the result is an array of "heatmaps", the probability of a body part being in location x,y
  102. int H = result.size[2];
  103. int W = result.size[3];
  104. // find the position of the body parts
  105. vector<Point> points(22);
  106. for (int n=0; n<nparts; n++)
  107. {
  108. // Slice heatmap of corresponding body's part.
  109. Mat heatMap(H, W, CV_32F, result.ptr(0,n));
  110. // 1 maximum per heatmap
  111. Point p(-1,-1),pm;
  112. double conf;
  113. minMaxLoc(heatMap, 0, &conf, 0, &pm);
  114. if (conf > thresh)
  115. p = pm;
  116. points[n] = p;
  117. }
  118. // connect body parts and draw it !
  119. float SX = float(img.cols) / W;
  120. float SY = float(img.rows) / H;
  121. for (int n=0; n<npairs; n++)
  122. {
  123. // lookup 2 connected body/hand parts
  124. Point2f a = points[POSE_PAIRS[midx][n][0]];
  125. Point2f b = points[POSE_PAIRS[midx][n][1]];
  126. // we did not find enough confidence before
  127. if (a.x<=0 || a.y<=0 || b.x<=0 || b.y<=0)
  128. continue;
  129. // scale to image size
  130. a.x*=SX; a.y*=SY;
  131. b.x*=SX; b.y*=SY;
  132. line(img, a, b, Scalar(0,200,0), 2);
  133. circle(img, a, 3, Scalar(0,0,200), -1);
  134. circle(img, b, 3, Scalar(0,0,200), -1);
  135. }
  136. imshow("OpenPose", img);
  137. waitKey();
  138. return 0;
  139. }