Initial commit
This commit is contained in:
commit
23c54057cd
|
@ -0,0 +1,3 @@
|
||||||
|
node_modules
|
||||||
|
.env
|
||||||
|
*.DS_Store
|
|
@ -0,0 +1,4 @@
|
||||||
|
PORT=7474
|
||||||
|
BIN=openpose
|
||||||
|
CWD=.
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.envString = envString;
|
||||||
|
exports.envFloat = envFloat;
|
||||||
|
exports.envInt = envInt;
|
||||||
|
function envString(variable, defaultString) {
|
||||||
|
return typeof process.env[variable] !== 'undefined' ? process.env[variable] : defaultString;
|
||||||
|
}
|
||||||
|
function envFloat(variable, defaultFloat) {
|
||||||
|
return typeof process.env[variable] !== 'undefined' ? parseFloat(process.env[variable]) : defaultFloat;
|
||||||
|
}
|
||||||
|
function envInt(variable, defaultInt) {
|
||||||
|
return typeof process.env[variable] !== 'undefined' ? parseInt(process.env[variable]) : defaultInt;
|
||||||
|
}
|
||||||
|
module.exports = { envString, envFloat, envInt };
|
||||||
|
//# sourceMappingURL=index.js.map
|
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/env/index.ts"],"names":[],"mappings":";;AAAA,8BAEC;AAED,4BAEC;AAED,wBAEC;AAVD,SAAgB,SAAS,CAAE,QAAiB,EAAE,aAAsB;IACnE,OAAO,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC;AAC7F,CAAC;AAED,SAAgB,QAAQ,CAAE,QAAiB,EAAE,YAAqB;IACjE,OAAO,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;AACxG,CAAC;AAED,SAAgB,MAAM,CAAE,QAAiB,EAAE,UAAmB;IAC7D,OAAO,OAAO,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC;AACpG,CAAC;AAED,MAAM,CAAC,OAAO,GAAG,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC"}
|
|
@ -0,0 +1,155 @@
|
||||||
|
"use strict";
|
||||||
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
||||||
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
||||||
|
};
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
require("dotenv/config");
|
||||||
|
const express_1 = __importDefault(require("express"));
|
||||||
|
const promises_1 = require("fs/promises");
|
||||||
|
const os_1 = require("os");
|
||||||
|
const path_1 = require("path");
|
||||||
|
const body_parser_1 = __importDefault(require("body-parser"));
|
||||||
|
const multer_1 = __importDefault(require("multer"));
|
||||||
|
const uuid_1 = require("uuid");
|
||||||
|
const log_1 = require("./log");
|
||||||
|
const env_1 = require("./env");
|
||||||
|
const shell_1 = require("./shell");
|
||||||
|
const PORT = (0, env_1.envInt)('PORT', 7474);
|
||||||
|
const BIN = (0, env_1.envString)('BIN', 'openpose');
|
||||||
|
const CWD = (0, env_1.envString)('CWD', '.');
|
||||||
|
const log = (0, log_1.createLog)('openpose_api');
|
||||||
|
const app = (0, express_1.default)();
|
||||||
|
const tmp = (0, os_1.tmpdir)();
|
||||||
|
const storage = multer_1.default.diskStorage({
|
||||||
|
destination: function (req, file, cb) {
|
||||||
|
cb(null, tmp);
|
||||||
|
},
|
||||||
|
filename: function (req, file, cb) {
|
||||||
|
cb(null, `${+new Date()}_${file.originalname}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
async function exists(path) {
|
||||||
|
try {
|
||||||
|
await (0, promises_1.access)(path);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
app.use(body_parser_1.default.json());
|
||||||
|
app.use(body_parser_1.default.urlencoded({ extended: true }));
|
||||||
|
const uploadImage = (0, multer_1.default)({ storage });
|
||||||
|
app.get('/', (req, res, next) => {
|
||||||
|
return res.send('/');
|
||||||
|
});
|
||||||
|
//./build/examples/openpose/openpose.bin -v 1 -image_dir ./examples/media/ -write_images ./output -write_json ./json --face --hand
|
||||||
|
app.post('/openpose', uploadImage.single('image'), async (req, res, next) => {
|
||||||
|
const id = (0, uuid_1.v4)();
|
||||||
|
const dir = (0, path_1.join)(tmp, id);
|
||||||
|
const image_dir = (0, path_1.join)(dir, 'image');
|
||||||
|
const json_dir = (0, path_1.join)(dir, 'json');
|
||||||
|
const json_file = (0, path_1.join)(json_dir, 'openpose_keypoints.json');
|
||||||
|
let json_exists = false;
|
||||||
|
let openpose_str = '{}';
|
||||||
|
let output;
|
||||||
|
let image_file;
|
||||||
|
let image_ext;
|
||||||
|
let sh;
|
||||||
|
//
|
||||||
|
const args = [
|
||||||
|
BIN,
|
||||||
|
'--render_pose', '0',
|
||||||
|
'-display', '0',
|
||||||
|
'-image_dir', image_dir,
|
||||||
|
'-write_json', json_dir
|
||||||
|
];
|
||||||
|
if (typeof req.file === 'undefined') {
|
||||||
|
return next(new Error('No image uploaded'));
|
||||||
|
}
|
||||||
|
image_ext = (0, path_1.extname)((0, path_1.basename)(req.file.path));
|
||||||
|
image_file = (0, path_1.join)(image_dir, `openpose${image_ext}`);
|
||||||
|
if (typeof req.body.face !== 'undefined' && req.body.face === 'true') {
|
||||||
|
args.push('--face');
|
||||||
|
}
|
||||||
|
if (typeof req.body.hand !== 'undefined' && req.body.hand === 'true') {
|
||||||
|
args.push('--hand');
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await (0, promises_1.mkdir)(dir);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
log.error(`Error making directory ${dir}`, err);
|
||||||
|
return next(new Error('Error making dir'));
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await (0, promises_1.mkdir)(image_dir);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
log.error(`Error making directory ${image_dir}`, err);
|
||||||
|
return next(new Error('Error making image_dir'));
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await (0, promises_1.mkdir)(json_dir);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
log.error(`Error making directory ${image_dir}`, err);
|
||||||
|
return next(new Error('Error making image_dir'));
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
await (0, promises_1.copyFile)(req.file.path, image_file);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
log.error(`Error copying file ${req.file.path}`, err);
|
||||||
|
return next(new Error('Error copying temp image'));
|
||||||
|
}
|
||||||
|
sh = new shell_1.Shell(args, CWD, null, null, null, true);
|
||||||
|
try {
|
||||||
|
await sh.execute();
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
log.error(`Error executing ${args.join(' ')}`, err);
|
||||||
|
return next(new Error('Error running openpose'));
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
json_exists = await exists(json_file);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
log.error(`Error checking json ${json_file} exists`, err);
|
||||||
|
return next(new Error('Error checking json exists'));
|
||||||
|
}
|
||||||
|
if (json_exists) {
|
||||||
|
try {
|
||||||
|
openpose_str = await (0, promises_1.readFile)(json_file, 'utf8');
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
log.error(`Error reading json file ${json_file}`, err);
|
||||||
|
return next(new Error('Error reading json file'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
log.error(`The json file ${json_file} does not exist`);
|
||||||
|
return next(new Error('Error running openpose'));
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
output = JSON.parse(openpose_str);
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
log.error(`Error parsing openpose json`, err);
|
||||||
|
return next(new Error('Error parsing openpose json'));
|
||||||
|
}
|
||||||
|
output.image = req.file.originalname;
|
||||||
|
try {
|
||||||
|
await (0, promises_1.rm)(dir, { recursive: true });
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
log.error(`Error unlinking ${dir}`, err);
|
||||||
|
return next(new Error('Error unlinking temp dir'));
|
||||||
|
}
|
||||||
|
return res.json(output);
|
||||||
|
});
|
||||||
|
app.listen(PORT, () => {
|
||||||
|
log.info(`Openpose API server running on port ${PORT}`);
|
||||||
|
log.info(`Using openpose binary ${BIN}`);
|
||||||
|
});
|
||||||
|
//# sourceMappingURL=index.js.map
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,48 @@
|
||||||
|
'use strict';
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.createLog = createLog;
|
||||||
|
/** @module log */
|
||||||
|
/** Wrapper for winston that tags streams and optionally writes files with a simple interface. */
|
||||||
|
/** Module now also supports optional papertrail integration, other services to follow */
|
||||||
|
const winston_1 = require("winston");
|
||||||
|
const { SPLAT } = require('triple-beam');
|
||||||
|
const { isObject } = require('lodash');
|
||||||
|
const APP_NAME = process.env.APP_NAME || 'default';
|
||||||
|
function formatObject(param) {
|
||||||
|
if (isObject(param)) {
|
||||||
|
return JSON.stringify(param);
|
||||||
|
}
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
const all = (0, winston_1.format)((info) => {
|
||||||
|
const splat = info[SPLAT] || [];
|
||||||
|
const message = formatObject(info.message);
|
||||||
|
const rest = splat.map(formatObject).join(' ');
|
||||||
|
info.message = `${message} ${rest}`;
|
||||||
|
return info;
|
||||||
|
});
|
||||||
|
const myFormat = winston_1.format.printf(({ level, message, label, timestamp }) => {
|
||||||
|
return `${timestamp} [${label}] ${level}: ${message}`;
|
||||||
|
});
|
||||||
|
/**
|
||||||
|
* Returns a winston logger configured to service
|
||||||
|
*
|
||||||
|
* @param {string} label Label appearing on logger
|
||||||
|
* @param {string} filename Optional file to write log to
|
||||||
|
*
|
||||||
|
* @returns {object} Winston logger
|
||||||
|
*/
|
||||||
|
function createLog(label, filename = null) {
|
||||||
|
const tports = [new (winston_1.transports.Console)()];
|
||||||
|
const fmat = winston_1.format.combine(all(), winston_1.format.label({ label }), winston_1.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss.SSS' }), winston_1.format.colorize(), myFormat);
|
||||||
|
let papertrailOpts;
|
||||||
|
if (filename !== null) {
|
||||||
|
tports.push(new (winston_1.transports.File)({ filename }));
|
||||||
|
}
|
||||||
|
return (0, winston_1.createLogger)({
|
||||||
|
format: fmat,
|
||||||
|
transports: tports
|
||||||
|
});
|
||||||
|
}
|
||||||
|
module.exports = { createLog };
|
||||||
|
//# sourceMappingURL=index.js.map
|
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/log/index.ts"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAuCZ,8BAmBC;AAxDD,kBAAkB;AAClB,iGAAiG;AACjG,yFAAyF;AAEzF,qCAA2D;AAC3D,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;AACzC,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;AAEvC,MAAM,QAAQ,GAAY,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,SAAS,CAAC;AAE5D,SAAS,YAAY,CAAE,KAAW;IAChC,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,GAAG,GAAG,IAAA,gBAAM,EAAC,CAAC,IAAU,EAAE,EAAE;IAC9B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;IAChC,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,IAAI,CAAC,OAAO,GAAG,GAAG,OAAO,IAAI,IAAI,EAAE,CAAC;IACpC,OAAO,IAAI,CAAC;AAChB,CAAC,CAAC,CAAC;AAEH,MAAM,QAAQ,GAAG,gBAAM,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAQ,EAAE,EAAE;IAC5E,OAAO,GAAG,SAAS,KAAK,KAAK,KAAK,KAAK,KAAK,OAAO,EAAE,CAAC;AACxD,CAAC,CAAC,CAAC;AAEH;;;;;;;EAOE;AACF,SAAgB,SAAS,CAAE,KAAc,EAAE,WAAoB,IAAI;IAC/D,MAAM,MAAM,GAAW,CAAE,IAAI,CAAC,oBAAU,CAAC,OAAO,CAAC,EAAE,CAAE,CAAC;IACtD,MAAM,IAAI,GAAS,gBAAM,CAAC,OAAO,CAC7B,GAAG,EAAE,EACL,gBAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,CAAC,EACvB,gBAAM,CAAC,SAAS,CAAC,EAAC,MAAM,EAAE,yBAAyB,EAAC,CAAC,EACrD,gBAAM,CAAC,QAAQ,EAAE,EACjB,QAAQ,CACX,CAAC;IACF,IAAI,cAAoB,CAAC;IAEzB,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACpB,MAAM,CAAC,IAAI,CAAE,IAAI,CAAC,oBAAU,CAAC,IAAI,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAE,CAAC;IACvD,CAAC;IAED,OAAO,IAAA,sBAAY,EAAC;QAChB,MAAM,EAAG,IAAI;QACb,UAAU,EAAG,MAAM;KACtB,CAAC,CAAC;AACP,CAAC;AAED,MAAM,CAAC,OAAO,GAAG,EAAE,SAAS,EAAE,CAAC"}
|
|
@ -0,0 +1,71 @@
|
||||||
|
"use strict";
|
||||||
|
Object.defineProperty(exports, "__esModule", { value: true });
|
||||||
|
exports.Shell = void 0;
|
||||||
|
const child_process_1 = require("child_process");
|
||||||
|
const log_1 = require("../log");
|
||||||
|
const os_1 = require("os");
|
||||||
|
class Shell {
|
||||||
|
constructor(args, cwd = null, stdio = null, stderr = null, after = null, silent = false) {
|
||||||
|
this.lines = [];
|
||||||
|
this.stdio = null;
|
||||||
|
this.stderr = null;
|
||||||
|
this.after = null;
|
||||||
|
this.silent = false;
|
||||||
|
const bin = args.shift();
|
||||||
|
this.bin = bin;
|
||||||
|
this.args = args;
|
||||||
|
this.stdio = stdio;
|
||||||
|
this.stderr = stderr;
|
||||||
|
this.silent = silent;
|
||||||
|
this.after = after;
|
||||||
|
this.cwd = cwd;
|
||||||
|
this.log = (0, log_1.createLog)(bin);
|
||||||
|
}
|
||||||
|
async execute() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const options = {};
|
||||||
|
if (this.cwd !== null) {
|
||||||
|
options.cwd = this.cwd;
|
||||||
|
}
|
||||||
|
this.child = (0, child_process_1.spawn)(this.bin, this.args, options);
|
||||||
|
this.log.info(`Shell: ${this.bin} ${this.args.join(' ')}`);
|
||||||
|
this.child.stdout.on('data', (data) => {
|
||||||
|
if (!this.silent)
|
||||||
|
this.log.info(data);
|
||||||
|
if (this.after !== null)
|
||||||
|
this.lines.push(data);
|
||||||
|
if (this.stdio !== null) {
|
||||||
|
this.stdio(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.child.stderr.on('data', (data) => {
|
||||||
|
if (!this.silent)
|
||||||
|
this.log.warn(data);
|
||||||
|
if (this.stderr !== null) {
|
||||||
|
this.stderr(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.child.on('close', (code) => {
|
||||||
|
if (this.after !== null) {
|
||||||
|
this.after(this.lines.join(os_1.EOL));
|
||||||
|
}
|
||||||
|
if (code === 0) {
|
||||||
|
this.log.info(`Complete: ${this.bin} ${this.args.join(' ')}`);
|
||||||
|
return resolve(code);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.log.error(`Error executing: ${this.bin} ${this.args.join(' ')}`);
|
||||||
|
return reject(code);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
kill() {
|
||||||
|
this.log.warn(`Killing: ${this.bin} ${this.args.join(' ')}`);
|
||||||
|
//this.child.stdin.pause();
|
||||||
|
this.child.kill();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.Shell = Shell;
|
||||||
|
module.exports = { Shell };
|
||||||
|
//# sourceMappingURL=index.js.map
|
|
@ -0,0 +1 @@
|
||||||
|
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/shell/index.ts"],"names":[],"mappings":"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"}
|
|
@ -0,0 +1,432 @@
|
||||||
|
Flags from ./src/logging.cc:
|
||||||
|
-alsologtoemail (log messages go to these email addresses in addition to
|
||||||
|
logfiles) type: string default: ""
|
||||||
|
-alsologtostderr (log messages go to stderr in addition to logfiles)
|
||||||
|
type: bool default: false
|
||||||
|
-colorlogtostderr (color messages logged to stderr (if supported by
|
||||||
|
terminal)) type: bool default: false
|
||||||
|
-drop_log_memory (Drop in-memory buffers of log contents. Logs can grow
|
||||||
|
very quickly and they are rarely read before they need to be evicted from
|
||||||
|
memory. Instead, drop them from memory as soon as they are flushed to
|
||||||
|
disk.) type: bool default: true
|
||||||
|
-log_backtrace_at (Emit a backtrace when logging at file:linenum.)
|
||||||
|
type: string default: ""
|
||||||
|
-log_dir (If specified, logfiles are written into this directory instead of
|
||||||
|
the default logging directory.) type: string default: ""
|
||||||
|
-log_link (Put additional links to the log files in this directory)
|
||||||
|
type: string default: ""
|
||||||
|
-log_prefix (Prepend the log prefix to the start of each log line)
|
||||||
|
type: bool default: true
|
||||||
|
-logbuflevel (Buffer log messages logged at this level or lower (-1 means
|
||||||
|
don't buffer; 0 means buffer INFO only; ...)) type: int32 default: 0
|
||||||
|
-logbufsecs (Buffer log messages for at most this many seconds) type: int32
|
||||||
|
default: 30
|
||||||
|
-logemaillevel (Email log messages logged at this level or higher (0 means
|
||||||
|
email all; 3 means email FATAL only; ...)) type: int32 default: 999
|
||||||
|
-logfile_mode (Log file mode/permissions.) type: int32 default: 436
|
||||||
|
-logmailer (Mailer used to send logging email) type: string
|
||||||
|
default: "/bin/mail"
|
||||||
|
-logtostderr (log messages go to stderr instead of logfiles) type: bool
|
||||||
|
default: false
|
||||||
|
-max_log_size (approx. maximum log file size (in MB). A value of 0 will be
|
||||||
|
silently overridden to 1.) type: int32 default: 1800
|
||||||
|
-minloglevel (Messages logged at a lower level than this don't actually get
|
||||||
|
logged anywhere) type: int32 default: 0
|
||||||
|
-stderrthreshold (log messages at or above this level are copied to stderr
|
||||||
|
in addition to logfiles. This flag obsoletes --alsologtostderr.)
|
||||||
|
type: int32 default: 2
|
||||||
|
-stop_logging_if_full_disk (Stop attempting to log to disk if the disk is
|
||||||
|
full.) type: bool default: false
|
||||||
|
|
||||||
|
Flags from ./src/utilities.cc:
|
||||||
|
-symbolize_stacktrace (Symbolize the stack trace in the tombstone)
|
||||||
|
type: bool default: true
|
||||||
|
|
||||||
|
Flags from ./src/vlog_is_on.cc:
|
||||||
|
-v (Show all VLOG(m) messages for m <= this. Overridable by --vmodule.)
|
||||||
|
type: int32 default: 0
|
||||||
|
-vmodule (per-module verbose level. Argument is a comma-separated list of
|
||||||
|
<module name>=<log level>. <module name> is a glob pattern, matched
|
||||||
|
against the filename base (that is, name ignoring .cc/.h./-inl.h). <log
|
||||||
|
level> overrides any value given by --v.) type: string default: ""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Flags from /build/gflags-WDCpEz/gflags-2.2.2/src/gflags.cc:
|
||||||
|
-flagfile (load flags from file) type: string default: ""
|
||||||
|
-fromenv (set flags from the environment [use 'export FLAGS_flag1=value'])
|
||||||
|
type: string default: ""
|
||||||
|
-tryfromenv (set flags from the environment if present) type: string
|
||||||
|
default: ""
|
||||||
|
-undefok (comma-separated list of flag names that it is okay to specify on
|
||||||
|
the command line even if the program does not define a flag with that
|
||||||
|
name. IMPORTANT: flags in this list that have arguments MUST use the
|
||||||
|
flag=value format) type: string default: ""
|
||||||
|
|
||||||
|
Flags from /build/gflags-WDCpEz/gflags-2.2.2/src/gflags_completions.cc:
|
||||||
|
-tab_completion_columns (Number of columns to use in output for tab
|
||||||
|
completion) type: int32 default: 80
|
||||||
|
-tab_completion_word (If non-empty, HandleCommandLineCompletions() will
|
||||||
|
hijack the process and attempt to do bash-style command line flag
|
||||||
|
completion on this value.) type: string default: ""
|
||||||
|
|
||||||
|
Flags from /build/gflags-WDCpEz/gflags-2.2.2/src/gflags_reporting.cc:
|
||||||
|
-help (show help on all flags [tip: all flags can have two dashes])
|
||||||
|
type: bool default: false currently: true
|
||||||
|
-helpfull (show help on all flags -- same as -help) type: bool
|
||||||
|
default: false
|
||||||
|
-helpmatch (show help on modules whose name contains the specified substr)
|
||||||
|
type: string default: ""
|
||||||
|
-helpon (show help on the modules named by this flag value) type: string
|
||||||
|
default: ""
|
||||||
|
-helppackage (show help on all modules in the main package) type: bool
|
||||||
|
default: false
|
||||||
|
-helpshort (show help on only the main module for this program) type: bool
|
||||||
|
default: false
|
||||||
|
-helpxml (produce an xml version of help) type: bool default: false
|
||||||
|
-version (show version and build info and exit) type: bool default: false
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Flags from /home/mmcwilliams/src/openpose/include/openpose/flags.hpp:
|
||||||
|
-3d (Running OpenPose 3-D reconstruction demo: 1) Reading from a stereo
|
||||||
|
camera system. 2) Performing 3-D reconstruction from the multiple views.
|
||||||
|
3) Displaying 3-D reconstruction results. Note that it will only display
|
||||||
|
1 person. If multiple people is present, it will fail.) type: bool
|
||||||
|
default: false
|
||||||
|
-3d_min_views (Minimum number of views required to reconstruct each
|
||||||
|
keypoint. By default (-1), it will require max(2, min(4, #cameras-1))
|
||||||
|
cameras to see the keypoint in order to reconstruct it.) type: int32
|
||||||
|
default: -1
|
||||||
|
-3d_views (Complementary option for `--image_dir` or `--video`. OpenPose
|
||||||
|
will read as many images per iteration, allowing tasks such as stereo
|
||||||
|
camera processing (`--3d`). Note that `--camera_parameter_path` must be
|
||||||
|
set. OpenPose must find as many `xml` files in the parameter folder as
|
||||||
|
this number indicates.) type: int32 default: -1
|
||||||
|
-alpha_heatmap (Blending factor (range 0-1) between heatmap and original
|
||||||
|
frame. 1 will only show the heatmap, 0 will only show the frame. Only
|
||||||
|
valid for GPU rendering.) type: double default: 0.69999999999999996
|
||||||
|
-alpha_pose (Blending factor (range 0-1) for the body part rendering. 1
|
||||||
|
will show it completely, 0 will hide it. Only valid for GPU rendering.)
|
||||||
|
type: double default: 0.59999999999999998
|
||||||
|
-body (Select 0 to disable body keypoint detection (e.g., for faster but
|
||||||
|
less accurate face keypoint detection, custom hand detector, etc.), 1
|
||||||
|
(default) for body keypoint estimation, and 2 to disable its internal
|
||||||
|
body pose estimation network but still still run the greedy association
|
||||||
|
parsing algorithm) type: int32 default: 1
|
||||||
|
-caffemodel_path (The combination `--model_folder` + `--caffemodel_path`
|
||||||
|
represents the whole path to the caffemodel file. If empty, it will use
|
||||||
|
the default OpenPose CaffeModel file.) type: string default: ""
|
||||||
|
-camera (The camera index for cv::VideoCapture. Integer in the range [0,
|
||||||
|
9]. Select a negative number (by default), to auto-detect and open the
|
||||||
|
first available camera.) type: int32 default: -1
|
||||||
|
-camera_parameter_path (String with the folder where the camera parameters
|
||||||
|
are located. If there is only 1 XML file (for single video, webcam, or
|
||||||
|
images from the same camera), you must specify the whole XML file path
|
||||||
|
(ending in .xml).) type: string default: "models/cameraParameters/flir/"
|
||||||
|
-camera_resolution (Set the camera resolution (either `--camera` or
|
||||||
|
`--flir_camera`). `-1x-1` will use the default 1280x720 for `--camera`,
|
||||||
|
or the maximum flir camera resolution available for `--flir_camera`)
|
||||||
|
type: string default: "-1x-1"
|
||||||
|
-cli_verbose (If -1, it will be disabled (default). If it is a positive
|
||||||
|
integer number, it will print on the command line every `verbose` frames.
|
||||||
|
If number in the range (0,1), it will print the progress every `verbose`
|
||||||
|
times the total of frames.) type: double default: -1
|
||||||
|
-disable_blending (If enabled, it will render the results (keypoint
|
||||||
|
skeletons or heatmaps) on a black background, instead of being rendered
|
||||||
|
into the original image. Related: `part_to_show`, `alpha_pose`, and
|
||||||
|
`alpha_pose`.) type: bool default: false
|
||||||
|
-disable_multi_thread (It would slightly reduce the frame rate in order to
|
||||||
|
highly reduce the lag. Mainly useful for 1) Cases where it is needed a
|
||||||
|
low latency (e.g., webcam in real-time scenarios with low-range GPU
|
||||||
|
devices); and 2) Debugging OpenPose when it is crashing to locate the
|
||||||
|
error.) type: bool default: false
|
||||||
|
-display (Display mode: -1 for automatic selection; 0 for no display
|
||||||
|
(useful if there is no X server and/or to slightly speed up the
|
||||||
|
processing if visual output is not required); 2 for 2-D display; 3 for
|
||||||
|
3-D display (if `--3d` enabled); and 1 for both 2-D and 3-D display.)
|
||||||
|
type: int32 default: -1
|
||||||
|
-face (Enables face keypoint detection. It will share some parameters from
|
||||||
|
the body pose, e.g. `model_folder`. Note that this will considerable slow
|
||||||
|
down the performance and increase the required GPU memory. In addition,
|
||||||
|
the greater number of people on the image, the slower OpenPose will be.)
|
||||||
|
type: bool default: false
|
||||||
|
-face_alpha_heatmap (Analogous to `alpha_heatmap` but applied to face.)
|
||||||
|
type: double default: 0.69999999999999996
|
||||||
|
-face_alpha_pose (Analogous to `alpha_pose` but applied to face.)
|
||||||
|
type: double default: 0.59999999999999998
|
||||||
|
-face_detector (Kind of face rectangle detector. Select 0 (default) to
|
||||||
|
select OpenPose body detector (most accurate one and fastest one if body
|
||||||
|
is enabled), 1 to select OpenCV face detector (not implemented for
|
||||||
|
hands), 2 to indicate that it will be provided by the user, or 3 to also
|
||||||
|
apply hand tracking (only for hand). Hand tracking might improve hand
|
||||||
|
keypoint detection for webcam (if the frame rate is high enough, i.e., >7
|
||||||
|
FPS per GPU) and video. This is not person ID tracking, it simply looks
|
||||||
|
for hands in positions at which hands were located in previous frames,
|
||||||
|
but it does not guarantee the same person ID among frames.) type: int32
|
||||||
|
default: 0
|
||||||
|
-face_net_resolution (Multiples of 16 and squared. Analogous to
|
||||||
|
`net_resolution` but applied to the face keypoint detector. 320x320
|
||||||
|
usually works fine while giving a substantial speed up when multiple
|
||||||
|
faces on the image.) type: string default: "368x368"
|
||||||
|
-face_render (Analogous to `render_pose` but applied to the face. Extra
|
||||||
|
option: -1 to use the same configuration that `render_pose` is using.)
|
||||||
|
type: int32 default: -1
|
||||||
|
-face_render_threshold (Analogous to `render_threshold`, but applied to the
|
||||||
|
face keypoints.) type: double default: 0.40000000000000002
|
||||||
|
-flir_camera (Whether to use FLIR (Point-Grey) stereo camera.) type: bool
|
||||||
|
default: false
|
||||||
|
-flir_camera_index (Select -1 (default) to run on all detected flir cameras
|
||||||
|
at once. Otherwise, select the flir camera index to run, where 0
|
||||||
|
corresponds to the detected flir camera with the lowest serial number,
|
||||||
|
and `n` to the `n`-th lowest serial number camera.) type: int32
|
||||||
|
default: -1
|
||||||
|
-fps_max (Maximum processing frame rate. By default (-1), OpenPose will
|
||||||
|
process frames as fast as possible. Example usage: If OpenPose is
|
||||||
|
displaying images too quickly, this can reduce the speed so the user can
|
||||||
|
analyze better each frame from the GUI.) type: double default: -1
|
||||||
|
-frame_first (Start on desired frame number. Indexes are 0-based, i.e., the
|
||||||
|
first frame has index 0.) type: uint64 default: 0
|
||||||
|
-frame_flip (Flip/mirror each frame (e.g., for real time webcam
|
||||||
|
demonstrations).) type: bool default: false
|
||||||
|
-frame_last (Finish on desired frame number. Select -1 to disable. Indexes
|
||||||
|
are 0-based, e.g., if set to 10, it will process 11 frames (0-10).)
|
||||||
|
type: uint64 default: 18446744073709551615
|
||||||
|
-frame_rotate (Rotate each frame, 4 possible values: 0, 90, 180, 270.)
|
||||||
|
type: int32 default: 0
|
||||||
|
-frame_step (Step or gap between processed frames. E.g., `--frame_step 5`
|
||||||
|
would read and process frames 0, 5, 10, etc..) type: uint64 default: 1
|
||||||
|
-frame_undistort (If false (default), it will not undistort the image, if
|
||||||
|
true, it will undistortionate them based on the camera parameters found
|
||||||
|
in `camera_parameter_path`) type: bool default: false
|
||||||
|
-frames_repeat (Repeat frames when finished.) type: bool default: false
|
||||||
|
-fullscreen (Run in full-screen mode (press f during runtime to toggle).)
|
||||||
|
type: bool default: false
|
||||||
|
-hand (Enables hand keypoint detection. It will share some parameters from
|
||||||
|
the body pose, e.g. `model_folder`. Analogously to `--face`, it will also
|
||||||
|
slow down the performance, increase the required GPU memory and its speed
|
||||||
|
depends on the number of people.) type: bool default: false
|
||||||
|
-hand_alpha_heatmap (Analogous to `alpha_heatmap` but applied to hand.)
|
||||||
|
type: double default: 0.69999999999999996
|
||||||
|
-hand_alpha_pose (Analogous to `alpha_pose` but applied to hand.)
|
||||||
|
type: double default: 0.59999999999999998
|
||||||
|
-hand_detector (Kind of hand rectangle detector. Analogous to
|
||||||
|
`--face_detector`.) type: int32 default: 0
|
||||||
|
-hand_net_resolution (Multiples of 16 and squared. Analogous to
|
||||||
|
`net_resolution` but applied to the hand keypoint detector.) type: string
|
||||||
|
default: "368x368"
|
||||||
|
-hand_render (Analogous to `render_pose` but applied to the hand. Extra
|
||||||
|
option: -1 to use the same configuration that `render_pose` is using.)
|
||||||
|
type: int32 default: -1
|
||||||
|
-hand_render_threshold (Analogous to `render_threshold`, but applied to the
|
||||||
|
hand keypoints.) type: double default: 0.20000000000000001
|
||||||
|
-hand_scale_number (Analogous to `scale_number` but applied to the hand
|
||||||
|
keypoint detector. Our best results were found with `hand_scale_number` =
|
||||||
|
6 and `hand_scale_range` = 0.4.) type: int32 default: 1
|
||||||
|
-hand_scale_range (Analogous purpose than `scale_gap` but applied to the
|
||||||
|
hand keypoint detector. Total range between smallest and biggest scale.
|
||||||
|
The scales will be centered in ratio 1. E.g., if scaleRange = 0.4 and
|
||||||
|
scalesNumber = 2, then there will be 2 scales, 0.8 and 1.2.) type: double
|
||||||
|
default: 0.40000000000000002
|
||||||
|
-heatmaps_add_PAFs (Same functionality as `add_heatmaps_parts`, but adding
|
||||||
|
the PAFs.) type: bool default: false
|
||||||
|
-heatmaps_add_bkg (Same functionality as `add_heatmaps_parts`, but adding
|
||||||
|
the heatmap corresponding to background.) type: bool default: false
|
||||||
|
-heatmaps_add_parts (If true, it will fill op::Datum::poseHeatMaps array
|
||||||
|
with the body part heatmaps, and analogously face & hand heatmaps to
|
||||||
|
op::Datum::faceHeatMaps & op::Datum::handHeatMaps. If more than one
|
||||||
|
`add_heatmaps_X` flag is enabled, it will place then in sequential memory
|
||||||
|
order: body parts + bkg + PAFs. It will follow the order on
|
||||||
|
POSE_BODY_PART_MAPPING in `src/openpose/pose/poseParameters.cpp`. Program
|
||||||
|
speed will considerably decrease. Not required for OpenPose, enable it
|
||||||
|
only if you intend to explicitly use this information later.) type: bool
|
||||||
|
default: false
|
||||||
|
-heatmaps_scale (Set 0 to scale op::Datum::poseHeatMaps in the range
|
||||||
|
[-1,1], 1 for [0,1]; 2 for integer rounded [0,255]; and 3 for no
|
||||||
|
scaling.) type: int32 default: 2
|
||||||
|
-identification (Experimental, not available yet. Whether to enable people
|
||||||
|
identification across frames.) type: bool default: false
|
||||||
|
-ik_threads (Experimental, not available yet. Whether to enable inverse
|
||||||
|
kinematics (IK) from 3-D keypoints to obtain 3-D joint angles. By default
|
||||||
|
(0 threads), it is disabled. Increasing the number of threads will
|
||||||
|
increase the speed but also the global system latency.) type: int32
|
||||||
|
default: 0
|
||||||
|
-image_dir (Process a directory of images. Use `examples/media/` for our
|
||||||
|
default example folder with 20 images. Read all standard formats (jpg,
|
||||||
|
png, bmp, etc.).) type: string default: ""
|
||||||
|
-ip_camera (String with the IP camera URL. It supports protocols like RTSP
|
||||||
|
and HTTP.) type: string default: ""
|
||||||
|
-keypoint_scale (Scaling of the (x,y) coordinates of the final pose data
|
||||||
|
array, i.e., the scale of the (x,y) coordinates that will be saved with
|
||||||
|
the `write_json` & `write_keypoint` flags. Select `0` to scale it to the
|
||||||
|
original source resolution; `1`to scale it to the net output size (set
|
||||||
|
with `net_resolution`); `2` to scale it to the final output size (set
|
||||||
|
with `resolution`); `3` to scale it in the range [0,1], where (0,0) would
|
||||||
|
be the top-left corner of the image, and (1,1) the bottom-right one; and
|
||||||
|
4 for range [-1,1], where (-1,-1) would be the top-left corner of the
|
||||||
|
image, and (1,1) the bottom-right one. Non related with `scale_number`
|
||||||
|
and `scale_gap`.) type: int32 default: 0
|
||||||
|
-logging_level (The logging level. Integer in the range [0, 255]. 0 will
|
||||||
|
output any opLog() message, while 255 will not output any. Current
|
||||||
|
OpenPose library messages are in the range 0-4: 1 for low priority
|
||||||
|
messages and 4 for important ones.) type: int32 default: 3
|
||||||
|
-maximize_positives (It reduces the thresholds to accept a person
|
||||||
|
candidate. It highly increases both false and true positives. I.e., it
|
||||||
|
maximizes average recall but could harm average precision.) type: bool
|
||||||
|
default: false
|
||||||
|
-model_folder (Folder path (absolute or relative) where the models (pose,
|
||||||
|
face, ...) are located.) type: string default: "models/"
|
||||||
|
-model_pose (Model to be used. E.g., `BODY_25` (fastest for CUDA version,
|
||||||
|
most accurate, and includes foot keypoints), `COCO` (18 keypoints), `MPI`
|
||||||
|
(15 keypoints, least accurate model but fastest on CPU), `MPI_4_layers`
|
||||||
|
(15 keypoints, even faster but less accurate).) type: string
|
||||||
|
default: "BODY_25"
|
||||||
|
-net_resolution (Multiples of 16. If it is increased, the accuracy
|
||||||
|
potentially increases. If it is decreased, the speed increases. For
|
||||||
|
maximum speed-accuracy balance, it should keep the closest aspect ratio
|
||||||
|
possible to the images or videos to be processed. Using `-1` in any of
|
||||||
|
the dimensions, OP will choose the optimal aspect ratio depending on the
|
||||||
|
user's input value. E.g., the default `-1x368` is equivalent to `656x368`
|
||||||
|
in 16:9 resolutions, e.g., full HD (1980x1080) and HD (1280x720)
|
||||||
|
resolutions.) type: string default: "-1x368"
|
||||||
|
-net_resolution_dynamic (This flag only applies to images or custom inputs
|
||||||
|
(not to video or webcam). If it is zero or a negative value, it means
|
||||||
|
that using `-1` in `net_resolution` will behave as explained in its
|
||||||
|
description. Otherwise, and to avoid out of memory errors, the `-1` in
|
||||||
|
`net_resolution` will clip to this value times the default 16/9 aspect
|
||||||
|
ratio value (which is 656 width for a 368 height). E.g.,
|
||||||
|
`net_resolution_dynamic 10 net_resolution -1x368` will clip to 6560x368
|
||||||
|
(10 x 656). Recommended 1 for small GPUs (to avoid out of memory errors
|
||||||
|
but maximize speed) and 0 for big GPUs (for maximum accuracy and speed).)
|
||||||
|
type: double default: 1
|
||||||
|
-no_gui_verbose (Do not write text on output images on GUI (e.g., number of
|
||||||
|
current frame and people). It does not affect the pose rendering.)
|
||||||
|
type: bool default: false
|
||||||
|
-num_gpu (The number of GPU devices to use. If negative, it will use all
|
||||||
|
the available GPUs in your machine.) type: int32 default: -1
|
||||||
|
-num_gpu_start (GPU device start number.) type: int32 default: 0
|
||||||
|
-number_people_max (This parameter will limit the maximum number of people
|
||||||
|
detected, by keeping the people with top scores. The score is based in
|
||||||
|
person area over the image, body part score, as well as joint score
|
||||||
|
(between each pair of connected body parts). Useful if you know the exact
|
||||||
|
number of people in the scene, so it can remove false positives (if all
|
||||||
|
the people have been detected. However, it might also include false
|
||||||
|
negatives by removing very small or highly occluded people. -1 will keep
|
||||||
|
them all.) type: int32 default: -1
|
||||||
|
-output_resolution (The image resolution (display and output). Use "-1x-1"
|
||||||
|
to force the program to use the input image resolution.) type: string
|
||||||
|
default: "-1x-1"
|
||||||
|
-part_candidates (Also enable `write_json` in order to save this
|
||||||
|
information. If true, it will fill the op::Datum::poseCandidates array
|
||||||
|
with the body part candidates. Candidates refer to all the detected body
|
||||||
|
parts, before being assembled into people. Note that the number of
|
||||||
|
candidates is equal or higher than the number of final body parts (i.e.,
|
||||||
|
after being assembled into people). The empty body parts are filled with
|
||||||
|
0s. Program speed will slightly decrease. Not required for OpenPose,
|
||||||
|
enable it only if you intend to explicitly use this information.)
|
||||||
|
type: bool default: false
|
||||||
|
-part_to_show (Prediction channel to visualize: 0 (default) for all the
|
||||||
|
body parts, 1 for the background heat map, 2 for the superposition of
|
||||||
|
heatmaps, 3 for the superposition of PAFs, 4-(4+#keypoints) for each body
|
||||||
|
part heat map, the following ones for each body part pair PAF.)
|
||||||
|
type: int32 default: 0
|
||||||
|
-process_real_time (Enable to keep the original source frame rate (e.g.,
|
||||||
|
for video). If the processing time is too long, it will skip frames. If
|
||||||
|
it is too fast, it will slow it down.) type: bool default: false
|
||||||
|
-profile_speed (If PROFILER_ENABLED was set in CMake or Makefile.config
|
||||||
|
files, OpenPose will show some runtime statistics at this frame number.)
|
||||||
|
type: int32 default: 1000
|
||||||
|
-prototxt_path (The combination `--model_folder` + `--prototxt_path`
|
||||||
|
represents the whole path to the prototxt file. If empty, it will use the
|
||||||
|
default OpenPose ProtoTxt file.) type: string default: ""
|
||||||
|
-render_pose (Set to 0 for no rendering, 1 for CPU rendering (slightly
|
||||||
|
faster), and 2 for GPU rendering (slower but greater functionality, e.g.,
|
||||||
|
`alpha_X` flags). If -1, it will pick CPU if CPU_ONLY is enabled, or GPU
|
||||||
|
if CUDA is enabled. If rendering is enabled, it will render both
|
||||||
|
`outputData` and `cvOutputData` with the original image and desired body
|
||||||
|
part to be shown (i.e., keypoints, heat maps or PAFs).) type: int32
|
||||||
|
default: -1
|
||||||
|
-render_threshold (Only estimated keypoints whose score confidences are
|
||||||
|
higher than this threshold will be rendered. Note: Rendered refers only
|
||||||
|
to visual display in the OpenPose basic GUI, not in the saved results.
|
||||||
|
Generally, a high threshold (> 0.5) will only render very clear body
|
||||||
|
parts; while small thresholds (~0.1) will also output guessed and
|
||||||
|
occluded keypoints, but also more false positives (i.e., wrong
|
||||||
|
detections).) type: double default: 0.050000000000000003
|
||||||
|
-scale_gap (Scale gap between scales. No effect unless scale_number > 1.
|
||||||
|
Initial scale is always 1. If you want to change the initial scale, you
|
||||||
|
actually want to multiply the `net_resolution` by your desired initial
|
||||||
|
scale.) type: double default: 0.25
|
||||||
|
-scale_number (Number of scales to average.) type: int32 default: 1
|
||||||
|
-tracking (Experimental, not available yet. Whether to enable people
|
||||||
|
tracking across frames. The value indicates the number of frames where
|
||||||
|
tracking is run between each OpenPose keypoint detection. Select -1
|
||||||
|
(default) to disable it or 0 to run simultaneously OpenPose keypoint
|
||||||
|
detector and tracking for potentially higher accuracy than only
|
||||||
|
OpenPose.) type: int32 default: -1
|
||||||
|
-udp_host (Experimental, not available yet. IP for UDP communication. E.g.,
|
||||||
|
`192.168.0.1`.) type: string default: ""
|
||||||
|
-udp_port (Experimental, not available yet. Port number for UDP
|
||||||
|
communication.) type: string default: "8051"
|
||||||
|
-upsampling_ratio (Upsampling ratio between the `net_resolution` and the
|
||||||
|
output net results. A value less or equal than 0 (default) will use the
|
||||||
|
network default value (recommended).) type: double default: 0
|
||||||
|
-video (Use a video file instead of the camera. Use
|
||||||
|
`examples/media/video.avi` for our default example video.) type: string
|
||||||
|
default: ""
|
||||||
|
-write_bvh (Experimental, not available yet. E.g.,
|
||||||
|
`~/Desktop/mocapResult.bvh`.) type: string default: ""
|
||||||
|
-write_coco_json (Full file path to write people pose data with JSON COCO
|
||||||
|
validation format. If foot, face, hands, etc. JSON is also desired
|
||||||
|
(`--write_coco_json_variants`), they are saved with different file name
|
||||||
|
suffix.) type: string default: ""
|
||||||
|
-write_coco_json_variant (Currently, this option is experimental and only
|
||||||
|
makes effect on car JSON generation. It selects the COCO variant for
|
||||||
|
cocoJsonSaver.) type: int32 default: 0
|
||||||
|
-write_coco_json_variants (Add 1 for body, add 2 for foot, 4 for face,
|
||||||
|
and/or 8 for hands. Use 0 to use all the possible candidates. E.g., 7
|
||||||
|
would mean body+foot+face COCO JSON.) type: int32 default: 1
|
||||||
|
-write_heatmaps (Directory to write body pose heatmaps in PNG format. At
|
||||||
|
least 1 `add_heatmaps_X` flag must be enabled.) type: string default: ""
|
||||||
|
-write_heatmaps_format (File extension and format for `write_heatmaps`,
|
||||||
|
analogous to `write_images_format`. For lossless compression, recommended
|
||||||
|
`png` for integer `heatmaps_scale` and `float` for floating values. See
|
||||||
|
`doc/02_output.md` for more details.) type: string default: "png"
|
||||||
|
-write_images (Directory to write rendered frames in `write_images_format`
|
||||||
|
image format.) type: string default: ""
|
||||||
|
-write_images_format (File extension and format for `write_images`, e.g.,
|
||||||
|
png, jpg or bmp. Check the OpenCV function cv::imwrite for all compatible
|
||||||
|
extensions.) type: string default: "png"
|
||||||
|
-write_json (Directory to write OpenPose output in JSON format. It includes
|
||||||
|
body, hand, and face pose keypoints (2-D and 3-D), as well as pose
|
||||||
|
candidates (if `--part_candidates` enabled).) type: string default: ""
|
||||||
|
-write_keypoint ((Deprecated, use `write_json`) Directory to write the
|
||||||
|
people pose keypoint data. Set format with `write_keypoint_format`.)
|
||||||
|
type: string default: ""
|
||||||
|
-write_keypoint_format ((Deprecated, use `write_json`) File extension and
|
||||||
|
format for `write_keypoint`: json, xml, yaml & yml. Json not available
|
||||||
|
for OpenCV < 3.0, use `write_json` instead.) type: string default: "yml"
|
||||||
|
-write_video (Full file path to write rendered frames in motion JPEG video
|
||||||
|
format. It might fail if the final path does not finish in `.avi`. It
|
||||||
|
internally uses cv::VideoWriter. Flag `write_video_fps` controls FPS.
|
||||||
|
Alternatively, the video extension can be `.mp4`, resulting in a file
|
||||||
|
with a much smaller size and allowing `--write_video_with_audio`.
|
||||||
|
However, that would require: 1) Ubuntu or Mac system, 2) FFmpeg library
|
||||||
|
installed (`sudo apt-get install ffmpeg`), 3) the creation temporarily of
|
||||||
|
a folder with the same file path than the final video (without the
|
||||||
|
extension) to storage the intermediate frames that will later be used to
|
||||||
|
generate the final MP4 video.) type: string default: ""
|
||||||
|
-write_video_3d (Analogous to `--write_video`, but applied to the 3D
|
||||||
|
output.) type: string default: ""
|
||||||
|
-write_video_adam (Experimental, not available yet. Analogous to
|
||||||
|
`--write_video`, but applied to Adam model.) type: string default: ""
|
||||||
|
-write_video_fps (Frame rate for the recorded video. By default, it will
|
||||||
|
try to get the input frames producer frame rate (e.g., input video or
|
||||||
|
webcam frame rate). If the input frames producer does not have a set FPS
|
||||||
|
(e.g., image_dir or webcam if OpenCV not compiled with its support), set
|
||||||
|
this value accordingly (e.g., to the frame rate displayed by the OpenPose
|
||||||
|
GUI).) type: double default: -1
|
||||||
|
-write_video_with_audio (If the input is video and the output is so too, it
|
||||||
|
will save the video with audio. It requires the output video file path
|
||||||
|
finishing in `.mp4` format (see `write_video` for details).) type: bool
|
||||||
|
default: false
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,31 @@
|
||||||
|
{
|
||||||
|
"name": "openpose_api",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"compile": "./node_modules/.bin/tsc -p tsconfig.json",
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "mattmcw",
|
||||||
|
"license": "MIT",
|
||||||
|
"description": "",
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/body-parser": "^1.19.5",
|
||||||
|
"@types/express": "^4.17.21",
|
||||||
|
"@types/multer": "^1.4.12",
|
||||||
|
"@types/node": "^22.7.5",
|
||||||
|
"@types/uuid": "^10.0.0",
|
||||||
|
"typescript": "^5.6.3"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"body-parser": "^1.20.3",
|
||||||
|
"dotenv": "^16.4.5",
|
||||||
|
"express": "^4.18.2",
|
||||||
|
"lodash": "^4.17.21",
|
||||||
|
"mime": "^4.0.4",
|
||||||
|
"multer": "^1.4.5-lts.1",
|
||||||
|
"triple-beam": "^1.4.1",
|
||||||
|
"uuid": "^10.0.0",
|
||||||
|
"winston": "^3.15.0"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# -F "hand=true" \
|
||||||
|
# -F "face=true" \
|
||||||
|
|
||||||
|
curl \
|
||||||
|
-m 240 \
|
||||||
|
-F "image=@examples/two_standing.jpg" \
|
||||||
|
'http://localhost:7474/openpose'
|
|
@ -0,0 +1,13 @@
|
||||||
|
export function envString (variable : string, defaultString : string) : string {
|
||||||
|
return typeof process.env[variable] !== 'undefined' ? process.env[variable] : defaultString;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function envFloat (variable : string, defaultFloat : number ) : number {
|
||||||
|
return typeof process.env[variable] !== 'undefined' ? parseFloat(process.env[variable]) : defaultFloat;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function envInt (variable : string, defaultInt : number ) : number {
|
||||||
|
return typeof process.env[variable] !== 'undefined' ? parseInt(process.env[variable]) : defaultInt;
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { envString, envFloat, envInt };
|
|
@ -0,0 +1,166 @@
|
||||||
|
import 'dotenv/config';
|
||||||
|
import express from 'express';
|
||||||
|
import { Express, Request, Response, NextFunction } from 'express'
|
||||||
|
import { access, copyFile, unlink, mkdir, readFile, rm } from 'fs/promises';
|
||||||
|
import { tmpdir } from 'os';
|
||||||
|
import { join, basename, resolve, extname } from 'path';
|
||||||
|
import bodyParser from 'body-parser';
|
||||||
|
import multer, { FileFilterCallback } from 'multer';
|
||||||
|
import { v4 as uuid } from 'uuid';
|
||||||
|
import getType from 'mime';
|
||||||
|
import { createLog } from './log'
|
||||||
|
import type { Logger } from 'winston';
|
||||||
|
import { envInt, envString } from './env';
|
||||||
|
import { Shell } from './shell';
|
||||||
|
|
||||||
|
const PORT : number = envInt('PORT', 7474);
|
||||||
|
const BIN : string = envString('BIN', 'openpose');
|
||||||
|
const CWD : string = envString('CWD', '.');
|
||||||
|
|
||||||
|
const log : Logger = createLog('openpose_api');
|
||||||
|
const app : Express = express();
|
||||||
|
const tmp : string = tmpdir();
|
||||||
|
|
||||||
|
const storage = multer.diskStorage({
|
||||||
|
destination: function (req : Request, file : Express.Multer.File, cb : Function) {
|
||||||
|
cb(null, tmp)
|
||||||
|
},
|
||||||
|
filename: function (req : Request, file : Express.Multer.File, cb : Function) {
|
||||||
|
cb(null, `${+new Date()}_${file.originalname}`)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
async function exists (path : string) : Promise<boolean> {
|
||||||
|
try {
|
||||||
|
await access(path);
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
app.use(bodyParser.json());
|
||||||
|
app.use(bodyParser.urlencoded({ extended: true }));
|
||||||
|
|
||||||
|
const uploadImage : any = multer({ storage });
|
||||||
|
|
||||||
|
app.get('/', (req: Request, res: Response, next : NextFunction) => {
|
||||||
|
return res.send('/');
|
||||||
|
});
|
||||||
|
|
||||||
|
//./build/examples/openpose/openpose.bin -v 1 -image_dir ./examples/media/ -write_images ./output -write_json ./json --face --hand
|
||||||
|
app.post('/openpose', uploadImage.single('image'), async (req: Request, res: Response, next : NextFunction) => {
|
||||||
|
const id : string = uuid();
|
||||||
|
const dir : string = join(tmp, id);
|
||||||
|
const image_dir : string = join(dir, 'image');
|
||||||
|
const json_dir : string = join(dir, 'json');
|
||||||
|
const json_file : string = join(json_dir, 'openpose_keypoints.json');
|
||||||
|
let json_exists : boolean = false;
|
||||||
|
let openpose_str : string = '{}';
|
||||||
|
let output : any;
|
||||||
|
let image_file : string;
|
||||||
|
let image_ext : string;
|
||||||
|
let sh : Shell;
|
||||||
|
//
|
||||||
|
const args : string[] = [
|
||||||
|
BIN,
|
||||||
|
'--render_pose', '0',
|
||||||
|
'-display', '0',
|
||||||
|
'-image_dir', image_dir,
|
||||||
|
'-write_json', json_dir
|
||||||
|
];
|
||||||
|
|
||||||
|
if (typeof req.file === 'undefined') {
|
||||||
|
return next(new Error('No image uploaded'));
|
||||||
|
}
|
||||||
|
|
||||||
|
image_ext = extname(basename(req.file.path));
|
||||||
|
image_file = join(image_dir, `openpose${image_ext}`);
|
||||||
|
|
||||||
|
if (typeof req.body.face !== 'undefined' && req.body.face === 'true') {
|
||||||
|
args.push('--face');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof req.body.hand !== 'undefined' && req.body.hand === 'true') {
|
||||||
|
args.push('--hand');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await mkdir(dir);
|
||||||
|
} catch (err) {
|
||||||
|
log.error(`Error making directory ${dir}`, err);
|
||||||
|
return next(new Error('Error making dir'));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await mkdir(image_dir);
|
||||||
|
} catch (err) {
|
||||||
|
log.error(`Error making directory ${image_dir}`, err);
|
||||||
|
return next(new Error('Error making image_dir'));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await mkdir(json_dir);
|
||||||
|
} catch (err) {
|
||||||
|
log.error(`Error making directory ${image_dir}`, err);
|
||||||
|
return next(new Error('Error making image_dir'));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await copyFile(req.file.path, image_file);
|
||||||
|
} catch (err) {
|
||||||
|
log.error(`Error copying file ${req.file.path}`, err);
|
||||||
|
return next(new Error('Error copying temp image'));
|
||||||
|
}
|
||||||
|
|
||||||
|
sh = new Shell(args, CWD, null, null, null, true);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await sh.execute();
|
||||||
|
} catch (err) {
|
||||||
|
log.error(`Error executing ${args.join(' ')}`, err);
|
||||||
|
return next(new Error('Error running openpose'));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
json_exists = await exists(json_file);
|
||||||
|
} catch (err) {
|
||||||
|
log.error(`Error checking json ${json_file} exists`, err);
|
||||||
|
return next(new Error('Error checking json exists'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json_exists) {
|
||||||
|
try {
|
||||||
|
openpose_str = await readFile(json_file, 'utf8');
|
||||||
|
} catch (err) {
|
||||||
|
log.error(`Error reading json file ${json_file}`, err);
|
||||||
|
return next(new Error('Error reading json file'));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.error(`The json file ${json_file} does not exist`);
|
||||||
|
return next(new Error('Error running openpose'));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
output = JSON.parse(openpose_str);
|
||||||
|
} catch (err) {
|
||||||
|
log.error(`Error parsing openpose json`, err);
|
||||||
|
return next(new Error('Error parsing openpose json'));
|
||||||
|
}
|
||||||
|
|
||||||
|
output.image = req.file.originalname;
|
||||||
|
|
||||||
|
try {
|
||||||
|
await rm(dir, { recursive: true });
|
||||||
|
} catch (err) {
|
||||||
|
log.error(`Error unlinking ${dir}`, err);
|
||||||
|
return next(new Error('Error unlinking temp dir'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return res.json(output);
|
||||||
|
});
|
||||||
|
|
||||||
|
app.listen(PORT, () => {
|
||||||
|
log.info(`Openpose API server running on port ${PORT}`);
|
||||||
|
log.info(`Using openpose binary ${BIN}`);
|
||||||
|
});
|
|
@ -0,0 +1,61 @@
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
/** @module log */
|
||||||
|
/** Wrapper for winston that tags streams and optionally writes files with a simple interface. */
|
||||||
|
/** Module now also supports optional papertrail integration, other services to follow */
|
||||||
|
|
||||||
|
import { format, transports, createLogger } from 'winston';
|
||||||
|
const { SPLAT } = require('triple-beam');
|
||||||
|
const { isObject } = require('lodash');
|
||||||
|
|
||||||
|
const APP_NAME : string = process.env.APP_NAME || 'default';
|
||||||
|
|
||||||
|
function formatObject (param : any) {
|
||||||
|
if (isObject(param)) {
|
||||||
|
return JSON.stringify(param);
|
||||||
|
}
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
|
||||||
|
const all = format((info : any) => {
|
||||||
|
const splat = info[SPLAT] || [];
|
||||||
|
const message = formatObject(info.message);
|
||||||
|
const rest = splat.map(formatObject).join(' ');
|
||||||
|
info.message = `${message} ${rest}`;
|
||||||
|
return info;
|
||||||
|
});
|
||||||
|
|
||||||
|
const myFormat = format.printf(({ level, message, label, timestamp } : any) => {
|
||||||
|
return `${timestamp} [${label}] ${level}: ${message}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a winston logger configured to service
|
||||||
|
*
|
||||||
|
* @param {string} label Label appearing on logger
|
||||||
|
* @param {string} filename Optional file to write log to
|
||||||
|
*
|
||||||
|
* @returns {object} Winston logger
|
||||||
|
*/
|
||||||
|
export function createLog (label : string, filename : string = null) {
|
||||||
|
const tports : any[] = [ new (transports.Console)() ];
|
||||||
|
const fmat : any = format.combine(
|
||||||
|
all(),
|
||||||
|
format.label({ label }),
|
||||||
|
format.timestamp({format: 'YYYY-MM-DD HH:mm:ss.SSS'}),
|
||||||
|
format.colorize(),
|
||||||
|
myFormat,
|
||||||
|
);
|
||||||
|
let papertrailOpts : any;
|
||||||
|
|
||||||
|
if (filename !== null) {
|
||||||
|
tports.push( new (transports.File)({ filename }) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return createLogger({
|
||||||
|
format : fmat,
|
||||||
|
transports : tports
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { createLog };
|
|
@ -0,0 +1,77 @@
|
||||||
|
import { spawn, ChildProcessWithoutNullStreams } from 'child_process';
|
||||||
|
import { createLog } from '../log';
|
||||||
|
import type { Logger } from 'winston';
|
||||||
|
import { EOL } from 'os';
|
||||||
|
|
||||||
|
export class Shell {
|
||||||
|
private child : ChildProcessWithoutNullStreams;
|
||||||
|
private log : Logger;
|
||||||
|
private bin : string;
|
||||||
|
private args : any[];
|
||||||
|
private cwd : string;
|
||||||
|
private lines : string[] = [];
|
||||||
|
private stdio : Function = null;
|
||||||
|
private stderr : Function = null;
|
||||||
|
private after : Function = null;
|
||||||
|
private silent : boolean = false;
|
||||||
|
|
||||||
|
constructor (args : any[], cwd : string = null, stdio : Function = null, stderr : Function = null, after : Function = null, silent : boolean = false) {
|
||||||
|
const bin : string = args.shift();
|
||||||
|
this.bin = bin;
|
||||||
|
this.args = args;
|
||||||
|
this.stdio = stdio;
|
||||||
|
this.stderr = stderr;
|
||||||
|
this.silent = silent;
|
||||||
|
this.after = after;
|
||||||
|
this.cwd = cwd;
|
||||||
|
this.log = createLog(bin);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async execute () : Promise<number> {
|
||||||
|
return new Promise((resolve : Function, reject : Function) => {
|
||||||
|
const options : any = {};
|
||||||
|
if (this.cwd !== null) {
|
||||||
|
options.cwd = this.cwd;
|
||||||
|
}
|
||||||
|
this.child = spawn(this.bin, this.args, options);
|
||||||
|
|
||||||
|
this.log.info(`Shell: ${this.bin} ${this.args.join(' ')}`);
|
||||||
|
|
||||||
|
this.child.stdout.on('data', (data : string) => {
|
||||||
|
if (!this.silent) this.log.info(data);
|
||||||
|
if (this.after !== null) this.lines.push(data);
|
||||||
|
if (this.stdio !== null) {
|
||||||
|
this.stdio(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.child.stderr.on('data', (data : string) => {
|
||||||
|
if (!this.silent) this.log.warn(data);
|
||||||
|
if (this.stderr !== null) {
|
||||||
|
this.stderr(data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.child.on('close', (code : number) => {
|
||||||
|
if (this.after !== null) {
|
||||||
|
this.after(this.lines.join(EOL));
|
||||||
|
}
|
||||||
|
if (code === 0) {
|
||||||
|
this.log.info(`Complete: ${this.bin} ${this.args.join(' ')}`);
|
||||||
|
return resolve(code);
|
||||||
|
} else {
|
||||||
|
this.log.error(`Error executing: ${this.bin} ${this.args.join(' ')}`);
|
||||||
|
return reject(code);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public kill () {
|
||||||
|
this.log.warn(`Killing: ${this.bin} ${this.args.join(' ')}`);
|
||||||
|
//this.child.stdin.pause();
|
||||||
|
this.child.kill();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = { Shell };
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "commonjs",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"target": "ES2020",
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"sourceMap": true,
|
||||||
|
"removeComments" : false,
|
||||||
|
"baseUrl" : "dist",
|
||||||
|
"outDir": "./dist/",
|
||||||
|
"rootDir" : "./src/",
|
||||||
|
"paths" : {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"exclude" : [
|
||||||
|
"./dist",
|
||||||
|
"./node_modules"
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue