OpenCV 4.12.0
開源計算機視覺
載入中...
搜尋中...
無匹配項
samples/dnn/openpose.cpp
//
// 這個示例演示瞭如何使用帶有 OpenCV 的 dnn 模組的預訓練 OpenPose 網路。
//
// 它可以用於人體姿勢檢測,使用 COCO 模型(18 個部位)
// http://posefs1.perception.cs.cmu.edu/OpenPose/models/pose/coco/pose_iter_440000.caffemodel
// https://raw.githubusercontent.com/opencv/opencv_extra/4.x/testdata/dnn/openpose_pose_coco.prototxt
//
// 或者 MPI 模型(16 個部位)
// http://posefs1.perception.cs.cmu.edu/OpenPose/models/pose/mpi/pose_iter_160000.caffemodel
// https://raw.githubusercontent.com/opencv/opencv_extra/4.x/testdata/dnn/openpose_pose_mpi_faster_4_stages.prototxt
//
//(為了簡化這個示例,身體模型被限制為單個人。)
//
//
// 你也可以嘗試手部姿勢模型
// http://posefs1.perception.cs.cmu.edu/OpenPose/models/hand/pose_iter_102000.caffemodel
// https://raw.githubusercontent.com/CMU-Perceptual-Computing-Lab/openpose/master/models/hand/pose_deploy.prototxt
//
#include <opencv2/dnn.hpp>
using namespace cv;
using namespace cv::dnn;
#include <iostream>
using namespace std;
// 連線表,格式為 [模型 ID][對 ID][從/到]
// 請檢視底部的詳細解釋
// https://github.com/CMU-Perceptual-Computing-Lab/openpose/blob/master/doc/output.md
//
const int POSE_PAIRS[3][20][2] = {
{ // COCO 身體
{1,2}, {1,5}, {2,3},
{3,4}, {5,6}, {6,7},
{1,8}, {8,9}, {9,10},
{1,11}, {11,12}, {12,13},
{1,0}, {0,14},
{14,16}, {0,15}, {15,17}
},
{ // MPI 身體
{0,1}, {1,2}, {2,3},
{3,4}, {1,5}, {5,6},
{6,7}, {1,14}, {14,8}, {8,9},
{9,10}, {14,11}, {11,12}, {12,13}
},
{ // 手
{0,1}, {1,2}, {2,3}, {3,4}, // 大拇指
{0,5}, {5,6}, {6,7}, {7,8}, // 小拇指
{0,9}, {9,10}, {10,11}, {11,12}, // 中指
{0,13}, {13,14}, {14,15}, {15,16}, // 無名指
{0,17}, {17,18}, {18,19}, {19,20} // 小指
}};
int main(int argc, char **argv)
{
CommandLineParser parser(argc, argv,
"{ h help | false | 列印此幫助訊息 }"
"{ p proto | | (必需)模型配置,例如 hand/pose.prototxt }"
"{ m model | | (必需)模型權重,例如 hand/pose_iter_102000.caffemodel }"
"{ i image | | (必需)影像檔案的路徑(包含單個人或手)}"
"{ d dataset | | 指定訓練的模型型別。它可以是 (COCO, MPI, HAND),具體取決於資料集。}"
"{ width | 368 | 透過調整到特定寬度來預處理輸入影像。}"
"{ height | 368 | 透過調整到特定高度來預處理輸入影像。}"
"{ t threshold | 0.1 | 熱圖的閾值或置信度值 }"
"{ s scale | 0.003922 | blob 的比例 }"
);
String modelTxt = samples::findFile(parser.get<string>("proto"));
String modelBin = samples::findFile(parser.get<string>("model"));
String imageFile = samples::findFile(parser.get<String>("image"));
String dataset = parser.get<String>("dataset");
int W_in = parser.get<int>("width");
int H_in = parser.get<int>("height");
float thresh = parser.get<float>("threshold");
float scale = parser.get<float>("scale");
if (parser.get<bool>("help") || modelTxt.empty() || modelBin.empty() || imageFile.empty())
{
cout << "一個演示使用預訓練的 OpenPose dnn 檢測人體或手部姿勢的示例應用程式。" << endl;
parser.printMessage();
return 0;
}
int midx, npairs, nparts;
if (!dataset.compare("COCO")) { midx = 0; npairs = 17; nparts = 18; }
else if (!dataset.compare("MPI")) { midx = 1; npairs = 14; nparts = 16; }
else if (!dataset.compare("HAND")) { midx = 2; npairs = 20; nparts = 22; }
else
{
std::cerr << "無法解釋資料集引數:" << dataset << std::endl;
exit(-1);
}
// 讀取網路模型
Net net = readNet(modelBin, modelTxt);
// 以及影像
Mat img = imread(imageFile);
if (img.empty())
{
std::cerr << "無法從檔案讀取影像:" << imageFile << std::endl;
exit(-1);
}
// 將其傳送到網路
Mat inputBlob = blobFromImage(img, scale, Size(W_in, H_in), Scalar(0, 0, 0), false, false);
net.setInput(inputBlob);
Mat result = net.forward();
// 結果是“熱圖”陣列,即身體部位位於 x,y 位置的機率
int H = result.size[2];
int W = result.size[3];
// 找到身體部位的位置
vector<Point> points(22);
for (int n=0; n<nparts; n++)
{
// 對相應身體部位的熱圖進行切片。
Mat heatMap(H, W, CV_32F, result.ptr(0,n));
// 每個熱圖 1 個最大值
Point p(-1,-1),pm;
double conf;
minMaxLoc(heatMap, 0, &conf, 0, &pm);
if (conf > thresh)
p = pm;
points[n] = p;
}
// 連線身體部位並繪製它!
float SX = float(img.cols) / W;
float SY = float(img.rows) / H;
for (int n=0; n<npairs; n++)
{
// 查詢 2 個連線的身體/手部部位
Point2f a = points[POSE_PAIRS[midx][n][0]];
Point2f b = points[POSE_PAIRS[midx][n][1]];
// 我們之前沒有找到足夠的置信度
if (a.x<=0 || a.y<=0 || b.x<=0 || b.y<=0)
continue;
// 縮放到影像大小
a.x*=SX; a.y*=SY;
b.x*=SX; b.y*=SY;
line(img, a, b, Scalar(0,200,0), 2);
circle(img, a, 3, Scalar(0,0,200), -1);
circle(img, b, 3, Scalar(0,0,200), -1);
}
imshow("OpenPose", img);
return 0;
}
如果陣列沒有元素,則返回 true。
int64_t int64
n 維密集陣列類
定義 mat.hpp:830
MatSize size
定義 mat.hpp:2187
uchar * ptr(int i0=0)
返回指向指定矩陣行的指標。
int cols
定義 mat.hpp:2165
cv::getTickFrequency
double getTickFrequency()
int rows
行數和列數,如果矩陣具有超過 2 個維度,則為 (-1, -1)
定義 mat.hpp:2165
_Tp y
點的 y 座標
定義 types.hpp:202
_Tp x
點的 x 座標
定義 types.hpp:201
用於指定影像或矩形大小的模板類。
Definition types.hpp:335
這個類允許建立和操作綜合人工神經網路。
定義 dnn.hpp:475
void setInput(CV_ND InputArray blob, const String &name="", double scalefactor=1.0, const Scalar &mean=Scalar())
設定網路的新輸入值。
Mat forward(const String &outputName=String())
執行前向傳遞以計算名稱為 outputName 的圖層的輸出。
void minMaxLoc(InputArray src, double *minVal, double *maxVal=0, Point *minLoc=0, Point *maxLoc=0, InputArray mask=noArray())
查詢陣列中的全域性最小值和最大值。
std::string String
定義 cvstd.hpp:151
#define CV_32F
Definition interface.h:78
@ circle
定義 gr_skig.hpp:62
Mat blobFromImage(InputArray image, double scalefactor=1.0, const Size &size=Size(), const Scalar &mean=Scalar(), bool swapRB=false, bool crop=false, int ddepth=CV_32F)
從影像建立 4 維 blob。 可選擇從中心調整影像大小和裁剪影像...
Net readNet(CV_WRAP_FILE_PATH const String &model, CV_WRAP_FILE_PATH const String &config="", const String &framework="")
讀取以支援的格式之一表示的深度學習網路。
void imshow(const String &winname, InputArray mat)
在指定視窗中顯示影像。
int waitKey(int delay=0)
等待按鍵按下。
CV_EXPORTS_W Mat imread(const String &filename, int flags=IMREAD_COLOR_BGR)
從檔案載入影像。
void line(InputOutputArray img, Point pt1, Point pt2, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)
繪製連線兩點的線段。
int main(int argc, char *argv[])
定義 highgui_qt.cpp:3
定義 all_layers.hpp:47
定義 core.hpp:107
STL 名稱空間。