diff --git a/.github/issue_template.md b/.github/issue_template.md index 1155cd3e..79b9614f 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -1,12 +1,25 @@ +### Posting rules +1. **No duplicated** posts. +2. **No** posts about **questions already answered in** the **documentation** (e.g. **no more low-speed nor out-of-memory questions**). +3. **Add** the **system configuration (all of it!), command and output** if you have some kind of error or performance question. +4. Set a **proper issue title**: add the Ubuntu/Windows word and be specific (e.g. do not simple call it: `Compile error`). +5. Only English comments. +Issues/comments that do not follow this will be **ignored or removed** with no further clarification. + + + ### Issue summary + ### Executed command (if any) + ### OpenPose output (if any) + ### Type of issue You might select multiple topics, delete the rest: - Compilation/installation error @@ -16,6 +29,8 @@ You might select multiple topics, delete the rest: - Enhancement / offering possible extensions / pull request / etc - Other (type your own type) + + ### Your system configuration **Operating system** (`lsb_release -a` on Ubuntu): **CUDA version** (`cat /usr/local/cuda/version.txt` in most cases): diff --git a/README.md b/README.md index 2b36976b..5baa2bb8 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ OpenPose - May 2017: Windows version released! - Jun 2017: Face released! - Check all the [release notes](doc/release_notes.md). +- Interested in an internship on CMU as OpenPose programmer? See [this link](https://docs.google.com/document/d/14SygG39NjIRZfx08clewTdFMGwVdtRu2acyCi3TYcHs/edit?usp=sharing) for details. diff --git a/doc/GUI_help/GUI_help.odt b/doc/GUI_help/GUI_help.odt index 9e2a190b..4fa66828 100644 Binary files a/doc/GUI_help/GUI_help.odt and b/doc/GUI_help/GUI_help.odt differ diff --git a/doc/GUI_help/GUI_help.png b/doc/GUI_help/GUI_help.png index b4fbbcc0..fa818e9c 100644 Binary files a/doc/GUI_help/GUI_help.png and b/doc/GUI_help/GUI_help.png differ diff --git a/doc/UML/1_0_0rc3/UML.mdj b/doc/UML/1_0_0rc3/UML.mdj index d72d4612..25a0fde2 100755 --- a/doc/UML/1_0_0rc3/UML.mdj +++ b/doc/UML/1_0_0rc3/UML.mdj @@ -5917,7 +5917,7 @@ "_parent": { "$ref": "AAAAAAFbHDZmRV10zeE=" }, - "name": "scaleKeypoints", + "name": "keypoint", "ownedElements": [ { "_type": "UMLDependency", @@ -6098,6 +6098,180 @@ "isFinalSpecialization": false, "isLeaf": false, "isActive": false + }, + { + "_type": "UMLClass", + "_id": "AAAAAAFbHFy4FZeOtro=", + "_parent": { + "$ref": "AAAAAAFbHDZmRV10zeE=" + }, + "name": "resizeAndMergeCaffe", + "ownedElements": [ + { + "_type": "UMLDependency", + "_id": "AAAAAAFbHGnvtqGnGyg=", + "_parent": { + "$ref": "AAAAAAFbHFy4FZeOtro=" + }, + "source": { + "$ref": "AAAAAAFbHFy4FZeOtro=" + }, + "target": { + "$ref": "AAAAAAFbHFyvbZc1D+I=" + }, + "visibility": "public" + }, + { + "_type": "UMLAssociation", + "_id": "AAAAAAFbHHIBi7QWc3M=", + "_parent": { + "$ref": "AAAAAAFbHFy4FZeOtro=" + }, + "end1": { + "_type": "UMLAssociationEnd", + "_id": "AAAAAAFbHHIBi7QXMuA=", + "_parent": { + "$ref": "AAAAAAFbHHIBi7QWc3M=" + }, + "reference": { + "$ref": "AAAAAAFbHFy4FZeOtro=" + }, + "visibility": "public", + "navigable": true, + "aggregation": "none", + "isReadOnly": false, + "isOrdered": false, + "isUnique": false, + "isDerived": false, + "isID": false + }, + "end2": { + "_type": "UMLAssociationEnd", + "_id": "AAAAAAFbHHIBi7QYUYc=", + "_parent": { + "$ref": "AAAAAAFbHHIBi7QWc3M=" + }, + "reference": { + "$ref": "AAAAAAFbHFzB0pgy9QE=" + }, + "visibility": "public", + "navigable": true, + "aggregation": "composite", + "isReadOnly": false, + "isOrdered": false, + "isUnique": false, + "isDerived": false, + "isID": false + }, + "visibility": "public", + "isDerived": false + } + ], + "visibility": "public", + "isAbstract": false, + "isFinalSpecialization": false, + "isLeaf": false, + "isActive": false + }, + { + "_type": "UMLClass", + "_id": "AAAAAAFbHFyvbZc1D+I=", + "_parent": { + "$ref": "AAAAAAFbHDZmRV10zeE=" + }, + "name": "resizeAndMergeBase", + "visibility": "public", + "isAbstract": false, + "isFinalSpecialization": false, + "isLeaf": false, + "isActive": false + }, + { + "_type": "UMLClass", + "_id": "AAAAAAFbHFy7rZe3LU0=", + "_parent": { + "$ref": "AAAAAAFbHDZmRV10zeE=" + }, + "name": "nmsBase", + "visibility": "public", + "isAbstract": false, + "isFinalSpecialization": false, + "isLeaf": false, + "isActive": false + }, + { + "_type": "UMLClass", + "_id": "AAAAAAFbHFy95Zfg+a8=", + "_parent": { + "$ref": "AAAAAAFbHDZmRV10zeE=" + }, + "name": "nmsCaffe", + "ownedElements": [ + { + "_type": "UMLDependency", + "_id": "AAAAAAFbHGnq5qGWd3A=", + "_parent": { + "$ref": "AAAAAAFbHFy95Zfg+a8=" + }, + "source": { + "$ref": "AAAAAAFbHFy95Zfg+a8=" + }, + "target": { + "$ref": "AAAAAAFbHFy7rZe3LU0=" + }, + "visibility": "public" + }, + { + "_type": "UMLAssociation", + "_id": "AAAAAAFbHHH8ArOmRco=", + "_parent": { + "$ref": "AAAAAAFbHFy95Zfg+a8=" + }, + "end1": { + "_type": "UMLAssociationEnd", + "_id": "AAAAAAFbHHH8ArOnTL8=", + "_parent": { + "$ref": "AAAAAAFbHHH8ArOmRco=" + }, + "reference": { + "$ref": "AAAAAAFbHFy95Zfg+a8=" + }, + "visibility": "public", + "navigable": true, + "aggregation": "none", + "isReadOnly": false, + "isOrdered": false, + "isUnique": false, + "isDerived": false, + "isID": false + }, + "end2": { + "_type": "UMLAssociationEnd", + "_id": "AAAAAAFbHHH8ArOo1Sw=", + "_parent": { + "$ref": "AAAAAAFbHHH8ArOmRco=" + }, + "reference": { + "$ref": "AAAAAAFbHFzB0pgy9QE=" + }, + "visibility": "public", + "navigable": true, + "aggregation": "composite", + "isReadOnly": false, + "isOrdered": false, + "isUnique": false, + "isDerived": false, + "isID": false + }, + "visibility": "public", + "isDerived": false + } + ], + "visibility": "public", + "isAbstract": false, + "isFinalSpecialization": false, + "isLeaf": false, + "isActive": false } ], "visibility": "public" @@ -6192,7 +6366,7 @@ "containerExtending": false, "left": 5, "top": 22, - "width": 775, + "width": 1039, "height": 13, "autoResize": false, "underline": false, @@ -6264,7 +6438,7 @@ "containerExtending": false, "left": 0, "top": 15, - "width": 785, + "width": 1049, "height": 25, "autoResize": false, "stereotypeLabel": { @@ -6323,6 +6497,18 @@ }, { "$ref": "AAAAAAFbgmGMA7e9i94=" + }, + { + "$ref": "AAAAAAFcswhpISqVrfU=" + }, + { + "$ref": "AAAAAAFcswhpISqLa4s=" + }, + { + "$ref": "AAAAAAFcswhpISqfnt8=" + }, + { + "$ref": "AAAAAAFcswhpISqprwk=" } ], "visible": true, @@ -6336,7 +6522,7 @@ "containerExtending": false, "left": 0, "top": 0, - "width": 785, + "width": 1049, "height": 385, "autoResize": false, "stereotypeDisplay": "label", @@ -9861,7 +10047,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 112, + "left": 640, "top": -192, "width": 0, "height": 13, @@ -9886,7 +10072,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 797, + "left": 1061, "top": 158, "width": 214, "height": 13, @@ -9912,7 +10098,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 112, + "left": 640, "top": -192, "width": 73, "height": 13, @@ -9938,7 +10124,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 112, + "left": 640, "top": -192, "width": 0, "height": 13, @@ -9958,7 +10144,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 792, + "left": 1056, "top": 151, "width": 224, "height": 25, @@ -9991,7 +10177,7 @@ "showShadow": true, "containerChangeable": true, "containerExtending": false, - "left": 792, + "left": 1056, "top": 136, "width": 224, "height": 192, @@ -10041,7 +10227,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 80, + "left": 608, "top": -344, "width": 0, "height": 13, @@ -10066,7 +10252,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 869, + "left": 1133, "top": 223, "width": 72, "height": 13, @@ -10092,7 +10278,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 80, + "left": 608, "top": -344, "width": 73, "height": 13, @@ -10118,7 +10304,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 80, + "left": 608, "top": -344, "width": 0, "height": 13, @@ -10138,7 +10324,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 864, + "left": 1128, "top": 216, "width": 82, "height": 25, @@ -10174,7 +10360,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 864, + "left": 1128, "top": 241, "width": 82, "height": 10, @@ -10198,7 +10384,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 864, + "left": 1128, "top": 251, "width": 82, "height": 10, @@ -10222,7 +10408,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 48, + "left": 312, "top": -208, "width": 10, "height": 10, @@ -10246,7 +10432,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 48, + "left": 312, "top": -208, "width": 10, "height": 10, @@ -10265,7 +10451,7 @@ "showShadow": true, "containerChangeable": true, "containerExtending": false, - "left": 864, + "left": 1128, "top": 216, "width": 82, "height": 45, @@ -10325,8 +10511,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 744, - "top": 170, + "left": 875, + "top": 168, "width": 0, "height": 13, "autoResize": false, @@ -10359,8 +10545,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 748, - "top": 156, + "left": 877, + "top": 153, "width": 0, "height": 13, "autoResize": false, @@ -10393,8 +10579,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 735, - "top": 199, + "left": 870, + "top": 197, "width": 0, "height": 13, "autoResize": false, @@ -10426,7 +10612,7 @@ "$ref": "AAAAAAFbHDiqGk19SxU=" }, "lineStyle": 1, - "points": "618:157;863:226", + "points": "620:148;1127:231", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -10468,7 +10654,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 550, + "left": 681, "top": 167, "width": 0, "height": 13, @@ -10502,7 +10688,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 552, + "left": 683, "top": 152, "width": 0, "height": 13, @@ -10536,7 +10722,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 545, + "left": 678, "top": 196, "width": 0, "height": 13, @@ -10569,7 +10755,7 @@ "$ref": "AAAAAAFbHDirkk2m0MU=" }, "lineStyle": 1, - "points": "234:145;863:232", + "points": "234:142;1127:234", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -12456,8 +12642,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 655, - "top": 169, + "left": 786, + "top": 168, "width": 0, "height": 13, "autoResize": false, @@ -12490,8 +12676,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 658, - "top": 154, + "left": 788, + "top": 153, "width": 0, "height": 13, "autoResize": false, @@ -12524,8 +12710,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 650, - "top": 198, + "left": 783, + "top": 197, "width": 0, "height": 13, "autoResize": false, @@ -12557,7 +12743,7 @@ "$ref": "AAAAAAFbJy96y08MtFk=" }, "lineStyle": 1, - "points": "444:150;863:230", + "points": "444:145;1127:233", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -13344,7 +13530,7 @@ "height": 13, "autoResize": false, "underline": false, - "text": "scaleKeypoints", + "text": "keypoint", "horizontalAlignment": 2, "verticalAlignment": 5, "wordWrap": false @@ -14452,8 +14638,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 809, - "top": 132, + "left": 947, + "top": 133, "width": 0, "height": 13, "autoResize": false, @@ -14486,8 +14672,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 819, - "top": 121, + "left": 952, + "top": 119, "width": 0, "height": 13, "autoResize": false, @@ -14520,8 +14706,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 790, - "top": 155, + "left": 936, + "top": 162, "width": 0, "height": 13, "autoResize": false, @@ -14553,7 +14739,7 @@ "$ref": "AAAAAAFbgmAJRXI9LpI=" }, "lineStyle": 1, - "points": "723:85;877:215", + "points": "758:85;1127:223", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -15143,6 +15329,1456 @@ "propertyLabel": { "$ref": "AAAAAAFbgmHlS7nuOWI=" } + }, + { + "_type": "UMLDependencyView", + "_id": "AAAAAAFcswhpHypfaIQ=", + "_parent": { + "$ref": "AAAAAAFbHDVYsl1GUQo=" + }, + "model": { + "$ref": "AAAAAAFbHGnq5qGWd3A=" + }, + "subViews": [ + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFcswhpHypgncQ=", + "_parent": { + "$ref": "AAAAAAFcswhpHypfaIQ=" + }, + "model": { + "$ref": "AAAAAAFbHGnq5qGWd3A=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 831, + "top": 183, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": 1.5707963267948966, + "distance": 15, + "hostEdge": { + "$ref": "AAAAAAFcswhpHypfaIQ=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFcswhpICphrpM=", + "_parent": { + "$ref": "AAAAAAFcswhpHypfaIQ=" + }, + "model": { + "$ref": "AAAAAAFbHGnq5qGWd3A=" + }, + "visible": null, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 846, + "top": 183, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": 1.5707963267948966, + "distance": 30, + "hostEdge": { + "$ref": "AAAAAAFcswhpHypfaIQ=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFcswhpICpieS0=", + "_parent": { + "$ref": "AAAAAAFcswhpHypfaIQ=" + }, + "model": { + "$ref": "AAAAAAFbHGnq5qGWd3A=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 802, + "top": 184, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": -1.5707963267948966, + "distance": 15, + "hostEdge": { + "$ref": "AAAAAAFcswhpHypfaIQ=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "head": { + "$ref": "AAAAAAFcswhpISqfnt8=" + }, + "tail": { + "$ref": "AAAAAAFcswhpISqprwk=" + }, + "lineStyle": 1, + "points": "818:157;817:223", + "stereotypeDisplay": "label", + "showVisibility": true, + "showProperty": true, + "nameLabel": { + "$ref": "AAAAAAFcswhpHypgncQ=" + }, + "stereotypeLabel": { + "$ref": "AAAAAAFcswhpICphrpM=" + }, + "propertyLabel": { + "$ref": "AAAAAAFcswhpICpieS0=" + } + }, + { + "_type": "UMLDependencyView", + "_id": "AAAAAAFcswhpICpj6qk=", + "_parent": { + "$ref": "AAAAAAFbHDVYsl1GUQo=" + }, + "model": { + "$ref": "AAAAAAFbHGnvtqGnGyg=" + }, + "subViews": [ + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFcswhpICpknBE=", + "_parent": { + "$ref": "AAAAAAFcswhpICpj6qk=" + }, + "model": { + "$ref": "AAAAAAFbHGnvtqGnGyg=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 965, + "top": 187, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": 1.5707963267948966, + "distance": 15, + "hostEdge": { + "$ref": "AAAAAAFcswhpICpj6qk=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFcswhpICplHfg=", + "_parent": { + "$ref": "AAAAAAFcswhpICpj6qk=" + }, + "model": { + "$ref": "AAAAAAFbHGnvtqGnGyg=" + }, + "visible": null, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 979, + "top": 191, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": 1.5707963267948966, + "distance": 30, + "hostEdge": { + "$ref": "AAAAAAFcswhpICpj6qk=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFcswhpICpmMPg=", + "_parent": { + "$ref": "AAAAAAFcswhpICpj6qk=" + }, + "model": { + "$ref": "AAAAAAFbHGnvtqGnGyg=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 936, + "top": 180, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": -1.5707963267948966, + "distance": 15, + "hostEdge": { + "$ref": "AAAAAAFcswhpICpj6qk=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "head": { + "$ref": "AAAAAAFcswhpISqLa4s=" + }, + "tail": { + "$ref": "AAAAAAFcswhpISqVrfU=" + }, + "lineStyle": 1, + "points": "961:157;942:223", + "stereotypeDisplay": "label", + "showVisibility": true, + "showProperty": true, + "nameLabel": { + "$ref": "AAAAAAFcswhpICpknBE=" + }, + "stereotypeLabel": { + "$ref": "AAAAAAFcswhpICplHfg=" + }, + "propertyLabel": { + "$ref": "AAAAAAFcswhpICpmMPg=" + } + }, + { + "_type": "UMLClassView", + "_id": "AAAAAAFcswhpISqVrfU=", + "_parent": { + "$ref": "AAAAAAFbHDVYsl1GUQo=" + }, + "model": { + "$ref": "AAAAAAFbHFy4FZeOtro=" + }, + "subViews": [ + { + "_type": "UMLNameCompartmentView", + "_id": "AAAAAAFcswhpISqWYto=", + "_parent": { + "$ref": "AAAAAAFcswhpISqVrfU=" + }, + "model": { + "$ref": "AAAAAAFbHFy4FZeOtro=" + }, + "subViews": [ + { + "_type": "LabelView", + "_id": "AAAAAAFcswhpISqXk7s=", + "_parent": { + "$ref": "AAAAAAFcswhpISqWYto=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 2, + "top": -796, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswhpISqYB1s=", + "_parent": { + "$ref": "AAAAAAFcswhpISqWYto=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;1", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 901, + "top": 119, + "width": 136, + "height": 13, + "autoResize": false, + "underline": false, + "text": "resizeAndMergeCaffe", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswhpISqZjxQ=", + "_parent": { + "$ref": "AAAAAAFcswhpISqWYto=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 2, + "top": -796, + "width": 72, + "height": 13, + "autoResize": false, + "underline": false, + "text": "(from core)", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswhpISqagFY=", + "_parent": { + "$ref": "AAAAAAFcswhpISqWYto=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 2, + "top": -796, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 1, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 896, + "top": 112, + "width": 146, + "height": 25, + "autoResize": false, + "stereotypeLabel": { + "$ref": "AAAAAAFcswhpISqXk7s=" + }, + "nameLabel": { + "$ref": "AAAAAAFcswhpISqYB1s=" + }, + "namespaceLabel": { + "$ref": "AAAAAAFcswhpISqZjxQ=" + }, + "propertyLabel": { + "$ref": "AAAAAAFcswhpISqagFY=" + } + }, + { + "_type": "UMLAttributeCompartmentView", + "_id": "AAAAAAFcswhpISqb7PE=", + "_parent": { + "$ref": "AAAAAAFcswhpISqVrfU=" + }, + "model": { + "$ref": "AAAAAAFbHFy4FZeOtro=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 896, + "top": 137, + "width": 146, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLOperationCompartmentView", + "_id": "AAAAAAFcswhpISqc8EI=", + "_parent": { + "$ref": "AAAAAAFcswhpISqVrfU=" + }, + "model": { + "$ref": "AAAAAAFbHFy4FZeOtro=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 896, + "top": 147, + "width": 146, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLReceptionCompartmentView", + "_id": "AAAAAAFcswhpISqdXCo=", + "_parent": { + "$ref": "AAAAAAFcswhpISqVrfU=" + }, + "model": { + "$ref": "AAAAAAFbHFy4FZeOtro=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -83, + "top": -262, + "width": 10, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLTemplateParameterCompartmentView", + "_id": "AAAAAAFcswhpISqeBic=", + "_parent": { + "$ref": "AAAAAAFcswhpISqVrfU=" + }, + "model": { + "$ref": "AAAAAAFbHFy4FZeOtro=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -83, + "top": -262, + "width": 10, + "height": 10, + "autoResize": false + } + ], + "containerView": { + "$ref": "AAAAAAFbHDZmRV12Zhg=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": true, + "containerExtending": false, + "left": 896, + "top": 112, + "width": 146, + "height": 45, + "autoResize": false, + "stereotypeDisplay": "label", + "showVisibility": true, + "showNamespace": false, + "showProperty": true, + "showType": true, + "nameCompartment": { + "$ref": "AAAAAAFcswhpISqWYto=" + }, + "wordWrap": false, + "suppressAttributes": false, + "suppressOperations": false, + "suppressReceptions": true, + "showMultiplicity": true, + "showOperationSignature": true, + "attributeCompartment": { + "$ref": "AAAAAAFcswhpISqb7PE=" + }, + "operationCompartment": { + "$ref": "AAAAAAFcswhpISqc8EI=" + }, + "receptionCompartment": { + "$ref": "AAAAAAFcswhpISqdXCo=" + }, + "templateParameterCompartment": { + "$ref": "AAAAAAFcswhpISqeBic=" + } + }, + { + "_type": "UMLClassView", + "_id": "AAAAAAFcswhpISqLa4s=", + "_parent": { + "$ref": "AAAAAAFbHDVYsl1GUQo=" + }, + "model": { + "$ref": "AAAAAAFbHFyvbZc1D+I=" + }, + "subViews": [ + { + "_type": "UMLNameCompartmentView", + "_id": "AAAAAAFcswhpISqMNYQ=", + "_parent": { + "$ref": "AAAAAAFcswhpISqLa4s=" + }, + "model": { + "$ref": "AAAAAAFbHFyvbZc1D+I=" + }, + "subViews": [ + { + "_type": "LabelView", + "_id": "AAAAAAFcswhpISqNlfI=", + "_parent": { + "$ref": "AAAAAAFcswhpISqMNYQ=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 266, + "top": -548, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswhpISqOlaY=", + "_parent": { + "$ref": "AAAAAAFcswhpISqMNYQ=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;1", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 869, + "top": 231, + "width": 134, + "height": 13, + "autoResize": false, + "underline": false, + "text": "resizeAndMergeBase", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswhpISqPOFg=", + "_parent": { + "$ref": "AAAAAAFcswhpISqMNYQ=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 266, + "top": -548, + "width": 72, + "height": 13, + "autoResize": false, + "underline": false, + "text": "(from core)", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswhpISqQtYk=", + "_parent": { + "$ref": "AAAAAAFcswhpISqMNYQ=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 266, + "top": -548, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 1, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 864, + "top": 224, + "width": 144, + "height": 25, + "autoResize": false, + "stereotypeLabel": { + "$ref": "AAAAAAFcswhpISqNlfI=" + }, + "nameLabel": { + "$ref": "AAAAAAFcswhpISqOlaY=" + }, + "namespaceLabel": { + "$ref": "AAAAAAFcswhpISqPOFg=" + }, + "propertyLabel": { + "$ref": "AAAAAAFcswhpISqQtYk=" + } + }, + { + "_type": "UMLAttributeCompartmentView", + "_id": "AAAAAAFcswhpISqR/mc=", + "_parent": { + "$ref": "AAAAAAFcswhpISqLa4s=" + }, + "model": { + "$ref": "AAAAAAFbHFyvbZc1D+I=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 864, + "top": 249, + "width": 144, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLOperationCompartmentView", + "_id": "AAAAAAFcswhpISqSyAs=", + "_parent": { + "$ref": "AAAAAAFcswhpISqLa4s=" + }, + "model": { + "$ref": "AAAAAAFbHFyvbZc1D+I=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 864, + "top": 259, + "width": 144, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLReceptionCompartmentView", + "_id": "AAAAAAFcswhpISqT4zI=", + "_parent": { + "$ref": "AAAAAAFcswhpISqLa4s=" + }, + "model": { + "$ref": "AAAAAAFbHFyvbZc1D+I=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 45, + "top": -126, + "width": 10, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLTemplateParameterCompartmentView", + "_id": "AAAAAAFcswhpISqUlZc=", + "_parent": { + "$ref": "AAAAAAFcswhpISqLa4s=" + }, + "model": { + "$ref": "AAAAAAFbHFyvbZc1D+I=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 45, + "top": -126, + "width": 10, + "height": 10, + "autoResize": false + } + ], + "containerView": { + "$ref": "AAAAAAFbHDZmRV12Zhg=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": true, + "containerExtending": false, + "left": 864, + "top": 224, + "width": 144, + "height": 45, + "autoResize": false, + "stereotypeDisplay": "label", + "showVisibility": true, + "showNamespace": false, + "showProperty": true, + "showType": true, + "nameCompartment": { + "$ref": "AAAAAAFcswhpISqMNYQ=" + }, + "wordWrap": false, + "suppressAttributes": false, + "suppressOperations": false, + "suppressReceptions": true, + "showMultiplicity": true, + "showOperationSignature": true, + "attributeCompartment": { + "$ref": "AAAAAAFcswhpISqR/mc=" + }, + "operationCompartment": { + "$ref": "AAAAAAFcswhpISqSyAs=" + }, + "receptionCompartment": { + "$ref": "AAAAAAFcswhpISqT4zI=" + }, + "templateParameterCompartment": { + "$ref": "AAAAAAFcswhpISqUlZc=" + } + }, + { + "_type": "UMLClassView", + "_id": "AAAAAAFcswhpISqfnt8=", + "_parent": { + "$ref": "AAAAAAFbHDVYsl1GUQo=" + }, + "model": { + "$ref": "AAAAAAFbHFy7rZe3LU0=" + }, + "subViews": [ + { + "_type": "UMLNameCompartmentView", + "_id": "AAAAAAFcswhpISqgjTg=", + "_parent": { + "$ref": "AAAAAAFcswhpISqfnt8=" + }, + "model": { + "$ref": "AAAAAAFbHFy7rZe3LU0=" + }, + "subViews": [ + { + "_type": "LabelView", + "_id": "AAAAAAFcswhpISqh4GQ=", + "_parent": { + "$ref": "AAAAAAFcswhpISqgjTg=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 710, + "top": -796, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswhpISqiL28=", + "_parent": { + "$ref": "AAAAAAFcswhpISqgjTg=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;1", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 789, + "top": 231, + "width": 57, + "height": 13, + "autoResize": false, + "underline": false, + "text": "nmsBase", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswhpISqjAKI=", + "_parent": { + "$ref": "AAAAAAFcswhpISqgjTg=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 710, + "top": -796, + "width": 72, + "height": 13, + "autoResize": false, + "underline": false, + "text": "(from core)", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswhpISqkUKE=", + "_parent": { + "$ref": "AAAAAAFcswhpISqgjTg=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 710, + "top": -796, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 1, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 784, + "top": 224, + "width": 67, + "height": 25, + "autoResize": false, + "stereotypeLabel": { + "$ref": "AAAAAAFcswhpISqh4GQ=" + }, + "nameLabel": { + "$ref": "AAAAAAFcswhpISqiL28=" + }, + "namespaceLabel": { + "$ref": "AAAAAAFcswhpISqjAKI=" + }, + "propertyLabel": { + "$ref": "AAAAAAFcswhpISqkUKE=" + } + }, + { + "_type": "UMLAttributeCompartmentView", + "_id": "AAAAAAFcswhpISql4lg=", + "_parent": { + "$ref": "AAAAAAFcswhpISqfnt8=" + }, + "model": { + "$ref": "AAAAAAFbHFy7rZe3LU0=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 784, + "top": 249, + "width": 67, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLOperationCompartmentView", + "_id": "AAAAAAFcswhpISqmmdg=", + "_parent": { + "$ref": "AAAAAAFcswhpISqfnt8=" + }, + "model": { + "$ref": "AAAAAAFbHFy7rZe3LU0=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 784, + "top": 259, + "width": 67, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLReceptionCompartmentView", + "_id": "AAAAAAFcswhpISqnqpM=", + "_parent": { + "$ref": "AAAAAAFcswhpISqfnt8=" + }, + "model": { + "$ref": "AAAAAAFbHFy7rZe3LU0=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 333, + "top": -246, + "width": 10, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLTemplateParameterCompartmentView", + "_id": "AAAAAAFcswhpISqouF8=", + "_parent": { + "$ref": "AAAAAAFcswhpISqfnt8=" + }, + "model": { + "$ref": "AAAAAAFbHFy7rZe3LU0=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 333, + "top": -246, + "width": 10, + "height": 10, + "autoResize": false + } + ], + "containerView": { + "$ref": "AAAAAAFbHDZmRV12Zhg=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": true, + "containerExtending": false, + "left": 784, + "top": 224, + "width": 67, + "height": 45, + "autoResize": false, + "stereotypeDisplay": "label", + "showVisibility": true, + "showNamespace": false, + "showProperty": true, + "showType": true, + "nameCompartment": { + "$ref": "AAAAAAFcswhpISqgjTg=" + }, + "wordWrap": false, + "suppressAttributes": false, + "suppressOperations": false, + "suppressReceptions": true, + "showMultiplicity": true, + "showOperationSignature": true, + "attributeCompartment": { + "$ref": "AAAAAAFcswhpISql4lg=" + }, + "operationCompartment": { + "$ref": "AAAAAAFcswhpISqmmdg=" + }, + "receptionCompartment": { + "$ref": "AAAAAAFcswhpISqnqpM=" + }, + "templateParameterCompartment": { + "$ref": "AAAAAAFcswhpISqouF8=" + } + }, + { + "_type": "UMLClassView", + "_id": "AAAAAAFcswhpISqprwk=", + "_parent": { + "$ref": "AAAAAAFbHDVYsl1GUQo=" + }, + "model": { + "$ref": "AAAAAAFbHFy95Zfg+a8=" + }, + "subViews": [ + { + "_type": "UMLNameCompartmentView", + "_id": "AAAAAAFcswhpISqqVXg=", + "_parent": { + "$ref": "AAAAAAFcswhpISqprwk=" + }, + "model": { + "$ref": "AAAAAAFbHFy95Zfg+a8=" + }, + "subViews": [ + { + "_type": "LabelView", + "_id": "AAAAAAFcswhpISqrj5w=", + "_parent": { + "$ref": "AAAAAAFcswhpISqqVXg=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -62, + "top": -1068, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswhpIiqsXfc=", + "_parent": { + "$ref": "AAAAAAFcswhpISqqVXg=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;1", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 789, + "top": 119, + "width": 59, + "height": 13, + "autoResize": false, + "underline": false, + "text": "nmsCaffe", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswhpIiqtLX0=", + "_parent": { + "$ref": "AAAAAAFcswhpISqqVXg=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -62, + "top": -1068, + "width": 72, + "height": 13, + "autoResize": false, + "underline": false, + "text": "(from core)", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswhpIiquJUA=", + "_parent": { + "$ref": "AAAAAAFcswhpISqqVXg=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -62, + "top": -1068, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 1, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 784, + "top": 112, + "width": 69, + "height": 25, + "autoResize": false, + "stereotypeLabel": { + "$ref": "AAAAAAFcswhpISqrj5w=" + }, + "nameLabel": { + "$ref": "AAAAAAFcswhpIiqsXfc=" + }, + "namespaceLabel": { + "$ref": "AAAAAAFcswhpIiqtLX0=" + }, + "propertyLabel": { + "$ref": "AAAAAAFcswhpIiquJUA=" + } + }, + { + "_type": "UMLAttributeCompartmentView", + "_id": "AAAAAAFcswhpIiqv2Bo=", + "_parent": { + "$ref": "AAAAAAFcswhpISqprwk=" + }, + "model": { + "$ref": "AAAAAAFbHFy95Zfg+a8=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 784, + "top": 137, + "width": 69, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLOperationCompartmentView", + "_id": "AAAAAAFcswhpIiqwekI=", + "_parent": { + "$ref": "AAAAAAFcswhpISqprwk=" + }, + "model": { + "$ref": "AAAAAAFbHFy95Zfg+a8=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 784, + "top": 147, + "width": 69, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLReceptionCompartmentView", + "_id": "AAAAAAFcswhpIiqxRAs=", + "_parent": { + "$ref": "AAAAAAFcswhpISqprwk=" + }, + "model": { + "$ref": "AAAAAAFbHFy95Zfg+a8=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -191, + "top": -390, + "width": 10, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLTemplateParameterCompartmentView", + "_id": "AAAAAAFcswhpIiqyBM8=", + "_parent": { + "$ref": "AAAAAAFcswhpISqprwk=" + }, + "model": { + "$ref": "AAAAAAFbHFy95Zfg+a8=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -191, + "top": -390, + "width": 10, + "height": 10, + "autoResize": false + } + ], + "containerView": { + "$ref": "AAAAAAFbHDZmRV12Zhg=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": true, + "containerExtending": false, + "left": 784, + "top": 112, + "width": 69, + "height": 45, + "autoResize": false, + "stereotypeDisplay": "label", + "showVisibility": true, + "showNamespace": false, + "showProperty": true, + "showType": true, + "nameCompartment": { + "$ref": "AAAAAAFcswhpISqqVXg=" + }, + "wordWrap": false, + "suppressAttributes": false, + "suppressOperations": false, + "suppressReceptions": true, + "showMultiplicity": true, + "showOperationSignature": true, + "attributeCompartment": { + "$ref": "AAAAAAFcswhpIiqv2Bo=" + }, + "operationCompartment": { + "$ref": "AAAAAAFcswhpIiqwekI=" + }, + "receptionCompartment": { + "$ref": "AAAAAAFcswhpIiqxRAs=" + }, + "templateParameterCompartment": { + "$ref": "AAAAAAFcswhpIiqyBM8=" + } } ] }, @@ -24535,49 +26171,6 @@ }, "name": "pose", "ownedElements": [ - { - "_type": "UMLClass", - "_id": "AAAAAAFbHFyW9ZXECgk=", - "_parent": { - "$ref": "AAAAAAFbHFxkJJWoCjs=" - }, - "name": "bodyPartConnectorBase", - "ownedElements": [ - { - "_type": "UMLDependency", - "_id": "AAAAAAFbHGLjx6FvWeI=", - "_parent": { - "$ref": "AAAAAAFbHFyW9ZXECgk=" - }, - "source": { - "$ref": "AAAAAAFbHFyW9ZXECgk=" - }, - "target": { - "$ref": "AAAAAAFbHGJ4XKFAf+Y=" - }, - "visibility": "public" - }, - { - "_type": "UMLDependency", - "_id": "AAAAAAFbHGMlpKGFzvA=", - "_parent": { - "$ref": "AAAAAAFbHFyW9ZXECgk=" - }, - "source": { - "$ref": "AAAAAAFbHFyW9ZXECgk=" - }, - "target": { - "$ref": "AAAAAAFbHFyptZbjGLg=" - }, - "visibility": "public" - } - ], - "visibility": "public", - "isAbstract": false, - "isFinalSpecialization": false, - "isLeaf": false, - "isActive": false - }, { "_type": "UMLClass", "_id": "AAAAAAFbHFyaDZXtVSk=", @@ -24750,202 +26343,13 @@ "isLeaf": false, "isActive": false }, - { - "_type": "UMLClass", - "_id": "AAAAAAFbHFytbZcMIfs=", - "_parent": { - "$ref": "AAAAAAFbHFxkJJWoCjs=" - }, - "name": "bodyPartConnectorCaffe", - "ownedElements": [ - { - "_type": "UMLDependency", - "_id": "AAAAAAFbHGwQTKLXKW4=", - "_parent": { - "$ref": "AAAAAAFbHFytbZcMIfs=" - }, - "source": { - "$ref": "AAAAAAFbHFytbZcMIfs=" - }, - "target": { - "$ref": "AAAAAAFbHFyW9ZXECgk=" - }, - "visibility": "public" - }, - { - "_type": "UMLDependency", - "_id": "AAAAAAFbHGwVTKL3GS0=", - "_parent": { - "$ref": "AAAAAAFbHFytbZcMIfs=" - }, - "source": { - "$ref": "AAAAAAFbHFytbZcMIfs=" - }, - "target": { - "$ref": "AAAAAAFbHFyptZbjGLg=" - }, - "visibility": "public" - }, - { - "_type": "UMLDependency", - "_id": "AAAAAAFbHGxt3qOc9Cg=", - "_parent": { - "$ref": "AAAAAAFbHFytbZcMIfs=" - }, - "source": { - "$ref": "AAAAAAFbHFytbZcMIfs=" - }, - "target": { - "$ref": "AAAAAAFbHFyjIpa6NmI=" - }, - "visibility": "public" - }, - { - "_type": "UMLAssociation", - "_id": "AAAAAAFbHHIVkrSVUkA=", - "_parent": { - "$ref": "AAAAAAFbHFytbZcMIfs=" - }, - "end1": { - "_type": "UMLAssociationEnd", - "_id": "AAAAAAFbHHIVkrSW4DQ=", - "_parent": { - "$ref": "AAAAAAFbHHIVkrSVUkA=" - }, - "reference": { - "$ref": "AAAAAAFbHFytbZcMIfs=" - }, - "visibility": "public", - "navigable": true, - "aggregation": "none", - "isReadOnly": false, - "isOrdered": false, - "isUnique": false, - "isDerived": false, - "isID": false - }, - "end2": { - "_type": "UMLAssociationEnd", - "_id": "AAAAAAFbHHIVkrSXJ+E=", - "_parent": { - "$ref": "AAAAAAFbHHIVkrSVUkA=" - }, - "reference": { - "$ref": "AAAAAAFbHFzB0pgy9QE=" - }, - "visibility": "public", - "navigable": true, - "aggregation": "composite", - "isReadOnly": false, - "isOrdered": false, - "isUnique": false, - "isDerived": false, - "isID": false - }, - "visibility": "public", - "isDerived": false - } - ], - "visibility": "public", - "isAbstract": false, - "isFinalSpecialization": false, - "isLeaf": false, - "isActive": false - }, - { - "_type": "UMLClass", - "_id": "AAAAAAFbHFyvbZc1D+I=", - "_parent": { - "$ref": "AAAAAAFbHFxkJJWoCjs=" - }, - "name": "resizeAndMergeBase", - "visibility": "public", - "isAbstract": false, - "isFinalSpecialization": false, - "isLeaf": false, - "isActive": false - }, - { - "_type": "UMLClass", - "_id": "AAAAAAFbHFy4FZeOtro=", - "_parent": { - "$ref": "AAAAAAFbHFxkJJWoCjs=" - }, - "name": "resizeAndMergeCaffe", - "ownedElements": [ - { - "_type": "UMLDependency", - "_id": "AAAAAAFbHGnvtqGnGyg=", - "_parent": { - "$ref": "AAAAAAFbHFy4FZeOtro=" - }, - "source": { - "$ref": "AAAAAAFbHFy4FZeOtro=" - }, - "target": { - "$ref": "AAAAAAFbHFyvbZc1D+I=" - }, - "visibility": "public" - }, - { - "_type": "UMLAssociation", - "_id": "AAAAAAFbHHIBi7QWc3M=", - "_parent": { - "$ref": "AAAAAAFbHFy4FZeOtro=" - }, - "end1": { - "_type": "UMLAssociationEnd", - "_id": "AAAAAAFbHHIBi7QXMuA=", - "_parent": { - "$ref": "AAAAAAFbHHIBi7QWc3M=" - }, - "reference": { - "$ref": "AAAAAAFbHFy4FZeOtro=" - }, - "visibility": "public", - "navigable": true, - "aggregation": "none", - "isReadOnly": false, - "isOrdered": false, - "isUnique": false, - "isDerived": false, - "isID": false - }, - "end2": { - "_type": "UMLAssociationEnd", - "_id": "AAAAAAFbHHIBi7QYUYc=", - "_parent": { - "$ref": "AAAAAAFbHHIBi7QWc3M=" - }, - "reference": { - "$ref": "AAAAAAFbHFzB0pgy9QE=" - }, - "visibility": "public", - "navigable": true, - "aggregation": "composite", - "isReadOnly": false, - "isOrdered": false, - "isUnique": false, - "isDerived": false, - "isID": false - }, - "visibility": "public", - "isDerived": false - } - ], - "visibility": "public", - "isAbstract": false, - "isFinalSpecialization": false, - "isLeaf": false, - "isActive": false - }, { "_type": "UMLClass", "_id": "AAAAAAFbHFzELZhbldE=", "_parent": { "$ref": "AAAAAAFbHFxkJJWoCjs=" }, - "name": "poseRenderGpu", + "name": "renderPose", "visibility": "public", "isAbstract": false, "isFinalSpecialization": false, @@ -25260,11 +26664,41 @@ }, { "_type": "UMLClass", - "_id": "AAAAAAFbHFy7rZe3LU0=", + "_id": "AAAAAAFbHFyW9ZXECgk=", "_parent": { "$ref": "AAAAAAFbHFxkJJWoCjs=" }, - "name": "nmsBase", + "name": "bodyPartConnectorBase", + "ownedElements": [ + { + "_type": "UMLDependency", + "_id": "AAAAAAFbHGLjx6FvWeI=", + "_parent": { + "$ref": "AAAAAAFbHFyW9ZXECgk=" + }, + "source": { + "$ref": "AAAAAAFbHFyW9ZXECgk=" + }, + "target": { + "$ref": "AAAAAAFbHGJ4XKFAf+Y=" + }, + "visibility": "public" + }, + { + "_type": "UMLDependency", + "_id": "AAAAAAFbHGMlpKGFzvA=", + "_parent": { + "$ref": "AAAAAAFbHFyW9ZXECgk=" + }, + "source": { + "$ref": "AAAAAAFbHFyW9ZXECgk=" + }, + "target": { + "$ref": "AAAAAAFbHFyptZbjGLg=" + }, + "visibility": "public" + } + ], "visibility": "public", "isAbstract": false, "isFinalSpecialization": false, @@ -25273,40 +26707,68 @@ }, { "_type": "UMLClass", - "_id": "AAAAAAFbHFy95Zfg+a8=", + "_id": "AAAAAAFbHFytbZcMIfs=", "_parent": { "$ref": "AAAAAAFbHFxkJJWoCjs=" }, - "name": "nmsCaffe", + "name": "bodyPartConnectorCaffe", "ownedElements": [ { "_type": "UMLDependency", - "_id": "AAAAAAFbHGnq5qGWd3A=", + "_id": "AAAAAAFbHGwQTKLXKW4=", "_parent": { - "$ref": "AAAAAAFbHFy95Zfg+a8=" + "$ref": "AAAAAAFbHFytbZcMIfs=" }, "source": { - "$ref": "AAAAAAFbHFy95Zfg+a8=" + "$ref": "AAAAAAFbHFytbZcMIfs=" }, "target": { - "$ref": "AAAAAAFbHFy7rZe3LU0=" + "$ref": "AAAAAAFbHFyW9ZXECgk=" + }, + "visibility": "public" + }, + { + "_type": "UMLDependency", + "_id": "AAAAAAFbHGwVTKL3GS0=", + "_parent": { + "$ref": "AAAAAAFbHFytbZcMIfs=" + }, + "source": { + "$ref": "AAAAAAFbHFytbZcMIfs=" + }, + "target": { + "$ref": "AAAAAAFbHFyptZbjGLg=" + }, + "visibility": "public" + }, + { + "_type": "UMLDependency", + "_id": "AAAAAAFbHGxt3qOc9Cg=", + "_parent": { + "$ref": "AAAAAAFbHFytbZcMIfs=" + }, + "source": { + "$ref": "AAAAAAFbHFytbZcMIfs=" + }, + "target": { + "$ref": "AAAAAAFbHFyjIpa6NmI=" }, "visibility": "public" }, { "_type": "UMLAssociation", - "_id": "AAAAAAFbHHH8ArOmRco=", + "_id": "AAAAAAFbHHIVkrSVUkA=", "_parent": { - "$ref": "AAAAAAFbHFy95Zfg+a8=" + "$ref": "AAAAAAFbHFytbZcMIfs=" }, "end1": { "_type": "UMLAssociationEnd", - "_id": "AAAAAAFbHHH8ArOnTL8=", + "_id": "AAAAAAFbHHIVkrSW4DQ=", "_parent": { - "$ref": "AAAAAAFbHHH8ArOmRco=" + "$ref": "AAAAAAFbHHIVkrSVUkA=" }, "reference": { - "$ref": "AAAAAAFbHFy95Zfg+a8=" + "$ref": "AAAAAAFbHFytbZcMIfs=" }, "visibility": "public", "navigable": true, @@ -25319,9 +26781,9 @@ }, "end2": { "_type": "UMLAssociationEnd", - "_id": "AAAAAAFbHHH8ArOo1Sw=", + "_id": "AAAAAAFbHHIVkrSXJ+E=", "_parent": { - "$ref": "AAAAAAFbHHH8ArOmRco=" + "$ref": "AAAAAAFbHHIVkrSVUkA=" }, "reference": { "$ref": "AAAAAAFbHFzB0pgy9QE=" @@ -25415,6 +26877,19 @@ "isFinalSpecialization": false, "isLeaf": false, "isActive": false + }, + { + "_type": "UMLClass", + "_id": "AAAAAAFcswXRoLSckR0=", + "_parent": { + "$ref": "AAAAAAFbHGJipqEm58o=" + }, + "name": "rectangle.hpp", + "visibility": "public", + "isAbstract": false, + "isFinalSpecialization": false, + "isLeaf": false, + "isActive": false } ], "visibility": "public" @@ -25620,12 +27095,6 @@ { "$ref": "AAAAAAFbHFytbpcOd/U=" }, - { - "$ref": "AAAAAAFbHFyvbZc3RwA=" - }, - { - "$ref": "AAAAAAFbHFy4FZeQTuQ=" - }, { "$ref": "AAAAAAFbHFzELphdmCE=" }, @@ -25637,12 +27106,6 @@ }, { "$ref": "AAAAAAFbHFzK5piG7DA=" - }, - { - "$ref": "AAAAAAFbHFy7rZe5yb0=" - }, - { - "$ref": "AAAAAAFbHFy95Zfi54c=" } ], "visible": true, @@ -27706,588 +29169,6 @@ "$ref": "AAAAAAFbHFytb5cXWA4=" } }, - { - "_type": "UMLClassView", - "_id": "AAAAAAFbHFyvbZc3RwA=", - "_parent": { - "$ref": "AAAAAAFbHDdYEV2Qawk=" - }, - "model": { - "$ref": "AAAAAAFbHFyvbZc1D+I=" - }, - "subViews": [ - { - "_type": "UMLNameCompartmentView", - "_id": "AAAAAAFbHFyvbZc4C3A=", - "_parent": { - "$ref": "AAAAAAFbHFyvbZc3RwA=" - }, - "model": { - "$ref": "AAAAAAFbHFyvbZc1D+I=" - }, - "subViews": [ - { - "_type": "LabelView", - "_id": "AAAAAAFbHFyvbZc5kUI=", - "_parent": { - "$ref": "AAAAAAFbHFyvbZc4C3A=" - }, - "visible": false, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": -656, - "top": -200, - "width": 0, - "height": 13, - "autoResize": false, - "underline": false, - "horizontalAlignment": 2, - "verticalAlignment": 5, - "wordWrap": false - }, - { - "_type": "LabelView", - "_id": "AAAAAAFbHFyvbZc6THM=", - "_parent": { - "$ref": "AAAAAAFbHFyvbZc4C3A=" - }, - "visible": true, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;1", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": 229, - "top": 567, - "width": 134, - "height": 13, - "autoResize": false, - "underline": false, - "text": "resizeAndMergeBase", - "horizontalAlignment": 2, - "verticalAlignment": 5, - "wordWrap": false - }, - { - "_type": "LabelView", - "_id": "AAAAAAFbHFyvbZc7p48=", - "_parent": { - "$ref": "AAAAAAFbHFyvbZc4C3A=" - }, - "visible": false, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": -656, - "top": -200, - "width": 72, - "height": 13, - "autoResize": false, - "underline": false, - "text": "(from pose)", - "horizontalAlignment": 2, - "verticalAlignment": 5, - "wordWrap": false - }, - { - "_type": "LabelView", - "_id": "AAAAAAFbHFyvbZc8l9I=", - "_parent": { - "$ref": "AAAAAAFbHFyvbZc4C3A=" - }, - "visible": false, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": -656, - "top": -200, - "width": 0, - "height": 13, - "autoResize": false, - "underline": false, - "horizontalAlignment": 1, - "verticalAlignment": 5, - "wordWrap": false - } - ], - "visible": true, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": 224, - "top": 560, - "width": 144, - "height": 25, - "autoResize": false, - "stereotypeLabel": { - "$ref": "AAAAAAFbHFyvbZc5kUI=" - }, - "nameLabel": { - "$ref": "AAAAAAFbHFyvbZc6THM=" - }, - "namespaceLabel": { - "$ref": "AAAAAAFbHFyvbZc7p48=" - }, - "propertyLabel": { - "$ref": "AAAAAAFbHFyvbZc8l9I=" - } - }, - { - "_type": "UMLAttributeCompartmentView", - "_id": "AAAAAAFbHFyvbpc9Q/A=", - "_parent": { - "$ref": "AAAAAAFbHFyvbZc3RwA=" - }, - "model": { - "$ref": "AAAAAAFbHFyvbZc1D+I=" - }, - "visible": true, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": 224, - "top": 585, - "width": 144, - "height": 10, - "autoResize": false - }, - { - "_type": "UMLOperationCompartmentView", - "_id": "AAAAAAFbHFyvbpc+c/o=", - "_parent": { - "$ref": "AAAAAAFbHFyvbZc3RwA=" - }, - "model": { - "$ref": "AAAAAAFbHFyvbZc1D+I=" - }, - "visible": true, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": 224, - "top": 595, - "width": 144, - "height": 10, - "autoResize": false - }, - { - "_type": "UMLReceptionCompartmentView", - "_id": "AAAAAAFbHFyvbpc/wXI=", - "_parent": { - "$ref": "AAAAAAFbHFyvbZc3RwA=" - }, - "model": { - "$ref": "AAAAAAFbHFyvbZc1D+I=" - }, - "visible": false, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": -536, - "top": -112, - "width": 10, - "height": 10, - "autoResize": false - }, - { - "_type": "UMLTemplateParameterCompartmentView", - "_id": "AAAAAAFbHFyvbpdAAyo=", - "_parent": { - "$ref": "AAAAAAFbHFyvbZc3RwA=" - }, - "model": { - "$ref": "AAAAAAFbHFyvbZc1D+I=" - }, - "visible": false, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": -536, - "top": -112, - "width": 10, - "height": 10, - "autoResize": false - } - ], - "containerView": { - "$ref": "AAAAAAFbHFxkJJWqH+E=" - }, - "visible": true, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": true, - "containerExtending": false, - "left": 224, - "top": 560, - "width": 144, - "height": 45, - "autoResize": false, - "stereotypeDisplay": "label", - "showVisibility": true, - "showNamespace": false, - "showProperty": true, - "showType": true, - "nameCompartment": { - "$ref": "AAAAAAFbHFyvbZc4C3A=" - }, - "wordWrap": false, - "suppressAttributes": false, - "suppressOperations": false, - "suppressReceptions": true, - "showMultiplicity": true, - "showOperationSignature": true, - "attributeCompartment": { - "$ref": "AAAAAAFbHFyvbpc9Q/A=" - }, - "operationCompartment": { - "$ref": "AAAAAAFbHFyvbpc+c/o=" - }, - "receptionCompartment": { - "$ref": "AAAAAAFbHFyvbpc/wXI=" - }, - "templateParameterCompartment": { - "$ref": "AAAAAAFbHFyvbpdAAyo=" - } - }, - { - "_type": "UMLClassView", - "_id": "AAAAAAFbHFy4FZeQTuQ=", - "_parent": { - "$ref": "AAAAAAFbHDdYEV2Qawk=" - }, - "model": { - "$ref": "AAAAAAFbHFy4FZeOtro=" - }, - "subViews": [ - { - "_type": "UMLNameCompartmentView", - "_id": "AAAAAAFbHFy4FpeRMeY=", - "_parent": { - "$ref": "AAAAAAFbHFy4FZeQTuQ=" - }, - "model": { - "$ref": "AAAAAAFbHFy4FZeOtro=" - }, - "subViews": [ - { - "_type": "LabelView", - "_id": "AAAAAAFbHFy4FpeSFbU=", - "_parent": { - "$ref": "AAAAAAFbHFy4FpeRMeY=" - }, - "visible": false, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": -1000, - "top": -416, - "width": 0, - "height": 13, - "autoResize": false, - "underline": false, - "horizontalAlignment": 2, - "verticalAlignment": 5, - "wordWrap": false - }, - { - "_type": "LabelView", - "_id": "AAAAAAFbHFy4FpeTkoY=", - "_parent": { - "$ref": "AAAAAAFbHFy4FpeRMeY=" - }, - "visible": true, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;1", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": 229, - "top": 463, - "width": 136, - "height": 13, - "autoResize": false, - "underline": false, - "text": "resizeAndMergeCaffe", - "horizontalAlignment": 2, - "verticalAlignment": 5, - "wordWrap": false - }, - { - "_type": "LabelView", - "_id": "AAAAAAFbHFy4FpeUTNc=", - "_parent": { - "$ref": "AAAAAAFbHFy4FpeRMeY=" - }, - "visible": false, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": -1000, - "top": -416, - "width": 72, - "height": 13, - "autoResize": false, - "underline": false, - "text": "(from pose)", - "horizontalAlignment": 2, - "verticalAlignment": 5, - "wordWrap": false - }, - { - "_type": "LabelView", - "_id": "AAAAAAFbHFy4FpeVlXs=", - "_parent": { - "$ref": "AAAAAAFbHFy4FpeRMeY=" - }, - "visible": false, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": -1000, - "top": -416, - "width": 0, - "height": 13, - "autoResize": false, - "underline": false, - "horizontalAlignment": 1, - "verticalAlignment": 5, - "wordWrap": false - } - ], - "visible": true, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": 224, - "top": 456, - "width": 146, - "height": 25, - "autoResize": false, - "stereotypeLabel": { - "$ref": "AAAAAAFbHFy4FpeSFbU=" - }, - "nameLabel": { - "$ref": "AAAAAAFbHFy4FpeTkoY=" - }, - "namespaceLabel": { - "$ref": "AAAAAAFbHFy4FpeUTNc=" - }, - "propertyLabel": { - "$ref": "AAAAAAFbHFy4FpeVlXs=" - } - }, - { - "_type": "UMLAttributeCompartmentView", - "_id": "AAAAAAFbHFy4FpeWkb8=", - "_parent": { - "$ref": "AAAAAAFbHFy4FZeQTuQ=" - }, - "model": { - "$ref": "AAAAAAFbHFy4FZeOtro=" - }, - "visible": true, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": 224, - "top": 481, - "width": 146, - "height": 10, - "autoResize": false - }, - { - "_type": "UMLOperationCompartmentView", - "_id": "AAAAAAFbHFy4FpeXKZk=", - "_parent": { - "$ref": "AAAAAAFbHFy4FZeQTuQ=" - }, - "model": { - "$ref": "AAAAAAFbHFy4FZeOtro=" - }, - "visible": true, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": 224, - "top": 491, - "width": 146, - "height": 10, - "autoResize": false - }, - { - "_type": "UMLReceptionCompartmentView", - "_id": "AAAAAAFbHFy4FpeYWpw=", - "_parent": { - "$ref": "AAAAAAFbHFy4FZeQTuQ=" - }, - "model": { - "$ref": "AAAAAAFbHFy4FZeOtro=" - }, - "visible": false, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": -712, - "top": -224, - "width": 10, - "height": 10, - "autoResize": false - }, - { - "_type": "UMLTemplateParameterCompartmentView", - "_id": "AAAAAAFbHFy4F5eZQQc=", - "_parent": { - "$ref": "AAAAAAFbHFy4FZeQTuQ=" - }, - "model": { - "$ref": "AAAAAAFbHFy4FZeOtro=" - }, - "visible": false, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": -712, - "top": -224, - "width": 10, - "height": 10, - "autoResize": false - } - ], - "containerView": { - "$ref": "AAAAAAFbHFxkJJWqH+E=" - }, - "visible": true, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": true, - "containerExtending": false, - "left": 224, - "top": 456, - "width": 146, - "height": 45, - "autoResize": false, - "stereotypeDisplay": "label", - "showVisibility": true, - "showNamespace": false, - "showProperty": true, - "showType": true, - "nameCompartment": { - "$ref": "AAAAAAFbHFy4FpeRMeY=" - }, - "wordWrap": false, - "suppressAttributes": false, - "suppressOperations": false, - "suppressReceptions": true, - "showMultiplicity": true, - "showOperationSignature": true, - "attributeCompartment": { - "$ref": "AAAAAAFbHFy4FpeWkb8=" - }, - "operationCompartment": { - "$ref": "AAAAAAFbHFy4FpeXKZk=" - }, - "receptionCompartment": { - "$ref": "AAAAAAFbHFy4FpeYWpw=" - }, - "templateParameterCompartment": { - "$ref": "AAAAAAFbHFy4F5eZQQc=" - } - }, { "_type": "UMLClassView", "_id": "AAAAAAFbHFzELphdmCE=", @@ -28354,7 +29235,7 @@ "height": 13, "autoResize": false, "underline": false, - "text": "poseRenderGpu", + "text": "renderPose", "horizontalAlignment": 2, "verticalAlignment": 5, "wordWrap": false @@ -28614,8 +29495,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": -1152, - "top": -1072, + "left": -1712, + "top": -1040, "width": 0, "height": 13, "autoResize": false, @@ -28639,8 +29520,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 413, - "top": 311, + "left": 133, + "top": 327, "width": 120, "height": 13, "autoResize": false, @@ -28665,8 +29546,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": -1152, - "top": -1072, + "left": -1712, + "top": -1040, "width": 72, "height": 13, "autoResize": false, @@ -28691,8 +29572,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": -1152, - "top": -1072, + "left": -1712, + "top": -1040, "width": 0, "height": 13, "autoResize": false, @@ -28711,8 +29592,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 408, - "top": 304, + "left": 128, + "top": 320, "width": 130, "height": 25, "autoResize": false, @@ -28747,8 +29628,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 408, - "top": 329, + "left": 128, + "top": 345, "width": 130, "height": 10, "autoResize": false @@ -28771,8 +29652,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 408, - "top": 339, + "left": 128, + "top": 355, "width": 130, "height": 10, "autoResize": false @@ -28795,8 +29676,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": -600, - "top": -576, + "left": -880, + "top": -560, "width": 10, "height": 10, "autoResize": false @@ -28819,8 +29700,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": -600, - "top": -576, + "left": -880, + "top": -560, "width": 10, "height": 10, "autoResize": false @@ -28838,8 +29719,8 @@ "showShadow": true, "containerChangeable": true, "containerExtending": false, - "left": 408, - "top": 304, + "left": 128, + "top": 320, "width": 130, "height": 45, "autoResize": false, @@ -29452,588 +30333,6 @@ "$ref": "AAAAAAFbHFzK55iPcVc=" } }, - { - "_type": "UMLClassView", - "_id": "AAAAAAFbHFy7rZe5yb0=", - "_parent": { - "$ref": "AAAAAAFbHDdYEV2Qawk=" - }, - "model": { - "$ref": "AAAAAAFbHFy7rZe3LU0=" - }, - "subViews": [ - { - "_type": "UMLNameCompartmentView", - "_id": "AAAAAAFbHFy7rpe6V8M=", - "_parent": { - "$ref": "AAAAAAFbHFy7rZe5yb0=" - }, - "model": { - "$ref": "AAAAAAFbHFy7rZe3LU0=" - }, - "subViews": [ - { - "_type": "LabelView", - "_id": "AAAAAAFbHFy7rpe70Ts=", - "_parent": { - "$ref": "AAAAAAFbHFy7rpe6V8M=" - }, - "visible": false, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": -440, - "top": -472, - "width": 0, - "height": 13, - "autoResize": false, - "underline": false, - "horizontalAlignment": 2, - "verticalAlignment": 5, - "wordWrap": false - }, - { - "_type": "LabelView", - "_id": "AAAAAAFbHFy7rpe8JrM=", - "_parent": { - "$ref": "AAAAAAFbHFy7rpe6V8M=" - }, - "visible": true, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;1", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": 73, - "top": 567, - "width": 57, - "height": 13, - "autoResize": false, - "underline": false, - "text": "nmsBase", - "horizontalAlignment": 2, - "verticalAlignment": 5, - "wordWrap": false - }, - { - "_type": "LabelView", - "_id": "AAAAAAFbHFy7rpe9fX8=", - "_parent": { - "$ref": "AAAAAAFbHFy7rpe6V8M=" - }, - "visible": false, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": -440, - "top": -472, - "width": 72, - "height": 13, - "autoResize": false, - "underline": false, - "text": "(from pose)", - "horizontalAlignment": 2, - "verticalAlignment": 5, - "wordWrap": false - }, - { - "_type": "LabelView", - "_id": "AAAAAAFbHFy7rpe+Aic=", - "_parent": { - "$ref": "AAAAAAFbHFy7rpe6V8M=" - }, - "visible": false, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": -440, - "top": -472, - "width": 0, - "height": 13, - "autoResize": false, - "underline": false, - "horizontalAlignment": 1, - "verticalAlignment": 5, - "wordWrap": false - } - ], - "visible": true, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": 68, - "top": 560, - "width": 67, - "height": 25, - "autoResize": false, - "stereotypeLabel": { - "$ref": "AAAAAAFbHFy7rpe70Ts=" - }, - "nameLabel": { - "$ref": "AAAAAAFbHFy7rpe8JrM=" - }, - "namespaceLabel": { - "$ref": "AAAAAAFbHFy7rpe9fX8=" - }, - "propertyLabel": { - "$ref": "AAAAAAFbHFy7rpe+Aic=" - } - }, - { - "_type": "UMLAttributeCompartmentView", - "_id": "AAAAAAFbHFy7rpe/fWU=", - "_parent": { - "$ref": "AAAAAAFbHFy7rZe5yb0=" - }, - "model": { - "$ref": "AAAAAAFbHFy7rZe3LU0=" - }, - "visible": true, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": 68, - "top": 585, - "width": 67, - "height": 10, - "autoResize": false - }, - { - "_type": "UMLOperationCompartmentView", - "_id": "AAAAAAFbHFy7rpfAyfc=", - "_parent": { - "$ref": "AAAAAAFbHFy7rZe5yb0=" - }, - "model": { - "$ref": "AAAAAAFbHFy7rZe3LU0=" - }, - "visible": true, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": 68, - "top": 595, - "width": 67, - "height": 10, - "autoResize": false - }, - { - "_type": "UMLReceptionCompartmentView", - "_id": "AAAAAAFbHFy7rpfBpkI=", - "_parent": { - "$ref": "AAAAAAFbHFy7rZe5yb0=" - }, - "model": { - "$ref": "AAAAAAFbHFy7rZe3LU0=" - }, - "visible": false, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": -400, - "top": -256, - "width": 10, - "height": 10, - "autoResize": false - }, - { - "_type": "UMLTemplateParameterCompartmentView", - "_id": "AAAAAAFbHFy7rpfC4aM=", - "_parent": { - "$ref": "AAAAAAFbHFy7rZe5yb0=" - }, - "model": { - "$ref": "AAAAAAFbHFy7rZe3LU0=" - }, - "visible": false, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": -400, - "top": -256, - "width": 10, - "height": 10, - "autoResize": false - } - ], - "containerView": { - "$ref": "AAAAAAFbHFxkJJWqH+E=" - }, - "visible": true, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": true, - "containerExtending": false, - "left": 68, - "top": 560, - "width": 67, - "height": 45, - "autoResize": false, - "stereotypeDisplay": "label", - "showVisibility": true, - "showNamespace": false, - "showProperty": true, - "showType": true, - "nameCompartment": { - "$ref": "AAAAAAFbHFy7rpe6V8M=" - }, - "wordWrap": false, - "suppressAttributes": false, - "suppressOperations": false, - "suppressReceptions": true, - "showMultiplicity": true, - "showOperationSignature": true, - "attributeCompartment": { - "$ref": "AAAAAAFbHFy7rpe/fWU=" - }, - "operationCompartment": { - "$ref": "AAAAAAFbHFy7rpfAyfc=" - }, - "receptionCompartment": { - "$ref": "AAAAAAFbHFy7rpfBpkI=" - }, - "templateParameterCompartment": { - "$ref": "AAAAAAFbHFy7rpfC4aM=" - } - }, - { - "_type": "UMLClassView", - "_id": "AAAAAAFbHFy95Zfi54c=", - "_parent": { - "$ref": "AAAAAAFbHDdYEV2Qawk=" - }, - "model": { - "$ref": "AAAAAAFbHFy95Zfg+a8=" - }, - "subViews": [ - { - "_type": "UMLNameCompartmentView", - "_id": "AAAAAAFbHFy95pfjA10=", - "_parent": { - "$ref": "AAAAAAFbHFy95Zfi54c=" - }, - "model": { - "$ref": "AAAAAAFbHFy95Zfg+a8=" - }, - "subViews": [ - { - "_type": "LabelView", - "_id": "AAAAAAFbHFy95pfk5rs=", - "_parent": { - "$ref": "AAAAAAFbHFy95pfjA10=" - }, - "visible": false, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": -1032, - "top": -768, - "width": 0, - "height": 13, - "autoResize": false, - "underline": false, - "horizontalAlignment": 2, - "verticalAlignment": 5, - "wordWrap": false - }, - { - "_type": "LabelView", - "_id": "AAAAAAFbHFy95pflDeI=", - "_parent": { - "$ref": "AAAAAAFbHFy95pfjA10=" - }, - "visible": true, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;1", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": 73, - "top": 463, - "width": 59, - "height": 13, - "autoResize": false, - "underline": false, - "text": "nmsCaffe", - "horizontalAlignment": 2, - "verticalAlignment": 5, - "wordWrap": false - }, - { - "_type": "LabelView", - "_id": "AAAAAAFbHFy95pfmtA4=", - "_parent": { - "$ref": "AAAAAAFbHFy95pfjA10=" - }, - "visible": false, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": -1032, - "top": -768, - "width": 72, - "height": 13, - "autoResize": false, - "underline": false, - "text": "(from pose)", - "horizontalAlignment": 2, - "verticalAlignment": 5, - "wordWrap": false - }, - { - "_type": "LabelView", - "_id": "AAAAAAFbHFy95pfnV80=", - "_parent": { - "$ref": "AAAAAAFbHFy95pfjA10=" - }, - "visible": false, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": -1032, - "top": -768, - "width": 0, - "height": 13, - "autoResize": false, - "underline": false, - "horizontalAlignment": 1, - "verticalAlignment": 5, - "wordWrap": false - } - ], - "visible": true, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": 68, - "top": 456, - "width": 69, - "height": 25, - "autoResize": false, - "stereotypeLabel": { - "$ref": "AAAAAAFbHFy95pfk5rs=" - }, - "nameLabel": { - "$ref": "AAAAAAFbHFy95pflDeI=" - }, - "namespaceLabel": { - "$ref": "AAAAAAFbHFy95pfmtA4=" - }, - "propertyLabel": { - "$ref": "AAAAAAFbHFy95pfnV80=" - } - }, - { - "_type": "UMLAttributeCompartmentView", - "_id": "AAAAAAFbHFy95pfogx8=", - "_parent": { - "$ref": "AAAAAAFbHFy95Zfi54c=" - }, - "model": { - "$ref": "AAAAAAFbHFy95Zfg+a8=" - }, - "visible": true, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": 68, - "top": 481, - "width": 69, - "height": 10, - "autoResize": false - }, - { - "_type": "UMLOperationCompartmentView", - "_id": "AAAAAAFbHFy95pfpvIw=", - "_parent": { - "$ref": "AAAAAAFbHFy95Zfi54c=" - }, - "model": { - "$ref": "AAAAAAFbHFy95Zfg+a8=" - }, - "visible": true, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": 68, - "top": 491, - "width": 69, - "height": 10, - "autoResize": false - }, - { - "_type": "UMLReceptionCompartmentView", - "_id": "AAAAAAFbHFy95pfqAaA=", - "_parent": { - "$ref": "AAAAAAFbHFy95Zfi54c=" - }, - "model": { - "$ref": "AAAAAAFbHFy95Zfg+a8=" - }, - "visible": false, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": -744, - "top": -432, - "width": 10, - "height": 10, - "autoResize": false - }, - { - "_type": "UMLTemplateParameterCompartmentView", - "_id": "AAAAAAFbHFy95pfr/Ks=", - "_parent": { - "$ref": "AAAAAAFbHFy95Zfi54c=" - }, - "model": { - "$ref": "AAAAAAFbHFy95Zfg+a8=" - }, - "visible": false, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": false, - "containerExtending": false, - "left": -744, - "top": -432, - "width": 10, - "height": 10, - "autoResize": false - } - ], - "containerView": { - "$ref": "AAAAAAFbHFxkJJWqH+E=" - }, - "visible": true, - "enabled": true, - "lineColor": "#000000", - "fillColor": "#ffffff", - "fontColor": "#000000", - "font": "Arial;13;0", - "showShadow": true, - "containerChangeable": true, - "containerExtending": false, - "left": 68, - "top": 456, - "width": 69, - "height": 45, - "autoResize": false, - "stereotypeDisplay": "label", - "showVisibility": true, - "showNamespace": false, - "showProperty": true, - "showType": true, - "nameCompartment": { - "$ref": "AAAAAAFbHFy95pfjA10=" - }, - "wordWrap": false, - "suppressAttributes": false, - "suppressOperations": false, - "suppressReceptions": true, - "showMultiplicity": true, - "showOperationSignature": true, - "attributeCompartment": { - "$ref": "AAAAAAFbHFy95pfogx8=" - }, - "operationCompartment": { - "$ref": "AAAAAAFbHFy95pfpvIw=" - }, - "receptionCompartment": { - "$ref": "AAAAAAFbHFy95pfqAaA=" - }, - "templateParameterCompartment": { - "$ref": "AAAAAAFbHFy95pfr/Ks=" - } - }, { "_type": "UMLPackageView", "_id": "AAAAAAFbHGJip6EoNT0=", @@ -30069,8 +30368,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 448, - "top": -384, + "left": 384, + "top": -448, "width": 0, "height": 13, "autoResize": false, @@ -30094,9 +30393,9 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 501, - "top": 742, - "width": 191, + "left": 141, + "top": 710, + "width": 655, "height": 13, "autoResize": false, "underline": false, @@ -30120,8 +30419,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 448, - "top": -384, + "left": 384, + "top": -448, "width": 72, "height": 13, "autoResize": false, @@ -30146,8 +30445,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 448, - "top": -384, + "left": 384, + "top": -448, "width": 0, "height": 13, "autoResize": false, @@ -30166,9 +30465,9 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 496, - "top": 735, - "width": 201, + "left": 136, + "top": 703, + "width": 665, "height": 25, "autoResize": false, "stereotypeLabel": { @@ -30188,6 +30487,21 @@ "containedViews": [ { "$ref": "AAAAAAFbHGJ4XaFCtvY=" + }, + { + "$ref": "AAAAAAFcswZnYipVtjM=" + }, + { + "$ref": "AAAAAAFbHFyvbZc3RwA=" + }, + { + "$ref": "AAAAAAFbHFy4FZeQTuQ=" + }, + { + "$ref": "AAAAAAFbHFy7rZe5yb0=" + }, + { + "$ref": "AAAAAAFbHFy95Zfi54c=" } ], "visible": true, @@ -30199,9 +30513,9 @@ "showShadow": true, "containerChangeable": true, "containerExtending": false, - "left": 496, - "top": 720, - "width": 201, + "left": 136, + "top": 688, + "width": 665, "height": 160, "autoResize": false, "stereotypeDisplay": "label", @@ -30249,8 +30563,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 304, - "top": -336, + "left": 272, + "top": -384, "width": 0, "height": 13, "autoResize": false, @@ -30274,8 +30588,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 573, - "top": 799, + "left": 557, + "top": 775, "width": 61, "height": 13, "autoResize": false, @@ -30300,8 +30614,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 304, - "top": -336, + "left": 272, + "top": -384, "width": 72, "height": 13, "autoResize": false, @@ -30326,8 +30640,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 304, - "top": -336, + "left": 272, + "top": -384, "width": 0, "height": 13, "autoResize": false, @@ -30346,8 +30660,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 568, - "top": 792, + "left": 552, + "top": 768, "width": 71, "height": 25, "autoResize": false, @@ -30382,8 +30696,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 568, - "top": 817, + "left": 552, + "top": 793, "width": 71, "height": 10, "autoResize": false @@ -30406,8 +30720,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 568, - "top": 827, + "left": 552, + "top": 803, "width": 71, "height": 10, "autoResize": false @@ -30430,8 +30744,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 128, - "top": -160, + "left": 72, + "top": -184, "width": 10, "height": 10, "autoResize": false @@ -30454,8 +30768,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 128, - "top": -160, + "left": 72, + "top": -184, "width": 10, "height": 10, "autoResize": false @@ -30473,8 +30787,8 @@ "showShadow": true, "containerChangeable": true, "containerExtending": false, - "left": 568, - "top": 792, + "left": 552, + "top": 768, "width": 71, "height": 45, "autoResize": false, @@ -30533,8 +30847,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 672, - "top": 644, + "left": 663, + "top": 633, "width": 0, "height": 13, "autoResize": false, @@ -30567,8 +30881,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 686, - "top": 649, + "left": 677, + "top": 639, "width": 0, "height": 13, "autoResize": false, @@ -30601,8 +30915,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 643, - "top": 635, + "left": 636, + "top": 622, "width": 0, "height": 13, "autoResize": false, @@ -30634,7 +30948,7 @@ "$ref": "AAAAAAFbHFyW9pXGlaM=" }, "lineStyle": 1, - "points": "705:501;611:791", + "points": "704:501;596:767", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -30819,8 +31133,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 115, - "top": 523, + "left": 201, + "top": 770, "width": 0, "height": 13, "autoResize": false, @@ -30853,8 +31167,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 130, - "top": 523, + "left": 216, + "top": 769, "width": 0, "height": 13, "autoResize": false, @@ -30887,8 +31201,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 86, - "top": 524, + "left": 172, + "top": 773, "width": 0, "height": 13, "autoResize": false, @@ -30920,7 +31234,7 @@ "$ref": "AAAAAAFbHFy95Zfi54c=" }, "lineStyle": 1, - "points": "102:501;101:559", + "points": "187:765;188:791", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -30962,8 +31276,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 309, - "top": 523, + "left": 333, + "top": 771, "width": 0, "height": 13, "autoResize": false, @@ -30996,8 +31310,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 324, - "top": 523, + "left": 348, + "top": 771, "width": 0, "height": 13, "autoResize": false, @@ -31030,8 +31344,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 280, - "top": 524, + "left": 304, + "top": 772, "width": 0, "height": 13, "autoResize": false, @@ -31063,7 +31377,7 @@ "$ref": "AAAAAAFbHFy4FZeQTuQ=" }, "lineStyle": 1, - "points": "296:501;295:559", + "points": "320:765;319:791", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -31248,8 +31562,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 549, - "top": 634, + "left": 542, + "top": 622, "width": 0, "height": 13, "autoResize": false, @@ -31282,8 +31596,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 563, - "top": 628, + "left": 556, + "top": 617, "width": 0, "height": 13, "autoResize": false, @@ -31316,8 +31630,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 522, - "top": 645, + "left": 513, + "top": 633, "width": 0, "height": 13, "autoResize": false, @@ -31349,7 +31663,7 @@ "$ref": "AAAAAAFbHFzK5piG7DA=" }, "lineStyle": 1, - "points": "478:501;594:791", + "points": "478:501;578:767", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -31391,8 +31705,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 522, - "top": 645, + "left": 513, + "top": 633, "width": 0, "height": 13, "autoResize": false, @@ -31425,8 +31739,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 508, - "top": 651, + "left": 499, + "top": 638, "width": 0, "height": 13, "autoResize": false, @@ -31459,8 +31773,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 549, - "top": 634, + "left": 542, + "top": 622, "width": 0, "height": 13, "autoResize": false, @@ -31493,8 +31807,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 570, - "top": 766, + "left": 554, + "top": 741, "width": 0, "height": 13, "autoResize": false, @@ -31527,8 +31841,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 557, - "top": 769, + "left": 541, + "top": 744, "width": 0, "height": 13, "autoResize": false, @@ -31561,8 +31875,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 597, - "top": 760, + "left": 582, + "top": 736, "width": 0, "height": 13, "autoResize": false, @@ -31629,7 +31943,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 462, + "left": 461, "top": 531, "width": 0, "height": 13, @@ -31697,8 +32011,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": -496, - "top": -96, + "left": -320, + "top": -88, "width": 10, "height": 10, "autoResize": false @@ -31721,8 +32035,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": -496, - "top": -96, + "left": -320, + "top": -88, "width": 10, "height": 10, "autoResize": false @@ -31744,7 +32058,7 @@ "$ref": "AAAAAAFbHGJ4XaFCtvY=" }, "lineStyle": 1, - "points": "594:791;478:501", + "points": "578:767;478:501", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -34126,8 +34440,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 484, - "top": 396, + "left": 336, + "top": 390, "width": 0, "height": 13, "autoResize": false, @@ -34160,8 +34474,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 499, - "top": 396, + "left": 343, + "top": 377, "width": 0, "height": 13, "autoResize": false, @@ -34194,8 +34508,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 455, - "top": 395, + "left": 323, + "top": 417, "width": 0, "height": 13, "autoResize": false, @@ -34227,7 +34541,7 @@ "$ref": "AAAAAAFbHFzB0pg0a44=" }, "lineStyle": 1, - "points": "472:349;469:455", + "points": "239:365;422:455", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -34269,8 +34583,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 270, - "top": 386, + "left": 174, + "top": 535, "width": 0, "height": 13, "autoResize": false, @@ -34303,8 +34617,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 264, - "top": 372, + "left": 159, + "top": 535, "width": 0, "height": 13, "autoResize": false, @@ -34337,8 +34651,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 281, - "top": 413, + "left": 203, + "top": 536, "width": 0, "height": 13, "autoResize": false, @@ -34371,8 +34685,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 155, - "top": 434, + "left": 171, + "top": 686, "width": 0, "height": 13, "autoResize": false, @@ -34405,8 +34719,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 152, - "top": 421, + "left": 158, + "top": 684, "width": 0, "height": 13, "autoResize": false, @@ -34439,8 +34753,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 161, - "top": 461, + "left": 198, + "top": 691, "width": 0, "height": 13, "autoResize": false, @@ -34473,8 +34787,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 386, - "top": 339, + "left": 176, + "top": 384, "width": 0, "height": 13, "autoResize": false, @@ -34507,8 +34821,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 379, - "top": 327, + "left": 163, + "top": 386, "width": 0, "height": 13, "autoResize": false, @@ -34541,8 +34855,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 400, - "top": 362, + "left": 204, + "top": 380, "width": 0, "height": 13, "autoResize": false, @@ -34622,7 +34936,7 @@ "$ref": "AAAAAAFbHFy95Zfi54c=" }, "lineStyle": 1, - "points": "137:464;416:349", + "points": "186:719;192:365", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -34690,8 +35004,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 374, - "top": 384, + "left": 241, + "top": 540, "width": 0, "height": 13, "autoResize": false, @@ -34724,8 +35038,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 364, - "top": 373, + "left": 227, + "top": 545, "width": 0, "height": 13, "autoResize": false, @@ -34758,8 +35072,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 393, - "top": 407, + "left": 270, + "top": 531, "width": 0, "height": 13, "autoResize": false, @@ -34792,8 +35106,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 332, - "top": 420, + "left": 290, + "top": 692, "width": 0, "height": 13, "autoResize": false, @@ -34826,8 +35140,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 325, - "top": 409, + "left": 277, + "top": 694, "width": 0, "height": 13, "autoResize": false, @@ -34860,8 +35174,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 347, - "top": 444, + "left": 318, + "top": 688, "width": 0, "height": 13, "autoResize": false, @@ -34894,8 +35208,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 415, - "top": 348, + "left": 192, + "top": 388, "width": 0, "height": 13, "autoResize": false, @@ -34928,8 +35242,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 405, - "top": 340, + "left": 180, + "top": 394, "width": 0, "height": 13, "autoResize": false, @@ -34962,8 +35276,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 436, - "top": 366, + "left": 217, + "top": 375, "width": 0, "height": 13, "autoResize": false, @@ -34996,8 +35310,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 0, - "top": -104, + "left": 216, + "top": -96, "width": 10, "height": 10, "autoResize": false @@ -35020,8 +35334,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 0, - "top": -104, + "left": 216, + "top": -96, "width": 10, "height": 10, "autoResize": false @@ -35043,7 +35357,7 @@ "$ref": "AAAAAAFbHFy4FZeQTuQ=" }, "lineStyle": 1, - "points": "323:455;445:349", + "points": "313:719;199:365", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -35111,8 +35425,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 633, - "top": 361, + "left": 495, + "top": 369, "width": 0, "height": 13, "autoResize": false, @@ -35145,8 +35459,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 631, - "top": 376, + "left": 494, + "top": 384, "width": 0, "height": 13, "autoResize": false, @@ -35179,8 +35493,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 638, - "top": 332, + "left": 496, + "top": 340, "width": 0, "height": 13, "autoResize": false, @@ -35213,8 +35527,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 706, - "top": 373, + "left": 708, + "top": 384, "width": 0, "height": 13, "autoResize": false, @@ -35247,8 +35561,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 702, - "top": 386, + "left": 704, + "top": 397, "width": 0, "height": 13, "autoResize": false, @@ -35281,8 +35595,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 715, - "top": 347, + "left": 714, + "top": 357, "width": 0, "height": 13, "autoResize": false, @@ -35315,8 +35629,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 561, - "top": 349, + "left": 282, + "top": 356, "width": 0, "height": 13, "autoResize": false, @@ -35349,8 +35663,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 561, - "top": 363, + "left": 284, + "top": 370, "width": 0, "height": 13, "autoResize": false, @@ -35383,8 +35697,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 561, - "top": 322, + "left": 280, + "top": 328, "width": 0, "height": 13, "autoResize": false, @@ -35464,7 +35778,7 @@ "$ref": "AAAAAAFbHFytbpcOd/U=" }, "lineStyle": 1, - "points": "735:369;538:337", + "points": "735:377;258:346", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -35532,8 +35846,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 281, - "top": 413, + "left": 203, + "top": 536, "width": 0, "height": 13, "autoResize": false, @@ -35566,8 +35880,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 287, - "top": 427, + "left": 218, + "top": 536, "width": 0, "height": 13, "autoResize": false, @@ -35600,8 +35914,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 270, - "top": 386, + "left": 174, + "top": 535, "width": 0, "height": 13, "autoResize": false, @@ -35633,7 +35947,7 @@ "$ref": "AAAAAAFbHFzB0pg0a44=" }, "lineStyle": 1, - "points": "416:349;137:464", + "points": "192:365;186:719", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -35675,8 +35989,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 393, - "top": 407, + "left": 270, + "top": 531, "width": 0, "height": 13, "autoResize": false, @@ -35709,8 +36023,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 403, - "top": 418, + "left": 284, + "top": 526, "width": 0, "height": 13, "autoResize": false, @@ -35743,8 +36057,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 374, - "top": 384, + "left": 241, + "top": 540, "width": 0, "height": 13, "autoResize": false, @@ -35776,7 +36090,7 @@ "$ref": "AAAAAAFbHFzB0pg0a44=" }, "lineStyle": 1, - "points": "445:349;323:455", + "points": "199:365;313:719", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -35818,8 +36132,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 638, - "top": 332, + "left": 497, + "top": 340, "width": 0, "height": 13, "autoResize": false, @@ -35852,8 +36166,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 640, - "top": 317, + "left": 498, + "top": 325, "width": 0, "height": 13, "autoResize": false, @@ -35886,8 +36200,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 633, - "top": 361, + "left": 494, + "top": 369, "width": 0, "height": 13, "autoResize": false, @@ -35919,7 +36233,7 @@ "$ref": "AAAAAAFbHFzB0pg0a44=" }, "lineStyle": 1, - "points": "538:337;735:369", + "points": "258:346;735:377", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -35961,8 +36275,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 370, - "top": 304, + "left": 234, + "top": 287, "width": 0, "height": 13, "autoResize": false, @@ -35995,8 +36309,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 365, - "top": 318, + "left": 225, + "top": 275, "width": 0, "height": 13, "autoResize": false, @@ -36029,8 +36343,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 379, - "top": 275, + "left": 251, + "top": 312, "width": 0, "height": 13, "autoResize": false, @@ -36063,8 +36377,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 377, - "top": 306, + "left": 237, + "top": 285, "width": 0, "height": 13, "autoResize": false, @@ -36097,8 +36411,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 371, - "top": 318, + "left": 231, + "top": 273, "width": 0, "height": 13, "autoResize": false, @@ -36131,8 +36445,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 390, - "top": 281, + "left": 249, + "top": 310, "width": 0, "height": 13, "autoResize": false, @@ -36165,8 +36479,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 364, - "top": 302, + "left": 231, + "top": 290, "width": 0, "height": 13, "autoResize": false, @@ -36199,8 +36513,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 362, - "top": 315, + "left": 221, + "top": 280, "width": 0, "height": 13, "autoResize": false, @@ -36233,8 +36547,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 368, - "top": 274, + "left": 250, + "top": 309, "width": 0, "height": 13, "autoResize": false, @@ -36314,7 +36628,7 @@ "$ref": "AAAAAAFbHFzB0pg0a44=" }, "lineStyle": 1, - "points": "407:306;344:286", + "points": "225:319;261:293", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -36382,8 +36696,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 379, - "top": 275, + "left": 251, + "top": 312, "width": 0, "height": 13, "autoResize": false, @@ -36416,8 +36730,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 383, - "top": 261, + "left": 260, + "top": 324, "width": 0, "height": 13, "autoResize": false, @@ -36450,8 +36764,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 370, - "top": 304, + "left": 234, + "top": 287, "width": 0, "height": 13, "autoResize": false, @@ -36483,7 +36797,7 @@ "$ref": "AAAAAAFbHFy/tZgLHvQ=" }, "lineStyle": 1, - "points": "344:286;407:306", + "points": "261:293;225:319", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -36525,8 +36839,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 461, - "top": 528, + "left": 453, + "top": 516, "width": 0, "height": 13, "autoResize": false, @@ -36559,8 +36873,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 474, - "top": 521, + "left": 466, + "top": 509, "width": 0, "height": 13, "autoResize": false, @@ -36593,8 +36907,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 434, - "top": 543, + "left": 426, + "top": 531, "width": 0, "height": 13, "autoResize": false, @@ -36626,7 +36940,7 @@ "$ref": "AAAAAAFbHFy/tZgLHvQ=" }, "lineStyle": 1, - "points": "307:293;590:791", + "points": "307:293;574:767", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -36639,6 +36953,1461 @@ "propertyLabel": { "$ref": "AAAAAAFbHHSf7cWXNhk=" } + }, + { + "_type": "UMLClassView", + "_id": "AAAAAAFcswZnYipVtjM=", + "_parent": { + "$ref": "AAAAAAFbHDdYEV2Qawk=" + }, + "model": { + "$ref": "AAAAAAFcswXRoLSckR0=" + }, + "subViews": [ + { + "_type": "UMLNameCompartmentView", + "_id": "AAAAAAFcswZnYipWjY4=", + "_parent": { + "$ref": "AAAAAAFcswZnYipVtjM=" + }, + "model": { + "$ref": "AAAAAAFcswXRoLSckR0=" + }, + "subViews": [ + { + "_type": "LabelView", + "_id": "AAAAAAFcswZnYipXk+w=", + "_parent": { + "$ref": "AAAAAAFcswZnYipWjY4=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -244, + "top": 928, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswZnYipYmSQ=", + "_parent": { + "$ref": "AAAAAAFcswZnYipWjY4=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;1", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 637, + "top": 775, + "width": 88, + "height": 13, + "autoResize": false, + "underline": false, + "text": "rectangle.hpp", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswZnYipZ+XA=", + "_parent": { + "$ref": "AAAAAAFcswZnYipWjY4=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -244, + "top": 928, + "width": 72, + "height": 13, + "autoResize": false, + "underline": false, + "text": "(from core)", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswZnYipatsE=", + "_parent": { + "$ref": "AAAAAAFcswZnYipWjY4=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -244, + "top": 928, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 1, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 632, + "top": 768, + "width": 98, + "height": 25, + "autoResize": false, + "stereotypeLabel": { + "$ref": "AAAAAAFcswZnYipXk+w=" + }, + "nameLabel": { + "$ref": "AAAAAAFcswZnYipYmSQ=" + }, + "namespaceLabel": { + "$ref": "AAAAAAFcswZnYipZ+XA=" + }, + "propertyLabel": { + "$ref": "AAAAAAFcswZnYipatsE=" + } + }, + { + "_type": "UMLAttributeCompartmentView", + "_id": "AAAAAAFcswZnYipbZ/0=", + "_parent": { + "$ref": "AAAAAAFcswZnYipVtjM=" + }, + "model": { + "$ref": "AAAAAAFcswXRoLSckR0=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 632, + "top": 793, + "width": 98, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLOperationCompartmentView", + "_id": "AAAAAAFcswZnYipcT0k=", + "_parent": { + "$ref": "AAAAAAFcswZnYipVtjM=" + }, + "model": { + "$ref": "AAAAAAFcswXRoLSckR0=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 632, + "top": 803, + "width": 98, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLReceptionCompartmentView", + "_id": "AAAAAAFcswZnYypdFNI=", + "_parent": { + "$ref": "AAAAAAFcswZnYipVtjM=" + }, + "model": { + "$ref": "AAAAAAFcswXRoLSckR0=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -254, + "top": 724, + "width": 10, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLTemplateParameterCompartmentView", + "_id": "AAAAAAFcswZnYypeYYs=", + "_parent": { + "$ref": "AAAAAAFcswZnYipVtjM=" + }, + "model": { + "$ref": "AAAAAAFcswXRoLSckR0=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -254, + "top": 724, + "width": 10, + "height": 10, + "autoResize": false + } + ], + "containerView": { + "$ref": "AAAAAAFbHGJip6EoNT0=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": true, + "containerExtending": false, + "left": 632, + "top": 768, + "width": 98, + "height": 45, + "autoResize": false, + "stereotypeDisplay": "label", + "showVisibility": true, + "showNamespace": false, + "showProperty": true, + "showType": true, + "nameCompartment": { + "$ref": "AAAAAAFcswZnYipWjY4=" + }, + "wordWrap": false, + "suppressAttributes": false, + "suppressOperations": false, + "suppressReceptions": true, + "showMultiplicity": true, + "showOperationSignature": true, + "attributeCompartment": { + "$ref": "AAAAAAFcswZnYipbZ/0=" + }, + "operationCompartment": { + "$ref": "AAAAAAFcswZnYipcT0k=" + }, + "receptionCompartment": { + "$ref": "AAAAAAFcswZnYypdFNI=" + }, + "templateParameterCompartment": { + "$ref": "AAAAAAFcswZnYypeYYs=" + } + }, + { + "_type": "UMLClassView", + "_id": "AAAAAAFbHFyvbZc3RwA=", + "_parent": { + "$ref": "AAAAAAFbHDdYEV2Qawk=" + }, + "model": { + "$ref": "AAAAAAFbHFyvbZc1D+I=" + }, + "subViews": [ + { + "_type": "UMLNameCompartmentView", + "_id": "AAAAAAFbHFyvbZc4C3A=", + "_parent": { + "$ref": "AAAAAAFbHFyvbZc3RwA=" + }, + "model": { + "$ref": "AAAAAAFbHFyvbZc1D+I=" + }, + "subViews": [ + { + "_type": "LabelView", + "_id": "AAAAAAFbHFyvbZc5kUI=", + "_parent": { + "$ref": "AAAAAAFbHFyvbZc4C3A=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -616, + "top": 544, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFbHFyvbZc6THM=", + "_parent": { + "$ref": "AAAAAAFbHFyvbZc4C3A=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;1", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 253, + "top": 799, + "width": 134, + "height": 13, + "autoResize": false, + "underline": false, + "text": "resizeAndMergeBase", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFbHFyvbZc7p48=", + "_parent": { + "$ref": "AAAAAAFbHFyvbZc4C3A=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -616, + "top": 544, + "width": 72, + "height": 13, + "autoResize": false, + "underline": false, + "text": "(from core)", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFbHFyvbZc8l9I=", + "_parent": { + "$ref": "AAAAAAFbHFyvbZc4C3A=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -616, + "top": 544, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 1, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 248, + "top": 792, + "width": 144, + "height": 25, + "autoResize": false, + "stereotypeLabel": { + "$ref": "AAAAAAFbHFyvbZc5kUI=" + }, + "nameLabel": { + "$ref": "AAAAAAFbHFyvbZc6THM=" + }, + "namespaceLabel": { + "$ref": "AAAAAAFbHFyvbZc7p48=" + }, + "propertyLabel": { + "$ref": "AAAAAAFbHFyvbZc8l9I=" + } + }, + { + "_type": "UMLAttributeCompartmentView", + "_id": "AAAAAAFbHFyvbpc9Q/A=", + "_parent": { + "$ref": "AAAAAAFbHFyvbZc3RwA=" + }, + "model": { + "$ref": "AAAAAAFbHFyvbZc1D+I=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 248, + "top": 817, + "width": 144, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLOperationCompartmentView", + "_id": "AAAAAAFbHFyvbpc+c/o=", + "_parent": { + "$ref": "AAAAAAFbHFyvbZc3RwA=" + }, + "model": { + "$ref": "AAAAAAFbHFyvbZc1D+I=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 248, + "top": 827, + "width": 144, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLReceptionCompartmentView", + "_id": "AAAAAAFbHFyvbpc/wXI=", + "_parent": { + "$ref": "AAAAAAFbHFyvbZc3RwA=" + }, + "model": { + "$ref": "AAAAAAFbHFyvbZc1D+I=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -520, + "top": 400, + "width": 10, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLTemplateParameterCompartmentView", + "_id": "AAAAAAFbHFyvbpdAAyo=", + "_parent": { + "$ref": "AAAAAAFbHFyvbZc3RwA=" + }, + "model": { + "$ref": "AAAAAAFbHFyvbZc1D+I=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -520, + "top": 400, + "width": 10, + "height": 10, + "autoResize": false + } + ], + "containerView": { + "$ref": "AAAAAAFbHGJip6EoNT0=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": true, + "containerExtending": false, + "left": 248, + "top": 792, + "width": 144, + "height": 45, + "autoResize": false, + "stereotypeDisplay": "label", + "showVisibility": true, + "showNamespace": false, + "showProperty": true, + "showType": true, + "nameCompartment": { + "$ref": "AAAAAAFbHFyvbZc4C3A=" + }, + "wordWrap": false, + "suppressAttributes": false, + "suppressOperations": false, + "suppressReceptions": true, + "showMultiplicity": true, + "showOperationSignature": true, + "attributeCompartment": { + "$ref": "AAAAAAFbHFyvbpc9Q/A=" + }, + "operationCompartment": { + "$ref": "AAAAAAFbHFyvbpc+c/o=" + }, + "receptionCompartment": { + "$ref": "AAAAAAFbHFyvbpc/wXI=" + }, + "templateParameterCompartment": { + "$ref": "AAAAAAFbHFyvbpdAAyo=" + } + }, + { + "_type": "UMLClassView", + "_id": "AAAAAAFbHFy4FZeQTuQ=", + "_parent": { + "$ref": "AAAAAAFbHDdYEV2Qawk=" + }, + "model": { + "$ref": "AAAAAAFbHFy4FZeOtro=" + }, + "subViews": [ + { + "_type": "UMLNameCompartmentView", + "_id": "AAAAAAFbHFy4FpeRMeY=", + "_parent": { + "$ref": "AAAAAAFbHFy4FZeQTuQ=" + }, + "model": { + "$ref": "AAAAAAFbHFy4FZeOtro=" + }, + "subViews": [ + { + "_type": "LabelView", + "_id": "AAAAAAFbHFy4FpeSFbU=", + "_parent": { + "$ref": "AAAAAAFbHFy4FpeRMeY=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -960, + "top": 392, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFbHFy4FpeTkoY=", + "_parent": { + "$ref": "AAAAAAFbHFy4FpeRMeY=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;1", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 253, + "top": 727, + "width": 136, + "height": 13, + "autoResize": false, + "underline": false, + "text": "resizeAndMergeCaffe", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFbHFy4FpeUTNc=", + "_parent": { + "$ref": "AAAAAAFbHFy4FpeRMeY=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -960, + "top": 392, + "width": 72, + "height": 13, + "autoResize": false, + "underline": false, + "text": "(from core)", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFbHFy4FpeVlXs=", + "_parent": { + "$ref": "AAAAAAFbHFy4FpeRMeY=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -960, + "top": 392, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 1, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 248, + "top": 720, + "width": 146, + "height": 25, + "autoResize": false, + "stereotypeLabel": { + "$ref": "AAAAAAFbHFy4FpeSFbU=" + }, + "nameLabel": { + "$ref": "AAAAAAFbHFy4FpeTkoY=" + }, + "namespaceLabel": { + "$ref": "AAAAAAFbHFy4FpeUTNc=" + }, + "propertyLabel": { + "$ref": "AAAAAAFbHFy4FpeVlXs=" + } + }, + { + "_type": "UMLAttributeCompartmentView", + "_id": "AAAAAAFbHFy4FpeWkb8=", + "_parent": { + "$ref": "AAAAAAFbHFy4FZeQTuQ=" + }, + "model": { + "$ref": "AAAAAAFbHFy4FZeOtro=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 248, + "top": 745, + "width": 146, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLOperationCompartmentView", + "_id": "AAAAAAFbHFy4FpeXKZk=", + "_parent": { + "$ref": "AAAAAAFbHFy4FZeQTuQ=" + }, + "model": { + "$ref": "AAAAAAFbHFy4FZeOtro=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 248, + "top": 755, + "width": 146, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLReceptionCompartmentView", + "_id": "AAAAAAFbHFy4FpeYWpw=", + "_parent": { + "$ref": "AAAAAAFbHFy4FZeQTuQ=" + }, + "model": { + "$ref": "AAAAAAFbHFy4FZeOtro=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -696, + "top": 320, + "width": 10, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLTemplateParameterCompartmentView", + "_id": "AAAAAAFbHFy4F5eZQQc=", + "_parent": { + "$ref": "AAAAAAFbHFy4FZeQTuQ=" + }, + "model": { + "$ref": "AAAAAAFbHFy4FZeOtro=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -696, + "top": 320, + "width": 10, + "height": 10, + "autoResize": false + } + ], + "containerView": { + "$ref": "AAAAAAFbHGJip6EoNT0=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": true, + "containerExtending": false, + "left": 248, + "top": 720, + "width": 146, + "height": 45, + "autoResize": false, + "stereotypeDisplay": "label", + "showVisibility": true, + "showNamespace": false, + "showProperty": true, + "showType": true, + "nameCompartment": { + "$ref": "AAAAAAFbHFy4FpeRMeY=" + }, + "wordWrap": false, + "suppressAttributes": false, + "suppressOperations": false, + "suppressReceptions": true, + "showMultiplicity": true, + "showOperationSignature": true, + "attributeCompartment": { + "$ref": "AAAAAAFbHFy4FpeWkb8=" + }, + "operationCompartment": { + "$ref": "AAAAAAFbHFy4FpeXKZk=" + }, + "receptionCompartment": { + "$ref": "AAAAAAFbHFy4FpeYWpw=" + }, + "templateParameterCompartment": { + "$ref": "AAAAAAFbHFy4F5eZQQc=" + } + }, + { + "_type": "UMLClassView", + "_id": "AAAAAAFbHFy7rZe5yb0=", + "_parent": { + "$ref": "AAAAAAFbHDdYEV2Qawk=" + }, + "model": { + "$ref": "AAAAAAFbHFy7rZe3LU0=" + }, + "subViews": [ + { + "_type": "UMLNameCompartmentView", + "_id": "AAAAAAFbHFy7rpe6V8M=", + "_parent": { + "$ref": "AAAAAAFbHFy7rZe5yb0=" + }, + "model": { + "$ref": "AAAAAAFbHFy7rZe3LU0=" + }, + "subViews": [ + { + "_type": "LabelView", + "_id": "AAAAAAFbHFy7rpe70Ts=", + "_parent": { + "$ref": "AAAAAAFbHFy7rpe6V8M=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -144, + "top": 288, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFbHFy7rpe8JrM=", + "_parent": { + "$ref": "AAAAAAFbHFy7rpe6V8M=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;1", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 161, + "top": 799, + "width": 57, + "height": 13, + "autoResize": false, + "underline": false, + "text": "nmsBase", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFbHFy7rpe9fX8=", + "_parent": { + "$ref": "AAAAAAFbHFy7rpe6V8M=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -144, + "top": 288, + "width": 72, + "height": 13, + "autoResize": false, + "underline": false, + "text": "(from core)", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFbHFy7rpe+Aic=", + "_parent": { + "$ref": "AAAAAAFbHFy7rpe6V8M=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -144, + "top": 288, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 1, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 156, + "top": 792, + "width": 67, + "height": 25, + "autoResize": false, + "stereotypeLabel": { + "$ref": "AAAAAAFbHFy7rpe70Ts=" + }, + "nameLabel": { + "$ref": "AAAAAAFbHFy7rpe8JrM=" + }, + "namespaceLabel": { + "$ref": "AAAAAAFbHFy7rpe9fX8=" + }, + "propertyLabel": { + "$ref": "AAAAAAFbHFy7rpe+Aic=" + } + }, + { + "_type": "UMLAttributeCompartmentView", + "_id": "AAAAAAFbHFy7rpe/fWU=", + "_parent": { + "$ref": "AAAAAAFbHFy7rZe5yb0=" + }, + "model": { + "$ref": "AAAAAAFbHFy7rZe3LU0=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 156, + "top": 817, + "width": 67, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLOperationCompartmentView", + "_id": "AAAAAAFbHFy7rpfAyfc=", + "_parent": { + "$ref": "AAAAAAFbHFy7rZe5yb0=" + }, + "model": { + "$ref": "AAAAAAFbHFy7rZe3LU0=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 156, + "top": 827, + "width": 67, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLReceptionCompartmentView", + "_id": "AAAAAAFbHFy7rpfBpkI=", + "_parent": { + "$ref": "AAAAAAFbHFy7rZe5yb0=" + }, + "model": { + "$ref": "AAAAAAFbHFy7rZe3LU0=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -192, + "top": 272, + "width": 10, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLTemplateParameterCompartmentView", + "_id": "AAAAAAFbHFy7rpfC4aM=", + "_parent": { + "$ref": "AAAAAAFbHFy7rZe5yb0=" + }, + "model": { + "$ref": "AAAAAAFbHFy7rZe3LU0=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -192, + "top": 272, + "width": 10, + "height": 10, + "autoResize": false + } + ], + "containerView": { + "$ref": "AAAAAAFbHGJip6EoNT0=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": true, + "containerExtending": false, + "left": 156, + "top": 792, + "width": 67, + "height": 45, + "autoResize": false, + "stereotypeDisplay": "label", + "showVisibility": true, + "showNamespace": false, + "showProperty": true, + "showType": true, + "nameCompartment": { + "$ref": "AAAAAAFbHFy7rpe6V8M=" + }, + "wordWrap": false, + "suppressAttributes": false, + "suppressOperations": false, + "suppressReceptions": true, + "showMultiplicity": true, + "showOperationSignature": true, + "attributeCompartment": { + "$ref": "AAAAAAFbHFy7rpe/fWU=" + }, + "operationCompartment": { + "$ref": "AAAAAAFbHFy7rpfAyfc=" + }, + "receptionCompartment": { + "$ref": "AAAAAAFbHFy7rpfBpkI=" + }, + "templateParameterCompartment": { + "$ref": "AAAAAAFbHFy7rpfC4aM=" + } + }, + { + "_type": "UMLClassView", + "_id": "AAAAAAFbHFy95Zfi54c=", + "_parent": { + "$ref": "AAAAAAFbHDdYEV2Qawk=" + }, + "model": { + "$ref": "AAAAAAFbHFy95Zfg+a8=" + }, + "subViews": [ + { + "_type": "UMLNameCompartmentView", + "_id": "AAAAAAFbHFy95pfjA10=", + "_parent": { + "$ref": "AAAAAAFbHFy95Zfi54c=" + }, + "model": { + "$ref": "AAAAAAFbHFy95Zfg+a8=" + }, + "subViews": [ + { + "_type": "LabelView", + "_id": "AAAAAAFbHFy95pfk5rs=", + "_parent": { + "$ref": "AAAAAAFbHFy95pfjA10=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -744, + "top": 56, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFbHFy95pflDeI=", + "_parent": { + "$ref": "AAAAAAFbHFy95pfjA10=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;1", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 157, + "top": 727, + "width": 59, + "height": 13, + "autoResize": false, + "underline": false, + "text": "nmsCaffe", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFbHFy95pfmtA4=", + "_parent": { + "$ref": "AAAAAAFbHFy95pfjA10=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -744, + "top": 56, + "width": 72, + "height": 13, + "autoResize": false, + "underline": false, + "text": "(from core)", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFbHFy95pfnV80=", + "_parent": { + "$ref": "AAAAAAFbHFy95pfjA10=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -744, + "top": 56, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 1, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 152, + "top": 720, + "width": 69, + "height": 25, + "autoResize": false, + "stereotypeLabel": { + "$ref": "AAAAAAFbHFy95pfk5rs=" + }, + "nameLabel": { + "$ref": "AAAAAAFbHFy95pflDeI=" + }, + "namespaceLabel": { + "$ref": "AAAAAAFbHFy95pfmtA4=" + }, + "propertyLabel": { + "$ref": "AAAAAAFbHFy95pfnV80=" + } + }, + { + "_type": "UMLAttributeCompartmentView", + "_id": "AAAAAAFbHFy95pfogx8=", + "_parent": { + "$ref": "AAAAAAFbHFy95Zfi54c=" + }, + "model": { + "$ref": "AAAAAAFbHFy95Zfg+a8=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 152, + "top": 745, + "width": 69, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLOperationCompartmentView", + "_id": "AAAAAAFbHFy95pfpvIw=", + "_parent": { + "$ref": "AAAAAAFbHFy95Zfi54c=" + }, + "model": { + "$ref": "AAAAAAFbHFy95Zfg+a8=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 152, + "top": 755, + "width": 69, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLReceptionCompartmentView", + "_id": "AAAAAAFbHFy95pfqAaA=", + "_parent": { + "$ref": "AAAAAAFbHFy95Zfi54c=" + }, + "model": { + "$ref": "AAAAAAFbHFy95Zfg+a8=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -540, + "top": 128, + "width": 10, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLTemplateParameterCompartmentView", + "_id": "AAAAAAFbHFy95pfr/Ks=", + "_parent": { + "$ref": "AAAAAAFbHFy95Zfi54c=" + }, + "model": { + "$ref": "AAAAAAFbHFy95Zfg+a8=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -540, + "top": 128, + "width": 10, + "height": 10, + "autoResize": false + } + ], + "containerView": { + "$ref": "AAAAAAFbHGJip6EoNT0=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": true, + "containerExtending": false, + "left": 152, + "top": 720, + "width": 69, + "height": 45, + "autoResize": false, + "stereotypeDisplay": "label", + "showVisibility": true, + "showNamespace": false, + "showProperty": true, + "showType": true, + "nameCompartment": { + "$ref": "AAAAAAFbHFy95pfjA10=" + }, + "wordWrap": false, + "suppressAttributes": false, + "suppressOperations": false, + "suppressReceptions": true, + "showMultiplicity": true, + "showOperationSignature": true, + "attributeCompartment": { + "$ref": "AAAAAAFbHFy95pfogx8=" + }, + "operationCompartment": { + "$ref": "AAAAAAFbHFy95pfpvIw=" + }, + "receptionCompartment": { + "$ref": "AAAAAAFbHFy95pfqAaA=" + }, + "templateParameterCompartment": { + "$ref": "AAAAAAFbHFy95pfr/Ks=" + } } ] }, @@ -36979,6 +38748,77 @@ "isFinalSpecialization": false, "isLeaf": false, "isActive": false + }, + { + "_type": "UMLClass", + "_id": "AAAAAAFcswO76bJsmb4=", + "_parent": { + "$ref": "AAAAAAFbHInAVcvEP2c=" + }, + "name": "keypoint", + "ownedElements": [ + { + "_type": "UMLDependency", + "_id": "AAAAAAFcswPht7KYSAs=", + "_parent": { + "$ref": "AAAAAAFcswO76bJsmb4=" + }, + "source": { + "$ref": "AAAAAAFcswO76bJsmb4=" + }, + "target": { + "$ref": "AAAAAAFbH1KdscyQvqc=" + }, + "visibility": "public" + }, + { + "_type": "UMLDependency", + "_id": "AAAAAAFcswPmlrKpfyc=", + "_parent": { + "$ref": "AAAAAAFcswO76bJsmb4=" + }, + "source": { + "$ref": "AAAAAAFcswO76bJsmb4=" + }, + "target": { + "$ref": "AAAAAAFbH1K01c4qGfA=" + }, + "visibility": "public" + }, + { + "_type": "UMLDependency", + "_id": "AAAAAAFcswRgfbSHUnE=", + "_parent": { + "$ref": "AAAAAAFcswO76bJsmb4=" + }, + "source": { + "$ref": "AAAAAAFcswO76bJsmb4=" + }, + "target": { + "$ref": "AAAAAAFbHGJ4XKFAf+Y=" + }, + "visibility": "public" + }, + { + "_type": "UMLDependency", + "_id": "AAAAAAFcswYObrTJy5s=", + "_parent": { + "$ref": "AAAAAAFcswO76bJsmb4=" + }, + "source": { + "$ref": "AAAAAAFcswO76bJsmb4=" + }, + "target": { + "$ref": "AAAAAAFcswXRoLSckR0=" + }, + "visibility": "public" + } + ], + "visibility": "public", + "isAbstract": false, + "isFinalSpecialization": false, + "isLeaf": false, + "isActive": false } ], "visibility": "public" @@ -37177,6 +39017,9 @@ }, { "$ref": "AAAAAAFbH1Kwgs3av4U=" + }, + { + "$ref": "AAAAAAFcswO767JuzTE=" } ], "visible": true, @@ -38402,7 +40245,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 1032, + "left": 904, "top": -208, "width": 0, "height": 13, @@ -38427,7 +40270,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 549, + "left": 485, "top": 159, "width": 46, "height": 13, @@ -38453,7 +40296,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 1032, + "left": 904, "top": -208, "width": 78, "height": 13, @@ -38479,7 +40322,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 1032, + "left": 904, "top": -208, "width": 0, "height": 13, @@ -38499,7 +40342,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 544, + "left": 480, "top": 152, "width": 56, "height": 25, @@ -38535,7 +40378,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 544, + "left": 480, "top": 177, "width": 56, "height": 10, @@ -38559,7 +40402,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 544, + "left": 480, "top": 187, "width": 56, "height": 10, @@ -38583,7 +40426,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 680, + "left": 616, "top": -104, "width": 10, "height": 10, @@ -38607,7 +40450,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 680, + "left": 616, "top": -104, "width": 10, "height": 10, @@ -38626,7 +40469,7 @@ "showShadow": true, "containerChangeable": true, "containerExtending": false, - "left": 544, + "left": 480, "top": 152, "width": 56, "height": 45, @@ -39275,7 +41118,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 744, + "left": 680, "top": 0, "width": 0, "height": 13, @@ -39300,7 +41143,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 445, + "left": 413, "top": 159, "width": 48, "height": 13, @@ -39326,7 +41169,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 744, + "left": 680, "top": 0, "width": 78, "height": 13, @@ -39352,7 +41195,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 744, + "left": 680, "top": 0, "width": 0, "height": 13, @@ -39372,7 +41215,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 440, + "left": 408, "top": 152, "width": 58, "height": 25, @@ -39408,7 +41251,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 440, + "left": 408, "top": 177, "width": 58, "height": 10, @@ -39432,7 +41275,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 440, + "left": 408, "top": 187, "width": 58, "height": 10, @@ -39456,7 +41299,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 552, + "left": 520, "top": 24, "width": 10, "height": 10, @@ -39480,7 +41323,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 552, + "left": 520, "top": 24, "width": 10, "height": 10, @@ -39499,7 +41342,7 @@ "showShadow": true, "containerChangeable": true, "containerExtending": false, - "left": 440, + "left": 408, "top": 152, "width": 58, "height": 45, @@ -41014,8 +42857,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 584, - "top": 260, + "left": 552, + "top": 255, "width": 0, "height": 13, "autoResize": false, @@ -41048,8 +42891,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 599, - "top": 260, + "left": 566, + "top": 250, "width": 0, "height": 13, "autoResize": false, @@ -41082,8 +42925,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 555, - "top": 259, + "left": 523, + "top": 264, "width": 0, "height": 13, "autoResize": false, @@ -41115,7 +42958,7 @@ "$ref": "AAAAAAFbH1Kncc02gVk=" }, "lineStyle": 1, - "points": "571:197;569:335", + "points": "515:197;561:335", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -41157,8 +43000,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 437, - "top": 231, + "left": 406, + "top": 229, "width": 0, "height": 13, "autoResize": false, @@ -41191,8 +43034,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 442, - "top": 245, + "left": 412, + "top": 243, "width": 0, "height": 13, "autoResize": false, @@ -41225,7 +43068,7 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 426, + "left": 393, "top": 202, "width": 0, "height": 13, @@ -41258,7 +43101,7 @@ "$ref": "AAAAAAFbH1Kncc02gVk=" }, "lineStyle": 1, - "points": "543:184;322:262", + "points": "479:187;322:257", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -41300,8 +43143,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 399, - "top": 269, + "left": 384, + "top": 268, "width": 0, "height": 13, "autoResize": false, @@ -41334,8 +43177,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 410, - "top": 279, + "left": 396, + "top": 276, "width": 0, "height": 13, "autoResize": false, @@ -41368,8 +43211,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 376, - "top": 250, + "left": 359, + "top": 251, "width": 0, "height": 13, "autoResize": false, @@ -41401,7 +43244,7 @@ "$ref": "AAAAAAFbH1KhQcy7aPg=" }, "lineStyle": 1, - "points": "448:197;329:335", + "points": "420:197;325:335", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -41443,8 +43286,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 385, - "top": 229, + "left": 367, + "top": 230, "width": 0, "height": 13, "autoResize": false, @@ -41477,8 +43320,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 392, - "top": 242, + "left": 375, + "top": 243, "width": 0, "height": 13, "autoResize": false, @@ -41511,8 +43354,8 @@ "showShadow": true, "containerChangeable": false, "containerExtending": false, - "left": 370, - "top": 202, + "left": 350, + "top": 205, "width": 0, "height": 13, "autoResize": false, @@ -41544,7 +43387,7 @@ "$ref": "AAAAAAFbH1KhQcy7aPg=" }, "lineStyle": 1, - "points": "439:190;318:255", + "points": "407:193;311:255", "stereotypeDisplay": "label", "showVisibility": true, "showProperty": true, @@ -42272,6 +44115,1631 @@ "propertyLabel": { "$ref": "AAAAAAFbH4LrtNH89TQ=" } + }, + { + "_type": "UMLClassView", + "_id": "AAAAAAFcswO767JuzTE=", + "_parent": { + "$ref": "AAAAAAFbHImRMcuZ6y8=" + }, + "model": { + "$ref": "AAAAAAFcswO76bJsmb4=" + }, + "subViews": [ + { + "_type": "UMLNameCompartmentView", + "_id": "AAAAAAFcswO767Jv7cY=", + "_parent": { + "$ref": "AAAAAAFcswO767JuzTE=" + }, + "model": { + "$ref": "AAAAAAFcswO76bJsmb4=" + }, + "subViews": [ + { + "_type": "LabelView", + "_id": "AAAAAAFcswO77LJwV44=", + "_parent": { + "$ref": "AAAAAAFcswO767Jv7cY=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 208, + "top": -144, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswO77LJxhXE=", + "_parent": { + "$ref": "AAAAAAFcswO767Jv7cY=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;1", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 589, + "top": 159, + "width": 54, + "height": 13, + "autoResize": false, + "underline": false, + "text": "keypoint", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswO77LJyqRc=", + "_parent": { + "$ref": "AAAAAAFcswO767Jv7cY=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 208, + "top": -144, + "width": 78, + "height": 13, + "autoResize": false, + "underline": false, + "text": "(from utilities)", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswO77LJz4mI=", + "_parent": { + "$ref": "AAAAAAFcswO767Jv7cY=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 208, + "top": -144, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 1, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 584, + "top": 152, + "width": 64, + "height": 25, + "autoResize": false, + "stereotypeLabel": { + "$ref": "AAAAAAFcswO77LJwV44=" + }, + "nameLabel": { + "$ref": "AAAAAAFcswO77LJxhXE=" + }, + "namespaceLabel": { + "$ref": "AAAAAAFcswO77LJyqRc=" + }, + "propertyLabel": { + "$ref": "AAAAAAFcswO77LJz4mI=" + } + }, + { + "_type": "UMLAttributeCompartmentView", + "_id": "AAAAAAFcswO77LJ0Um8=", + "_parent": { + "$ref": "AAAAAAFcswO767JuzTE=" + }, + "model": { + "$ref": "AAAAAAFcswO76bJsmb4=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 584, + "top": 177, + "width": 64, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLOperationCompartmentView", + "_id": "AAAAAAFcswO77bJ1zqg=", + "_parent": { + "$ref": "AAAAAAFcswO767JuzTE=" + }, + "model": { + "$ref": "AAAAAAFcswO76bJsmb4=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 584, + "top": 187, + "width": 64, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLReceptionCompartmentView", + "_id": "AAAAAAFcswO77bJ2ZoE=", + "_parent": { + "$ref": "AAAAAAFcswO767JuzTE=" + }, + "model": { + "$ref": "AAAAAAFcswO76bJsmb4=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 104, + "top": -120, + "width": 10, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLTemplateParameterCompartmentView", + "_id": "AAAAAAFcswO77bJ3Yfc=", + "_parent": { + "$ref": "AAAAAAFcswO767JuzTE=" + }, + "model": { + "$ref": "AAAAAAFcswO76bJsmb4=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 104, + "top": -120, + "width": 10, + "height": 10, + "autoResize": false + } + ], + "containerView": { + "$ref": "AAAAAAFbHInAVcvGkAM=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": true, + "containerExtending": false, + "left": 584, + "top": 152, + "width": 64, + "height": 45, + "autoResize": false, + "stereotypeDisplay": "label", + "showVisibility": true, + "showNamespace": false, + "showProperty": true, + "showType": true, + "nameCompartment": { + "$ref": "AAAAAAFcswO767Jv7cY=" + }, + "wordWrap": false, + "suppressAttributes": false, + "suppressOperations": false, + "suppressReceptions": true, + "showMultiplicity": true, + "showOperationSignature": true, + "attributeCompartment": { + "$ref": "AAAAAAFcswO77LJ0Um8=" + }, + "operationCompartment": { + "$ref": "AAAAAAFcswO77bJ1zqg=" + }, + "receptionCompartment": { + "$ref": "AAAAAAFcswO77bJ2ZoE=" + }, + "templateParameterCompartment": { + "$ref": "AAAAAAFcswO77bJ3Yfc=" + } + }, + { + "_type": "UMLDependencyView", + "_id": "AAAAAAFcswPht7KaXPM=", + "_parent": { + "$ref": "AAAAAAFbHImRMcuZ6y8=" + }, + "model": { + "$ref": "AAAAAAFcswPht7KYSAs=" + }, + "subViews": [ + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFcswPhuLKbI0g=", + "_parent": { + "$ref": "AAAAAAFcswPht7KaXPM=" + }, + "model": { + "$ref": "AAAAAAFcswPht7KYSAs=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 456, + "top": 232, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": 1.5707963267948966, + "distance": 15, + "hostEdge": { + "$ref": "AAAAAAFcswPht7KaXPM=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFcswPhuLKcUrE=", + "_parent": { + "$ref": "AAAAAAFcswPht7KaXPM=" + }, + "model": { + "$ref": "AAAAAAFcswPht7KYSAs=" + }, + "visible": null, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 460, + "top": 246, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": 1.5707963267948966, + "distance": 30, + "hostEdge": { + "$ref": "AAAAAAFcswPht7KaXPM=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFcswPhuLKdcZs=", + "_parent": { + "$ref": "AAAAAAFcswPht7KaXPM=" + }, + "model": { + "$ref": "AAAAAAFcswPht7KYSAs=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 447, + "top": 203, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": -1.5707963267948966, + "distance": 15, + "hostEdge": { + "$ref": "AAAAAAFcswPht7KaXPM=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "head": { + "$ref": "AAAAAAFbH1KdscySwQk=" + }, + "tail": { + "$ref": "AAAAAAFcswO767JuzTE=" + }, + "lineStyle": 1, + "points": "583:184;322:264", + "stereotypeDisplay": "label", + "showVisibility": true, + "showProperty": true, + "nameLabel": { + "$ref": "AAAAAAFcswPhuLKbI0g=" + }, + "stereotypeLabel": { + "$ref": "AAAAAAFcswPhuLKcUrE=" + }, + "propertyLabel": { + "$ref": "AAAAAAFcswPhuLKdcZs=" + } + }, + { + "_type": "UMLDependencyView", + "_id": "AAAAAAFcswPmlrKrC/8=", + "_parent": { + "$ref": "AAAAAAFbHImRMcuZ6y8=" + }, + "model": { + "$ref": "AAAAAAFcswPmlrKpfyc=" + }, + "subViews": [ + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFcswPmmLKswyg=", + "_parent": { + "$ref": "AAAAAAFcswPmlrKrC/8=" + }, + "model": { + "$ref": "AAAAAAFcswPmlrKpfyc=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 537, + "top": 270, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": 1.5707963267948966, + "distance": 15, + "hostEdge": { + "$ref": "AAAAAAFcswPmlrKrC/8=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFcswPmmLKtd10=", + "_parent": { + "$ref": "AAAAAAFcswPmlrKrC/8=" + }, + "model": { + "$ref": "AAAAAAFcswPmlrKpfyc=" + }, + "visible": null, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 548, + "top": 280, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": 1.5707963267948966, + "distance": 30, + "hostEdge": { + "$ref": "AAAAAAFcswPmlrKrC/8=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFcswPmmLKutEc=", + "_parent": { + "$ref": "AAAAAAFcswPmlrKrC/8=" + }, + "model": { + "$ref": "AAAAAAFcswPmlrKpfyc=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 516, + "top": 249, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": -1.5707963267948966, + "distance": 15, + "hostEdge": { + "$ref": "AAAAAAFcswPmlrKrC/8=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "head": { + "$ref": "AAAAAAFbH1K01c4swqY=" + }, + "tail": { + "$ref": "AAAAAAFcswO767JuzTE=" + }, + "lineStyle": 1, + "points": "593:197;462:335", + "stereotypeDisplay": "label", + "showVisibility": true, + "showProperty": true, + "nameLabel": { + "$ref": "AAAAAAFcswPmmLKswyg=" + }, + "stereotypeLabel": { + "$ref": "AAAAAAFcswPmmLKtd10=" + }, + "propertyLabel": { + "$ref": "AAAAAAFcswPmmLKutEc=" + } + }, + { + "_type": "UMLPackageView", + "_id": "AAAAAAFcswQsMiotLBc=", + "_parent": { + "$ref": "AAAAAAFbHImRMcuZ6y8=" + }, + "model": { + "$ref": "AAAAAAFbHGJipqEm58o=" + }, + "subViews": [ + { + "_type": "UMLNameCompartmentView", + "_id": "AAAAAAFcswQsMyoufrg=", + "_parent": { + "$ref": "AAAAAAFcswQsMiotLBc=" + }, + "model": { + "$ref": "AAAAAAFbHGJipqEm58o=" + }, + "subViews": [ + { + "_type": "LabelView", + "_id": "AAAAAAFcswQsMyovxio=", + "_parent": { + "$ref": "AAAAAAFcswQsMyoufrg=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#e2e2e2", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 684, + "top": -1352, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswQsMyowDWk=", + "_parent": { + "$ref": "AAAAAAFcswQsMyoufrg=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#e2e2e2", + "fontColor": "#000000", + "font": "Arial;13;1", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 697, + "top": 246, + "width": 191, + "height": 13, + "autoResize": false, + "underline": false, + "text": "core", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswQsMyoxlOg=", + "_parent": { + "$ref": "AAAAAAFcswQsMyoufrg=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#e2e2e2", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 684, + "top": -1352, + "width": 72, + "height": 13, + "autoResize": false, + "underline": false, + "text": "(from pose)", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswQsMyoy7m4=", + "_parent": { + "$ref": "AAAAAAFcswQsMyoufrg=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#e2e2e2", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 684, + "top": -1352, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 1, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#e2e2e2", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 692, + "top": 239, + "width": 201, + "height": 25, + "autoResize": false, + "stereotypeLabel": { + "$ref": "AAAAAAFcswQsMyovxio=" + }, + "nameLabel": { + "$ref": "AAAAAAFcswQsMyowDWk=" + }, + "namespaceLabel": { + "$ref": "AAAAAAFcswQsMyoxlOg=" + }, + "propertyLabel": { + "$ref": "AAAAAAFcswQsMyoy7m4=" + } + } + ], + "containedViews": [ + { + "$ref": "AAAAAAFcswXRobSeQTI=" + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#e2e2e2", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": true, + "containerExtending": false, + "left": 692, + "top": 224, + "width": 201, + "height": 160, + "autoResize": false, + "stereotypeDisplay": "label", + "showVisibility": true, + "showNamespace": false, + "showProperty": true, + "showType": true, + "nameCompartment": { + "$ref": "AAAAAAFcswQsMyoufrg=" + }, + "wordWrap": false + }, + { + "_type": "UMLClassView", + "_id": "AAAAAAFcswQsMyozWzc=", + "_parent": { + "$ref": "AAAAAAFbHImRMcuZ6y8=" + }, + "model": { + "$ref": "AAAAAAFbHGJ4XKFAf+Y=" + }, + "subViews": [ + { + "_type": "UMLNameCompartmentView", + "_id": "AAAAAAFcswQsMyo0nco=", + "_parent": { + "$ref": "AAAAAAFcswQsMyozWzc=" + }, + "model": { + "$ref": "AAAAAAFbHGJ4XKFAf+Y=" + }, + "subViews": [ + { + "_type": "LabelView", + "_id": "AAAAAAFcswQsMyo12jk=", + "_parent": { + "$ref": "AAAAAAFcswQsMyo0nco=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 420, + "top": -1304, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswQsMyo2Jk4=", + "_parent": { + "$ref": "AAAAAAFcswQsMyo0nco=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;1", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 709, + "top": 303, + "width": 61, + "height": 13, + "autoResize": false, + "underline": false, + "text": "array.hpp", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswQsNCo3wc0=", + "_parent": { + "$ref": "AAAAAAFcswQsMyo0nco=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 420, + "top": -1304, + "width": 72, + "height": 13, + "autoResize": false, + "underline": false, + "text": "(from core)", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswQsNCo4KUo=", + "_parent": { + "$ref": "AAAAAAFcswQsMyo0nco=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 420, + "top": -1304, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 1, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 704, + "top": 296, + "width": 71, + "height": 25, + "autoResize": false, + "stereotypeLabel": { + "$ref": "AAAAAAFcswQsMyo12jk=" + }, + "nameLabel": { + "$ref": "AAAAAAFcswQsMyo2Jk4=" + }, + "namespaceLabel": { + "$ref": "AAAAAAFcswQsNCo3wc0=" + }, + "propertyLabel": { + "$ref": "AAAAAAFcswQsNCo4KUo=" + } + }, + { + "_type": "UMLAttributeCompartmentView", + "_id": "AAAAAAFcswQsNCo59gQ=", + "_parent": { + "$ref": "AAAAAAFcswQsMyozWzc=" + }, + "model": { + "$ref": "AAAAAAFbHGJ4XKFAf+Y=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 704, + "top": 321, + "width": 71, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLOperationCompartmentView", + "_id": "AAAAAAFcswQsNCo62r0=", + "_parent": { + "$ref": "AAAAAAFcswQsMyozWzc=" + }, + "model": { + "$ref": "AAAAAAFbHGJ4XKFAf+Y=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 704, + "top": 331, + "width": 71, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLReceptionCompartmentView", + "_id": "AAAAAAFcswQsNCo7VEo=", + "_parent": { + "$ref": "AAAAAAFcswQsMyozWzc=" + }, + "model": { + "$ref": "AAAAAAFbHGJ4XKFAf+Y=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 264, + "top": -656, + "width": 10, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLTemplateParameterCompartmentView", + "_id": "AAAAAAFcswQsNCo8cwg=", + "_parent": { + "$ref": "AAAAAAFcswQsMyozWzc=" + }, + "model": { + "$ref": "AAAAAAFbHGJ4XKFAf+Y=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 264, + "top": -656, + "width": 10, + "height": 10, + "autoResize": false + } + ], + "containerView": { + "$ref": "AAAAAAFcswQsMiotLBc=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": true, + "containerExtending": false, + "left": 704, + "top": 296, + "width": 71, + "height": 45, + "autoResize": false, + "stereotypeDisplay": "label", + "showVisibility": true, + "showNamespace": false, + "showProperty": true, + "showType": true, + "nameCompartment": { + "$ref": "AAAAAAFcswQsMyo0nco=" + }, + "wordWrap": false, + "suppressAttributes": false, + "suppressOperations": false, + "suppressReceptions": true, + "showMultiplicity": true, + "showOperationSignature": true, + "attributeCompartment": { + "$ref": "AAAAAAFcswQsNCo59gQ=" + }, + "operationCompartment": { + "$ref": "AAAAAAFcswQsNCo62r0=" + }, + "receptionCompartment": { + "$ref": "AAAAAAFcswQsNCo7VEo=" + }, + "templateParameterCompartment": { + "$ref": "AAAAAAFcswQsNCo8cwg=" + } + }, + { + "_type": "UMLDependencyView", + "_id": "AAAAAAFcswRgfrSJFJE=", + "_parent": { + "$ref": "AAAAAAFbHImRMcuZ6y8=" + }, + "model": { + "$ref": "AAAAAAFcswRgfbSHUnE=" + }, + "subViews": [ + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFcswRgfrSKZRk=", + "_parent": { + "$ref": "AAAAAAFcswRgfrSJFJE=" + }, + "model": { + "$ref": "AAAAAAFcswRgfbSHUnE=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 688, + "top": 230, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": 1.5707963267948966, + "distance": 15, + "hostEdge": { + "$ref": "AAAAAAFcswRgfrSJFJE=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFcswRgfrSLYpo=", + "_parent": { + "$ref": "AAAAAAFcswRgfrSJFJE=" + }, + "model": { + "$ref": "AAAAAAFcswRgfbSHUnE=" + }, + "visible": null, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 699, + "top": 220, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": 1.5707963267948966, + "distance": 30, + "hostEdge": { + "$ref": "AAAAAAFcswRgfrSJFJE=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFcswRgfrSM3LQ=", + "_parent": { + "$ref": "AAAAAAFcswRgfrSJFJE=" + }, + "model": { + "$ref": "AAAAAAFcswRgfbSHUnE=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 665, + "top": 249, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": -1.5707963267948966, + "distance": 15, + "hostEdge": { + "$ref": "AAAAAAFcswRgfrSJFJE=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "head": { + "$ref": "AAAAAAFcswQsMyozWzc=" + }, + "tail": { + "$ref": "AAAAAAFcswO767JuzTE=" + }, + "lineStyle": 1, + "points": "635:197;719:295", + "stereotypeDisplay": "label", + "showVisibility": true, + "showProperty": true, + "nameLabel": { + "$ref": "AAAAAAFcswRgfrSKZRk=" + }, + "stereotypeLabel": { + "$ref": "AAAAAAFcswRgfrSLYpo=" + }, + "propertyLabel": { + "$ref": "AAAAAAFcswRgfrSM3LQ=" + } + }, + { + "_type": "UMLClassView", + "_id": "AAAAAAFcswXRobSeQTI=", + "_parent": { + "$ref": "AAAAAAFbHImRMcuZ6y8=" + }, + "model": { + "$ref": "AAAAAAFcswXRoLSckR0=" + }, + "subViews": [ + { + "_type": "UMLNameCompartmentView", + "_id": "AAAAAAFcswXRobSflPc=", + "_parent": { + "$ref": "AAAAAAFcswXRobSeQTI=" + }, + "model": { + "$ref": "AAAAAAFcswXRoLSckR0=" + }, + "subViews": [ + { + "_type": "LabelView", + "_id": "AAAAAAFcswXRorSg5C0=", + "_parent": { + "$ref": "AAAAAAFcswXRobSflPc=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -64, + "top": -24, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswXRorShg3Y=", + "_parent": { + "$ref": "AAAAAAFcswXRobSflPc=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;1", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 789, + "top": 303, + "width": 88, + "height": 13, + "autoResize": false, + "underline": false, + "text": "rectangle.hpp", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswXRorSiCCE=", + "_parent": { + "$ref": "AAAAAAFcswXRobSflPc=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -64, + "top": -24, + "width": 72, + "height": 13, + "autoResize": false, + "underline": false, + "text": "(from core)", + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "LabelView", + "_id": "AAAAAAFcswXRorSj40E=", + "_parent": { + "$ref": "AAAAAAFcswXRobSflPc=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -64, + "top": -24, + "width": 0, + "height": 13, + "autoResize": false, + "underline": false, + "horizontalAlignment": 1, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 784, + "top": 296, + "width": 98, + "height": 25, + "autoResize": false, + "stereotypeLabel": { + "$ref": "AAAAAAFcswXRorSg5C0=" + }, + "nameLabel": { + "$ref": "AAAAAAFcswXRorShg3Y=" + }, + "namespaceLabel": { + "$ref": "AAAAAAFcswXRorSiCCE=" + }, + "propertyLabel": { + "$ref": "AAAAAAFcswXRorSj40E=" + } + }, + { + "_type": "UMLAttributeCompartmentView", + "_id": "AAAAAAFcswXRorSkfOs=", + "_parent": { + "$ref": "AAAAAAFcswXRobSeQTI=" + }, + "model": { + "$ref": "AAAAAAFcswXRoLSckR0=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 784, + "top": 321, + "width": 98, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLOperationCompartmentView", + "_id": "AAAAAAFcswXRo7Sl4M0=", + "_parent": { + "$ref": "AAAAAAFcswXRobSeQTI=" + }, + "model": { + "$ref": "AAAAAAFcswXRoLSckR0=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 784, + "top": 331, + "width": 98, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLReceptionCompartmentView", + "_id": "AAAAAAFcswXRo7SmR9Q=", + "_parent": { + "$ref": "AAAAAAFcswXRobSeQTI=" + }, + "model": { + "$ref": "AAAAAAFcswXRoLSckR0=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -56, + "top": 0, + "width": 10, + "height": 10, + "autoResize": false + }, + { + "_type": "UMLTemplateParameterCompartmentView", + "_id": "AAAAAAFcswXRpLSn0qc=", + "_parent": { + "$ref": "AAAAAAFcswXRobSeQTI=" + }, + "model": { + "$ref": "AAAAAAFcswXRoLSckR0=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": -56, + "top": 0, + "width": 10, + "height": 10, + "autoResize": false + } + ], + "containerView": { + "$ref": "AAAAAAFcswQsMiotLBc=" + }, + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": true, + "containerExtending": false, + "left": 784, + "top": 296, + "width": 98, + "height": 45, + "autoResize": false, + "stereotypeDisplay": "label", + "showVisibility": true, + "showNamespace": false, + "showProperty": true, + "showType": true, + "nameCompartment": { + "$ref": "AAAAAAFcswXRobSflPc=" + }, + "wordWrap": false, + "suppressAttributes": false, + "suppressOperations": false, + "suppressReceptions": true, + "showMultiplicity": true, + "showOperationSignature": true, + "attributeCompartment": { + "$ref": "AAAAAAFcswXRorSkfOs=" + }, + "operationCompartment": { + "$ref": "AAAAAAFcswXRo7Sl4M0=" + }, + "receptionCompartment": { + "$ref": "AAAAAAFcswXRo7SmR9Q=" + }, + "templateParameterCompartment": { + "$ref": "AAAAAAFcswXRpLSn0qc=" + } + }, + { + "_type": "UMLDependencyView", + "_id": "AAAAAAFcswYOb7TLOOA=", + "_parent": { + "$ref": "AAAAAAFbHImRMcuZ6y8=" + }, + "model": { + "$ref": "AAAAAAFcswYObrTJy5s=" + }, + "subViews": [ + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFcswYOb7TMUQ4=", + "_parent": { + "$ref": "AAAAAAFcswYOb7TLOOA=" + }, + "model": { + "$ref": "AAAAAAFcswYObrTJy5s=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 730, + "top": 226, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": 1.5707963267948966, + "distance": 15, + "hostEdge": { + "$ref": "AAAAAAFcswYOb7TLOOA=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFcswYOcLTN/Ro=", + "_parent": { + "$ref": "AAAAAAFcswYOb7TLOOA=" + }, + "model": { + "$ref": "AAAAAAFcswYObrTJy5s=" + }, + "visible": null, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 738, + "top": 214, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": 1.5707963267948966, + "distance": 30, + "hostEdge": { + "$ref": "AAAAAAFcswYOb7TLOOA=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + }, + { + "_type": "EdgeLabelView", + "_id": "AAAAAAFcswYOcLTOwQQ=", + "_parent": { + "$ref": "AAAAAAFcswYOb7TLOOA=" + }, + "model": { + "$ref": "AAAAAAFcswYObrTJy5s=" + }, + "visible": false, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "left": 713, + "top": 251, + "width": 0, + "height": 13, + "autoResize": false, + "alpha": -1.5707963267948966, + "distance": 15, + "hostEdge": { + "$ref": "AAAAAAFcswYOb7TLOOA=" + }, + "edgePosition": 1, + "underline": false, + "horizontalAlignment": 2, + "verticalAlignment": 5, + "wordWrap": false + } + ], + "visible": true, + "enabled": true, + "lineColor": "#000000", + "fillColor": "#ffffff", + "fontColor": "#000000", + "font": "Arial;13;0", + "showShadow": true, + "containerChangeable": false, + "containerExtending": false, + "head": { + "$ref": "AAAAAAFcswXRobSeQTI=" + }, + "tail": { + "$ref": "AAAAAAFcswO767JuzTE=" + }, + "lineStyle": 1, + "points": "648:196;797:295", + "stereotypeDisplay": "label", + "showVisibility": true, + "showProperty": true, + "nameLabel": { + "$ref": "AAAAAAFcswYOb7TMUQ4=" + }, + "stereotypeLabel": { + "$ref": "AAAAAAFcswYOcLTN/Ro=" + }, + "propertyLabel": { + "$ref": "AAAAAAFcswYOcLTOwQQ=" + } } ] } diff --git a/doc/UML/1_0_0rc3/UML.pdf b/doc/UML/1_0_0rc3/UML.pdf index b643b206..318d53d2 100644 Binary files a/doc/UML/1_0_0rc3/UML.pdf and b/doc/UML/1_0_0rc3/UML.pdf differ diff --git a/doc/demo_overview.md b/doc/demo_overview.md index d2deadff..f21b503e 100644 --- a/doc/demo_overview.md +++ b/doc/demo_overview.md @@ -44,13 +44,13 @@ Each flag is divided into flag name, default value, and description. - DEFINE_int32(part_to_show, 0, "Part to show from the start."); - DEFINE_bool(disable_blending, false, "If blending is enabled, it will merge the results with the original frame. If disabled, it will only display the results."); 8. OpenPose Rendering Pose -- DEFINE_bool(no_render_pose, false, "If false, it will fill both `outputData` and `cvOutputData` with the original image + desired part to be shown. If true, it will leave them empty."); -- DEFINE_double(alpha_pose, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will hide it."); -- DEFINE_double(alpha_heatmap, 0.7, "Blending factor (range 0-1) between heatmap and original frame. 1 will only show the heatmap, 0 will only show the frame."); +- DEFINE_int32(render_pose, 1, "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 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)."); +- DEFINE_double(alpha_pose, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will hide it. Only valid for GPU rendering."); +- DEFINE_double(alpha_heatmap, 0.7, "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."); 9. OpenPose Rendering Face -- DEFINE_bool(no_render_face, false, "Analogous to `no_render_pose` but applied to the face keypoints and heat maps."); -- DEFINE_double(alpha_face, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will hide it."); -- DEFINE_double(alpha_heatmap_face, 0.7, "Blending factor (range 0-1) between heatmap and original frame. 1 will only show the heatmap, 0 will only show the frame."); +- DEFINE_int32(render_face, -1, "Analogous to `render_pose` but applied to the face. Extra option: -1 to use the same configuration that `render_pose` is using."); +- DEFINE_double(alpha_face, 0.6, "Analogous to `alpha_pose` but applied to face."); +- DEFINE_double(alpha_heatmap_face, 0.7, "Analogous to `alpha_heatmap` but applied to face."); 10. Display - DEFINE_bool(fullscreen, false, "Run in full-screen mode (press f during runtime to toggle)."); - DEFINE_bool(process_real_time, false, "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."); @@ -60,11 +60,11 @@ Each flag is divided into flag name, default value, and description. - DEFINE_string(write_images, "", "Directory to write rendered frames in `write_images_format` image format."); - DEFINE_string(write_images_format, "png", "File extension and format for `write_images`, e.g. png, jpg or bmp. Check the OpenCV function cv::imwrite for all compatible extensions."); - DEFINE_string(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."); -- DEFINE_string(write_keypoint, "", "Directory to write the people body pose keypoint data. Desired format on `write_keypoint_format`."); -- DEFINE_string(write_keypoint_format, "yml", "File extension and format for `write_keypoint`: json, xml, yaml and yml. Json not available for OpenCV < 3.0, use `write_keypoint_json` instead."); -- DEFINE_string(write_keypoint_json, "", "Directory to write people pose data with *.json format, compatible with any OpenCV version."); +- DEFINE_string(write_keypoint, "", "Directory to write the people pose keypoint data. Format with `write_keypoint_format`."); +- DEFINE_string(write_keypoint_format, "yml", "File extension and format for `write_keypoint`: json, xml, yaml & yml. Json not available for OpenCV < 3.0, use `write_keypoint_json` instead."); +- DEFINE_string(write_keypoint_json, "", "Directory to write people pose data in *.json format, compatible with any OpenCV version."); - DEFINE_string(write_coco_json, "", "Full file path to write people pose data with *.json COCO validation format."); -- DEFINE_string(write_heatmaps, "", "Directory to write heatmaps with *.png format. At least 1 `add_heatmaps_X` flag must be enabled."); +- DEFINE_string(write_heatmaps, "", "Directory to write heatmaps in *.png format. At least 1 `add_heatmaps_X` flag must be enabled."); - DEFINE_string(write_heatmaps_format, "png", "File extension and format for `write_heatmaps`, analogous to `write_images_format`. Recommended `png` or any compressed and lossless format."); ## Multiple Scales diff --git a/doc/media/keypoints_hand.odt b/doc/media/keypoints_hand.odt new file mode 100644 index 00000000..362910e4 Binary files /dev/null and b/doc/media/keypoints_hand.odt differ diff --git a/doc/media/keypoints_hand.png b/doc/media/keypoints_hand.png new file mode 100644 index 00000000..3fb38a8d Binary files /dev/null and b/doc/media/keypoints_hand.png differ diff --git a/doc/release_notes.md b/doc/release_notes.md index e474c3b0..f9437051 100644 --- a/doc/release_notes.md +++ b/doc/release_notes.md @@ -15,7 +15,7 @@ OpenPose Library - Release Notes 1. Main improvements: 1. Rendering max resolution from 720p to >32k images. 2. Highly improved documentation. -2. Functions or paremeters renamed: +2. Functions or parameters renamed: 1. Demo renamed from rtpose to openpose. 3. Main bugs fixed: 1. Demo uses exec instead of start, so it works with more OpenCV custom compiled versions. @@ -25,14 +25,14 @@ OpenPose Library - Release Notes ## OpenPose 1.0.0rc3 1. Main improvements: 1. Added face keypoint detection. - 2. Added Windows 10 compatibily. + 2. Added Windows 10 compatibility. 3. Auto-detection of the number of GPUs. 4. MPI visualization more similar to COCO one. 5. Rendering max resolution from 720p to >32k images. 6. GUI info adder working when the worker TDatum has more than 1 Datum. - 7. It prints out the error description before throwing the exception (so that it is writen on the Windows cmd). + 7. It prints out the error description before throwing the exception (so that it is written on the Windows cmd). 8. Highly improved documentation. -2. Functions or paremeters renamed: +2. Functions or parameters renamed: 1. Flag `write_pose` renamed as `write_keypoint` and it also applies to face and/or hands. 2. Flag `write_pose_json` renamed as `write_keypoint_json` and it also applies to face and/or hands. 3. Flag `write_pose_format` renamed as `write_keypoint_format` and it also applies to face and/or hands. @@ -46,11 +46,15 @@ OpenPose Library - Release Notes ## Current version (future OpenPose 1.0.0rc4) 1. Main improvements: - 1. Check() functions give more feedback. - 2. Improved documentation. -2. Functions or paremeters renamed: - 1. `Datum::scaleRatios` to save the relative scale ratio when multi-scale. + 1. Increased accuracy on multi-scale (added `Datum::scaleRatios` to save the relative scale ratio when multi-scale). + 2. Increased speed ~3-5% by adding CPU rendering and setting it as default rendering. + 3. Check() functions give more feedback. + 4. WCocoJsonSaver finished and removed its 3599-image limit. + 5. Improved documentation. +2. Functions or parameters renamed: + 1. Render flags renamed in the demo in order to incorporate the CPU/GPU rendering. 3. Main bugs fixed: 1. Fixed bug in Array::getConstCvMat() if mVolume=0, now returning empty cv::Mat. 2. Fixed bug: `--process_real_time` threw error with webcam. - 3. Fixed bug: Face not working with output resolution different to input. + 3. Fixed bug: Face not working when input and output resolutions are different. + 4. Fixed some bugs that prevented debug version to run. diff --git a/examples/openpose/openpose.cpp b/examples/openpose/openpose.cpp index b180e74e..f1f3646d 100755 --- a/examples/openpose/openpose.cpp +++ b/examples/openpose/openpose.cpp @@ -16,12 +16,12 @@ // This file should only be used for the user to take specific examples. // C++ std library dependencies -#include // std::atomic +#include #include // `std::chrono::` functions and classes, e.g. std::chrono::milliseconds #include // sscanf -#include // std::string +#include #include // std::this_thread -#include // std::vector +#include // Other 3rdpary depencencies #include // DEFINE_bool, DEFINE_int32, DEFINE_int64, DEFINE_uint64, DEFINE_double, DEFINE_string #include // google::InitGoogleLogging @@ -45,77 +45,98 @@ // Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose // executable. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`. // Debugging -DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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."); +DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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."); // Producer DEFINE_int32(camera, 0, "The camera index for cv::VideoCapture. Integer in the range [0, 9]."); DEFINE_string(camera_resolution, "1280x720", "Size of the camera frames to ask for."); -DEFINE_string(video, "", "Use a video file instead of the camera. Use `examples/media/video.avi` for our default example video."); -DEFINE_string(image_dir, "", "Process a directory of images. Use `examples/media/` for our default example folder with 20 images."); +DEFINE_string(video, "", "Use a video file instead of the camera. Use `examples/media/video.avi` for our default" + " example video."); +DEFINE_string(image_dir, "", "Process a directory of images. Use `examples/media/` for our default example folder with 20" + " images."); DEFINE_uint64(frame_first, 0, "Start on desired frame number. Indexes are 0-based, i.e. the first frame has index 0."); -DEFINE_uint64(frame_last, -1, "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)."); +DEFINE_uint64(frame_last, -1, "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)."); DEFINE_bool(frame_flip, false, "Flip/mirror each frame (e.g. for real time webcam demonstrations)."); DEFINE_int32(frame_rotate, 0, "Rotate each frame, 4 possible values: 0, 90, 180, 270."); DEFINE_bool(frames_repeat, false, "Repeat frames when finished."); // OpenPose DEFINE_string(model_folder, "models/", "Folder where the pose models (COCO and MPI) are located."); -DEFINE_string(resolution, "1280x720", "The image resolution (display and output). Use \"-1x-1\" to force the program to use the default images resolution."); -DEFINE_int32(num_gpu, -1, "The number of GPU devices to use. If negative, it will use all the available GPUs in your machine."); +DEFINE_string(resolution, "1280x720", "The image resolution (display and output). Use \"-1x-1\" to force the program to use the" + " default images resolution."); +DEFINE_int32(num_gpu, -1, "The number of GPU devices to use. If negative, it will use all the available GPUs in your" + " machine."); DEFINE_int32(num_gpu_start, 0, "GPU device start number."); -DEFINE_int32(keypoint_scale, 0, "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_keypoint` & `write_keypoint_json` 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], and 4 for range [-1,1]. Non related with `num_scales` and `scale_gap`."); +DEFINE_int32(keypoint_scale, 0, "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_keypoint` & `write_keypoint_json` 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], and 4 for range [-1,1]. Non related" + " with `num_scales` and `scale_gap`."); // OpenPose Body Pose DEFINE_string(model_pose, "COCO", "Model to be used (e.g. COCO, MPI, MPI_4_layers)."); -DEFINE_string(net_resolution, "656x368", "Multiples of 16. If it is increased, the accuracy usually increases. If it is decreased, the speed increases."); +DEFINE_string(net_resolution, "656x368", "Multiples of 16. If it is increased, the accuracy usually increases. If it is decreased," + " the speed increases."); DEFINE_int32(num_scales, 1, "Number of scales to average."); -DEFINE_double(scale_gap, 0.3, "Scale gap between scales. No effect unless num_scales>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."); -DEFINE_bool(heatmaps_add_parts, false, "If true, it will add the body part heatmaps to the final op::Datum::poseHeatMaps array (program speed will decrease). Not" - " required for our library, enable it only if you intend to process this information later. 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 `include/openpose/pose/poseParameters.hpp`."); -DEFINE_bool(heatmaps_add_bkg, false, "Same functionality as `add_heatmaps_parts`, but adding the heatmap corresponding to background."); +DEFINE_double(scale_gap, 0.3, "Scale gap between scales. No effect unless num_scales>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."); +DEFINE_bool(heatmaps_add_parts, false, "If true, it will add the body part heatmaps to the final op::Datum::poseHeatMaps array" + " (program speed will decrease). Not required for our library, enable it only if you intend" + " to process this information later. 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 `include/openpose/pose/poseParameters.hpp`."); +DEFINE_bool(heatmaps_add_bkg, false, "Same functionality as `add_heatmaps_parts`, but adding the heatmap corresponding to" + " background."); DEFINE_bool(heatmaps_add_PAFs, false, "Same functionality as `add_heatmaps_parts`, but adding the PAFs."); // OpenPose Face -DEFINE_bool(face, false, "Enables face keypoint detection. It will share some parameters from the body pose, e.g. `model_folder`."); -DEFINE_string(face_net_resolution, "368x368", "Multiples of 16. 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."); +DEFINE_bool(face, false, "Enables face keypoint detection. It will share some parameters from the body pose, e.g." + " `model_folder`."); +DEFINE_string(face_net_resolution, "368x368", "Multiples of 16. 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."); // OpenPose Hand // OpenPose Rendering DEFINE_int32(part_to_show, 0, "Part to show from the start."); -DEFINE_bool(disable_blending, false, "If blending is enabled, it will merge the results with the original frame. If disabled, it will only display the results."); +DEFINE_bool(disable_blending, false, "If blending is enabled, it will merge the results with the original frame. If disabled, it" + " will only display the results."); // OpenPose Rendering Pose -DEFINE_bool(no_render_pose, false, "If false, it will fill both `outputData` and `cvOutputData` with the original image + desired part to be shown." - " If true, it will leave them empty."); -DEFINE_double(alpha_pose, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will hide it."); -DEFINE_double(alpha_heatmap, 0.7, "Blending factor (range 0-1) between heatmap and original frame. 1 will only show the heatmap, 0 will only show the frame."); +DEFINE_int32(render_pose, 1, "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 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)."); +DEFINE_double(alpha_pose, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will" + " hide it. Only valid for GPU rendering."); +DEFINE_double(alpha_heatmap, 0.7, "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."); // OpenPose Rendering Face -DEFINE_bool(no_render_face, false, "Analogous to `no_render_pose` but applied to the face keypoints and heat maps."); -DEFINE_double(alpha_face, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will hide it."); -DEFINE_double(alpha_heatmap_face, 0.7, "Blending factor (range 0-1) between heatmap and original frame. 1 will only show the heatmap, 0 will only show the frame."); +DEFINE_int32(render_face, -1, "Analogous to `render_pose` but applied to the face. Extra option: -1 to use the same" + " configuration that `render_pose` is using."); +DEFINE_double(alpha_face, 0.6, "Analogous to `alpha_pose` but applied to face."); +DEFINE_double(alpha_heatmap_face, 0.7, "Analogous to `alpha_heatmap` but applied to face."); // Display DEFINE_bool(fullscreen, false, "Run in full-screen mode (press f during runtime to toggle)."); -DEFINE_bool(process_real_time, false, "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."); -DEFINE_bool(no_gui_verbose, false, "Do not write text on output images on GUI (e.g. number of current frame and people). It does not affect the pose rendering."); +DEFINE_bool(process_real_time, false, "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."); +DEFINE_bool(no_gui_verbose, false, "Do not write text on output images on GUI (e.g. number of current frame and people). It" + " does not affect the pose rendering."); DEFINE_bool(no_display, false, "Do not open a display window."); // Result Saving DEFINE_string(write_images, "", "Directory to write rendered frames in `write_images_format` image format."); -DEFINE_string(write_images_format, "png", "File extension and format for `write_images`, e.g. png, jpg or bmp. Check the OpenCV function cv::imwrite" - " for all compatible extensions."); -DEFINE_string(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."); -DEFINE_string(write_keypoint, "", "Directory to write the people body pose keypoint data. Desired format on `write_keypoint_format`."); -DEFINE_string(write_keypoint_format, "yml", "File extension and format for `write_keypoint`: json, xml, yaml and yml. Json not available for OpenCV < 3.0," - " use `write_keypoint_json` instead."); -DEFINE_string(write_keypoint_json, "", "Directory to write people pose data with *.json format, compatible with any OpenCV version."); +DEFINE_string(write_images_format, "png", "File extension and format for `write_images`, e.g. png, jpg or bmp. Check the OpenCV" + " function cv::imwrite for all compatible extensions."); +DEFINE_string(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."); +DEFINE_string(write_keypoint, "", "Directory to write the people pose keypoint data. Format with `write_keypoint_format`."); +DEFINE_string(write_keypoint_format, "yml", "File extension and format for `write_keypoint`: json, xml, yaml & yml. Json not available" + " for OpenCV < 3.0, use `write_keypoint_json` instead."); +DEFINE_string(write_keypoint_json, "", "Directory to write people pose data in *.json format, compatible with any OpenCV version."); DEFINE_string(write_coco_json, "", "Full file path to write people pose data with *.json COCO validation format."); -DEFINE_string(write_heatmaps, "", "Directory to write heatmaps with *.png format. At least 1 `add_heatmaps_X` flag must be enabled."); -DEFINE_string(write_heatmaps_format, "png", "File extension and format for `write_heatmaps`, analogous to `write_images_format`. Recommended `png` or any compressed and" - " lossless format."); +DEFINE_string(write_heatmaps, "", "Directory to write heatmaps in *.png format. At least 1 `add_heatmaps_X` flag must be" + " enabled."); +DEFINE_string(write_heatmaps_format, "png", "File extension and format for `write_heatmaps`, analogous to `write_images_format`." + " Recommended `png` or any compressed and lossless format."); op::PoseModel gflagToPoseModel(const std::string& poseModeString) { @@ -148,7 +169,8 @@ op::ScaleMode gflagToScaleMode(const int keypointScale) return op::ScaleMode::PlusMinusOne; else { - const std::string message = "String does not correspond to any scale mode: (0, 1, 2, 3, 4) for (InputResolution, NetOutputResolution, OutputResolution, ZeroToOne, PlusMinusOne)."; + const std::string message = "String does not correspond to any scale mode: (0, 1, 2, 3, 4) for (InputResolution," + " NetOutputResolution, OutputResolution, ZeroToOne, PlusMinusOne)."; op::error(message, __LINE__, __FUNCTION__, __FILE__); return op::ScaleMode::InputResolution; } @@ -175,7 +197,8 @@ op::ProducerType gflagsToProducerType(const std::string& imageDirectory, const s return op::ProducerType::Webcam; } -std::shared_ptr gflagsToProducer(const std::string& imageDirectory, const std::string& videoPath, const int webcamIndex, const op::Point webcamResolution) +std::shared_ptr gflagsToProducer(const std::string& imageDirectory, const std::string& videoPath, const int webcamIndex, + const op::Point webcamResolution) { op::log("", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__); const auto type = gflagsToProducerType(imageDirectory, videoPath, webcamIndex); @@ -193,39 +216,60 @@ std::shared_ptr gflagsToProducer(const std::string& imageDirectory } } -std::vector gflagToHeatMaps(const bool heatmaps_add_parts, const bool heatmaps_add_bkg, const bool heatmaps_add_PAFs) +std::vector gflagToHeatMaps(const bool heatMapsAddParts, const bool heatMapsAddBkg, const bool heatMapsAddPAFs) { - std::vector heatMapTypes; - if (heatmaps_add_parts) + if (heatMapsAddParts) heatMapTypes.emplace_back(op::HeatMapType::Parts); - if (heatmaps_add_bkg) + if (heatMapsAddBkg) heatMapTypes.emplace_back(op::HeatMapType::Background); - if (heatmaps_add_PAFs) + if (heatMapsAddPAFs) heatMapTypes.emplace_back(op::HeatMapType::PAFs); return heatMapTypes; } +op::RenderMode gflagToRenderMode(const int renderFlag, const int renderPoseFlag = -2) +{ + if (renderFlag == -1 && renderPoseFlag != -2) + return gflagToRenderMode(renderPoseFlag, -2); + else if (renderFlag == 0) + return op::RenderMode::None; + else if (renderFlag == 1) + return op::RenderMode::Cpu; + else if (renderFlag == 2) + return op::RenderMode::Gpu; + else + { + op::error("Undefined RenderMode selected.", __LINE__, __FUNCTION__, __FILE__); + return op::RenderMode::None; + } +} + // Google flags into program variables -std::tuple, op::Point, op::Point, op::Point, std::shared_ptr, op::PoseModel, op::ScaleMode, std::vector> gflagsToOpParameters() +std::tuple, op::Point, op::Point, op::Point, std::shared_ptr, op::PoseModel, + op::ScaleMode, std::vector> gflagsToOpParameters() { op::log("", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__); // cameraFrameSize op::Point cameraFrameSize; auto nRead = sscanf(FLAGS_camera_resolution.c_str(), "%dx%d", &cameraFrameSize.x, &cameraFrameSize.y); - op::checkE(nRead, 2, "Error, camera resolution format (" + FLAGS_camera_resolution + ") invalid, should be e.g., 1280x720", __LINE__, __FUNCTION__, __FILE__); + op::checkE(nRead, 2, "Error, camera resolution format (" + FLAGS_camera_resolution + ") invalid, should be e.g., 1280x720", + __LINE__, __FUNCTION__, __FILE__); // outputSize op::Point outputSize; nRead = sscanf(FLAGS_resolution.c_str(), "%dx%d", &outputSize.x, &outputSize.y); - op::checkE(nRead, 2, "Error, resolution format (" + FLAGS_resolution + ") invalid, should be e.g., 960x540 ", __LINE__, __FUNCTION__, __FILE__); + op::checkE(nRead, 2, "Error, resolution format (" + FLAGS_resolution + ") invalid, should be e.g., 960x540 ", + __LINE__, __FUNCTION__, __FILE__); // netInputSize op::Point netInputSize; nRead = sscanf(FLAGS_net_resolution.c_str(), "%dx%d", &netInputSize.x, &netInputSize.y); - op::checkE(nRead, 2, "Error, net resolution format (" + FLAGS_net_resolution + ") invalid, should be e.g., 656x368 (multiples of 16)", __LINE__, __FUNCTION__, __FILE__); + op::checkE(nRead, 2, "Error, net resolution format (" + FLAGS_net_resolution + ") invalid, should be e.g., 656x368 (multiples of 16)", + __LINE__, __FUNCTION__, __FILE__); // faceNetInputSize op::Point faceNetInputSize; nRead = sscanf(FLAGS_face_net_resolution.c_str(), "%dx%d", &faceNetInputSize.x, &faceNetInputSize.y); - op::checkE(nRead, 2, "Error, face net resolution format (" + FLAGS_face_net_resolution + ") invalid, should be e.g., 368x368 (multiples of 16)", __LINE__, __FUNCTION__, __FILE__); + op::checkE(nRead, 2, "Error, face net resolution format (" + FLAGS_face_net_resolution + + ") invalid, should be e.g., 368x368 (multiples of 16)", __LINE__, __FUNCTION__, __FILE__); // producerType const auto producerSharedPtr = gflagsToProducer(FLAGS_image_dir, FLAGS_video, FLAGS_camera, cameraFrameSize); // poseModel @@ -257,25 +301,29 @@ int opRealTimePoseDemo() op::PoseModel poseModel; op::ScaleMode keypointScale; std::vector heatMapTypes; - std::tie(cameraFrameSize, outputSize, netInputSize, faceNetInputSize, producerSharedPtr, poseModel, keypointScale, heatMapTypes) = gflagsToOpParameters(); + std::tie(cameraFrameSize, outputSize, netInputSize, faceNetInputSize, producerSharedPtr, poseModel, keypointScale, + heatMapTypes) = gflagsToOpParameters(); // OpenPose wrapper op::log("Configuring OpenPose wrapper.", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__); op::Wrapper> opWrapper; // Pose configuration (use WrapperStructPose{} for default and recommended configuration) - const op::WrapperStructPose wrapperStructPose{netInputSize, outputSize, keypointScale, FLAGS_num_gpu, FLAGS_num_gpu_start, FLAGS_num_scales, (float)FLAGS_scale_gap, - !FLAGS_no_render_pose, poseModel, !FLAGS_disable_blending, (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, + const op::WrapperStructPose wrapperStructPose{netInputSize, outputSize, keypointScale, FLAGS_num_gpu, FLAGS_num_gpu_start, + FLAGS_num_scales, (float)FLAGS_scale_gap, gflagToRenderMode(FLAGS_render_pose), poseModel, + !FLAGS_disable_blending, (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, FLAGS_model_folder, heatMapTypes, op::ScaleMode::UnsignedChar}; - // (Experimental, function and class names might change in next versions) Face configuration (use op::WrapperStructFace{} to disable it) - const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, !FLAGS_no_render_face, (float)FLAGS_alpha_face, (float)FLAGS_alpha_heatmap_face}; - // (Experimental, function and class names might change in next versions) Hand configuration (use op::WrapperStructFace{} to disable it) + // Face configuration (use op::WrapperStructFace{} to disable it) + const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, gflagToRenderMode(FLAGS_render_face, FLAGS_render_pose), + (float)FLAGS_alpha_face, (float)FLAGS_alpha_heatmap_face}; + // Hand configuration (use op::WrapperStructHand{} to disable it) const op::experimental::WrapperStructHand wrapperStructHand{false}; // Producer (use default to disable any input) - const op::WrapperStructInput wrapperStructInput{producerSharedPtr, FLAGS_frame_first, FLAGS_frame_last, FLAGS_process_real_time, FLAGS_frame_flip, - FLAGS_frame_rotate, FLAGS_frames_repeat}; + const op::WrapperStructInput wrapperStructInput{producerSharedPtr, FLAGS_frame_first, FLAGS_frame_last, FLAGS_process_real_time, + FLAGS_frame_flip, FLAGS_frame_rotate, FLAGS_frames_repeat}; // Consumer (comment or use default argument to disable any output) - const op::WrapperStructOutput wrapperStructOutput{!FLAGS_no_display, !FLAGS_no_gui_verbose, FLAGS_fullscreen, FLAGS_write_keypoint, op::stringToDataFormat(FLAGS_write_keypoint_format), - FLAGS_write_keypoint_json, FLAGS_write_coco_json, FLAGS_write_images, FLAGS_write_images_format, FLAGS_write_video, + const op::WrapperStructOutput wrapperStructOutput{!FLAGS_no_display, !FLAGS_no_gui_verbose, FLAGS_fullscreen, FLAGS_write_keypoint, + op::stringToDataFormat(FLAGS_write_keypoint_format), FLAGS_write_keypoint_json, + FLAGS_write_coco_json, FLAGS_write_images, FLAGS_write_images_format, FLAGS_write_video, FLAGS_write_heatmaps, FLAGS_write_heatmaps_format}; // Configure wrapper opWrapper.configure(wrapperStructPose, wrapperStructFace, wrapperStructHand, wrapperStructInput, wrapperStructOutput); @@ -310,7 +358,8 @@ int opRealTimePoseDemo() // opWrapper.stop(); // Measuring total time - const auto totalTimeSec = (double)std::chrono::duration_cast(std::chrono::high_resolution_clock::now()-timerBegin).count() * 1e-9; + const auto now = std::chrono::high_resolution_clock::now(); + const auto totalTimeSec = (double)std::chrono::duration_cast(now-timerBegin).count() * 1e-9; const auto message = "Real-time pose estimation demo successfully finished. Total time: " + std::to_string(totalTimeSec) + " seconds."; op::log(message, op::Priority::Max); diff --git a/examples/tutorial_pose/1_extract_from_image.cpp b/examples/tutorial_pose/1_extract_from_image.cpp index 1018bef7..8bbffe06 100644 --- a/examples/tutorial_pose/1_extract_from_image.cpp +++ b/examples/tutorial_pose/1_extract_from_image.cpp @@ -22,21 +22,26 @@ // Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose // executable. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`. // Debugging -DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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."); +DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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."); // Producer DEFINE_string(image_path, "examples/media/COCO_val2014_000000000192.jpg", "Process the desired image."); // OpenPose DEFINE_string(model_pose, "COCO", "Model to be used (e.g. COCO, MPI, MPI_4_layers)."); DEFINE_string(model_folder, "models/", "Folder path (absolute or relative) where the models (pose, face, ...) are located."); -DEFINE_string(net_resolution, "656x368", "Multiples of 16. If it is increased, the accuracy usually increases. If it is decreased, the speed increases."); -DEFINE_string(resolution, "1280x720", "The image resolution (display). Use \"-1x-1\" to force the program to use the default images resolution."); +DEFINE_string(net_resolution, "656x368", "Multiples of 16. If it is increased, the accuracy usually increases. If it is decreased," + " the speed increases."); +DEFINE_string(resolution, "1280x720", "The image resolution (display and output). Use \"-1x-1\" to force the program to use the" + " default images resolution."); DEFINE_int32(num_gpu_start, 0, "GPU device start number."); -DEFINE_double(scale_gap, 0.3, "Scale gap between scales. No effect unless num_scales>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."); +DEFINE_double(scale_gap, 0.3, "Scale gap between scales. No effect unless num_scales>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."); DEFINE_int32(num_scales, 1, "Number of scales to average."); // OpenPose Rendering -DEFINE_double(alpha_pose, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will hide it."); +DEFINE_double(alpha_pose, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will" + " hide it. Only valid for GPU rendering."); op::PoseModel gflagToPoseModel(const std::string& poseModeString) { @@ -61,11 +66,13 @@ std::tuple, op::Point, op::Point, op::PoseModel> gflags // outputSize op::Point outputSize; auto nRead = sscanf(FLAGS_resolution.c_str(), "%dx%d", &outputSize.x, &outputSize.y); - op::checkE(nRead, 2, "Error, resolution format (" + FLAGS_resolution + ") invalid, should be e.g., 960x540 ", __LINE__, __FUNCTION__, __FILE__); + op::checkE(nRead, 2, "Error, resolution format (" + FLAGS_resolution + ") invalid, should be e.g., 960x540 ", + __LINE__, __FUNCTION__, __FILE__); // netInputSize op::Point netInputSize; nRead = sscanf(FLAGS_net_resolution.c_str(), "%dx%d", &netInputSize.x, &netInputSize.y); - op::checkE(nRead, 2, "Error, net resolution format (" + FLAGS_net_resolution + ") invalid, should be e.g., 656x368 (multiples of 16)", __LINE__, __FUNCTION__, __FILE__); + op::checkE(nRead, 2, "Error, net resolution format (" + FLAGS_net_resolution + ") invalid, should be e.g., 656x368 (multiples of 16)", + __LINE__, __FUNCTION__, __FILE__); // netOutputSize const auto netOutputSize = netInputSize; // poseModel diff --git a/examples/tutorial_pose/2_extract_pose_or_heatmat_from_image.cpp b/examples/tutorial_pose/2_extract_pose_or_heatmat_from_image.cpp index 4f55a072..b6867875 100644 --- a/examples/tutorial_pose/2_extract_pose_or_heatmat_from_image.cpp +++ b/examples/tutorial_pose/2_extract_pose_or_heatmat_from_image.cpp @@ -22,23 +22,29 @@ // Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose // executable. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`. // Debugging -DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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."); +DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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."); // Producer DEFINE_string(image_path, "examples/media/COCO_val2014_000000000192.jpg", "Process the desired image."); // OpenPose DEFINE_string(model_pose, "COCO", "Model to be used (e.g. COCO, MPI, MPI_4_layers)."); DEFINE_string(model_folder, "models/", "Folder path (absolute or relative) where the models (pose, face, ...) are located."); -DEFINE_string(net_resolution, "656x368", "Multiples of 16. If it is increased, the accuracy usually increases. If it is decreased, the speed increases."); -DEFINE_string(resolution, "1280x720", "The image resolution (display). Use \"-1x-1\" to force the program to use the default images resolution."); +DEFINE_string(net_resolution, "656x368", "Multiples of 16. If it is increased, the accuracy usually increases. If it is decreased," + " the speed increases."); +DEFINE_string(resolution, "1280x720", "The image resolution (display and output). Use \"-1x-1\" to force the program to use the" + " default images resolution."); DEFINE_int32(num_gpu_start, 0, "GPU device start number."); -DEFINE_double(scale_gap, 0.3, "Scale gap between scales. No effect unless num_scales>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."); +DEFINE_double(scale_gap, 0.3, "Scale gap between scales. No effect unless num_scales>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."); DEFINE_int32(num_scales, 1, "Number of scales to average."); // OpenPose Rendering DEFINE_int32(part_to_show, 19, "Part to show from the start."); -DEFINE_double(alpha_pose, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will hide it."); -DEFINE_double(alpha_heatmap, 0.7, "Blending factor (range 0-1) between heatmap and original frame. 1 will only show the heatmap, 0 will only show the frame."); +DEFINE_double(alpha_pose, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will" + " hide it. Only valid for GPU rendering."); +DEFINE_double(alpha_heatmap, 0.7, "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."); op::PoseModel gflagToPoseModel(const std::string& poseModeString) { @@ -63,11 +69,13 @@ std::tuple, op::Point, op::Point, op::PoseModel> gflags // outputSize op::Point outputSize; auto nRead = sscanf(FLAGS_resolution.c_str(), "%dx%d", &outputSize.x, &outputSize.y); - op::checkE(nRead, 2, "Error, resolution format (" + FLAGS_resolution + ") invalid, should be e.g., 960x540 ", __LINE__, __FUNCTION__, __FILE__); + op::checkE(nRead, 2, "Error, resolution format (" + FLAGS_resolution + ") invalid, should be e.g., 960x540 ", + __LINE__, __FUNCTION__, __FILE__); // netInputSize op::Point netInputSize; nRead = sscanf(FLAGS_net_resolution.c_str(), "%dx%d", &netInputSize.x, &netInputSize.y); - op::checkE(nRead, 2, "Error, net resolution format (" + FLAGS_net_resolution + ") invalid, should be e.g., 656x368 (multiples of 16)", __LINE__, __FUNCTION__, __FILE__); + op::checkE(nRead, 2, "Error, net resolution format (" + FLAGS_net_resolution + ") invalid, should be e.g., 656x368 (multiples of 16)", + __LINE__, __FUNCTION__, __FILE__); // netOutputSize const auto netOutputSize = netInputSize; // poseModel @@ -100,8 +108,9 @@ int openPoseTutorialPose2() // Step 3 - Initialize all required classes op::CvMatToOpInput cvMatToOpInput{netInputSize, FLAGS_num_scales, (float)FLAGS_scale_gap}; op::CvMatToOpOutput cvMatToOpOutput{outputSize}; - std::shared_ptr poseExtractorPtr = std::make_shared(netInputSize, netOutputSize, outputSize, FLAGS_num_scales, - poseModel, FLAGS_model_folder, FLAGS_num_gpu_start); + std::shared_ptr poseExtractorPtr = std::make_shared(netInputSize, netOutputSize, outputSize, + FLAGS_num_scales, poseModel, + FLAGS_model_folder, FLAGS_num_gpu_start); op::PoseRenderer poseRenderer{netOutputSize, outputSize, poseModel, poseExtractorPtr, (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap}; poseRenderer.setElementToRender(FLAGS_part_to_show); op::OpOutputToCvMat opOutputToCvMat{outputSize}; diff --git a/examples/tutorial_thread/1_openpose_read_and_display.cpp b/examples/tutorial_thread/1_openpose_read_and_display.cpp index 11437cf3..76907cc9 100644 --- a/examples/tutorial_thread/1_openpose_read_and_display.cpp +++ b/examples/tutorial_thread/1_openpose_read_and_display.cpp @@ -21,19 +21,23 @@ // Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose // executable. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`. // Debugging -DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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."); +DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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."); // Producer DEFINE_int32(camera, 0, "The camera index for cv::VideoCapture. Integer in the range [0, 9]."); DEFINE_string(camera_resolution, "1280x720", "Size of the camera frames to ask for."); -DEFINE_string(video, "", "Use a video file instead of the camera. Use `examples/media/video.avi` for our default example video."); -DEFINE_string(image_dir, "", "Process a directory of images. Use `examples/media/` for our default example folder with 20 images."); +DEFINE_string(video, "", "Use a video file instead of the camera. Use `examples/media/video.avi` for our default" + " example video."); +DEFINE_string(image_dir, "", "Process a directory of images. Use `examples/media/` for our default example folder with 20" + " images."); // OpenPose -DEFINE_string(resolution, "1280x720", "The image resolution (display). Use \"-1x-1\" to force the program to use the default images resolution."); +DEFINE_string(resolution, "1280x720", "The image resolution (display and output). Use \"-1x-1\" to force the program to use the" + " default images resolution."); // Consumer DEFINE_bool(fullscreen, false, "Run in full-screen mode (press f during runtime to toggle)."); -DEFINE_bool(process_real_time, false, "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."); +DEFINE_bool(process_real_time, false, "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."); // Determine type of frame source op::ProducerType gflagsToProducerType(const std::string& imageDirectory, const std::string& videoPath, const int webcamIndex) @@ -56,7 +60,8 @@ op::ProducerType gflagsToProducerType(const std::string& imageDirectory, const s return op::ProducerType::Webcam; } -std::shared_ptr gflagsToProducer(const std::string& imageDirectory, const std::string& videoPath, const int webcamIndex, const op::Point webcamResolution) +std::shared_ptr gflagsToProducer(const std::string& imageDirectory, const std::string& videoPath, const int webcamIndex, + const op::Point webcamResolution) { op::log("", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__); const auto type = gflagsToProducerType(imageDirectory, videoPath, webcamIndex); @@ -81,11 +86,13 @@ std::tuple, op::Point, std::shared_ptr> gflags // cameraFrameSize op::Point cameraFrameSize; auto nRead = sscanf(FLAGS_camera_resolution.c_str(), "%dx%d", &cameraFrameSize.x, &cameraFrameSize.y); - op::checkE(nRead, 2, "Error, camera resolution format (" + FLAGS_camera_resolution + ") invalid, should be e.g., 1280x720", __LINE__, __FUNCTION__, __FILE__); + op::checkE(nRead, 2, "Error, camera resolution format (" + FLAGS_camera_resolution + ") invalid, should be e.g., 1280x720", + __LINE__, __FUNCTION__, __FILE__); // outputSize op::Point outputSize; nRead = sscanf(FLAGS_resolution.c_str(), "%dx%d", &outputSize.x, &outputSize.y); - op::checkE(nRead, 2, "Error, resolution format (" + FLAGS_resolution + ") invalid, should be e.g., 960x540 ", __LINE__, __FUNCTION__, __FILE__); + op::checkE(nRead, 2, "Error, camera resolution format (" + FLAGS_camera_resolution + ") invalid, should be e.g., 1280x720", + __LINE__, __FUNCTION__, __FILE__); // producerType const auto producerSharedPtr = gflagsToProducer(FLAGS_image_dir, FLAGS_video, FLAGS_camera, cameraFrameSize); @@ -121,7 +128,8 @@ int openPoseTutorialThread1() if (producerSize.area() > 0) outputSize = producerSize; else - op::error("Output resolution = input resolution not valid for image reading (size might change between images).", __LINE__, __FUNCTION__, __FILE__); + op::error("Output resolution = input resolution not valid for image reading (size might change between images).", + __LINE__, __FUNCTION__, __FILE__); } // Step 4 - Setting thread workers && manager typedef std::vector TypedefDatumsNoPtr; @@ -138,7 +146,8 @@ int openPoseTutorialThread1() // ------------------------- CONFIGURING THREADING ------------------------- // In this simple multi-thread example, we will do the following: // 3 (virtual) queues: 0, 1, 2 - // 1 real queue: 1. The first and last queue ids (in this case 0 and 2) are not actual queues, but the beginning and end of the processing sequence + // 1 real queue: 1. The first and last queue ids (in this case 0 and 2) are not actual queues, but the beginning and end of the processing + // sequence // 2 threads: 0, 1 // wDatumProducer will generate frames (there is no real queue 0) and push them on queue 1 // wGui will pop frames from queue 1 and process them (there is no real queue 2) diff --git a/examples/tutorial_thread/2_user_processing_function.cpp b/examples/tutorial_thread/2_user_processing_function.cpp index faef043d..9ca9b7cc 100644 --- a/examples/tutorial_thread/2_user_processing_function.cpp +++ b/examples/tutorial_thread/2_user_processing_function.cpp @@ -22,19 +22,23 @@ // Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose // executable. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`. // Debugging -DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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."); +DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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."); // Producer DEFINE_int32(camera, 0, "The camera index for cv::VideoCapture. Integer in the range [0, 9]."); DEFINE_string(camera_resolution, "1280x720", "Size of the camera frames to ask for."); -DEFINE_string(video, "", "Use a video file instead of the camera. Use `examples/media/video.avi` for our default example video."); -DEFINE_string(image_dir, "", "Process a directory of images. Use `examples/media/` for our default example folder with 20 images."); +DEFINE_string(video, "", "Use a video file instead of the camera. Use `examples/media/video.avi` for our default" + " example video."); +DEFINE_string(image_dir, "", "Process a directory of images. Use `examples/media/` for our default example folder with 20" + " images."); // OpenPose -DEFINE_string(resolution, "1280x720", "The image resolution (display). Use \"-1x-1\" to force the program to use the default images resolution."); +DEFINE_string(resolution, "1280x720", "The image resolution (display and output). Use \"-1x-1\" to force the program to use the" + " default images resolution."); // Consumer DEFINE_bool(fullscreen, false, "Run in full-screen mode (press f during runtime to toggle)."); -DEFINE_bool(process_real_time, false, "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."); +DEFINE_bool(process_real_time, false, "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."); // This class can be implemented either as a template or as a simple class given // that the user usually knows which kind of data he will move between the queues, @@ -90,7 +94,8 @@ op::ProducerType gflagsToProducerType(const std::string& imageDirectory, const s return op::ProducerType::Webcam; } -std::shared_ptr gflagsToProducer(const std::string& imageDirectory, const std::string& videoPath, const int webcamIndex, const op::Point webcamResolution) +std::shared_ptr gflagsToProducer(const std::string& imageDirectory, const std::string& videoPath, const int webcamIndex, + const op::Point webcamResolution) { op::log("", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__); const auto type = gflagsToProducerType(imageDirectory, videoPath, webcamIndex); @@ -115,11 +120,13 @@ std::tuple, op::Point, std::shared_ptr> gflags // cameraFrameSize op::Point cameraFrameSize; auto nRead = sscanf(FLAGS_camera_resolution.c_str(), "%dx%d", &cameraFrameSize.x, &cameraFrameSize.y); - op::checkE(nRead, 2, "Error, camera resolution format (" + FLAGS_camera_resolution + ") invalid, should be e.g., 1280x720", __LINE__, __FUNCTION__, __FILE__); + op::checkE(nRead, 2, "Error, camera resolution format (" + FLAGS_camera_resolution + ") invalid, should be e.g., 1280x720", + __LINE__, __FUNCTION__, __FILE__); // outputSize op::Point outputSize; nRead = sscanf(FLAGS_resolution.c_str(), "%dx%d", &outputSize.x, &outputSize.y); - op::checkE(nRead, 2, "Error, resolution format (" + FLAGS_resolution + ") invalid, should be e.g., 960x540 ", __LINE__, __FUNCTION__, __FILE__); + op::checkE(nRead, 2, "Error, camera resolution format (" + FLAGS_camera_resolution + ") invalid, should be e.g., 1280x720", + __LINE__, __FUNCTION__, __FILE__); // producerType const auto producerSharedPtr = gflagsToProducer(FLAGS_image_dir, FLAGS_video, FLAGS_camera, cameraFrameSize); @@ -155,7 +162,8 @@ int openPoseTutorialThread2() if (producerSize.area() > 0) outputSize = producerSize; else - op::error("Output resolution = input resolution not valid for image reading (size might change between images).", __LINE__, __FUNCTION__, __FILE__); + op::error("Output resolution = input resolution not valid for image reading (size might change between images).", + __LINE__, __FUNCTION__, __FILE__); } // Step 4 - Setting thread workers && manager typedef std::vector TypedefDatumsNoPtr; @@ -174,7 +182,8 @@ int openPoseTutorialThread2() // ------------------------- CONFIGURING THREADING ------------------------- // In this simple multi-thread example, we will do the following: // 3 (virtual) queues: 0, 1, 2 - // 1 real queue: 1. The first and last queue ids (in this case 0 and 2) are not actual queues, but the beginning and end of the processing sequence + // 1 real queue: 1. The first and last queue ids (in this case 0 and 2) are not actual queues, but the beginning and end of the processing + // sequence // 2 threads: 0, 1 // wDatumProducer will generate frames (there is no real queue 0) and push them on queue 1 // wGui will pop frames from queue 1 and process them (there is no real queue 2) diff --git a/examples/tutorial_thread/3_user_input_processing_and_output.cpp b/examples/tutorial_thread/3_user_input_processing_and_output.cpp index afefbc1a..b63ed618 100644 --- a/examples/tutorial_thread/3_user_input_processing_and_output.cpp +++ b/examples/tutorial_thread/3_user_input_processing_and_output.cpp @@ -27,8 +27,9 @@ // Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose // executable. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`. // Debugging -DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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."); +DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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."); // Producer DEFINE_string(image_dir, "examples/media/", "Process a directory of images."); // Consumer @@ -183,7 +184,8 @@ int openPoseTutorialThread3() // ------------------------- CONFIGURING THREADING ------------------------- // In this simple multi-thread example, we will do the following: // 3 (virtual) queues: 0, 1, 2 - // 1 real queue: 1. The first and last queue ids (in this case 0 and 2) are not actual queues, but the beginning and end of the processing sequence + // 1 real queue: 1. The first and last queue ids (in this case 0 and 2) are not actual queues, but the beginning and end of the processing + // sequence // 2 threads: 0, 1 // wUserInput will generate frames (there is no real queue 0) and push them on queue 1 // wGui will pop frames from queue 1 and process them (there is no real queue 2) diff --git a/examples/tutorial_thread/4_user_input_processing_output_and_datum.cpp b/examples/tutorial_thread/4_user_input_processing_output_and_datum.cpp index 6d590a96..a0fb9778 100644 --- a/examples/tutorial_thread/4_user_input_processing_output_and_datum.cpp +++ b/examples/tutorial_thread/4_user_input_processing_output_and_datum.cpp @@ -27,8 +27,9 @@ // Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose // executable. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`. // Debugging -DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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."); +DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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."); // Producer DEFINE_string(image_dir, "examples/media/", "Process a directory of images."); // Consumer @@ -36,7 +37,8 @@ DEFINE_bool(fullscreen, false, "Run in full-screen mode // If the user needs his own variables, he can inherit the op::Datum struct and add them -// UserDatum can be directly used by the OpenPose wrapper because it inherits from op::Datum, just define Wrapper instead of Wrapper +// UserDatum can be directly used by the OpenPose wrapper because it inherits from op::Datum, just define Wrapper instead of +// Wrapper struct UserDatum : public op::Datum { bool boolThatUserNeedsForSomeReason; @@ -195,7 +197,8 @@ int openPoseTutorialThread4() // ------------------------- CONFIGURING THREADING ------------------------- // In this simple multi-thread example, we will do the following: // 3 (virtual) queues: 0, 1, 2 - // 1 real queue: 1. The first and last queue ids (in this case 0 and 2) are not actual queues, but the beginning and end of the processing sequence + // 1 real queue: 1. The first and last queue ids (in this case 0 and 2) are not actual queues, but the beginning and end of the processing + // sequence // 2 threads: 0, 1 // wUserInput will generate frames (there is no real queue 0) and push them on queue 1 // wGui will pop frames from queue 1 and process them (there is no real queue 2) diff --git a/examples/tutorial_wrapper/1_user_asynchronous.cpp b/examples/tutorial_wrapper/1_user_asynchronous.cpp index b6ca99b6..4aafee84 100644 --- a/examples/tutorial_wrapper/1_user_asynchronous.cpp +++ b/examples/tutorial_wrapper/1_user_asynchronous.cpp @@ -14,12 +14,12 @@ // This file should only be used for the user to take specific examples. // C++ std library dependencies -#include // std::atomic +#include #include // `std::chrono::` functions and classes, e.g. std::chrono::milliseconds #include // sscanf -#include // std::string +#include #include // std::this_thread -#include // std::vector +#include // Other 3rdpary depencencies #include // DEFINE_bool, DEFINE_int32, DEFINE_int64, DEFINE_uint64, DEFINE_double, DEFINE_string #include // google::InitGoogleLogging @@ -43,67 +43,87 @@ // Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose // executable. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`. // Debugging -DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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."); +DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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."); // Producer DEFINE_string(image_dir, "examples/media/", "Process a directory of images."); // OpenPose DEFINE_string(model_folder, "models/", "Folder where the pose models (COCO and MPI) are located."); -DEFINE_string(resolution, "1280x720", "The image resolution (display and output). Use \"-1x-1\" to force the program to use the default images resolution."); -DEFINE_int32(num_gpu, -1, "The number of GPU devices to use. If negative, it will use all the available GPUs in your machine."); +DEFINE_string(resolution, "1280x720", "The image resolution (display and output). Use \"-1x-1\" to force the program to use the" + " default images resolution."); +DEFINE_int32(num_gpu, -1, "The number of GPU devices to use. If negative, it will use all the available GPUs in your" + " machine."); DEFINE_int32(num_gpu_start, 0, "GPU device start number."); -DEFINE_int32(keypoint_scale, 0, "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_keypoint` & `write_keypoint_json` 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], and 4 for range [-1,1]. Non related with `num_scales` and `scale_gap`."); +DEFINE_int32(keypoint_scale, 0, "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_keypoint` & `write_keypoint_json` 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], and 4 for range [-1,1]. Non related" + " with `num_scales` and `scale_gap`."); // OpenPose Body Pose DEFINE_string(model_pose, "COCO", "Model to be used (e.g. COCO, MPI, MPI_4_layers)."); -DEFINE_string(net_resolution, "656x368", "Multiples of 16. If it is increased, the accuracy usually increases. If it is decreased, the speed increases."); +DEFINE_string(net_resolution, "656x368", "Multiples of 16. If it is increased, the accuracy usually increases. If it is decreased," + " the speed increases."); DEFINE_int32(num_scales, 1, "Number of scales to average."); -DEFINE_double(scale_gap, 0.3, "Scale gap between scales. No effect unless num_scales>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."); -DEFINE_bool(heatmaps_add_parts, false, "If true, it will add the body part heatmaps to the final op::Datum::poseHeatMaps array (program speed will decrease). Not" - " required for our library, enable it only if you intend to process this information later. 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 `include/openpose/pose/poseParameters.hpp`."); -DEFINE_bool(heatmaps_add_bkg, false, "Same functionality as `add_heatmaps_parts`, but adding the heatmap corresponding to background."); +DEFINE_double(scale_gap, 0.3, "Scale gap between scales. No effect unless num_scales>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."); +DEFINE_bool(heatmaps_add_parts, false, "If true, it will add the body part heatmaps to the final op::Datum::poseHeatMaps array" + " (program speed will decrease). Not required for our library, enable it only if you intend" + " to process this information later. 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 `include/openpose/pose/poseParameters.hpp`."); +DEFINE_bool(heatmaps_add_bkg, false, "Same functionality as `add_heatmaps_parts`, but adding the heatmap corresponding to" + " background."); DEFINE_bool(heatmaps_add_PAFs, false, "Same functionality as `add_heatmaps_parts`, but adding the PAFs."); -DEFINE_int32(heatmaps_scale, 2, "Set 0 to scale op::Datum::poseHeatMaps in the range [0,1], 1 for [-1,1]; and 2 for integer rounded [0,255]."); +DEFINE_int32(heatmaps_scale, 2, "Set 0 to scale op::Datum::poseHeatMaps in the range [0,1], 1 for [-1,1]; and 2 for integer" + " rounded [0,255]."); // OpenPose Face -DEFINE_bool(face, false, "Enables face keypoint detection. It will share some parameters from the body pose, e.g. `model_folder`."); -DEFINE_string(face_net_resolution, "368x368", "Multiples of 16. 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."); +DEFINE_bool(face, false, "Enables face keypoint detection. It will share some parameters from the body pose, e.g." + " `model_folder`."); +DEFINE_string(face_net_resolution, "368x368", "Multiples of 16. 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."); // OpenPose Hand // OpenPose Rendering DEFINE_int32(part_to_show, 0, "Part to show from the start."); -DEFINE_bool(disable_blending, false, "If blending is enabled, it will merge the results with the original frame. If disabled, it will only display the results."); +DEFINE_bool(disable_blending, false, "If blending is enabled, it will merge the results with the original frame. If disabled, it" + " will only display the results."); // OpenPose Rendering Pose -DEFINE_bool(no_render_pose, false, "If false, it will fill both `outputData` and `cvOutputData` with the original image + desired part to be shown." - " If true, it will leave them empty."); -DEFINE_double(alpha_pose, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will hide it."); -DEFINE_double(alpha_heatmap, 0.7, "Blending factor (range 0-1) between heatmap and original frame. 1 will only show the heatmap, 0 will only show the frame."); +DEFINE_int32(render_pose, 1, "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 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)."); +DEFINE_double(alpha_pose, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will" + " hide it. Only valid for GPU rendering."); +DEFINE_double(alpha_heatmap, 0.7, "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."); // OpenPose Rendering Face -DEFINE_bool(no_render_face, false, "Analogous to `no_render_pose` but applied to the face keypoints and heat maps."); -DEFINE_double(alpha_face, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will hide it."); -DEFINE_double(alpha_heatmap_face, 0.7, "Blending factor (range 0-1) between heatmap and original frame. 1 will only show the heatmap, 0 will only show the frame."); +DEFINE_int32(render_face, -1, "Analogous to `render_pose` but applied to the face. Extra option: -1 to use the same" + " configuration that `render_pose` is using."); +DEFINE_double(alpha_face, 0.6, "Analogous to `alpha_pose` but applied to face."); +DEFINE_double(alpha_heatmap_face, 0.7, "Analogous to `alpha_heatmap` but applied to face."); // Result Saving DEFINE_string(write_images, "", "Directory to write rendered frames in `write_images_format` image format."); -DEFINE_string(write_images_format, "png", "File extension and format for `write_images`, e.g. png, jpg or bmp. Check the OpenCV function cv::imwrite" - " for all compatible extensions."); -DEFINE_string(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."); -DEFINE_string(write_keypoint, "", "Directory to write the people body pose keypoint data. Desired format on `write_keypoint_format`."); -DEFINE_string(write_keypoint_format, "yml", "File extension and format for `write_keypoint`: json, xml, yaml and yml. Json not available for OpenCV < 3.0," - " use `write_keypoint_json` instead."); -DEFINE_string(write_keypoint_json, "", "Directory to write people pose data with *.json format, compatible with any OpenCV version."); +DEFINE_string(write_images_format, "png", "File extension and format for `write_images`, e.g. png, jpg or bmp. Check the OpenCV" + " function cv::imwrite for all compatible extensions."); +DEFINE_string(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."); +DEFINE_string(write_keypoint, "", "Directory to write the people pose keypoint data. Format with `write_keypoint_format`."); +DEFINE_string(write_keypoint_format, "yml", "File extension and format for `write_keypoint`: json, xml, yaml & yml. Json not available" + " for OpenCV < 3.0, use `write_keypoint_json` instead."); +DEFINE_string(write_keypoint_json, "", "Directory to write people pose data in *.json format, compatible with any OpenCV version."); DEFINE_string(write_coco_json, "", "Full file path to write people pose data with *.json COCO validation format."); -DEFINE_string(write_heatmaps, "", "Directory to write heatmaps with *.png format. At least 1 `add_heatmaps_X` flag must be enabled."); -DEFINE_string(write_heatmaps_format, "png", "File extension and format for `write_heatmaps`, analogous to `write_images_format`. Recommended `png` or any compressed and" - " lossless format."); +DEFINE_string(write_heatmaps, "", "Directory to write heatmaps in *.png format. At least 1 `add_heatmaps_X` flag must be" + " enabled."); +DEFINE_string(write_heatmaps_format, "png", "File extension and format for `write_heatmaps`, analogous to `write_images_format`." + " Recommended `png` or any compressed and lossless format."); // If the user needs his own variables, he can inherit the op::Datum struct and add them -// UserDatum can be directly used by the OpenPose wrapper because it inherits from op::Datum, just define Wrapper instead of Wrapper +// UserDatum can be directly used by the OpenPose wrapper because it inherits from op::Datum, just define Wrapper instead of +// Wrapper struct UserDatum : public op::Datum { bool boolThatUserNeedsForSomeReason; @@ -224,41 +244,62 @@ op::ScaleMode gflagToScaleMode(const int keypointScale) return op::ScaleMode::PlusMinusOne; else { - const std::string message = "String does not correspond to any scale mode: (0, 1, 2, 3, 4) for (InputResolution, NetOutputResolution, OutputResolution, ZeroToOne, PlusMinusOne)."; + const std::string message = "String does not correspond to any scale mode: (0, 1, 2, 3, 4) for (InputResolution," + " NetOutputResolution, OutputResolution, ZeroToOne, PlusMinusOne)."; op::error(message, __LINE__, __FUNCTION__, __FILE__); return op::ScaleMode::InputResolution; } } -std::vector gflagToHeatMaps(const bool heatmaps_add_parts, const bool heatmaps_add_bkg, const bool heatmaps_add_PAFs) +std::vector gflagToHeatMaps(const bool heatMapsAddParts, const bool heatMapsAddBkg, const bool heatMapsAddPAFs) { - std::vector heatMapTypes; - if (heatmaps_add_parts) + if (heatMapsAddParts) heatMapTypes.emplace_back(op::HeatMapType::Parts); - if (heatmaps_add_bkg) + if (heatMapsAddBkg) heatMapTypes.emplace_back(op::HeatMapType::Background); - if (heatmaps_add_PAFs) + if (heatMapsAddPAFs) heatMapTypes.emplace_back(op::HeatMapType::PAFs); return heatMapTypes; } +op::RenderMode gflagToRenderMode(const int renderFlag, const int renderPoseFlag = -2) +{ + if (renderFlag == -1 && renderPoseFlag != -2) + return gflagToRenderMode(renderPoseFlag, -2); + else if (renderFlag == 0) + return op::RenderMode::None; + else if (renderFlag == 1) + return op::RenderMode::Cpu; + else if (renderFlag == 2) + return op::RenderMode::Gpu; + else + { + op::error("Undefined RenderMode selected.", __LINE__, __FUNCTION__, __FILE__); + return op::RenderMode::None; + } +} + // Google flags into program variables -std::tuple, op::Point, op::Point, op::PoseModel, op::ScaleMode, std::vector, op::ScaleMode> gflagsToOpParameters() +std::tuple, op::Point, op::Point, op::PoseModel, op::ScaleMode, std::vector, + op::ScaleMode> gflagsToOpParameters() { op::log("", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__); // outputSize op::Point outputSize; auto nRead = sscanf(FLAGS_resolution.c_str(), "%dx%d", &outputSize.x, &outputSize.y); - op::checkE(nRead, 2, "Error, resolution format (" + FLAGS_resolution + ") invalid, should be e.g., 960x540 ", __LINE__, __FUNCTION__, __FILE__); + op::checkE(nRead, 2, "Error, resolution format (" + FLAGS_resolution + ") invalid, should be e.g., 960x540 ", + __LINE__, __FUNCTION__, __FILE__); // netInputSize op::Point netInputSize; nRead = sscanf(FLAGS_net_resolution.c_str(), "%dx%d", &netInputSize.x, &netInputSize.y); - op::checkE(nRead, 2, "Error, net resolution format (" + FLAGS_net_resolution + ") invalid, should be e.g., 656x368 (multiples of 16)", __LINE__, __FUNCTION__, __FILE__); + op::checkE(nRead, 2, "Error, net resolution format (" + FLAGS_net_resolution + ") invalid, should be e.g., 656x368 (multiples of 16)", + __LINE__, __FUNCTION__, __FILE__); // faceNetInputSize op::Point faceNetInputSize; nRead = sscanf(FLAGS_face_net_resolution.c_str(), "%dx%d", &faceNetInputSize.x, &faceNetInputSize.y); - op::checkE(nRead, 2, "Error, face net resolution format (" + FLAGS_face_net_resolution + ") invalid, should be e.g., 368x368 (multiples of 16)", __LINE__, __FUNCTION__, __FILE__); + op::checkE(nRead, 2, "Error, face net resolution format (" + FLAGS_face_net_resolution + + ") invalid, should be e.g., 368x368 (multiples of 16)", __LINE__, __FUNCTION__, __FILE__); // poseModel const auto poseModel = gflagToPoseModel(FLAGS_model_pose); // keypointScale @@ -266,7 +307,8 @@ std::tuple, op::Point, op::Point, op::PoseModel, op::Sc // heatmaps to add const auto heatMapTypes = gflagToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg, FLAGS_heatmaps_add_PAFs); op::check(FLAGS_heatmaps_scale >= 0 && FLAGS_heatmaps_scale <= 2, "Non valid `heatmaps_scale`.", __LINE__, __FUNCTION__, __FILE__); - const auto heatMapScale = (FLAGS_heatmaps_scale == 0 ? op::ScaleMode::PlusMinusOne : (FLAGS_heatmaps_scale == 1 ? op::ScaleMode::ZeroToOne : op::ScaleMode::UnsignedChar )); + const auto heatMapScale = (FLAGS_heatmaps_scale == 0 ? op::ScaleMode::PlusMinusOne + : (FLAGS_heatmaps_scale == 1 ? op::ScaleMode::ZeroToOne : op::ScaleMode::UnsignedChar )); // return return std::make_tuple(outputSize, netInputSize, faceNetInputSize, poseModel, keypointScale, heatMapTypes, heatMapScale); } @@ -297,16 +339,19 @@ int openPoseTutorialWrapper1() const bool displayGui = false; const bool guiVerbose = false; const bool fullScreen = false; - const op::WrapperStructPose wrapperStructPose{netInputSize, outputSize, keypointScale, FLAGS_num_gpu, FLAGS_num_gpu_start, FLAGS_num_scales, (float)FLAGS_scale_gap, - !FLAGS_no_render_pose, poseModel, !FLAGS_disable_blending, (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, + const op::WrapperStructPose wrapperStructPose{netInputSize, outputSize, keypointScale, FLAGS_num_gpu, FLAGS_num_gpu_start, + FLAGS_num_scales, (float)FLAGS_scale_gap, gflagToRenderMode(FLAGS_render_pose), poseModel, + !FLAGS_disable_blending, (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, FLAGS_model_folder, heatMapTypes, heatMapScale}; - // (Experimental, function and class names might change in next versions) Face configuration (use op::WrapperStructFace{} to disable it) - const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, !FLAGS_no_render_face, (float)FLAGS_alpha_face, (float)FLAGS_alpha_heatmap_face}; - // (Experimental, function and class names might change in next versions) Hand configuration (use op::WrapperStructFace{} to disable it) + // Face configuration (use op::WrapperStructFace{} to disable it) + const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, gflagToRenderMode(FLAGS_render_face, FLAGS_render_pose), + (float)FLAGS_alpha_face, (float)FLAGS_alpha_heatmap_face}; + // Hand configuration (use op::WrapperStructHand{} to disable it) const op::experimental::WrapperStructHand wrapperStructHand{false}; // Consumer (comment or use default argument to disable any output) - const op::WrapperStructOutput wrapperStructOutput{displayGui, guiVerbose, fullScreen, FLAGS_write_keypoint, op::stringToDataFormat(FLAGS_write_keypoint_format), - FLAGS_write_keypoint_json, FLAGS_write_coco_json, FLAGS_write_images, FLAGS_write_images_format, FLAGS_write_video, + const op::WrapperStructOutput wrapperStructOutput{displayGui, guiVerbose, fullScreen, FLAGS_write_keypoint, + op::stringToDataFormat(FLAGS_write_keypoint_format), FLAGS_write_keypoint_json, + FLAGS_write_coco_json, FLAGS_write_images, FLAGS_write_images_format, FLAGS_write_video, FLAGS_write_heatmaps, FLAGS_write_heatmaps_format}; // Configure wrapper opWrapper.configure(wrapperStructPose, wrapperStructFace, wrapperStructHand, op::WrapperStructInput{}, wrapperStructOutput); @@ -339,7 +384,8 @@ int openPoseTutorialWrapper1() opWrapper.stop(); // Measuring total time - const auto totalTimeSec = (double)std::chrono::duration_cast(std::chrono::high_resolution_clock::now()-timerBegin).count() * 1e-9; + const auto now = std::chrono::high_resolution_clock::now(); + const auto totalTimeSec = (double)std::chrono::duration_cast(now-timerBegin).count() * 1e-9; const auto message = "Real-time pose estimation demo successfully finished. Total time: " + std::to_string(totalTimeSec) + " seconds."; op::log(message, op::Priority::Max); diff --git a/examples/tutorial_wrapper/2_user_synchronous.cpp b/examples/tutorial_wrapper/2_user_synchronous.cpp index 3a5f00d1..571bda0e 100644 --- a/examples/tutorial_wrapper/2_user_synchronous.cpp +++ b/examples/tutorial_wrapper/2_user_synchronous.cpp @@ -14,12 +14,12 @@ // This file should only be used for the user to take specific examples. // C++ std library dependencies -#include // std::atomic +#include #include // `std::chrono::` functions and classes, e.g. std::chrono::milliseconds #include // sscanf -#include // std::string +#include #include // std::this_thread -#include // std::vector +#include // Other 3rdpary depencencies #include // DEFINE_bool, DEFINE_int32, DEFINE_int64, DEFINE_uint64, DEFINE_double, DEFINE_string #include // google::InitGoogleLogging @@ -43,67 +43,87 @@ // Note: This command will show you flags for other unnecessary 3rdparty files. Check only the flags for the OpenPose // executable. E.g. for `openpose.bin`, look for `Flags from examples/openpose/openpose.cpp:`. // Debugging -DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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."); +DEFINE_int32(logging_level, 3, "The logging level. Integer in the range [0, 255]. 0 will output any log() 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."); // Producer DEFINE_string(image_dir, "examples/media/", "Process a directory of images."); // OpenPose DEFINE_string(model_folder, "models/", "Folder where the pose models (COCO and MPI) are located."); -DEFINE_string(resolution, "1280x720", "The image resolution (display and output). Use \"-1x-1\" to force the program to use the default images resolution."); -DEFINE_int32(num_gpu, -1, "The number of GPU devices to use. If negative, it will use all the available GPUs in your machine."); +DEFINE_string(resolution, "1280x720", "The image resolution (display and output). Use \"-1x-1\" to force the program to use the" + " default images resolution."); +DEFINE_int32(num_gpu, -1, "The number of GPU devices to use. If negative, it will use all the available GPUs in your" + " machine."); DEFINE_int32(num_gpu_start, 0, "GPU device start number."); -DEFINE_int32(keypoint_scale, 0, "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_keypoint` & `write_keypoint_json` 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], and 4 for range [-1,1]. Non related with `num_scales` and `scale_gap`."); +DEFINE_int32(keypoint_scale, 0, "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_keypoint` & `write_keypoint_json` 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], and 4 for range [-1,1]. Non related" + " with `num_scales` and `scale_gap`."); // OpenPose Body Pose DEFINE_string(model_pose, "COCO", "Model to be used (e.g. COCO, MPI, MPI_4_layers)."); -DEFINE_string(net_resolution, "656x368", "Multiples of 16. If it is increased, the accuracy usually increases. If it is decreased, the speed increases."); +DEFINE_string(net_resolution, "656x368", "Multiples of 16. If it is increased, the accuracy usually increases. If it is decreased," + " the speed increases."); DEFINE_int32(num_scales, 1, "Number of scales to average."); -DEFINE_double(scale_gap, 0.3, "Scale gap between scales. No effect unless num_scales>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."); -DEFINE_bool(heatmaps_add_parts, false, "If true, it will add the body part heatmaps to the final op::Datum::poseHeatMaps array (program speed will decrease). Not" - " required for our library, enable it only if you intend to process this information later. 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 `include/openpose/pose/poseParameters.hpp`."); -DEFINE_bool(heatmaps_add_bkg, false, "Same functionality as `add_heatmaps_parts`, but adding the heatmap corresponding to background."); +DEFINE_double(scale_gap, 0.3, "Scale gap between scales. No effect unless num_scales>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."); +DEFINE_bool(heatmaps_add_parts, false, "If true, it will add the body part heatmaps to the final op::Datum::poseHeatMaps array" + " (program speed will decrease). Not required for our library, enable it only if you intend" + " to process this information later. 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 `include/openpose/pose/poseParameters.hpp`."); +DEFINE_bool(heatmaps_add_bkg, false, "Same functionality as `add_heatmaps_parts`, but adding the heatmap corresponding to" + " background."); DEFINE_bool(heatmaps_add_PAFs, false, "Same functionality as `add_heatmaps_parts`, but adding the PAFs."); -DEFINE_int32(heatmaps_scale, 2, "Set 0 to scale op::Datum::poseHeatMaps in the range [0,1], 1 for [-1,1]; and 2 for integer rounded [0,255]."); +DEFINE_int32(heatmaps_scale, 2, "Set 0 to scale op::Datum::poseHeatMaps in the range [0,1], 1 for [-1,1]; and 2 for integer" + " rounded [0,255]."); // OpenPose Face -DEFINE_bool(face, false, "Enables face keypoint detection. It will share some parameters from the body pose, e.g. `model_folder`."); -DEFINE_string(face_net_resolution, "368x368", "Multiples of 16. 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."); +DEFINE_bool(face, false, "Enables face keypoint detection. It will share some parameters from the body pose, e.g." + " `model_folder`."); +DEFINE_string(face_net_resolution, "368x368", "Multiples of 16. 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."); // OpenPose Hand // OpenPose Rendering DEFINE_int32(part_to_show, 0, "Part to show from the start."); -DEFINE_bool(disable_blending, false, "If blending is enabled, it will merge the results with the original frame. If disabled, it will only display the results."); +DEFINE_bool(disable_blending, false, "If blending is enabled, it will merge the results with the original frame. If disabled, it" + " will only display the results."); // OpenPose Rendering Pose -DEFINE_bool(no_render_pose, false, "If false, it will fill both `outputData` and `cvOutputData` with the original image + desired part to be shown." - " If true, it will leave them empty."); -DEFINE_double(alpha_pose, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will hide it."); -DEFINE_double(alpha_heatmap, 0.7, "Blending factor (range 0-1) between heatmap and original frame. 1 will only show the heatmap, 0 will only show the frame."); +DEFINE_int32(render_pose, 1, "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 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)."); +DEFINE_double(alpha_pose, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will" + " hide it. Only valid for GPU rendering."); +DEFINE_double(alpha_heatmap, 0.7, "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."); // OpenPose Rendering Face -DEFINE_bool(no_render_face, false, "Analogous to `no_render_pose` but applied to the face keypoints and heat maps."); -DEFINE_double(alpha_face, 0.6, "Blending factor (range 0-1) for the body part rendering. 1 will show it completely, 0 will hide it."); -DEFINE_double(alpha_heatmap_face, 0.7, "Blending factor (range 0-1) between heatmap and original frame. 1 will only show the heatmap, 0 will only show the frame."); +DEFINE_int32(render_face, -1, "Analogous to `render_pose` but applied to the face. Extra option: -1 to use the same" + " configuration that `render_pose` is using."); +DEFINE_double(alpha_face, 0.6, "Analogous to `alpha_pose` but applied to face."); +DEFINE_double(alpha_heatmap_face, 0.7, "Analogous to `alpha_heatmap` but applied to face."); // Result Saving DEFINE_string(write_images, "", "Directory to write rendered frames in `write_images_format` image format."); -DEFINE_string(write_images_format, "png", "File extension and format for `write_images`, e.g. png, jpg or bmp. Check the OpenCV function cv::imwrite" - " for all compatible extensions."); -DEFINE_string(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."); -DEFINE_string(write_keypoint, "", "Directory to write the people body pose keypoint data. Desired format on `write_keypoint_format`."); -DEFINE_string(write_keypoint_format, "yml", "File extension and format for `write_keypoint`: json, xml, yaml and yml. Json not available for OpenCV < 3.0," - " use `write_keypoint_json` instead."); -DEFINE_string(write_keypoint_json, "", "Directory to write people pose data with *.json format, compatible with any OpenCV version."); +DEFINE_string(write_images_format, "png", "File extension and format for `write_images`, e.g. png, jpg or bmp. Check the OpenCV" + " function cv::imwrite for all compatible extensions."); +DEFINE_string(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."); +DEFINE_string(write_keypoint, "", "Directory to write the people pose keypoint data. Format with `write_keypoint_format`."); +DEFINE_string(write_keypoint_format, "yml", "File extension and format for `write_keypoint`: json, xml, yaml & yml. Json not available" + " for OpenCV < 3.0, use `write_keypoint_json` instead."); +DEFINE_string(write_keypoint_json, "", "Directory to write people pose data in *.json format, compatible with any OpenCV version."); DEFINE_string(write_coco_json, "", "Full file path to write people pose data with *.json COCO validation format."); -DEFINE_string(write_heatmaps, "", "Directory to write heatmaps with *.png format. At least 1 `add_heatmaps_X` flag must be enabled."); -DEFINE_string(write_heatmaps_format, "png", "File extension and format for `write_heatmaps`, analogous to `write_images_format`. Recommended `png` or any compressed and" - " lossless format."); +DEFINE_string(write_heatmaps, "", "Directory to write heatmaps in *.png format. At least 1 `add_heatmaps_X` flag must be" + " enabled."); +DEFINE_string(write_heatmaps_format, "png", "File extension and format for `write_heatmaps`, analogous to `write_images_format`." + " Recommended `png` or any compressed and lossless format."); // If the user needs his own variables, he can inherit the op::Datum struct and add them -// UserDatum can be directly used by the OpenPose wrapper because it inherits from op::Datum, just define Wrapper instead of Wrapper +// UserDatum can be directly used by the OpenPose wrapper because it inherits from op::Datum, just define Wrapper instead of +// Wrapper struct UserDatum : public op::Datum { bool boolThatUserNeedsForSomeReason; @@ -269,41 +289,62 @@ op::ScaleMode gflagToScaleMode(const int keypointScale) return op::ScaleMode::PlusMinusOne; else { - const std::string message = "String does not correspond to any scale mode: (0, 1, 2, 3, 4) for (InputResolution, NetOutputResolution, OutputResolution, ZeroToOne, PlusMinusOne)."; + const std::string message = "String does not correspond to any scale mode: (0, 1, 2, 3, 4) for (InputResolution," + " NetOutputResolution, OutputResolution, ZeroToOne, PlusMinusOne)."; op::error(message, __LINE__, __FUNCTION__, __FILE__); return op::ScaleMode::InputResolution; } } -std::vector gflagToHeatMaps(const bool heatmaps_add_parts, const bool heatmaps_add_bkg, const bool heatmaps_add_PAFs) +std::vector gflagToHeatMaps(const bool heatMapsAddParts, const bool heatMapsAddBkg, const bool heatMapsAddPAFs) { - std::vector heatMapTypes; - if (heatmaps_add_parts) + if (heatMapsAddParts) heatMapTypes.emplace_back(op::HeatMapType::Parts); - if (heatmaps_add_bkg) + if (heatMapsAddBkg) heatMapTypes.emplace_back(op::HeatMapType::Background); - if (heatmaps_add_PAFs) + if (heatMapsAddPAFs) heatMapTypes.emplace_back(op::HeatMapType::PAFs); return heatMapTypes; } +op::RenderMode gflagToRenderMode(const int renderFlag, const int renderPoseFlag = -2) +{ + if (renderFlag == -1 && renderPoseFlag != -2) + return gflagToRenderMode(renderPoseFlag, -2); + else if (renderFlag == 0) + return op::RenderMode::None; + else if (renderFlag == 1) + return op::RenderMode::Cpu; + else if (renderFlag == 2) + return op::RenderMode::Gpu; + else + { + op::error("Undefined RenderMode selected.", __LINE__, __FUNCTION__, __FILE__); + return op::RenderMode::None; + } +} + // Google flags into program variables -std::tuple, op::Point, op::Point, op::PoseModel, op::ScaleMode, std::vector, op::ScaleMode> gflagsToOpParameters() +std::tuple, op::Point, op::Point, op::PoseModel, op::ScaleMode, std::vector, + op::ScaleMode> gflagsToOpParameters() { op::log("", op::Priority::Low, __LINE__, __FUNCTION__, __FILE__); // outputSize op::Point outputSize; auto nRead = sscanf(FLAGS_resolution.c_str(), "%dx%d", &outputSize.x, &outputSize.y); - op::checkE(nRead, 2, "Error, resolution format (" + FLAGS_resolution + ") invalid, should be e.g., 960x540 ", __LINE__, __FUNCTION__, __FILE__); + op::checkE(nRead, 2, "Error, resolution format (" + FLAGS_resolution + ") invalid, should be e.g., 960x540 ", + __LINE__, __FUNCTION__, __FILE__); // netInputSize op::Point netInputSize; nRead = sscanf(FLAGS_net_resolution.c_str(), "%dx%d", &netInputSize.x, &netInputSize.y); - op::checkE(nRead, 2, "Error, net resolution format (" + FLAGS_net_resolution + ") invalid, should be e.g., 656x368 (multiples of 16)", __LINE__, __FUNCTION__, __FILE__); + op::checkE(nRead, 2, "Error, net resolution format (" + FLAGS_net_resolution + ") invalid, should be e.g., 656x368 (multiples of 16)", + __LINE__, __FUNCTION__, __FILE__); // faceNetInputSize op::Point faceNetInputSize; nRead = sscanf(FLAGS_face_net_resolution.c_str(), "%dx%d", &faceNetInputSize.x, &faceNetInputSize.y); - op::checkE(nRead, 2, "Error, face net resolution format (" + FLAGS_face_net_resolution + ") invalid, should be e.g., 368x368 (multiples of 16)", __LINE__, __FUNCTION__, __FILE__); + op::checkE(nRead, 2, "Error, face net resolution format (" + FLAGS_face_net_resolution + + ") invalid, should be e.g., 368x368 (multiples of 16)", __LINE__, __FUNCTION__, __FILE__); // poseModel const auto poseModel = gflagToPoseModel(FLAGS_model_pose); // keypointScale @@ -311,7 +352,8 @@ std::tuple, op::Point, op::Point, op::PoseModel, op::Sc // heatmaps to add const auto heatMapTypes = gflagToHeatMaps(FLAGS_heatmaps_add_parts, FLAGS_heatmaps_add_bkg, FLAGS_heatmaps_add_PAFs); op::check(FLAGS_heatmaps_scale >= 0 && FLAGS_heatmaps_scale <= 2, "Non valid `heatmaps_scale`.", __LINE__, __FUNCTION__, __FILE__); - const auto heatMapScale = (FLAGS_heatmaps_scale == 0 ? op::ScaleMode::PlusMinusOne : (FLAGS_heatmaps_scale == 1 ? op::ScaleMode::ZeroToOne : op::ScaleMode::UnsignedChar )); + const auto heatMapScale = (FLAGS_heatmaps_scale == 0 ? op::ScaleMode::PlusMinusOne + : (FLAGS_heatmaps_scale == 1 ? op::ScaleMode::ZeroToOne : op::ScaleMode::UnsignedChar )); // return return std::make_tuple(outputSize, netInputSize, faceNetInputSize, poseModel, keypointScale, heatMapTypes, heatMapScale); } @@ -359,16 +401,19 @@ int openPoseTutorialWrapper2() const bool displayGui = false; const bool guiVerbose = false; const bool fullScreen = false; - const op::WrapperStructPose wrapperStructPose{netInputSize, outputSize, keypointScale, FLAGS_num_gpu, FLAGS_num_gpu_start, FLAGS_num_scales, (float)FLAGS_scale_gap, - !FLAGS_no_render_pose, poseModel, !FLAGS_disable_blending, (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, + const op::WrapperStructPose wrapperStructPose{netInputSize, outputSize, keypointScale, FLAGS_num_gpu, FLAGS_num_gpu_start, + FLAGS_num_scales, (float)FLAGS_scale_gap, gflagToRenderMode(FLAGS_render_pose), poseModel, + !FLAGS_disable_blending, (float)FLAGS_alpha_pose, (float)FLAGS_alpha_heatmap, FLAGS_part_to_show, FLAGS_model_folder, heatMapTypes, heatMapScale}; - // (Experimental, function and class names might change in next versions) Face configuration (use op::WrapperStructFace{} to disable it) - const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, !FLAGS_no_render_face, (float)FLAGS_alpha_face, (float)FLAGS_alpha_heatmap_face}; - // (Experimental, function and class names might change in next versions) Hand configuration (use op::WrapperStructFace{} to disable it) + // Face configuration (use op::WrapperStructFace{} to disable it) + const op::WrapperStructFace wrapperStructFace{FLAGS_face, faceNetInputSize, gflagToRenderMode(FLAGS_render_face, FLAGS_render_pose), + (float)FLAGS_alpha_face, (float)FLAGS_alpha_heatmap_face}; + // Hand configuration (use op::WrapperStructHand{} to disable it) const op::experimental::WrapperStructHand wrapperStructHand{false}; // Consumer (comment or use default argument to disable any output) - const op::WrapperStructOutput wrapperStructOutput{displayGui, guiVerbose, fullScreen, FLAGS_write_keypoint, op::stringToDataFormat(FLAGS_write_keypoint_format), - FLAGS_write_keypoint_json, FLAGS_write_coco_json, FLAGS_write_images, FLAGS_write_images_format, FLAGS_write_video, + const op::WrapperStructOutput wrapperStructOutput{displayGui, guiVerbose, fullScreen, FLAGS_write_keypoint, + op::stringToDataFormat(FLAGS_write_keypoint_format), FLAGS_write_keypoint_json, + FLAGS_write_coco_json, FLAGS_write_images, FLAGS_write_images_format, FLAGS_write_video, FLAGS_write_heatmaps, FLAGS_write_heatmaps_format}; // Configure wrapper opWrapper.configure(wrapperStructPose, wrapperStructFace, wrapperStructHand, op::WrapperStructInput{}, wrapperStructOutput); @@ -400,7 +445,8 @@ int openPoseTutorialWrapper2() // opWrapper.stop(); // Measuring total time - const auto totalTimeSec = (double)std::chrono::duration_cast(std::chrono::high_resolution_clock::now()-timerBegin).count() * 1e-9; + const auto now = std::chrono::high_resolution_clock::now(); + const auto totalTimeSec = (double)std::chrono::duration_cast(now-timerBegin).count() * 1e-9; const auto message = "Real-time pose estimation demo successfully finished. Total time: " + std::to_string(totalTimeSec) + " seconds."; op::log(message, op::Priority::Max); diff --git a/include/openpose/core/array.hpp b/include/openpose/core/array.hpp index e9a77518..23e005e5 100644 --- a/include/openpose/core/array.hpp +++ b/include/openpose/core/array.hpp @@ -211,12 +211,6 @@ namespace op return spData.get(); } - // Disabled because people might try to modify it in illegal ways and change the allocated memory (e.g. resizing), leading to huge errors - // inline cv::Mat& getCvMat() - // { - // return mCvMatData.second; - // } - /** * Return a cv::Mat wrapper to the data. It forbids the data to be modified. * OpenCV only admits unsigned char, signed char, int, float & double. If the T class is not supported by OpenCV, it will throw an error. @@ -229,6 +223,14 @@ namespace op */ const cv::Mat& getConstCvMat() const; + /** + * Analogous to getConstCvMat, but in this case it returns a editable cv::Mat. + * Very important: Only allowed functions which do not provoke data reallocation. + * E.g. resizing functions will not work and they would provoke an undefined behaviour and/or execution crashes. + * @return A cv::Mat pointing to the data. + */ + cv::Mat& getCvMat(); + /** * [] operator * Similar to the [] operator for raw pointer data. diff --git a/include/openpose/core/datum.hpp b/include/openpose/core/datum.hpp index a948e037..abdceb99 100644 --- a/include/openpose/core/datum.hpp +++ b/include/openpose/core/datum.hpp @@ -2,7 +2,7 @@ #define OPENPOSE_CORE_DATUM_HPP #include // std::shared_ptr -#include // std::string +#include #include // cv::Mat #include "array.hpp" #include "point.hpp" diff --git a/include/openpose/core/enumClasses.hpp b/include/openpose/core/enumClasses.hpp index f7821883..ea1e0960 100644 --- a/include/openpose/core/enumClasses.hpp +++ b/include/openpose/core/enumClasses.hpp @@ -19,6 +19,13 @@ namespace op Background, PAFs, }; + + enum class RenderMode : unsigned char + { + None, + Cpu, + Gpu, + }; } #endif // OPENPOSE_CORE_ENUM_CLASSES_HPP diff --git a/include/openpose/core/headers.hpp b/include/openpose/core/headers.hpp index 89655e5e..513879ef 100644 --- a/include/openpose/core/headers.hpp +++ b/include/openpose/core/headers.hpp @@ -18,7 +18,6 @@ #include "renderer.hpp" #include "resizeAndMergeBase.hpp" #include "resizeAndMergeCaffe.hpp" -#include "scaleKeypoints.hpp" #include "wCvMatToOpInput.hpp" #include "wCvMatToOpOutput.hpp" #include "wKeypointScaler.hpp" diff --git a/include/openpose/core/renderer.hpp b/include/openpose/core/renderer.hpp index f06da407..518b6910 100644 --- a/include/openpose/core/renderer.hpp +++ b/include/openpose/core/renderer.hpp @@ -11,8 +11,8 @@ namespace op class Renderer { public: - explicit Renderer(const unsigned long long volume, const float alphaKeypoint, const float alphaHeatMap, const unsigned int elementToRender = 0u, - const unsigned int numberElementsToRender = 0u); + explicit Renderer(const unsigned long long volume, const float alphaKeypoint, const float alphaHeatMap, + const unsigned int elementToRender = 0u, const unsigned int numberElementsToRender = 0u); ~Renderer(); @@ -22,9 +22,11 @@ namespace op void setElementToRender(const int elementToRender); - std::tuple, std::shared_ptr, std::shared_ptr>, std::shared_ptr> getSharedParameters(); + std::tuple, std::shared_ptr, std::shared_ptr>, + std::shared_ptr> getSharedParameters(); - void setSharedParametersAndIfLast(const std::tuple, std::shared_ptr, std::shared_ptr>, + void setSharedParametersAndIfLast(const std::tuple, std::shared_ptr, + std::shared_ptr>, std::shared_ptr>& tuple, const bool isLast); float getAlphaKeypoint() const; diff --git a/include/openpose/core/scaleKeypoints.hpp b/include/openpose/core/scaleKeypoints.hpp deleted file mode 100644 index 3c1a7e54..00000000 --- a/include/openpose/core/scaleKeypoints.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef OPENPOSE_CORE_SCALE_KEYPOINTS_HPP -#define OPENPOSE_CORE_SCALE_KEYPOINTS_HPP - -#include "array.hpp" - -namespace op -{ - void scaleKeypoints(Array& keypoints, const float scale); - - void scaleKeypoints(Array& keypoints, const float scaleX, const float scaleY); - - void scaleKeypoints(Array& keypoints, const float scaleX, const float scaleY, const float offsetX, const float offsetY); -} - -#endif // OPENPOSE_CORE_SCALE_KEYPOINTS_HPP diff --git a/include/openpose/core/wKeypointScaler.hpp b/include/openpose/core/wKeypointScaler.hpp index 64f159a0..3829eb37 100644 --- a/include/openpose/core/wKeypointScaler.hpp +++ b/include/openpose/core/wKeypointScaler.hpp @@ -3,7 +3,6 @@ #include #include "keypointScaler.hpp" -#include "scaleKeypoints.hpp" namespace op { diff --git a/include/openpose/experimental/hand/handParameters.hpp b/include/openpose/experimental/hand/handParameters.hpp index 97ee9f51..1ef87fbf 100644 --- a/include/openpose/experimental/hand/handParameters.hpp +++ b/include/openpose/experimental/hand/handParameters.hpp @@ -9,7 +9,33 @@ namespace op const auto HAND_MAX_HANDS = 2*POSE_MAX_PEOPLE; const auto HAND_NUMBER_PARTS = 21u; - #define HAND_PAIRS_TO_RENDER {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} + #define HAND_PAIRS_RENDER_GPU {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} + const std::vector HAND_PAIRS_RENDER {HAND_PAIRS_RENDER_GPU}; + #define HAND_COLORS_RENDER \ + 179.f, 0.f, 0.f, \ + 204.f, 0.f, 0.f, \ + 230.f, 0.f, 0.f, \ + 255.f, 0.f, 0.f, \ + 143.f, 179.f, 0.f, \ + 163.f, 204.f, 0.f, \ + 184.f, 230.f, 0.f, \ + 204.f, 255.f, 0.f, \ + 0.f, 179.f, 71.f, \ + 0.f, 204.f, 82.f, \ + 0.f, 230.f, 92.f, \ + 0.f, 255.f, 102.f, \ + 0.f, 71.f, 179.f, \ + 0.f, 82.f, 204.f, \ + 0.f, 92.f, 230.f, \ + 0.f, 102.f, 255.f, \ + 143.f, 0.f, 179.f, \ + 163.f, 0.f, 204.f, \ + 184.f, 0.f, 230.f, \ + 204.f, 0.f, 255.f, \ + 179.f, 179.f, 179.f, \ + 179.f, 179.f, 179.f, \ + 179.f, 179.f, 179.f, \ + 179.f, 179.f, 179.f // Constant parameters const auto HAND_CCN_DECREASE_FACTOR = 8.f; diff --git a/include/openpose/experimental/hand/handRenderGpu.hpp b/include/openpose/experimental/hand/handRenderGpu.hpp deleted file mode 100644 index ba1dcd82..00000000 --- a/include/openpose/experimental/hand/handRenderGpu.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef OPENPOSE_HAND_GPU_HAND_RENDER_HPP -#define OPENPOSE_HAND_GPU_HAND_RENDER_HPP - -#include -#include "handParameters.hpp" - -namespace op -{ - void renderHandsGpu(float* framePtr, const Point& frameSize, const float* const handsPtr, const int numberHands, const float alphaColorToAdd = HAND_DEFAULT_ALPHA_KEYPOINT); -} - -#endif // OPENPOSE_HAND_GPU_HAND_RENDER_HPP diff --git a/include/openpose/experimental/hand/handRenderer.hpp b/include/openpose/experimental/hand/handRenderer.hpp index d0d1cacd..cb969511 100644 --- a/include/openpose/experimental/hand/handRenderer.hpp +++ b/include/openpose/experimental/hand/handRenderer.hpp @@ -2,9 +2,11 @@ #define OPENPOSE_HAND_HAND_RENDERER_HPP #include +#include #include #include #include +#include "handParameters.hpp" namespace op { @@ -13,17 +15,23 @@ namespace op class HandRenderer : public Renderer { public: - explicit HandRenderer(const Point& frameSize); + HandRenderer(const Point& frameSize, const float alphaKeypoint = HAND_DEFAULT_ALPHA_KEYPOINT, + const float alphaHeatMap = HAND_DEFAULT_ALPHA_HEAT_MAP, const RenderMode renderMode = RenderMode::Cpu); ~HandRenderer(); void initializationOnThread(); - void renderHands(Array& outputData, const Array& handKeypoints); + void renderHand(Array& outputData, const Array& handKeypoints); private: const Point mFrameSize; - float* pGpuHands; // GPU aux memory + const RenderMode mRenderMode; + float* pGpuHands; // GPU aux memory + + void renderHandCpu(Array& outputData, const Array& handKeypoints); + + void renderHandGpu(Array& outputData, const Array& handKeypoints); DELETE_COPY(HandRenderer); }; diff --git a/include/openpose/experimental/hand/headers.hpp b/include/openpose/experimental/hand/headers.hpp index 9d8fd4c5..af333395 100644 --- a/include/openpose/experimental/hand/headers.hpp +++ b/include/openpose/experimental/hand/headers.hpp @@ -6,7 +6,7 @@ #include "handExtractor.hpp" #include "handParameters.hpp" #include "handRenderer.hpp" -#include "handRenderGpu.hpp" +#include "renderHand.hpp" #include "wHandExtractor.hpp" #include "wHandRenderer.hpp" diff --git a/include/openpose/experimental/hand/renderHand.hpp b/include/openpose/experimental/hand/renderHand.hpp new file mode 100644 index 00000000..8fb9fdd7 --- /dev/null +++ b/include/openpose/experimental/hand/renderHand.hpp @@ -0,0 +1,16 @@ +#ifndef OPENPOSE_HAND_GPU_HAND_RENDER_HPP +#define OPENPOSE_HAND_GPU_HAND_RENDER_HPP + +#include +#include +#include "handParameters.hpp" + +namespace op +{ + void renderHandKeypointsCpu(Array& frameArray, const Array& handKeypoints); + + void renderHandKeypointsGpu(float* framePtr, const Point& frameSize, const float* const handsPtr, const int numberHands, + const float alphaColorToAdd = HAND_DEFAULT_ALPHA_KEYPOINT); +} + +#endif // OPENPOSE_HAND_GPU_HAND_RENDER_HPP diff --git a/include/openpose/experimental/hand/wHandRenderer.hpp b/include/openpose/experimental/hand/wHandRenderer.hpp index bb4d0031..5ef87337 100644 --- a/include/openpose/experimental/hand/wHandRenderer.hpp +++ b/include/openpose/experimental/hand/wHandRenderer.hpp @@ -65,7 +65,7 @@ namespace op const auto profilerKey = Profiler::timerInit(__LINE__, __FUNCTION__, __FILE__); // Render people hands for (auto& tDatum : *tDatums) - spHandRenderer->renderHands(tDatum.outputData, tDatum.handKeypoints); + spHandRenderer->renderHand(tDatum.outputData, tDatum.handKeypoints); // Profiling speed Profiler::timerEnd(profilerKey); Profiler::printAveragedTimeMsOnIterationX(profilerKey, __LINE__, __FUNCTION__, __FILE__, Profiler::DEFAULT_X); diff --git a/include/openpose/experimental/producer/wPeoplePoseLoader.hpp b/include/openpose/experimental/producer/wPeoplePoseLoader.hpp index f93e01b2..b5acd1a9 100644 --- a/include/openpose/experimental/producer/wPeoplePoseLoader.hpp +++ b/include/openpose/experimental/producer/wPeoplePoseLoader.hpp @@ -7,7 +7,7 @@ // namespace op // { -// template +// template // class wPoseLoader : public Worker // { // public: diff --git a/include/openpose/face/faceParameters.hpp b/include/openpose/face/faceParameters.hpp index 54fe45e8..aa2b8756 100644 --- a/include/openpose/face/faceParameters.hpp +++ b/include/openpose/face/faceParameters.hpp @@ -9,10 +9,12 @@ namespace op const auto FACE_MAX_FACES = POSE_MAX_PEOPLE; const auto FACE_NUMBER_PARTS = 70u; - #define FACE_PAIRS_TO_RENDER {0,1, 1,2, 2,3, 3,4, 4,5, 5,6, 6,7, 7,8, 8,9, 9,10, 10,11, 11,12, 12,13, 13,14, 14,15, 15,16, 17,18, 18,19, 19,20, \ + #define FACE_PAIRS_RENDER_GPU {0,1, 1,2, 2,3, 3,4, 4,5, 5,6, 6,7, 7,8, 8,9, 9,10, 10,11, 11,12, 12,13, 13,14, 14,15, 15,16, 17,18, 18,19, 19,20, \ 20,21, 22,23, 23,24, 24,25, 25,26, 27,28, 28,29, 29,30, 31,32, 32,33, 33,34, 34,35, 36,37, 37,38, 38,39, 39,40, 40,41, \ 41,36, 42,43, 43,44, 44,45, 45,46, 46,47, 47,42, 48,49, 49,50, 50,51, 51,52, 52,53, 53,54, 54,55, 55,56, 56,57, 57,58, \ 58,59, 59,48, 60,61, 61,62, 62,63, 63,64, 64,65, 65,66, 66,67, 67,60} + const std::vector FACE_PAIRS_RENDER {FACE_PAIRS_RENDER_GPU}; + #define FACE_COLORS_RENDER 255.f, 255.f, 255.f // Constant parameters const auto FACE_CCN_DECREASE_FACTOR = 8.f; diff --git a/include/openpose/face/faceRenderGpu.hpp b/include/openpose/face/faceRenderGpu.hpp deleted file mode 100644 index 47f6c4c4..00000000 --- a/include/openpose/face/faceRenderGpu.hpp +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef OPENPOSE_FACE_GPU_FACE_RENDER_HPP -#define OPENPOSE_FACE_GPU_FACE_RENDER_HPP - -#include -#include "faceParameters.hpp" - -namespace op -{ - void renderFaceGpu(float* framePtr, const Point& frameSize, const float* const facePtr, const int numberFace, const float alphaColorToAdd = FACE_DEFAULT_ALPHA_KEYPOINT); -} - -#endif // OPENPOSE_FACE_GPU_FACE_RENDER_HPP diff --git a/include/openpose/face/faceRenderer.hpp b/include/openpose/face/faceRenderer.hpp index 1ab61e01..02038063 100644 --- a/include/openpose/face/faceRenderer.hpp +++ b/include/openpose/face/faceRenderer.hpp @@ -2,9 +2,11 @@ #define OPENPOSE_FACE_FACE_RENDERER_HPP #include +#include #include #include #include +#include "faceParameters.hpp" namespace op { @@ -12,7 +14,7 @@ namespace op { public: explicit FaceRenderer(const Point& frameSize, const float alphaKeypoint = FACE_DEFAULT_ALPHA_KEYPOINT, - const float alphaHeatMap = FACE_DEFAULT_ALPHA_HEAT_MAP); + const float alphaHeatMap = FACE_DEFAULT_ALPHA_HEAT_MAP, const RenderMode renderMode = RenderMode::Cpu); ~FaceRenderer(); @@ -22,7 +24,12 @@ namespace op private: const Point mFrameSize; - float* pGpuFace; // GPU aux memory + const RenderMode mRenderMode; + float* pGpuFace; // GPU aux memory + + void renderFaceCpu(Array& outputData, const Array& faceKeypoints); + + void renderFaceGpu(Array& outputData, const Array& faceKeypoints); DELETE_COPY(FaceRenderer); }; diff --git a/include/openpose/face/headers.hpp b/include/openpose/face/headers.hpp index b1b66629..0bdeba98 100644 --- a/include/openpose/face/headers.hpp +++ b/include/openpose/face/headers.hpp @@ -7,7 +7,7 @@ #include "faceExtractor.hpp" #include "faceParameters.hpp" #include "faceRenderer.hpp" -#include "faceRenderGpu.hpp" +#include "renderFace.hpp" #include "wFaceDetector.hpp" #include "wFaceExtractor.hpp" #include "wFaceRenderer.hpp" diff --git a/include/openpose/face/renderFace.hpp b/include/openpose/face/renderFace.hpp new file mode 100644 index 00000000..e1e18039 --- /dev/null +++ b/include/openpose/face/renderFace.hpp @@ -0,0 +1,16 @@ +#ifndef OPENPOSE_FACE_RENDER_FACE_HPP +#define OPENPOSE_FACE_RENDER_FACE_HPP + +#include +#include +#include "faceParameters.hpp" + +namespace op +{ + void renderFaceKeypointsCpu(Array& frameArray, const Array& faceKeypoints); + + void renderFaceKeypointsGpu(float* framePtr, const Point& frameSize, const float* const facePtr, const int numberFace, + const float alphaColorToAdd = FACE_DEFAULT_ALPHA_KEYPOINT); +} + +#endif // OPENPOSE_FACE_RENDER_FACE_HPP diff --git a/include/openpose/pose/headers.hpp b/include/openpose/pose/headers.hpp index 879defe8..9cf37453 100644 --- a/include/openpose/pose/headers.hpp +++ b/include/openpose/pose/headers.hpp @@ -8,8 +8,8 @@ #include "poseExtractor.hpp" #include "poseExtractorCaffe.hpp" #include "poseRenderer.hpp" -#include "poseRenderGpu.hpp" #include "poseParameters.hpp" +#include "renderPose.hpp" #include "wPoseExtractor.hpp" #include "wPoseRenderer.hpp" diff --git a/include/openpose/pose/poseParameters.hpp b/include/openpose/pose/poseParameters.hpp index 4e5b8e6a..e36b4eb7 100644 --- a/include/openpose/pose/poseParameters.hpp +++ b/include/openpose/pose/poseParameters.hpp @@ -31,10 +31,30 @@ namespace op {17, "LEar"}, {18, "Background"} }; - const unsigned int POSE_COCO_NUMBER_PARTS = 18u; // Equivalent to size of std::map POSE_COCO_BODY_PARTS - 1 (removing background) - const std::vector POSE_COCO_MAP_IDX {31,32, 39,40, 33,34, 35,36, 41,42, 43,44, 19,20, 21,22, 23,24, 25,26, 27,28, 29,30, 47,48, 49,50, 53,54, 51,52, 55,56, 37,38, 45,46}; - #define POSE_COCO_PAIRS_TO_RENDER {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} - const std::vector POSE_COCO_PAIRS {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, 2,16, 5,17}; + const unsigned int POSE_COCO_NUMBER_PARTS = 18u; // Equivalent to size of std::map POSE_COCO_BODY_PARTS - 1 (removing background) + const std::vector POSE_COCO_MAP_IDX {31,32, 39,40, 33,34, 35,36, 41,42, 43,44, 19,20, 21,22, 23,24, 25,26, 27,28, 29,30, 47,48, 49,50, 53,54, 51,52, 55,56, 37,38, 45,46}; + #define POSE_COCO_PAIRS_RENDER_GPU {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} + const std::vector POSE_COCO_PAIRS_RENDER {POSE_COCO_PAIRS_RENDER_GPU}; + const std::vector POSE_COCO_PAIRS {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, 2,16, 5,17}; + #define POSE_COCO_COLORS_RENDER \ + 255.f, 0.f, 0.f, \ + 255.f, 85.f, 0.f, \ + 255.f, 170.f, 0.f, \ + 255.f, 255.f, 0.f, \ + 170.f, 255.f, 0.f, \ + 85.f, 255.f, 0.f, \ + 0.f, 255.f, 0.f, \ + 0.f, 255.f, 85.f, \ + 0.f, 255.f, 170.f, \ + 0.f, 255.f, 255.f, \ + 0.f, 170.f, 255.f, \ + 0.f, 85.f, 255.f, \ + 0.f, 0.f, 255.f, \ + 85.f, 0.f, 255.f, \ + 170.f, 0.f, 255.f, \ + 255.f, 0.f, 255.f, \ + 255.f, 0.f, 170.f, \ + 255.f, 0.f, 85.f const std::map POSE_MPI_BODY_PARTS{ {0, "Head"}, @@ -56,8 +76,25 @@ namespace op }; const unsigned int POSE_MPI_NUMBER_PARTS = 15; // Equivalent to size of std::map POSE_MPI_NUMBER_PARTS - 1 (removing background) const std::vector POSE_MPI_MAP_IDX {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43}; - #define POSE_MPI_PAIRS_TO_RENDER { 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} - const std::vector POSE_MPI_PAIRS POSE_MPI_PAIRS_TO_RENDER; + #define POSE_MPI_PAIRS_RENDER_GPU { 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} + const std::vector POSE_MPI_PAIRS POSE_MPI_PAIRS_RENDER_GPU; + // MPI colors chosen such that they are closed to COCO colors + #define POSE_MPI_COLORS_RENDER \ + 255.f, 0.f, 85.f, \ + 255.f, 0.f, 0.f, \ + 255.f, 85.f, 0.f, \ + 255.f, 170.f, 0.f, \ + 255.f, 255.f, 0.f, \ + 170.f, 255.f, 0.f, \ + 85.f, 255.f, 0.f, \ + 43.f, 255.f, 0.f, \ + 0.f, 255.f, 0.f, \ + 0.f, 255.f, 85.f, \ + 0.f, 255.f, 170.f, \ + 0.f, 255.f, 255.f, \ + 0.f, 170.f, 255.f, \ + 0.f, 85.f, 255.f, \ + 0.f, 0.f, 255.f // Constant Global Parameters const unsigned int POSE_MAX_PEOPLE = 96u; @@ -67,6 +104,7 @@ namespace op const std::array POSE_MAX_PEAKS{ POSE_MAX_PEOPLE, POSE_MAX_PEOPLE, POSE_MAX_PEOPLE}; const std::array POSE_NUMBER_BODY_PARTS{ POSE_COCO_NUMBER_PARTS, POSE_MPI_NUMBER_PARTS, POSE_MPI_NUMBER_PARTS}; const std::array, 3> POSE_BODY_PART_PAIRS{ POSE_COCO_PAIRS, POSE_MPI_PAIRS, POSE_MPI_PAIRS}; + const std::array, 3> POSE_BODY_PART_PAIRS_RENDER{POSE_COCO_PAIRS_RENDER, POSE_MPI_PAIRS, POSE_MPI_PAIRS}; const std::array, 3> POSE_MAP_IDX{ POSE_COCO_MAP_IDX, POSE_MPI_MAP_IDX, POSE_MPI_MAP_IDX}; const std::array POSE_PROTOTXT{ "pose/coco/pose_deploy_linevec.prototxt", "pose/mpi/pose_deploy_linevec.prototxt", @@ -74,17 +112,17 @@ namespace op const std::array POSE_TRAINED_MODEL{ "pose/coco/pose_iter_440000.caffemodel", "pose/mpi/pose_iter_160000.caffemodel", "pose/mpi/pose_iter_160000.caffemodel"}; - // POSE_BODY_PART_MAPPING crashes on Windows at dynamic initialization, to avoid this crash: - // POSE_BODY_PART_MAPPING has been moved to poseParameters.cpp and getPoseBodyPartMapping() wraps it - //const std::array, 3> POSE_BODY_PART_MAPPING{ POSE_COCO_BODY_PARTS, POSE_MPI_BODY_PARTS, POSE_MPI_BODY_PARTS}; - const std::map& getPoseBodyPartMapping(const PoseModel poseModel); + // POSE_BODY_PART_MAPPING crashes on Windows at dynamic initialization, to avoid this crash: + // POSE_BODY_PART_MAPPING has been moved to poseParameters.cpp and getPoseBodyPartMapping() wraps it + //const std::array, 3> POSE_BODY_PART_MAPPING{ POSE_COCO_BODY_PARTS, POSE_MPI_BODY_PARTS, POSE_MPI_BODY_PARTS}; + const std::map& getPoseBodyPartMapping(const PoseModel poseModel); // Default Model Parameters // They might be modified on running time const std::array POSE_DEFAULT_NMS_THRESHOLD{ 0.05f, 0.6f, 0.3f}; - const std::array POSE_DEFAULT_CONNECT_INTER_MIN_ABOVE_THRESHOLD{ 9, 8, 8}; + const std::array POSE_DEFAULT_CONNECT_INTER_MIN_ABOVE_THRESHOLD{ 9, 8, 8}; const std::array POSE_DEFAULT_CONNECT_INTER_THRESHOLD{ 0.05f, 0.01f, 0.01f}; - const std::array POSE_DEFAULT_CONNECT_MIN_SUBSET_CNT{ 3, 3, 3}; + const std::array POSE_DEFAULT_CONNECT_MIN_SUBSET_CNT{ 3, 3, 3}; const std::array POSE_DEFAULT_CONNECT_MIN_SUBSET_SCORE{ 0.4f, 0.4f, 0.4f}; // Rendering default parameters diff --git a/include/openpose/pose/poseRenderGpu.hpp b/include/openpose/pose/poseRenderGpu.hpp deleted file mode 100644 index d42743cc..00000000 --- a/include/openpose/pose/poseRenderGpu.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef OPENPOSE_POSE_GPU_POSE_RENDER_HPP -#define OPENPOSE_POSE_GPU_POSE_RENDER_HPP - -#include -#include "enumClasses.hpp" -#include "poseParameters.hpp" - -namespace op -{ - void renderPoseGpu(float* framePtr, const PoseModel poseModel, const int numberPeople, const Point& frameSize, const float* const posePtr, - const bool googlyEyes = false, const bool blendOriginalFrame = true, const float alphaBlending = POSE_DEFAULT_ALPHA_KEYPOINT); - void renderBodyPartGpu(float* frame, const PoseModel poseModel, const Point& frameSize, const float* const heatmap, const Point& heatmapSize, - const float scaleToKeepRatio, const int part, const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP); - void renderBodyPartsGpu(float* frame, const PoseModel poseModel, const Point& frameSize, const float* const heatmap, const Point& heatmapSize, - const float scaleToKeepRatio, const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP); - void renderPartAffinityFieldGpu(float* framePtr, const PoseModel poseModel, const Point& frameSize, const float* const heatmapPtr, - const Point& heatmapSize, const float scaleToKeepRatio, const int part, const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP); - void renderPartAffinityFieldsGpu(float* framePtr, const PoseModel poseModel, const Point& frameSize, const float* const heatmapPtr, - const Point& heatmapSize, const float scaleToKeepRatio, const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP); -} - -#endif // OPENPOSE_POSE_GPU_POSE_RENDER_HPP diff --git a/include/openpose/pose/poseRenderer.hpp b/include/openpose/pose/poseRenderer.hpp index 4ad50bf5..daf6c57a 100644 --- a/include/openpose/pose/poseRenderer.hpp +++ b/include/openpose/pose/poseRenderer.hpp @@ -3,6 +3,7 @@ #include // std::shared_ptr #include +#include #include #include #include @@ -14,9 +15,10 @@ namespace op class PoseRenderer : public Renderer { public: - explicit PoseRenderer(const Point& heatMapsSize, const Point& outputSize, const PoseModel poseModel, const std::shared_ptr& poseExtractor, - const bool blendOriginalFrame = true, const float alphaKeypoint = POSE_DEFAULT_ALPHA_KEYPOINT, - const float alphaHeatMap = POSE_DEFAULT_ALPHA_HEAT_MAP, const unsigned int elementToRender = 0u); + explicit PoseRenderer(const Point& heatMapsSize, const Point& outputSize, const PoseModel poseModel, + const std::shared_ptr& poseExtractor, const bool blendOriginalFrame = true, + const float alphaKeypoint = POSE_DEFAULT_ALPHA_KEYPOINT, const float alphaHeatMap = POSE_DEFAULT_ALPHA_HEAT_MAP, + const unsigned int elementToRender = 0u, const RenderMode renderMode = RenderMode::Cpu); ~PoseRenderer(); @@ -38,10 +40,15 @@ namespace op const PoseModel mPoseModel; const std::map mPartIndexToName; const std::shared_ptr spPoseExtractor; + const RenderMode mRenderMode; std::atomic mBlendOriginalFrame; std::atomic mShowGooglyEyes; // Init with thread - float* pGpuPose; // GPU aux memory + float* pGpuPose; // GPU aux memory + + std::pair renderPoseCpu(Array& outputData, const Array& poseKeypoints, const float scaleNetToOutput = -1.f); + + std::pair renderPoseGpu(Array& outputData, const Array& poseKeypoints, const float scaleNetToOutput = -1.f); DELETE_COPY(PoseRenderer); }; diff --git a/include/openpose/pose/renderPose.hpp b/include/openpose/pose/renderPose.hpp new file mode 100644 index 00000000..d8e86c2f --- /dev/null +++ b/include/openpose/pose/renderPose.hpp @@ -0,0 +1,36 @@ +#ifndef OPENPOSE_POSE_RENDER_POSE_HPP +#define OPENPOSE_POSE_RENDER_POSE_HPP + +#include // cv::Mat +#include +#include +#include "enumClasses.hpp" +#include "poseParameters.hpp" + +namespace op +{ + void renderPoseKeypointsCpu(Array& frameArray, const Array& poseKeypoints, const PoseModel poseModel, + const bool blendOriginalFrame = true); + + void renderPoseKeypointsGpu(float* framePtr, const PoseModel poseModel, const int numberPeople, const Point& frameSize, + const float* const posePtr, const bool googlyEyes = false, const bool blendOriginalFrame = true, + const float alphaBlending = POSE_DEFAULT_ALPHA_KEYPOINT); + + void renderPoseHeatMapGpu(float* frame, const PoseModel poseModel, const Point& frameSize, const float* const heatmap, + const Point& heatmapSize, const float scaleToKeepRatio, const int part, + const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP); + + void renderPoseHeatMapsGpu(float* frame, const PoseModel poseModel, const Point& frameSize, const float* const heatmap, + const Point& heatmapSize, const float scaleToKeepRatio, + const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP); + + void renderPosePAFGpu(float* framePtr, const PoseModel poseModel, const Point& frameSize, const float* const heatmapPtr, + const Point& heatmapSize, const float scaleToKeepRatio, const int part, + const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP); + + void renderPosePAFsGpu(float* framePtr, const PoseModel poseModel, const Point& frameSize, const float* const heatmapPtr, + const Point& heatmapSize, const float scaleToKeepRatio, + const float alphaBlending = POSE_DEFAULT_ALPHA_HEAT_MAP); +} + +#endif // OPENPOSE_POSE_RENDER_POSE_HPP diff --git a/include/openpose/thread/workerConsumer.hpp b/include/openpose/thread/workerConsumer.hpp index 66b146b1..00c894c3 100644 --- a/include/openpose/thread/workerConsumer.hpp +++ b/include/openpose/thread/workerConsumer.hpp @@ -13,7 +13,7 @@ namespace op inline void work(TDatums& tDatums) { - workConsumer(tDatums); + workConsumer(tDatums); } protected: diff --git a/include/openpose/utilities/cuda.hpp b/include/openpose/utilities/cuda.hpp index 6c2d880a..b3de9b86 100644 --- a/include/openpose/utilities/cuda.hpp +++ b/include/openpose/utilities/cuda.hpp @@ -20,7 +20,7 @@ namespace op return (totalRequired + numberCudaThreads - 1) / numberCudaThreads; } - dim3 getNumberCudaBlocks(const Point& frameSize, const dim3 numberCudaThreads = dim3{ CUDA_NUM_THREADS, CUDA_NUM_THREADS, 1 }); + dim3 getNumberCudaBlocks(const Point& frameSize, const dim3 numberCudaThreads = dim3{ CUDA_NUM_THREADS, CUDA_NUM_THREADS, 1 }); std::pair getNumberCudaThreadsAndBlocks(const Point& frameSize); } diff --git a/include/openpose/utilities/headers.hpp b/include/openpose/utilities/headers.hpp index c0acf06a..7043f03a 100644 --- a/include/openpose/utilities/headers.hpp +++ b/include/openpose/utilities/headers.hpp @@ -8,6 +8,7 @@ #include "errorAndLog.hpp" #include "fastMath.hpp" #include "fileSystem.hpp" +#include "keypoint.hpp" #include "macros.hpp" #include "openCv.hpp" #include "pointerContainer.hpp" diff --git a/include/openpose/utilities/keypoint.hpp b/include/openpose/utilities/keypoint.hpp new file mode 100644 index 00000000..4b5d08ed --- /dev/null +++ b/include/openpose/utilities/keypoint.hpp @@ -0,0 +1,28 @@ +#ifndef OPENPOSE_UTILITIES_KEYPOINT_HPP +#define OPENPOSE_UTILITIES_KEYPOINT_HPP + +#include +#include +#include + +namespace op +{ + float getDistance(const float* keypointPtr, const int elementA, const int elementB); + + void scaleKeypoints(Array& keypoints, const float scale); + + void scaleKeypoints(Array& keypoints, const float scaleX, const float scaleY); + + void scaleKeypoints(Array& keypoints, const float scaleX, const float scaleY, const float offsetX, const float offsetY); + + void renderKeypointsCpu(Array& frameArray, const Array& keypoints, const std::vector& pairs, + const std::vector colors, const float thicknessCircleRatio, const float thicknessLineRatioWRTCircle); + + Rectangle getKeypointsRectangle(const float* keypointPtr, const int numberBodyParts, const float threshold); + + int getKeypointsArea(const float* keypointPtr, const int numberBodyParts, const float threshold); + + int getBiggestPerson(const Array& keypoints, const float threshold); +} + +#endif // OPENPOSE_UTILITIES_KEYPOINT_HPP diff --git a/include/openpose/wrapper/wrapper.hpp b/include/openpose/wrapper/wrapper.hpp index cd5d353f..8fac32f6 100644 --- a/include/openpose/wrapper/wrapper.hpp +++ b/include/openpose/wrapper/wrapper.hpp @@ -80,17 +80,15 @@ namespace op // Consumer (keep default values to disable any output) const WrapperStructOutput& wrapperStructOutput = WrapperStructOutput{}); - // THIS FUNCTION IS NOT IMPLEMENTED YET -> COMING SOON // Similar to the previos configure, but it includes hand extraction and rendering void configure(const WrapperStructPose& wrapperStructPose, // Hand (use the default WrapperStructHand{} to disable any hand detector) - const experimental::WrapperStructHand& wrapperHandStruct, + const experimental::WrapperStructHand& wrapperStructHand, // Producer (set producerSharedPtr = nullptr or use the default WrapperStructInput{} to disable any input) const WrapperStructInput& wrapperStructInput, // Consumer (keep default values to disable any output) const WrapperStructOutput& wrapperStructOutput = WrapperStructOutput{}); - // THIS FUNCTION IS NOT IMPLEMENTED YET -> COMING SOON // Similar to the previos configure, but it includes hand extraction and rendering void configure(const WrapperStructPose& wrapperStructPose, // Face (use the default WrapperStructFace{} to disable any face detector) @@ -100,13 +98,12 @@ namespace op // Consumer (keep default values to disable any output) const WrapperStructOutput& wrapperStructOutput = WrapperStructOutput{}); - // THIS FUNCTION IS NOT IMPLEMENTED YET -> COMING SOON // Similar to the previos configure, but it includes hand extraction and rendering void configure(const WrapperStructPose& wrapperStructPose = WrapperStructPose{}, // Face (use the default WrapperStructFace{} to disable any face detector) const WrapperStructFace& wrapperStructFace = WrapperStructFace{}, // Hand (use the default WrapperStructHand{} to disable any hand detector) - const experimental::WrapperStructHand& wrapperHandStruct = experimental::WrapperStructHand{}, + const experimental::WrapperStructHand& wrapperStructHand = experimental::WrapperStructHand{}, // Producer (set producerSharedPtr = nullptr or use the default WrapperStructInput{} to disable any input) const WrapperStructInput& wrapperStructInput = WrapperStructInput{}, // Consumer (keep default values to disable any output) @@ -372,12 +369,14 @@ namespace op } template - void Wrapper::configure(const WrapperStructPose& wrapperStructPose, const WrapperStructInput& wrapperStructInput, + void Wrapper::configure(const WrapperStructPose& wrapperStructPose, + const WrapperStructInput& wrapperStructInput, const WrapperStructOutput& wrapperStructOutput) { try { - configure(wrapperStructPose, WrapperStructFace{}, experimental::WrapperStructHand{}, wrapperStructInput, wrapperStructOutput); + configure(wrapperStructPose, WrapperStructFace{}, experimental::WrapperStructHand{}, + wrapperStructInput, wrapperStructOutput); } catch (const std::exception& e) { @@ -386,12 +385,15 @@ namespace op } template - void Wrapper::configure(const WrapperStructPose& wrapperStructPose, const WrapperStructFace& wrapperStructFace, - const WrapperStructInput& wrapperStructInput, const WrapperStructOutput& wrapperStructOutput) + void Wrapper::configure(const WrapperStructPose& wrapperStructPose, + const WrapperStructFace& wrapperStructFace, + const WrapperStructInput& wrapperStructInput, + const WrapperStructOutput& wrapperStructOutput) { try { - configure(wrapperStructPose, wrapperStructFace, experimental::WrapperStructHand{}, wrapperStructInput, wrapperStructOutput); + configure(wrapperStructPose, wrapperStructFace, experimental::WrapperStructHand{}, + wrapperStructInput, wrapperStructOutput); } catch (const std::exception& e) { @@ -400,12 +402,15 @@ namespace op } template - void Wrapper::configure(const WrapperStructPose& wrapperStructPose, const experimental::WrapperStructHand& wrapperHandStruct, - const WrapperStructInput& wrapperStructInput, const WrapperStructOutput& wrapperStructOutput) + void Wrapper::configure(const WrapperStructPose& wrapperStructPose, + const experimental::WrapperStructHand& wrapperStructHand, + const WrapperStructInput& wrapperStructInput, + const WrapperStructOutput& wrapperStructOutput) { try { - configure(wrapperStructPose, WrapperStructFace{}, wrapperHandStruct, wrapperStructInput, wrapperStructOutput); + configure(wrapperStructPose, WrapperStructFace{}, wrapperStructHand, + wrapperStructInput, wrapperStructOutput); } catch (const std::exception& e) { @@ -414,8 +419,10 @@ namespace op } template - void Wrapper::configure(const WrapperStructPose& wrapperStructPose, const WrapperStructFace& wrapperStructFace, - const experimental::WrapperStructHand& wrapperHandStruct, const WrapperStructInput& wrapperStructInput, + void Wrapper::configure(const WrapperStructPose& wrapperStructPose, + const WrapperStructFace& wrapperStructFace, + const experimental::WrapperStructHand& wrapperStructHand, + const WrapperStructInput& wrapperStructInput, const WrapperStructOutput& wrapperStructOutput) { try @@ -426,8 +433,9 @@ namespace op typedef std::shared_ptr TDatumsPtr; // Required parameters - const auto renderOutput = wrapperStructPose.renderOutput || wrapperStructFace.renderOutput; - const auto renderFace = wrapperStructFace.enable && wrapperStructFace.renderOutput; + const auto renderOutput = wrapperStructPose.renderMode != RenderMode::None || wrapperStructFace.renderMode != RenderMode::None; + const auto renderOutputGpu = wrapperStructPose.renderMode == RenderMode::Gpu || wrapperStructFace.renderMode == RenderMode::Gpu; + const auto renderFace = wrapperStructFace.enable && wrapperStructFace.renderMode != RenderMode::None; // Check no wrong/contradictory flags enabled if (wrapperStructPose.alphaKeypoint < 0. || wrapperStructPose.alphaKeypoint > 1. @@ -563,22 +571,38 @@ namespace op // Pose renderers std::vector> poseRenderers; - if (wrapperStructPose.renderOutput || renderOutput) + std::shared_ptr poseCpuRenderer; + std::vector cpuRenderers; + if (renderOutputGpu || wrapperStructPose.renderMode == RenderMode::Cpu) { - // If !wrapperStructPose.renderOutput but renderOutput, then we create an alpha = 0 pose renderer + // If !wrapperStructPose.renderMode == RenderMode::Gpu but renderOutput, then we create an alpha = 0 pose renderer // in order to keep the removing background option - const auto alphaKeypoint = (wrapperStructPose.renderOutput ? wrapperStructPose.alphaKeypoint : 0.f); - const auto alphaHeatMap = (wrapperStructPose.renderOutput ? wrapperStructPose.alphaHeatMap : 0.f); - for (auto gpuId = 0; gpuId < poseExtractors.size(); gpuId++) + const auto alphaKeypoint = (wrapperStructPose.renderMode != RenderMode::None ? wrapperStructPose.alphaKeypoint : 0.f); + const auto alphaHeatMap = (wrapperStructPose.renderMode != RenderMode::None ? wrapperStructPose.alphaHeatMap : 0.f); + // GPU rendering + if (renderOutputGpu) { - poseRenderers.emplace_back(std::make_shared( - poseNetOutputSize, finalOutputSize, wrapperStructPose.poseModel, poseExtractors[gpuId], - wrapperStructPose.blendOriginalFrame, alphaKeypoint, - alphaHeatMap, wrapperStructPose.defaultPartToRender - )); + for (auto gpuId = 0; gpuId < poseExtractors.size(); gpuId++) + { + poseRenderers.emplace_back(std::make_shared( + poseNetOutputSize, finalOutputSize, wrapperStructPose.poseModel, poseExtractors[gpuId], + wrapperStructPose.blendOriginalFrame, alphaKeypoint, + alphaHeatMap, wrapperStructPose.defaultPartToRender, wrapperStructPose.renderMode + )); + } } + // CPU rendering + if (wrapperStructPose.renderMode == RenderMode::Cpu) + { + poseCpuRenderer = std::make_shared( + poseNetOutputSize, finalOutputSize, wrapperStructPose.poseModel, nullptr, + wrapperStructPose.blendOriginalFrame, alphaKeypoint, + alphaHeatMap, wrapperStructPose.defaultPartToRender, wrapperStructPose.renderMode + ); + cpuRenderers.emplace_back(std::make_shared>(poseCpuRenderer)); + } + log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); } - log("", Priority::Low, __LINE__, __FUNCTION__, __FILE__); // Input cvMat to OpenPose format const auto cvMatToOpInput = std::make_shared( @@ -589,7 +613,6 @@ namespace op spWCvMatToOpOutput = std::make_shared>(cvMatToOpOutput); // Pose extractor(s) - spWPoses.clear(); spWPoses.resize(poseExtractors.size()); for (auto i = 0; i < spWPoses.size(); i++) spWPoses.at(i) = {std::make_shared>(poseExtractors.at(i))}; @@ -612,7 +635,7 @@ namespace op } // Hand extractor(s) - if (wrapperHandStruct.extractAndRenderHands) + if (wrapperStructHand.extractAndRenderHands) { for (auto gpuId = 0; gpuId < spWPoses.size(); gpuId++) { @@ -624,44 +647,76 @@ namespace op } // Pose renderer(s) - if (!poseRenderers.empty()) + if (renderOutputGpu && !poseRenderers.empty()) for (auto i = 0; i < spWPoses.size(); i++) spWPoses.at(i).emplace_back(std::make_shared>(poseRenderers.at(i))); - // Hands renderer(s) - if (wrapperHandStruct.extractAndRenderHands) - { - for (auto i = 0; i < spWPoses.size(); i++) - { - // Construct hands renderer - const auto handRenderer = std::make_shared(finalOutputSize); - // Performance boost -> share spGpuMemoryPtr for all renderers - if (!poseRenderers.empty()) - { - const bool isLastRenderer = (!renderFace); - handRenderer->setSharedParametersAndIfLast(poseRenderers.at(i)->getSharedParameters(), isLastRenderer); - } - // Add worker - spWPoses.at(i).emplace_back(std::make_shared>(handRenderer)); - } - } - // Face renderer(s) if (renderFace) { - for (auto i = 0; i < spWPoses.size(); i++) + // CPU rendering + if (wrapperStructFace.renderMode == RenderMode::Cpu) { // Construct face renderer - const auto faceRenderer = std::make_shared(finalOutputSize, wrapperStructFace.alphaKeypoint, wrapperStructFace.alphaHeatMap); - // Performance boost -> share spGpuMemoryPtr for all renderers - if (!poseRenderers.empty()) - { - const bool isLastRenderer = true; - faceRenderer->setSharedParametersAndIfLast(poseRenderers.at(i)->getSharedParameters(), isLastRenderer); - } + const auto faceRenderer = std::make_shared(finalOutputSize, wrapperStructFace.alphaKeypoint, + wrapperStructFace.alphaHeatMap, + wrapperStructFace.renderMode); // Add worker - spWPoses.at(i).emplace_back(std::make_shared>(faceRenderer)); + cpuRenderers.emplace_back(std::make_shared>(faceRenderer)); } + // GPU rendering + else if (wrapperStructFace.renderMode == RenderMode::Gpu) + { + for (auto i = 0; i < spWPoses.size(); i++) + { + // Construct face renderer + const auto faceRenderer = std::make_shared(finalOutputSize, wrapperStructFace.alphaKeypoint, + wrapperStructFace.alphaHeatMap, + wrapperStructFace.renderMode); + // Performance boost -> share spGpuMemoryPtr for all renderers + if (!poseRenderers.empty()) + { + const bool isLastRenderer = (!wrapperStructHand.extractAndRenderHands); + faceRenderer->setSharedParametersAndIfLast(poseRenderers.at(i)->getSharedParameters(), isLastRenderer); + } + // Add worker + spWPoses.at(i).emplace_back(std::make_shared>(faceRenderer)); + } + } + else + error("Unknown RenderMode.", __LINE__, __FUNCTION__, __FILE__); + } + + // Hands renderer(s) + if (wrapperStructHand.extractAndRenderHands) + { + // CPU rendering + // if (wrapperStructHand.renderMode == RenderMode::Cpu) + { + // Construct hand renderer + const auto handRenderer = std::make_shared(finalOutputSize); + // Add worker + cpuRenderers.emplace_back(std::make_shared>(handRenderer)); + } + // GPU rendering + // else if (wrapperStructHand.renderMode == RenderMode::Gpu) + // { + // for (auto i = 0; i < spWPoses.size(); i++) + // { + // // Construct hands renderer + // const auto handRenderer = std::make_shared(finalOutputSize); + // // Performance boost -> share spGpuMemoryPtr for all renderers + // if (!poseRenderers.empty()) + // { + // const bool isLastRenderer = true; + // handRenderer->setSharedParametersAndIfLast(poseRenderers.at(i)->getSharedParameters(), isLastRenderer); + // } + // // Add worker + // spWPoses.at(i).emplace_back(std::make_shared>(handRenderer)); + // } + // } + // else + // error("Unknown RenderMode.", __LINE__, __FUNCTION__, __FILE__); } // Itermediate workers (e.g. OpenPose format to cv::Mat, json & frames recorder, ...) @@ -672,6 +727,7 @@ namespace op // Frames processor (OpenPose format -> cv::Mat format) if (renderOutput) { + mPostProcessingWs = mergeWorkers(mPostProcessingWs, cpuRenderers); const auto opOutputToCvMat = std::make_shared(finalOutputSize); mPostProcessingWs.emplace_back(std::make_shared>(opOutputToCvMat)); } @@ -692,7 +748,7 @@ namespace op mOutputWs.emplace_back(std::make_shared>(keypointSaver)); if (wrapperStructFace.enable) mOutputWs.emplace_back(std::make_shared>(keypointSaver)); - if (wrapperHandStruct.extractAndRenderHands) + if (wrapperStructHand.extractAndRenderHands) mOutputWs.emplace_back(std::make_shared>(keypointSaver)); } // Write people pose data on disk (json format) @@ -702,7 +758,7 @@ namespace op mOutputWs.emplace_back(std::make_shared>(keypointJsonSaver)); if (wrapperStructFace.enable) mOutputWs.emplace_back(std::make_shared>(keypointJsonSaver)); - if (wrapperHandStruct.extractAndRenderHands) + if (wrapperStructHand.extractAndRenderHands) mOutputWs.emplace_back(std::make_shared>(keypointJsonSaver)); } // Write people pose data on disk (COCO validation json format) @@ -750,7 +806,8 @@ namespace op if (wrapperStructOutput.displayGui) { const auto gui = std::make_shared( - wrapperStructOutput.fullScreen, finalOutputSize, mThreadManager.getIsRunningSharedPtr(), spVideoSeek, poseExtractors, poseRenderers + wrapperStructOutput.fullScreen, finalOutputSize, mThreadManager.getIsRunningSharedPtr(), spVideoSeek, poseExtractors, + (wrapperStructPose.renderMode == RenderMode::Cpu ? std::vector>{poseCpuRenderer} : poseRenderers) ); spWGui = {std::make_shared>(gui)}; } diff --git a/include/openpose/wrapper/wrapperStructFace.hpp b/include/openpose/wrapper/wrapperStructFace.hpp index 29f79dd0..b9aa36f0 100644 --- a/include/openpose/wrapper/wrapperStructFace.hpp +++ b/include/openpose/wrapper/wrapperStructFace.hpp @@ -1,6 +1,7 @@ #ifndef OPENPOSE_WRAPPER_WRAPPER_STRUCT_FACE_HPP #define OPENPOSE_WRAPPER_WRAPPER_STRUCT_FACE_HPP +#include #include #include @@ -27,9 +28,10 @@ namespace op Point netInputSize; /** - * Whether to render the output (pose locations, face, background or PAF heat maps). + * Whether to render the output (pose locations, body, background or PAF heat maps) with CPU or GPU. + * Select `None` for no rendering, `Cpu` or `Gpu` por CPU and GPU rendering respectively. */ - bool renderOutput; + RenderMode renderMode; /** * Rendering blending alpha value of the pose point locations with respect to the background image. @@ -49,7 +51,8 @@ namespace op * Since all the elements of the struct are public, they can also be manually filled. */ WrapperStructFace(const bool enable = false, const Point& netInputSize = Point{368, 368}, - const bool renderOutput = false, const float alphaKeypoint = FACE_DEFAULT_ALPHA_KEYPOINT, + const RenderMode renderMode = RenderMode::None, + const float alphaKeypoint = FACE_DEFAULT_ALPHA_KEYPOINT, const float alphaHeatMap = FACE_DEFAULT_ALPHA_HEAT_MAP); }; } diff --git a/include/openpose/wrapper/wrapperStructPose.hpp b/include/openpose/wrapper/wrapperStructPose.hpp index 2c3bb3fe..a8844d84 100644 --- a/include/openpose/wrapper/wrapperStructPose.hpp +++ b/include/openpose/wrapper/wrapperStructPose.hpp @@ -63,9 +63,10 @@ namespace op float scaleGap; /** - * Whether to render the output (pose locations, body, background or PAF heat maps). + * Whether to render the output (pose locations, body, background or PAF heat maps) with CPU or GPU. + * Select `None` for no rendering, `Cpu` or `Gpu` por CPU and GPU rendering respectively. */ - bool renderOutput; + RenderMode renderMode; /** * Pose model, it affects the number of body parts to render @@ -124,7 +125,7 @@ namespace op */ WrapperStructPose(const Point& netInputSize = Point{656, 368}, const Point& outputSize = Point{1280, 720}, const ScaleMode keypointScale = ScaleMode::InputResolution, const int gpuNumber = 1, const int gpuNumberStart = 0, - const int scalesNumber = 1, const float scaleGap = 0.15f, const bool renderOutput = false, + const int scalesNumber = 1, const float scaleGap = 0.15f, const RenderMode renderMode = RenderMode::None, const PoseModel poseModel = PoseModel::COCO_18, const bool blendOriginalFrame = true, const float alphaKeypoint = POSE_DEFAULT_ALPHA_KEYPOINT, const float alphaHeatMap = POSE_DEFAULT_ALPHA_HEAT_MAP, const int defaultPartToRender = 0, const std::string& modelFolder = "models/", diff --git a/models/pose/coco/pose_deploy_linevec.prototxt b/models/pose/coco/pose_deploy_linevec.prototxt index 2048c2e8..fbe0c824 100755 --- a/models/pose/coco/pose_deploy_linevec.prototxt +++ b/models/pose/coco/pose_deploy_linevec.prototxt @@ -1,8 +1,8 @@ input: "image" input_dim: 1 input_dim: 3 -input_dim: 1 # This value will be defined at runtime -input_dim: 1 # This value will be defined at runtime +input_dim: 1 # This value will be defined at runtime +input_dim: 1 # This value will be defined at runtime layer { name: "conv1_1" type: "Convolution" diff --git a/models/pose/mpi/pose_deploy_linevec.prototxt b/models/pose/mpi/pose_deploy_linevec.prototxt index c4251176..54492d68 100755 --- a/models/pose/mpi/pose_deploy_linevec.prototxt +++ b/models/pose/mpi/pose_deploy_linevec.prototxt @@ -1,8 +1,8 @@ input: "image" input_dim: 1 input_dim: 3 -input_dim: 1 # This value will be defined at runtime -input_dim: 1 # This value will be defined at runtime +input_dim: 1 # This value will be defined at runtime +input_dim: 1 # This value will be defined at runtime layer { name: "conv1_1" type: "Convolution" diff --git a/models/pose/mpi/pose_deploy_linevec_faster_4_stages.prototxt b/models/pose/mpi/pose_deploy_linevec_faster_4_stages.prototxt index f92c6fc2..02ec1833 100644 --- a/models/pose/mpi/pose_deploy_linevec_faster_4_stages.prototxt +++ b/models/pose/mpi/pose_deploy_linevec_faster_4_stages.prototxt @@ -1,8 +1,8 @@ input: "image" input_dim: 1 input_dim: 3 -input_dim: 1 # This value will be defined at runtime -input_dim: 1 # This value will be defined at runtime +input_dim: 1 # This value will be defined at runtime +input_dim: 1 # This value will be defined at runtime layer { name: "conv1_1" type: "Convolution" diff --git a/src/openpose/core/array.cpp b/src/openpose/core/array.cpp index 3d42813b..d16f2385 100644 --- a/src/openpose/core/array.cpp +++ b/src/openpose/core/array.cpp @@ -322,13 +322,25 @@ namespace op { try { - if (mCvMatData.first) - return mCvMatData.second; - else - { + if (!mCvMatData.first) error("Array: cv::Mat functions only valid for T types defined by OpenCV: unsigned char, signed char, int, float & double", __LINE__, __FUNCTION__, __FILE__); - return mCvMatData.second; - } + return mCvMatData.second; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return mCvMatData.second; + } + } + + template + cv::Mat& Array::getCvMat() + { + try + { + if (!mCvMatData.first) + error("Array: cv::Mat functions only valid for T types defined by OpenCV: unsigned char, signed char, int, float & double", __LINE__, __FUNCTION__, __FILE__); + return mCvMatData.second; } catch (const std::exception& e) { diff --git a/src/openpose/core/keypointScaler.cpp b/src/openpose/core/keypointScaler.cpp index c2081f75..c90ca765 100644 --- a/src/openpose/core/keypointScaler.cpp +++ b/src/openpose/core/keypointScaler.cpp @@ -1,5 +1,5 @@ -#include #include +#include #include namespace op diff --git a/src/openpose/core/renderer.cpp b/src/openpose/core/renderer.cpp index bc916ea7..dfde23fb 100644 --- a/src/openpose/core/renderer.cpp +++ b/src/openpose/core/renderer.cpp @@ -1,12 +1,14 @@ -#include -#include +#ifndef CPU_ONLY + #include + #include +#endif #include #include namespace op { - Renderer::Renderer(const unsigned long long volume, const float alphaKeypoint, const float alphaHeatMap, const unsigned int elementToRender, - const unsigned int numberElementsToRender) : + Renderer::Renderer(const unsigned long long volume, const float alphaKeypoint, const float alphaHeatMap, + const unsigned int elementToRender, const unsigned int numberElementsToRender) : spGpuMemoryPtr{std::make_shared()}, spElementToRender{std::make_shared>(elementToRender)}, spNumberElementsToRender{std::make_shared(numberElementsToRender)}, @@ -23,8 +25,10 @@ namespace op { try { - if (mIsLastRenderer) - cudaFree(*spGpuMemoryPtr); + #ifndef CPU_ONLY + if (mIsLastRenderer) + cudaFree(*spGpuMemoryPtr); + #endif } catch (const std::exception& e) { @@ -36,8 +40,10 @@ namespace op { try { - if (mIsFirstRenderer) - cudaMalloc((void**)(spGpuMemoryPtr.get()), mVolume * sizeof(float)); + #ifndef CPU_ONLY + if (mIsFirstRenderer) + cudaMalloc((void**)(spGpuMemoryPtr.get()), mVolume * sizeof(float)); + #endif } catch (const std::exception& e) { @@ -74,7 +80,8 @@ namespace op } } - std::tuple, std::shared_ptr, std::shared_ptr>, std::shared_ptr> Renderer::getSharedParameters() + std::tuple, std::shared_ptr, std::shared_ptr>, + std::shared_ptr> Renderer::getSharedParameters() { try { @@ -88,7 +95,8 @@ namespace op } } - void Renderer::setSharedParametersAndIfLast(const std::tuple, std::shared_ptr, std::shared_ptr>, + void Renderer::setSharedParametersAndIfLast(const std::tuple, std::shared_ptr, + std::shared_ptr>, std::shared_ptr>& tuple, const bool isLast) { try @@ -160,11 +168,16 @@ namespace op { try { - if (!*spGpuMemoryAllocated) - { - cudaMemcpy(*spGpuMemoryPtr, cpuMemory, mVolume * sizeof(float), cudaMemcpyHostToDevice); - *spGpuMemoryAllocated = true; - } + #ifndef CPU_ONLY + if (!*spGpuMemoryAllocated) + { + cudaMemcpy(*spGpuMemoryPtr, cpuMemory, mVolume * sizeof(float), cudaMemcpyHostToDevice); + *spGpuMemoryAllocated = true; + } + #else + error("GPU rendering not available if `CPU_ONLY` is set.", __LINE__, __FUNCTION__, __FILE__); + UNUSED(cpuMemory); + #endif } catch (const std::exception& e) { @@ -176,11 +189,16 @@ namespace op { try { - if (*spGpuMemoryAllocated && mIsLastRenderer) - { - cudaMemcpy(cpuMemory, *spGpuMemoryPtr, mVolume * sizeof(float), cudaMemcpyDeviceToHost); - *spGpuMemoryAllocated = false; - } + #ifndef CPU_ONLY + if (*spGpuMemoryAllocated && mIsLastRenderer) + { + cudaMemcpy(cpuMemory, *spGpuMemoryPtr, mVolume * sizeof(float), cudaMemcpyDeviceToHost); + *spGpuMemoryAllocated = false; + } + #else + error("GPU rendering not available if `CPU_ONLY` is set.", __LINE__, __FUNCTION__, __FILE__); + UNUSED(cpuMemory); + #endif } catch (const std::exception& e) { diff --git a/src/openpose/core/scaleKeypoints.cpp b/src/openpose/core/scaleKeypoints.cpp deleted file mode 100644 index 9952fde1..00000000 --- a/src/openpose/core/scaleKeypoints.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include - -namespace op -{ - const std::string errorMessage = "This function is only for array of dimension: [sizeA x sizeB x 3]."; - - void scaleKeypoints(Array& keypoints, const float scale) - { - try - { - scaleKeypoints(keypoints, scale, scale); - } - catch (const std::exception& e) - { - error(e.what(), __LINE__, __FUNCTION__, __FILE__); - } - } - - void scaleKeypoints(Array& keypoints, const float scaleX, const float scaleY) - { - try - { - if (scaleX != 1. && scaleY != 1.) - { - // Error check - if (!keypoints.empty() && keypoints.getSize(2) != 3) - error(errorMessage, __LINE__, __FUNCTION__, __FILE__); - // Get #people and #parts - const auto numberPeople = keypoints.getSize(0); - const auto numberParts = keypoints.getSize(1); - // For each person - for (auto person = 0 ; person < numberPeople ; person++) - { - // For each body part - for (auto part = 0 ; part < numberParts ; part++) - { - const auto finalIndex = 3*(person*numberParts + part); - keypoints[finalIndex] *= scaleX; - keypoints[finalIndex+1] *= scaleY; - } - } - } - } - catch (const std::exception& e) - { - error(e.what(), __LINE__, __FUNCTION__, __FILE__); - } - } - - void scaleKeypoints(Array& keypoints, const float scaleX, const float scaleY, const float offsetX, const float offsetY) - { - try - { - if (scaleX != 1. && scaleY != 1.) - { - // Error check - if (!keypoints.empty() && keypoints.getSize(2) != 3) - error(errorMessage, __LINE__, __FUNCTION__, __FILE__); - // Get #people and #parts - const auto numberPeople = keypoints.getSize(0); - const auto numberParts = keypoints.getSize(1); - // For each person - for (auto person = 0 ; person < numberPeople ; person++) - { - // For each body part - for (auto part = 0 ; part < numberParts ; part++) - { - const auto finalIndex = 3*(person*numberParts + part); - keypoints[finalIndex] = keypoints[finalIndex] * scaleX + offsetX; - keypoints[finalIndex+1] = keypoints[finalIndex+1] * scaleY + offsetY; - } - } - } - } - catch (const std::exception& e) - { - error(e.what(), __LINE__, __FUNCTION__, __FILE__); - } - } -} diff --git a/src/openpose/experimental/hand/handRenderer.cpp b/src/openpose/experimental/hand/handRenderer.cpp index 1a30e284..46be2796 100644 --- a/src/openpose/experimental/hand/handRenderer.cpp +++ b/src/openpose/experimental/hand/handRenderer.cpp @@ -1,7 +1,8 @@ -#include -#include -#include -#include +#ifndef CPU_ONLY + #include + #include +#endif +#include #include #include #include @@ -10,9 +11,10 @@ namespace op { namespace experimental { - HandRenderer::HandRenderer(const Point& frameSize) : - Renderer{(unsigned long long)(frameSize.area() * 3), HAND_DEFAULT_ALPHA_KEYPOINT, HAND_DEFAULT_ALPHA_HEAT_MAP}, - mFrameSize{frameSize} + HandRenderer::HandRenderer(const Point& frameSize, const float alphaKeypoint, const float alphaHeatMap, const RenderMode renderMode) : + Renderer{(unsigned long long)(frameSize.area() * 3), alphaKeypoint, alphaHeatMap}, + mFrameSize{frameSize}, + mRenderMode{renderMode} { } @@ -21,7 +23,9 @@ namespace op try { // Free CUDA pointers - Note that if pointers are 0 (i.e. nullptr), no operation is performed. - cudaFree(pGpuHands); + #ifndef CPU_ONLY + cudaFree(pGpuHands); + #endif } catch (const std::exception& e) { @@ -33,8 +37,13 @@ namespace op { try { + log("Starting initialization on thread.", Priority::Low, __LINE__, __FUNCTION__, __FILE__); Renderer::initializationOnThread(); - cudaMalloc((void**)(&pGpuHands), 2*HAND_NUMBER_PARTS * 3 * sizeof(float)); + // GPU memory allocation for rendering + #ifndef CPU_ONLY + cudaMalloc((void**)(&pGpuHands), 2*HAND_NUMBER_PARTS * 3 * sizeof(float)); + #endif + log("Finished initialization on thread.", Priority::Low, __LINE__, __FUNCTION__, __FILE__); } catch (const std::exception& e) { @@ -42,25 +51,67 @@ namespace op } } - void HandRenderer::renderHands(Array& outputData, const Array& handKeypoints) + void HandRenderer::renderHand(Array& outputData, const Array& handKeypoints) { try { - const auto elementRendered = spElementToRender->load(); // I prefer std::round(T&) over intRound(T) for std::atomic - const auto numberPeople = handKeypoints.getSize(0); + // Security checks + if (outputData.empty()) + error("Empty Array outputData.", __LINE__, __FUNCTION__, __FILE__); + + // CPU rendering + if (mRenderMode == RenderMode::Cpu) + renderHandCpu(outputData, handKeypoints); + // GPU rendering - if (numberPeople > 0 && elementRendered == 0) - { - cpuToGpuMemoryIfNotCopiedYet(outputData.getPtr()); - // Draw faceKeypoints - cudaMemcpy(pGpuHands, handKeypoints.getConstPtr(), 2*HAND_NUMBER_PARTS*3 * sizeof(float), cudaMemcpyHostToDevice); - renderHandsGpu(*spGpuMemoryPtr, mFrameSize, pGpuHands, handKeypoints.getSize(0)); - // CUDA check + else + renderHandGpu(outputData, handKeypoints); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + void HandRenderer::renderHandCpu(Array& outputData, const Array& handKeypoints) + { + try + { + renderHandKeypointsCpu(outputData, handKeypoints); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + void HandRenderer::renderHandGpu(Array& outputData, const Array& handKeypoints) + { + try + { + // GPU rendering + #ifndef CPU_ONLY + const auto elementRendered = spElementToRender->load(); // I prefer std::round(T&) over intRound(T) for std::atomic + const auto numberPeople = handKeypoints.getSize(0); + // GPU rendering + if (numberPeople > 0 && elementRendered == 0) + { + cpuToGpuMemoryIfNotCopiedYet(outputData.getPtr()); + // Draw handKeypoints + cudaMemcpy(pGpuHands, handKeypoints.getConstPtr(), 2*HAND_NUMBER_PARTS*3 * sizeof(float), cudaMemcpyHostToDevice); + renderHandKeypointsGpu(*spGpuMemoryPtr, mFrameSize, pGpuHands, handKeypoints.getSize(0)); + // CUDA check + cudaCheck(__LINE__, __FUNCTION__, __FILE__); + } + // GPU memory to CPU if last renderer + gpuToCpuMemoryIfLastRenderer(outputData.getPtr()); cudaCheck(__LINE__, __FUNCTION__, __FILE__); - } - // GPU memory to CPU if last renderer - gpuToCpuMemoryIfLastRenderer(outputData.getPtr()); - cudaCheck(__LINE__, __FUNCTION__, __FILE__); + // CPU_ONLY mode + #else + error("GPU rendering not available if `CPU_ONLY` is set.", __LINE__, __FUNCTION__, __FILE__); + UNUSED(outputData); + UNUSED(handKeypoints); + #endif } catch (const std::exception& e) { diff --git a/src/openpose/experimental/hand/renderHand.cpp b/src/openpose/experimental/hand/renderHand.cpp new file mode 100644 index 00000000..29d882e0 --- /dev/null +++ b/src/openpose/experimental/hand/renderHand.cpp @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include + +namespace op +{ + const std::vector COLORS{HAND_COLORS_RENDER}; + + void renderHandKeypointsCpu(Array& frameArray, const Array& handKeypoints) + { + try + { + if (!frameArray.empty()) + { + // Parameters + const auto thicknessCircleRatio = 1.f/200.f; + const auto thicknessLineRatioWRTCircle = 0.75f; + const auto& pairs = HAND_PAIRS_RENDER; + + // Render keypoints + renderKeypointsCpu(frameArray, handKeypoints, pairs, COLORS, thicknessCircleRatio, thicknessLineRatioWRTCircle); + } + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } +} diff --git a/src/openpose/experimental/hand/handRenderGpu.cu b/src/openpose/experimental/hand/renderHand.cu similarity index 63% rename from src/openpose/experimental/hand/handRenderGpu.cu rename to src/openpose/experimental/hand/renderHand.cu index 99922b67..3bc53df2 100644 --- a/src/openpose/experimental/hand/handRenderGpu.cu +++ b/src/openpose/experimental/hand/renderHand.cu @@ -3,37 +3,12 @@ #include #include #include -#include +#include namespace op { - __constant__ const unsigned int PART_PAIRS_GPU[] = HAND_PAIRS_TO_RENDER; - __constant__ const float RGB_COLORS[] = { - 179.f, 0.f, 0.f, - 204.f, 0.f, 0.f, - 230.f, 0.f, 0.f, - 255.f, 0.f, 0.f, - 143.f, 179.f, 0.f, - 163.f, 204.f, 0.f, - 184.f, 230.f, 0.f, - 204.f, 255.f, 0.f, - 0.f, 179.f, 71.f, - 0.f, 204.f, 82.f, - 0.f, 230.f, 92.f, - 0.f, 255.f, 102.f, - 0.f, 71.f, 179.f, - 0.f, 82.f, 204.f, - 0.f, 92.f, 230.f, - 0.f, 102.f, 255.f, - 143.f, 0.f, 179.f, - 163.f, 0.f, 204.f, - 184.f, 0.f, 230.f, - 204.f, 0.f, 255.f, - 179.f, 179.f, 179.f, - 179.f, 179.f, 179.f, - 179.f, 179.f, 179.f, - 179.f, 179.f, 179.f - }; + __constant__ const unsigned int PART_PAIRS_GPU[] = HAND_PAIRS_RENDER_GPU; + __constant__ const float COLORS[] = {HAND_COLORS_RENDER}; @@ -51,18 +26,19 @@ namespace op // Other parameters const auto numberPartPairs = sizeof(PART_PAIRS_GPU) / (2*sizeof(PART_PAIRS_GPU[0])); - const auto numberColors = sizeof(RGB_COLORS) / (3*sizeof(RGB_COLORS[0])); + const auto numberColors = sizeof(COLORS) / (3*sizeof(COLORS[0])); const auto radius = fastMin(targetWidth, targetHeight) / 100.f; const auto stickwidth = fastMin(targetWidth, targetHeight) / 80.f; // Render key points renderKeypoints(targetPtr, sharedMaxs, sharedMins, sharedScaleF, globalIdx, x, y, targetWidth, targetHeight, handsPtr, PART_PAIRS_GPU, numberHands, - HAND_NUMBER_PARTS, numberPartPairs, RGB_COLORS, numberColors, + HAND_NUMBER_PARTS, numberPartPairs, COLORS, numberColors, radius, stickwidth, threshold, alphaColorToAdd); } - void renderHandsGpu(float* framePtr, const Point& frameSize, const float* const handsPtr, const int numberHands, const float alphaColorToAdd) + void renderHandKeypointsGpu(float* framePtr, const Point& frameSize, const float* const handsPtr, const int numberHands, + const float alphaColorToAdd) { try { @@ -72,7 +48,8 @@ namespace op dim3 threadsPerBlock; dim3 numBlocks; std::tie(threadsPerBlock, numBlocks) = getNumberCudaThreadsAndBlocks(frameSize); - renderHandsParts<<>>(framePtr, frameSize.x, frameSize.y, handsPtr, numberHands, threshold, alphaColorToAdd); + renderHandsParts<<>>(framePtr, frameSize.x, frameSize.y, handsPtr, numberHands, threshold, + alphaColorToAdd); cudaCheck(__LINE__, __FUNCTION__, __FILE__); } } diff --git a/src/openpose/face/faceDetector.cpp b/src/openpose/face/faceDetector.cpp index 3c2a88bd..5c681fbd 100644 --- a/src/openpose/face/faceDetector.cpp +++ b/src/openpose/face/faceDetector.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include namespace op @@ -16,21 +17,6 @@ namespace op { } - float getDistance(const float* posePtr, const int elementA, const int elementB) - { - try - { - const auto pixelX = posePtr[elementA*3] - posePtr[elementB*3]; - const auto pixelY = posePtr[elementA*3+1] - posePtr[elementB*3+1]; - return std::sqrt(pixelX*pixelX+pixelY*pixelY); - } - catch (const std::exception& e) - { - error(e.what(), __LINE__, __FUNCTION__, __FILE__); - return -1.f; - } - } - inline Rectangle getFaceFromPoseKeypoints(const Array& poseKeypoints, const unsigned int personIndex, const unsigned int neck, const unsigned int nose, const unsigned int lEar, const unsigned int rEar, const unsigned int lEye, const unsigned int rEye, const float threshold) diff --git a/src/openpose/face/faceExtractor.cpp b/src/openpose/face/faceExtractor.cpp index 30d1cd84..8f4fab54 100644 --- a/src/openpose/face/faceExtractor.cpp +++ b/src/openpose/face/faceExtractor.cpp @@ -10,9 +10,11 @@ namespace op { - FaceExtractor::FaceExtractor(const Point& netInputSize, const Point& netOutputSize, const std::string& modelFolder, const int gpuId) : + FaceExtractor::FaceExtractor(const Point& netInputSize, const Point& netOutputSize, const std::string& modelFolder, + const int gpuId) : mNetOutputSize{netOutputSize}, - spNet{std::make_shared(std::array{1, 3, mNetOutputSize.y, mNetOutputSize.x}, modelFolder + FACE_PROTOTXT, modelFolder + FACE_TRAINED_MODEL, gpuId)}, + spNet{std::make_shared(std::array{1, 3, mNetOutputSize.y, mNetOutputSize.x}, modelFolder + FACE_PROTOTXT, + modelFolder + FACE_TRAINED_MODEL, gpuId)}, spResizeAndMergeCaffe{std::make_shared>()}, spNmsCaffe{std::make_shared>()}, mFaceImageCrop{mNetOutputSize.area()*3} @@ -21,6 +23,7 @@ namespace op { checkE(netOutputSize.x, netInputSize.x, "Net input and output size must be equal.", __LINE__, __FUNCTION__, __FILE__); checkE(netOutputSize.y, netInputSize.y, "Net input and output size must be equal.", __LINE__, __FUNCTION__, __FILE__); + checkE(netInputSize.x, netInputSize.y, "Net input size must be squared.", __LINE__, __FUNCTION__, __FILE__); // Properties for (auto& property : mProperties) property = 0.; @@ -77,24 +80,25 @@ namespace op // Set face size const auto numberPeople = (int)faceRectangles.size(); - mFaceKeypoints.reset({numberPeople, FACE_NUMBER_PARTS, 3}, 0); -// // Commented lines are for debugging -// log("\nAreas:"); -// cv::Mat cvInputDataCopy = cvInputData.clone(); + mFaceKeypoints.reset({numberPeople, (int)FACE_NUMBER_PARTS, 3}, 0); + + // // Debugging + // cv::Mat cvInputDataCopy = cvInputData.clone(); + // Extract face keypoints for each person for (auto person = 0 ; person < numberPeople ; person++) { // Only consider faces with a minimum pixel area const auto faceAreaSquared = std::sqrt(faceRectangles.at(person).area()); + // // Debugging + // log(std::to_string(cvInputData.cols) + " " + std::to_string(cvInputData.rows)); + // cv::rectangle(cvInputDataCopy, + // cv::Point{(int)faceRectangle.x, (int)faceRectangle.y}, + // cv::Point{(int)faceRectangle.bottomRight().x, (int)faceRectangle.bottomRight().y}, + // cv::Scalar{0,0,255}, 2); // Get parts if (faceAreaSquared > 50) { const auto& faceRectangle = faceRectangles.at(person); -// log(faceAreaSquared); -// log(std::to_string(cvInputData.cols) + " " + std::to_string(cvInputData.rows)); -// cv::rectangle(cvInputDataCopy, -// cv::Point{(int)faceRectangle.x, (int)faceRectangle.y}, -// cv::Point{(int)faceRectangle.bottomRight().x, (int)faceRectangle.bottomRight().y}, -// cv::Scalar{255,0,255}, 2); // Get face position(s) const Point faceCenterPosition{faceRectangle.topLeft()}; const auto faceSize = fastMax(faceRectangle.width, faceRectangle.height); @@ -112,8 +116,11 @@ namespace op // cv::Mat -> float* uCharCvMatToFloatPtr(mFaceImageCrop.getPtr(), faceImage, true); -// if (person < 5) -// cv::imshow("faceImage" + std::to_string(person), faceImage); + + // // Debugging + // if (person < 5) + // cv::imshow("faceImage" + std::to_string(person), faceImage); + // 1. Caffe deep network auto* inputDataGpuPtr = spNet->getInputDataGpuPtr(); cudaMemcpy(inputDataGpuPtr, mFaceImageCrop.getPtr(), mNetOutputSize.area() * 3 * sizeof(float), cudaMemcpyHostToDevice); @@ -162,7 +169,7 @@ namespace op const auto x = facePeaksPtr[xyIndex]; const auto y = facePeaksPtr[xyIndex + 1]; const auto score = facePeaksPtr[xyIndex + 2]; - const auto baseIndex = (person * FACE_NUMBER_PARTS + part) * 3; + const auto baseIndex = mFaceKeypoints.getSize(2) * (person * mFaceKeypoints.getSize(1) + part); mFaceKeypoints[baseIndex] = scaleInputToOutput * (Mscaling.at(0,0) * x + Mscaling.at(0,1) * y + Mscaling.at(0,2)); mFaceKeypoints[baseIndex+1] = scaleInputToOutput * (Mscaling.at(1,0) * x + Mscaling.at(1,1) * y + Mscaling.at(1,2)); mFaceKeypoints[baseIndex+2] = score; @@ -170,7 +177,8 @@ namespace op } } } -// cv::imshow("AcvInputDataCopy", cvInputDataCopy); + // // Debugging + // cv::imshow("AcvInputDataCopy", cvInputDataCopy); } else mFaceKeypoints.reset(); diff --git a/src/openpose/face/faceRenderer.cpp b/src/openpose/face/faceRenderer.cpp index 48689d86..b1d9d8ca 100644 --- a/src/openpose/face/faceRenderer.cpp +++ b/src/openpose/face/faceRenderer.cpp @@ -1,16 +1,18 @@ -#include -#include -#include -#include +#ifndef CPU_ONLY + #include + #include +#endif +#include #include #include #include namespace op { - FaceRenderer::FaceRenderer(const Point& frameSize, const float alphaKeypoint, const float alphaHeatMap) : + FaceRenderer::FaceRenderer(const Point& frameSize, const float alphaKeypoint, const float alphaHeatMap, const RenderMode renderMode) : Renderer{(unsigned long long)(frameSize.area() * 3), alphaKeypoint, alphaHeatMap}, - mFrameSize{frameSize} + mFrameSize{frameSize}, + mRenderMode{renderMode} { } @@ -19,7 +21,9 @@ namespace op try { // Free CUDA pointers - Note that if pointers are 0 (i.e. nullptr), no operation is performed. - cudaFree(pGpuFace); + #ifndef CPU_ONLY + cudaFree(pGpuFace); + #endif } catch (const std::exception& e) { @@ -31,8 +35,13 @@ namespace op { try { + log("Starting initialization on thread.", Priority::Low, __LINE__, __FUNCTION__, __FILE__); Renderer::initializationOnThread(); - cudaMalloc((void**)(&pGpuFace), POSE_MAX_PEOPLE * FACE_NUMBER_PARTS * 3 * sizeof(float)); + // GPU memory allocation for rendering + #ifndef CPU_ONLY + cudaMalloc((void**)(&pGpuFace), POSE_MAX_PEOPLE * FACE_NUMBER_PARTS * 3 * sizeof(float)); + #endif + log("Finished initialization on thread.", Priority::Low, __LINE__, __FUNCTION__, __FILE__); } catch (const std::exception& e) { @@ -44,21 +53,63 @@ namespace op { try { - const auto elementRendered = spElementToRender->load(); // I prefer std::round(T&) over intRound(T) for std::atomic - const auto numberPeople = faceKeypoints.getSize(0); + // Security checks + if (outputData.empty()) + error("Empty Array outputData.", __LINE__, __FUNCTION__, __FILE__); + + // CPU rendering + if (mRenderMode == RenderMode::Cpu) + renderFaceCpu(outputData, faceKeypoints); + // GPU rendering - if (numberPeople > 0 && elementRendered == 0) - { - cpuToGpuMemoryIfNotCopiedYet(outputData.getPtr()); - // Draw faceKeypoints - cudaMemcpy(pGpuFace, faceKeypoints.getConstPtr(), faceKeypoints.getSize(0) * FACE_NUMBER_PARTS * 3 * sizeof(float), cudaMemcpyHostToDevice); - renderFaceGpu(*spGpuMemoryPtr, mFrameSize, pGpuFace, faceKeypoints.getSize(0), getAlphaKeypoint()); - // CUDA check + else + renderFaceGpu(outputData, faceKeypoints); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + void FaceRenderer::renderFaceCpu(Array& outputData, const Array& faceKeypoints) + { + try + { + renderFaceKeypointsCpu(outputData, faceKeypoints); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + void FaceRenderer::renderFaceGpu(Array& outputData, const Array& faceKeypoints) + { + try + { + // GPU rendering + #ifndef CPU_ONLY + const auto elementRendered = spElementToRender->load(); // I prefer std::round(T&) over intRound(T) for std::atomic + const auto numberPeople = faceKeypoints.getSize(0); + if (numberPeople > 0 && elementRendered == 0) + { + cpuToGpuMemoryIfNotCopiedYet(outputData.getPtr()); + // Draw faceKeypoints + cudaMemcpy(pGpuFace, faceKeypoints.getConstPtr(), faceKeypoints.getSize(0) * FACE_NUMBER_PARTS * 3 * sizeof(float), + cudaMemcpyHostToDevice); + renderFaceKeypointsGpu(*spGpuMemoryPtr, mFrameSize, pGpuFace, faceKeypoints.getSize(0), getAlphaKeypoint()); + // CUDA check + cudaCheck(__LINE__, __FUNCTION__, __FILE__); + } + // GPU memory to CPU if last renderer + gpuToCpuMemoryIfLastRenderer(outputData.getPtr()); cudaCheck(__LINE__, __FUNCTION__, __FILE__); - } - // GPU memory to CPU if last renderer - gpuToCpuMemoryIfLastRenderer(outputData.getPtr()); - cudaCheck(__LINE__, __FUNCTION__, __FILE__); + // CPU_ONLY mode + #else + error("GPU rendering not available if `CPU_ONLY` is set.", __LINE__, __FUNCTION__, __FILE__); + UNUSED(outputData); + UNUSED(faceKeypoints); + #endif } catch (const std::exception& e) { diff --git a/src/openpose/face/renderFace.cpp b/src/openpose/face/renderFace.cpp new file mode 100644 index 00000000..2f7aa70e --- /dev/null +++ b/src/openpose/face/renderFace.cpp @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include + +namespace op +{ + const std::vector COLORS{FACE_COLORS_RENDER}; + + void renderFaceKeypointsCpu(Array& frameArray, const Array& faceKeypoints) + { + try + { + if (!frameArray.empty()) + { + // Parameters + const auto thicknessCircleRatio = 1.f/75.f; + const auto thicknessLineRatioWRTCircle = 0.334f; + const auto& pairs = FACE_PAIRS_RENDER; + + // Render keypoints + renderKeypointsCpu(frameArray, faceKeypoints, pairs, COLORS, thicknessCircleRatio, thicknessLineRatioWRTCircle); + } + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } +} diff --git a/src/openpose/face/faceRenderGpu.cu b/src/openpose/face/renderFace.cu similarity index 79% rename from src/openpose/face/faceRenderGpu.cu rename to src/openpose/face/renderFace.cu index b8d66d75..e4e5823f 100644 --- a/src/openpose/face/faceRenderGpu.cu +++ b/src/openpose/face/renderFace.cu @@ -3,15 +3,13 @@ #include #include #include -#include +#include namespace op { const dim3 THREADS_PER_BLOCK{128, 128, 1}; - __constant__ const unsigned int PART_PAIRS_GPU[] = FACE_PAIRS_TO_RENDER; - __constant__ const float RGB_COLORS[] = { - 255.f, 255.f, 255.f, - }; + __constant__ const unsigned int PART_PAIRS_GPU[] = FACE_PAIRS_RENDER_GPU; + __constant__ const float COLORS[] = {FACE_COLORS_RENDER}; @@ -29,18 +27,19 @@ namespace op // Other parameters const auto numberPartPairs = sizeof(PART_PAIRS_GPU) / (2*sizeof(PART_PAIRS_GPU[0])); - const auto numberColors = sizeof(RGB_COLORS) / (3*sizeof(RGB_COLORS[0])); + const auto numberColors = sizeof(COLORS) / (3*sizeof(COLORS[0])); const auto radius = fastMin(targetWidth, targetHeight) / 120.f; const auto stickwidth = fastMin(targetWidth, targetHeight) / 250.f; // Render key points renderKeypoints(targetPtr, sharedMaxs, sharedMins, sharedScaleF, globalIdx, x, y, targetWidth, targetHeight, facePtr, PART_PAIRS_GPU, numberFaces, - FACE_NUMBER_PARTS, numberPartPairs, RGB_COLORS, numberColors, + FACE_NUMBER_PARTS, numberPartPairs, COLORS, numberColors, radius, stickwidth, threshold, alphaColorToAdd); } - void renderFaceGpu(float* framePtr, const Point& frameSize, const float* const facePtr, const int numberFaces, const float alphaColorToAdd) + void renderFaceKeypointsGpu(float* framePtr, const Point& frameSize, const float* const facePtr, const int numberFaces, + const float alphaColorToAdd) { try { @@ -48,7 +47,8 @@ namespace op { const auto threshold = 0.4f; const auto numBlocks = getNumberCudaBlocks(frameSize, THREADS_PER_BLOCK); - renderFaceParts<<>>(framePtr, frameSize.x, frameSize.y, facePtr, numberFaces, threshold, alphaColorToAdd); + renderFaceParts<<>>(framePtr, frameSize.x, frameSize.y, facePtr, numberFaces, threshold, + alphaColorToAdd); cudaCheck(__LINE__, __FUNCTION__, __FILE__); } } diff --git a/src/openpose/pose/poseExtractor.cpp b/src/openpose/pose/poseExtractor.cpp index 88185285..0e58c8fa 100644 --- a/src/openpose/pose/poseExtractor.cpp +++ b/src/openpose/pose/poseExtractor.cpp @@ -7,78 +7,6 @@ namespace op { - // In case I wanna order the pose keypoints by area - // inline int getPersonArea(const float* posePtr, const int numberBodyParts, const float threshold) - // { - // try - // { - // if (numberBodyParts < 1) - // error("Number body parts must be > 0", __LINE__, __FUNCTION__, __FILE__); - - // unsigned int minX = -1; - // unsigned int maxX = 0u; - // unsigned int minY = -1; - // unsigned int maxY = 0u; - // for (auto part = 0 ; part < numberBodyParts ; part++) - // { - // const auto score = posePtr[3*part + 2]; - // if (score > threshold) - // { - // const auto x = posePtr[3*part]; - // const auto y = posePtr[3*part + 1]; - // // Set X - // if (maxX < x) - // maxX = x; - // if (minX > x) - // minX = x; - // // Set Y - // if (maxY < y) - // maxY = y; - // if (minY > y) - // minY = y; - // } - // } - // return (maxX - minX) * (maxY - minY); - // } - // catch (const std::exception& e) - // { - // error(e.what(), __LINE__, __FUNCTION__, __FILE__); - // return 0; - // } - // } - - // inline int getPersonWithMaxArea(const Array& poseKeypoints, const float threshold) - // { - // try - // { - // if (!poseKeypoints.empty()) - // { - // const auto numberPeople = poseKeypoints.getSize(0); - // const auto numberBodyParts = poseKeypoints.getSize(1); - // const auto area = numberBodyParts * poseKeypoints.getSize(2); - // auto biggestPoseIndex = -1; - // auto biggestArea = -1; - // for (auto person = 0 ; person < numberPeople ; person++) - // { - // const auto newPersonArea = getPersonArea(&poseKeypoints[person*area], numberBodyParts, threshold); - // if (newPersonArea > biggestArea) - // { - // biggestArea = newPersonArea; - // biggestPoseIndex = person; - // } - // } - // return biggestPoseIndex; - // } - // else - // return -1; - // } - // catch (const std::exception& e) - // { - // error(e.what(), __LINE__, __FUNCTION__, __FILE__); - // return -1; - // } - // } - bool heatMapTypesHas(const std::vector& heatMapTypes, const HeatMapType heatMapType) { try diff --git a/src/openpose/pose/poseParameters.cpp b/src/openpose/pose/poseParameters.cpp index 65255adf..5f70117f 100644 --- a/src/openpose/pose/poseParameters.cpp +++ b/src/openpose/pose/poseParameters.cpp @@ -3,7 +3,7 @@ namespace op { - const std::array, 3> POSE_BODY_PART_MAPPING{ POSE_COCO_BODY_PARTS, POSE_MPI_BODY_PARTS, POSE_MPI_BODY_PARTS }; + const std::array, 3> POSE_BODY_PART_MAPPING{ POSE_COCO_BODY_PARTS, POSE_MPI_BODY_PARTS, POSE_MPI_BODY_PARTS }; unsigned int poseBodyPartMapStringToKey(const PoseModel poseModel, const std::vector& strings) { @@ -24,29 +24,29 @@ namespace op } } - unsigned int poseBodyPartMapStringToKey(const PoseModel poseModel, const std::string& string) - { - try - { - return poseBodyPartMapStringToKey(poseModel, std::vector{string}); - } - catch (const std::exception& e) - { - error(e.what(), __LINE__, __FUNCTION__, __FILE__); - return 0; - } - } + unsigned int poseBodyPartMapStringToKey(const PoseModel poseModel, const std::string& string) + { + try + { + return poseBodyPartMapStringToKey(poseModel, std::vector{string}); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return 0; + } + } - const std::map& getPoseBodyPartMapping(const PoseModel poseModel) - { - try - { - return POSE_BODY_PART_MAPPING.at((int)poseModel); - } - catch (const std::exception& e) - { - error(e.what(), __LINE__, __FUNCTION__, __FILE__); - return POSE_BODY_PART_MAPPING[(int)poseModel]; - } - } + const std::map& getPoseBodyPartMapping(const PoseModel poseModel) + { + try + { + return POSE_BODY_PART_MAPPING.at((int)poseModel); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return POSE_BODY_PART_MAPPING[(int)poseModel]; + } + } } diff --git a/src/openpose/pose/poseRenderer.cpp b/src/openpose/pose/poseRenderer.cpp index c349d4a5..09953b4a 100644 --- a/src/openpose/pose/poseRenderer.cpp +++ b/src/openpose/pose/poseRenderer.cpp @@ -1,7 +1,9 @@ -#include -#include +#ifndef CPU_ONLY + #include + #include +#endif #include -#include +#include #include #include #include @@ -37,8 +39,10 @@ namespace op } } - PoseRenderer::PoseRenderer(const Point& heatMapsSize, const Point& outputSize, const PoseModel poseModel, const std::shared_ptr& poseExtractor, - const bool blendOriginalFrame, const float alphaKeypoint, const float alphaHeatMap, const unsigned int elementToRender) : + PoseRenderer::PoseRenderer(const Point& heatMapsSize, const Point& outputSize, const PoseModel poseModel, + const std::shared_ptr& poseExtractor, const bool blendOriginalFrame, + const float alphaKeypoint, const float alphaHeatMap, const unsigned int elementToRender, + const RenderMode renderMode) : // #body elements to render = #body parts (size()) + #body part pair connections + 3 (+whole pose +whole heatmaps +PAFs) // POSE_BODY_PART_MAPPING crashes on Windows, replaced by getPoseBodyPartMapping Renderer{(unsigned long long)(outputSize.area() * 3), alphaKeypoint, alphaHeatMap, elementToRender, @@ -48,6 +52,7 @@ namespace op mPoseModel{poseModel}, mPartIndexToName{createPartToName(poseModel)}, spPoseExtractor{poseExtractor}, + mRenderMode{renderMode}, mBlendOriginalFrame{blendOriginalFrame}, mShowGooglyEyes{false}, pGpuPose{nullptr} @@ -59,7 +64,9 @@ namespace op try { // Free CUDA pointers - Note that if pointers are 0 (i.e. nullptr), no operation is performed. - cudaFree(pGpuPose); + #ifndef CPU_ONLY + cudaFree(pGpuPose); + #endif } catch (const std::exception& e) { @@ -71,11 +78,13 @@ namespace op { try { - // GPU memory allocation for rendering log("Starting initialization on thread.", Priority::Low, __LINE__, __FUNCTION__, __FILE__); Renderer::initializationOnThread(); - cudaMalloc((void**)(&pGpuPose), POSE_MAX_PEOPLE * POSE_NUMBER_BODY_PARTS[(int)mPoseModel] * 3 * sizeof(float)); - cudaCheck(__LINE__, __FUNCTION__, __FILE__); + // GPU memory allocation for rendering + #ifndef CPU_ONLY + cudaMalloc((void**)(&pGpuPose), POSE_MAX_PEOPLE * POSE_NUMBER_BODY_PARTS[(int)mPoseModel] * 3 * sizeof(float)); + cudaCheck(__LINE__, __FUNCTION__, __FILE__); + #endif log("Finished initialization on thread.", Priority::Low, __LINE__, __FUNCTION__, __FILE__); } catch (const std::exception& e) @@ -134,73 +143,135 @@ namespace op } } - std::pair PoseRenderer::renderPose(Array& outputData, const Array& poseKeypoints, const float scaleNetToOutput) + std::pair PoseRenderer::renderPose(Array& outputData, const Array& poseKeypoints, + const float scaleNetToOutput) { try { // Security checks if (outputData.empty()) - error("Empty outputData.", __LINE__, __FUNCTION__, __FILE__); + error("Empty Array outputData.", __LINE__, __FUNCTION__, __FILE__); - const auto elementRendered = spElementToRender->load(); // I prefer std::round(T&) over intRound(T) for std::atomic - const auto numberPeople = poseKeypoints.getSize(0); - std::string elementRenderedName; + // CPU rendering + if (mRenderMode == RenderMode::Cpu) + return renderPoseCpu(outputData, poseKeypoints, scaleNetToOutput); // GPU rendering - if (numberPeople > 0 || elementRendered != 0 || !mBlendOriginalFrame) + else + return renderPoseGpu(outputData, poseKeypoints, scaleNetToOutput); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return std::make_pair(-1, ""); + } + } + + std::pair PoseRenderer::renderPoseCpu(Array& outputData, const Array& poseKeypoints, + const float scaleNetToOutput) + { + try + { + const auto elementRendered = spElementToRender->load(); + + std::string elementRenderedName; + // CPU rendering + // Draw poseKeypoints + if (elementRendered == 0) + renderPoseKeypointsCpu(outputData, poseKeypoints, mPoseModel, mBlendOriginalFrame); + // Draw heat maps / PAFs + else { - cpuToGpuMemoryIfNotCopiedYet(outputData.getPtr()); - cudaCheck(__LINE__, __FUNCTION__, __FILE__); - const auto numberBodyParts = POSE_NUMBER_BODY_PARTS[(int)mPoseModel]; - const auto numberBodyPartsPlusBkg = numberBodyParts+1; - // Draw poseKeypoints - if (elementRendered == 0) + UNUSED(scaleNetToOutput); + error("CPU rendering only available for drawing keypoints, no heat maps nor PAFs.", __LINE__, __FUNCTION__, __FILE__); + } + // Return result + return std::make_pair(elementRendered, elementRenderedName); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return std::make_pair(-1, ""); + } + } + + std::pair PoseRenderer::renderPoseGpu(Array& outputData, const Array& poseKeypoints, + const float scaleNetToOutput) + { + try + { + const auto elementRendered = spElementToRender->load(); + + std::string elementRenderedName; + // GPU rendering + #ifndef CPU_ONLY + const auto numberPeople = poseKeypoints.getSize(0); + if (numberPeople > 0 || elementRendered != 0 || !mBlendOriginalFrame) { - if (!poseKeypoints.empty()) - cudaMemcpy(pGpuPose, poseKeypoints.getConstPtr(), numberPeople * numberBodyParts * 3 * sizeof(float), cudaMemcpyHostToDevice); - renderPoseGpu(*spGpuMemoryPtr, mPoseModel, numberPeople, mOutputSize, pGpuPose, mShowGooglyEyes, mBlendOriginalFrame, getAlphaKeypoint()); - } - else - { - if (scaleNetToOutput == -1.f) - error("Non valid scaleNetToOutput.", __LINE__, __FUNCTION__, __FILE__); - // Draw specific body part or bkg - if (elementRendered <= numberBodyPartsPlusBkg) + cpuToGpuMemoryIfNotCopiedYet(outputData.getPtr()); + cudaCheck(__LINE__, __FUNCTION__, __FILE__); + const auto numberBodyParts = POSE_NUMBER_BODY_PARTS[(int)mPoseModel]; + const auto numberBodyPartsPlusBkg = numberBodyParts+1; + // Draw poseKeypoints + if (elementRendered == 0) { - elementRenderedName = mPartIndexToName.at(elementRendered-1); - renderBodyPartGpu(*spGpuMemoryPtr, mPoseModel, mOutputSize, spPoseExtractor->getHeatMapCpuConstPtr(), mHeatMapsSize, - scaleNetToOutput, elementRendered, (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f)); + if (!poseKeypoints.empty()) + cudaMemcpy(pGpuPose, poseKeypoints.getConstPtr(), numberPeople * numberBodyParts * 3 * sizeof(float), + cudaMemcpyHostToDevice); + renderPoseKeypointsGpu(*spGpuMemoryPtr, mPoseModel, numberPeople, mOutputSize, pGpuPose, + mShowGooglyEyes, mBlendOriginalFrame, getAlphaKeypoint()); } - // Draw PAFs (Part Affinity Fields) - else if (elementRendered == numberBodyPartsPlusBkg+1) - { - elementRenderedName = "Heatmaps"; - renderBodyPartsGpu(*spGpuMemoryPtr, mPoseModel, mOutputSize, spPoseExtractor->getHeatMapCpuConstPtr(), mHeatMapsSize, scaleNetToOutput, - (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f)); - } - // Draw PAFs (Part Affinity Fields) - else if (elementRendered == numberBodyPartsPlusBkg+2) - { - elementRenderedName = "PAFs (Part Affinity Fields)"; - renderPartAffinityFieldsGpu(*spGpuMemoryPtr, mPoseModel, mOutputSize, spPoseExtractor->getHeatMapCpuConstPtr(), - mHeatMapsSize, scaleNetToOutput, (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f)); - } - // Draw affinity between 2 body parts else { - const auto affinityPart = (elementRendered-numberBodyPartsPlusBkg-3)*2; - const auto affinityPartMapped = POSE_MAP_IDX[(int)mPoseModel].at(affinityPart); - elementRenderedName = mPartIndexToName.at(affinityPartMapped); - elementRenderedName = elementRenderedName.substr(0, elementRenderedName.find("(")); - renderPartAffinityFieldGpu(*spGpuMemoryPtr, mPoseModel, mOutputSize, spPoseExtractor->getHeatMapCpuConstPtr(), - mHeatMapsSize, scaleNetToOutput, affinityPartMapped, (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f)); - } + if (scaleNetToOutput == -1.f) + error("Non valid scaleNetToOutput.", __LINE__, __FUNCTION__, __FILE__); + // Draw specific body part or bkg + if (elementRendered <= numberBodyPartsPlusBkg) + { + elementRenderedName = mPartIndexToName.at(elementRendered-1); + renderPoseHeatMapGpu(*spGpuMemoryPtr, mPoseModel, mOutputSize, spPoseExtractor->getHeatMapCpuConstPtr(), + mHeatMapsSize, scaleNetToOutput, elementRendered, + (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f)); + } + // Draw PAFs (Part Affinity Fields) + else if (elementRendered == numberBodyPartsPlusBkg+1) + { + elementRenderedName = "Heatmaps"; + renderPoseHeatMapsGpu(*spGpuMemoryPtr, mPoseModel, mOutputSize, spPoseExtractor->getHeatMapCpuConstPtr(), + mHeatMapsSize, scaleNetToOutput, (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f)); + } + // Draw PAFs (Part Affinity Fields) + else if (elementRendered == numberBodyPartsPlusBkg+2) + { + elementRenderedName = "PAFs (Part Affinity Fields)"; + renderPosePAFsGpu(*spGpuMemoryPtr, mPoseModel, mOutputSize, spPoseExtractor->getHeatMapCpuConstPtr(), + mHeatMapsSize, scaleNetToOutput, (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f)); + } + // Draw affinity between 2 body parts + else + { + const auto affinityPart = (elementRendered-numberBodyPartsPlusBkg-3)*2; + const auto affinityPartMapped = POSE_MAP_IDX[(int)mPoseModel].at(affinityPart); + elementRenderedName = mPartIndexToName.at(affinityPartMapped); + elementRenderedName = elementRenderedName.substr(0, elementRenderedName.find("(")); + renderPosePAFGpu(*spGpuMemoryPtr, mPoseModel, mOutputSize, spPoseExtractor->getHeatMapCpuConstPtr(), + mHeatMapsSize, scaleNetToOutput, affinityPartMapped, + (mBlendOriginalFrame ? getAlphaHeatMap() : 1.f)); + } + } } - } - // GPU memory to CPU if last renderer - gpuToCpuMemoryIfLastRenderer(outputData.getPtr()); - cudaCheck(__LINE__, __FUNCTION__, __FILE__); - + // GPU memory to CPU if last renderer + gpuToCpuMemoryIfLastRenderer(outputData.getPtr()); + cudaCheck(__LINE__, __FUNCTION__, __FILE__); + // CPU_ONLY mode + #else + error("GPU rendering not available if `CPU_ONLY` is set.", __LINE__, __FUNCTION__, __FILE__); + UNUSED(elementRendered); + UNUSED(outputData); + UNUSED(poseKeypoints); + UNUSED(scaleNetToOutput); + #endif + // Return result return std::make_pair(elementRendered, elementRenderedName); } catch (const std::exception& e) diff --git a/src/openpose/pose/renderPose.cpp b/src/openpose/pose/renderPose.cpp new file mode 100644 index 00000000..9cb0aebf --- /dev/null +++ b/src/openpose/pose/renderPose.cpp @@ -0,0 +1,40 @@ +#include +#include +#include +#include +#include + +namespace op +{ + const std::vector COCO_COLORS{POSE_COCO_COLORS_RENDER}; + const std::vector MPI_COLORS{POSE_MPI_COLORS_RENDER}; + + void renderPoseKeypointsCpu(Array& frameArray, const Array& poseKeypoints, const PoseModel poseModel, const bool blendOriginalFrame) + { + try + { + if (!frameArray.empty()) + { + // Array --> cv::Mat + auto frame = frameArray.getCvMat(); + + // Background + if (!blendOriginalFrame) + frame.setTo(0.f); // [0-255] + + // Parameters + const auto thicknessCircleRatio = 1.f/75.f; + const auto thicknessLineRatioWRTCircle = 0.75f; + const auto& pairs = POSE_BODY_PART_PAIRS_RENDER[(int)poseModel]; + const auto& colors = (poseModel == PoseModel::COCO_18 ? COCO_COLORS : MPI_COLORS); + + // Render keypoints + renderKeypointsCpu(frameArray, poseKeypoints, pairs, colors, thicknessCircleRatio, thicknessLineRatioWRTCircle); + } + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } +} diff --git a/src/openpose/pose/poseRenderGpu.cu b/src/openpose/pose/renderPose.cu similarity index 79% rename from src/openpose/pose/poseRenderGpu.cu rename to src/openpose/pose/renderPose.cu index b01c7be9..675afc6d 100644 --- a/src/openpose/pose/poseRenderGpu.cu +++ b/src/openpose/pose/renderPose.cu @@ -1,74 +1,18 @@ -#include // std::pair #include #include #include #include #include -#include +#include namespace op { - // PI digits: http://www.piday.org/million/ - __constant__ const float PI = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745f; - __constant__ const unsigned int COCO_PAIRS_GPU[] = POSE_COCO_PAIRS_TO_RENDER; - __constant__ const unsigned int MPI_PAIRS_GPU[] = POSE_MPI_PAIRS_TO_RENDER; - __constant__ const float COCO_RGB_COLORS[] = { - 255.f, 0.f, 0.f, - 255.f, 85.f, 0.f, - 255.f, 170.f, 0.f, - 255.f, 255.f, 0.f, - 170.f, 255.f, 0.f, - 85.f, 255.f, 0.f, - 0.f, 255.f, 0.f, - 0.f, 255.f, 85.f, - 0.f, 255.f, 170.f, - 0.f, 255.f, 255.f, - 0.f, 170.f, 255.f, - 0.f, 85.f, 255.f, - 0.f, 0.f, 255.f, - 85.f, 0.f, 255.f, - 170.f, 0.f, 255.f, - 255.f, 0.f, 255.f, - 255.f, 0.f, 170.f, - 255.f, 0.f, 85.f, - }; - __constant__ const float MPI_RGB_COLORS[] = { // MPI colors chosen such that they are closed to COCO colors - 255.f, 0.f, 85.f, - 255.f, 0.f, 0.f, - 255.f, 85.f, 0.f, - 255.f, 170.f, 0.f, - 255.f, 255.f, 0.f, - 170.f, 255.f, 0.f, - 85.f, 255.f, 0.f, - 43.f, 255.f, 0.f, - 0.f, 255.f, 0.f, - 0.f, 255.f, 85.f, - 0.f, 255.f, 170.f, - 0.f, 255.f, 255.f, - 0.f, 170.f, 255.f, - 0.f, 85.f, 255.f, - 0.f, 0.f, 255.f, - }; - __constant__ const float RGB_COLORS_BACKGROUND[] = { - 255.f, 0.f, 0.f, - 255.f, 85.f, 0.f, - 255.f, 170.f, 0.f, - 255.f, 255.f, 0.f, - 170.f, 255.f, 0.f, - 85.f, 255.f, 0.f, - 0.f, 255.f, 0.f, - 0.f, 255.f, 85.f, - 0.f, 255.f, 170.f, - 0.f, 255.f, 255.f, - 0.f, 170.f, 255.f, - 0.f, 85.f, 255.f, - 0.f, 0.f, 255.f, - 85.f, 0.f, 255.f, - 170.f, 0.f, 255.f, - 255.f, 0.f, 255.f, - 255.f, 0.f, 170.f, - 255.f, 0.f, 85.f, - }; + // PI digits: http://www.piday.org/million/ + __constant__ const float PI = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745f; + __constant__ const unsigned int COCO_PAIRS_GPU[] = POSE_COCO_PAIRS_RENDER_GPU; + __constant__ const unsigned int MPI_PAIRS_GPU[] = POSE_MPI_PAIRS_RENDER_GPU; + __constant__ const float COCO_COLORS[] = {POSE_COCO_COLORS_RENDER}; + __constant__ const float MPI_COLORS[] = {POSE_MPI_COLORS_RENDER}; @@ -163,14 +107,14 @@ namespace op // Other parameters const auto numberPartPairs = sizeof(COCO_PAIRS_GPU) / (2*sizeof(COCO_PAIRS_GPU[0])); - const auto numberColors = sizeof(COCO_RGB_COLORS) / (3*sizeof(COCO_RGB_COLORS[0])); + const auto numberColors = sizeof(COCO_COLORS) / (3*sizeof(COCO_COLORS[0])); const auto radius = fastMin(targetWidth, targetHeight) / 100.f; const auto stickwidth = fastMin(targetWidth, targetHeight) / 120.f; // Render key points renderKeypoints(targetPtr, sharedMaxs, sharedMins, sharedScaleF, globalIdx, x, y, targetWidth, targetHeight, posePtr, COCO_PAIRS_GPU, numberPeople, - POSE_COCO_NUMBER_PARTS, numberPartPairs, COCO_RGB_COLORS, numberColors, + POSE_COCO_NUMBER_PARTS, numberPartPairs, COCO_COLORS, numberColors, radius, stickwidth, threshold, alphaColorToAdd, blendOriginalFrame, (googlyEyes ? 14 : -1), (googlyEyes ? 15 : -1)); } @@ -188,14 +132,14 @@ namespace op // Other parameters const auto numberPartPairs = sizeof(MPI_PAIRS_GPU) / (2*sizeof(MPI_PAIRS_GPU[0])); - const auto numberColors = sizeof(MPI_RGB_COLORS) / (3*sizeof(MPI_RGB_COLORS[0])); + const auto numberColors = sizeof(MPI_COLORS) / (3*sizeof(MPI_COLORS[0])); const auto radius = fastMin(targetWidth, targetHeight) / 100.f; const auto stickwidth = fastMin(targetWidth, targetHeight) / 120.f; // Render key points renderKeypoints(targetPtr, sharedMaxs, sharedMins, sharedScaleF, globalIdx, x, y, targetWidth, targetHeight, posePtr, MPI_PAIRS_GPU, numberPeople, - POSE_MPI_NUMBER_PARTS, numberPartPairs, MPI_RGB_COLORS, numberColors, + POSE_MPI_NUMBER_PARTS, numberPartPairs, MPI_COLORS, numberColors, radius, stickwidth, threshold, alphaColorToAdd, blendOriginalFrame); } @@ -205,7 +149,7 @@ namespace op const auto x = (blockIdx.x * blockDim.x) + threadIdx.x; const auto y = (blockIdx.y * blockDim.y) + threadIdx.y; - const auto numberColors = sizeof(RGB_COLORS_BACKGROUND)/(3*sizeof(RGB_COLORS_BACKGROUND[0])); + const auto numberColors = sizeof(COCO_COLORS)/(3*sizeof(COCO_COLORS[0])); if (x < targetWidth && y < targetHeight) { @@ -220,9 +164,9 @@ namespace op const auto offsetOrigin = part * heatMapArea; const auto value = __saturatef(heatMapPtr[offsetOrigin + yHeatMap*widthHeatMap + xHeatMap]); // __saturatef = trucate to [0,1] const auto rgbColorIndex = (part%numberColors)*3; - rgbColor[0] += value*RGB_COLORS_BACKGROUND[rgbColorIndex]; - rgbColor[1] += value*RGB_COLORS_BACKGROUND[rgbColorIndex+1]; - rgbColor[2] += value*RGB_COLORS_BACKGROUND[rgbColorIndex+2]; + rgbColor[0] += value*COCO_COLORS[rgbColorIndex]; + rgbColor[1] += value*COCO_COLORS[rgbColorIndex+1]; + rgbColor[2] += value*COCO_COLORS[rgbColorIndex+2]; } const auto blueIndex = y * targetWidth + x; @@ -340,9 +284,9 @@ namespace op } } - inline void renderKeypointsPartAffinityAux(float* framePtr, const PoseModel poseModel, const Point& frameSize, - const float* const heatMapPtr, const Point& heatMapSize, const float scaleToKeepRatio, - const int part, const int partsToRender, const float alphaBlending) + inline void renderPosePAFGpuAux(float* framePtr, const PoseModel poseModel, const Point& frameSize, + const float* const heatMapPtr, const Point& heatMapSize, const float scaleToKeepRatio, + const int part, const int partsToRender, const float alphaBlending) { try { @@ -363,8 +307,8 @@ namespace op } } - void renderPoseGpu(float* framePtr, const PoseModel poseModel, const int numberPeople, const Point& frameSize, const float* const posePtr, - const bool googlyEyes, const bool blendOriginalFrame, const float alphaBlending) + void renderPoseKeypointsGpu(float* framePtr, const PoseModel poseModel, const int numberPeople, const Point& frameSize, + const float* const posePtr, const bool googlyEyes, const bool blendOriginalFrame, const float alphaBlending) { try { @@ -398,8 +342,8 @@ namespace op } } - void renderBodyPartGpu(float* framePtr, const PoseModel poseModel, const Point& frameSize, const float* const heatMapPtr, - const Point& heatMapSize, const float scaleToKeepRatio, const int part, const float alphaBlending) + void renderPoseHeatMapGpu(float* framePtr, const PoseModel poseModel, const Point& frameSize, const float* const heatMapPtr, + const Point& heatMapSize, const float scaleToKeepRatio, const int part, const float alphaBlending) { try { @@ -422,8 +366,8 @@ namespace op } } - void renderBodyPartsGpu(float* framePtr, const PoseModel poseModel, const Point& frameSize, const float* const heatMapPtr, - const Point& heatMapSize, const float scaleToKeepRatio, const float alphaBlending) + void renderPoseHeatMapsGpu(float* framePtr, const PoseModel poseModel, const Point& frameSize, const float* const heatMapPtr, + const Point& heatMapSize, const float scaleToKeepRatio, const float alphaBlending) { try { @@ -446,12 +390,12 @@ namespace op } } - void renderPartAffinityFieldGpu(float* framePtr, const PoseModel poseModel, const Point& frameSize, const float* const heatMapPtr, - const Point& heatMapSize, const float scaleToKeepRatio, const int part, const float alphaBlending) + void renderPosePAFGpu(float* framePtr, const PoseModel poseModel, const Point& frameSize, const float* const heatMapPtr, + const Point& heatMapSize, const float scaleToKeepRatio, const int part, const float alphaBlending) { try { - renderKeypointsPartAffinityAux(framePtr, poseModel, frameSize, heatMapPtr, heatMapSize, scaleToKeepRatio, part, 1, alphaBlending); + renderPosePAFGpuAux(framePtr, poseModel, frameSize, heatMapPtr, heatMapSize, scaleToKeepRatio, part, 1, alphaBlending); } catch (const std::exception& e) { @@ -459,14 +403,14 @@ namespace op } } - void renderPartAffinityFieldsGpu(float* framePtr, const PoseModel poseModel, const Point& frameSize, const float* const heatMapPtr, - const Point& heatMapSize, const float scaleToKeepRatio, const float alphaBlending) + void renderPosePAFsGpu(float* framePtr, const PoseModel poseModel, const Point& frameSize, const float* const heatMapPtr, + const Point& heatMapSize, const float scaleToKeepRatio, const float alphaBlending) { try { const auto numberBodyPartPairs = (int)POSE_BODY_PART_PAIRS[(int)poseModel].size()/2; - renderKeypointsPartAffinityAux(framePtr, poseModel, frameSize, heatMapPtr, heatMapSize, scaleToKeepRatio, POSE_NUMBER_BODY_PARTS[(int)poseModel]+1, - numberBodyPartPairs, alphaBlending); + renderPosePAFGpuAux(framePtr, poseModel, frameSize, heatMapPtr, heatMapSize, scaleToKeepRatio, + POSE_NUMBER_BODY_PARTS[(int)poseModel]+1, numberBodyPartPairs, alphaBlending); } catch (const std::exception& e) { diff --git a/src/openpose/producer/defineTemplates.cpp b/src/openpose/producer/defineTemplates.cpp index aa8bf912..5f59c6e9 100644 --- a/src/openpose/producer/defineTemplates.cpp +++ b/src/openpose/producer/defineTemplates.cpp @@ -2,6 +2,6 @@ namespace op { - template class DatumProducer; + template class DatumProducer; template class WDatumProducer; } diff --git a/src/openpose/producer/videoReader.cpp b/src/openpose/producer/videoReader.cpp index f643dd79..bd2ea709 100644 --- a/src/openpose/producer/videoReader.cpp +++ b/src/openpose/producer/videoReader.cpp @@ -27,7 +27,7 @@ namespace op { try { - return VideoCaptureReader::getRawFrame(); + return VideoCaptureReader::getRawFrame(); } catch (const std::exception& e) { diff --git a/src/openpose/utilities/keypoint.cpp b/src/openpose/utilities/keypoint.cpp new file mode 100644 index 00000000..54aa8f7a --- /dev/null +++ b/src/openpose/utilities/keypoint.cpp @@ -0,0 +1,265 @@ +#include +#include +#include + +namespace op +{ + const std::string errorMessage = "The Array is not a RGB image. This function is only for array of dimension: [sizeA x sizeB x 3]."; + + float getDistance(const float* keypointPtr, const int elementA, const int elementB) + { + try + { + const auto pixelX = keypointPtr[elementA*3] - keypointPtr[elementB*3]; + const auto pixelY = keypointPtr[elementA*3+1] - keypointPtr[elementB*3+1]; + return std::sqrt(pixelX*pixelX+pixelY*pixelY); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return -1.f; + } + } + + void scaleKeypoints(Array& keypoints, const float scale) + { + try + { + scaleKeypoints(keypoints, scale, scale); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + void scaleKeypoints(Array& keypoints, const float scaleX, const float scaleY) + { + try + { + if (scaleX != 1. && scaleY != 1.) + { + // Error check + if (!keypoints.empty() && keypoints.getSize(2) != 3) + error(errorMessage, __LINE__, __FUNCTION__, __FILE__); + // Get #people and #parts + const auto numberPeople = keypoints.getSize(0); + const auto numberParts = keypoints.getSize(1); + // For each person + for (auto person = 0 ; person < numberPeople ; person++) + { + // For each body part + for (auto part = 0 ; part < numberParts ; part++) + { + const auto finalIndex = 3*(person*numberParts + part); + keypoints[finalIndex] *= scaleX; + keypoints[finalIndex+1] *= scaleY; + } + } + } + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + void scaleKeypoints(Array& keypoints, const float scaleX, const float scaleY, const float offsetX, const float offsetY) + { + try + { + if (scaleX != 1. && scaleY != 1.) + { + // Error check + if (!keypoints.empty() && keypoints.getSize(2) != 3) + error(errorMessage, __LINE__, __FUNCTION__, __FILE__); + // Get #people and #parts + const auto numberPeople = keypoints.getSize(0); + const auto numberParts = keypoints.getSize(1); + // For each person + for (auto person = 0 ; person < numberPeople ; person++) + { + // For each body part + for (auto part = 0 ; part < numberParts ; part++) + { + const auto finalIndex = keypoints.getSize(2)*(person*numberParts + part); + keypoints[finalIndex] = keypoints[finalIndex] * scaleX + offsetX; + keypoints[finalIndex+1] = keypoints[finalIndex+1] * scaleY + offsetY; + } + } + } + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + void renderKeypointsCpu(Array& frameArray, const Array& keypoints, const std::vector& pairs, + const std::vector colors, const float thicknessCircleRatio, const float thicknessLineRatioWRTCircle) + { + try + { + if (!frameArray.empty()) + { + // Array --> cv::Mat + auto frame = frameArray.getCvMat(); + + // Security check + if (frame.dims != 3 || frame.size[0] != 3) + error(errorMessage, __LINE__, __FUNCTION__, __FILE__); + + // Get frame channels + const auto width = frame.size[2]; + const auto height = frame.size[1]; + const auto area = width * height; + cv::Mat frameB{height, width, CV_32FC1, &frame.data[0]}; + cv::Mat frameG{height, width, CV_32FC1, &frame.data[area * sizeof(float) / sizeof(uchar)]}; + cv::Mat frameR{height, width, CV_32FC1, &frame.data[2 * area * sizeof(float) / sizeof(uchar)]}; + + // Parameters + const auto lineType = 8; + const auto shift = 0; + const auto threshold = 0.1; + const auto numberColors = colors.size(); + const auto numberBodyParts = keypoints.getSize(1); + const auto areaKeypoints = numberBodyParts * keypoints.getSize(2); + + // Keypoints + for (auto person = 0 ; person < keypoints.getSize(0) ; person++) + { + const auto personRectangle = getKeypointsRectangle(&keypoints[person*areaKeypoints], keypoints.getSize(1), threshold); + const auto ratioAreas = fastMin(1.f, fastMax(personRectangle.width/(float)width, personRectangle.height/(float)height)); + // Size-dependent variables + const auto thicknessCircle = fastMax(intRound(std::sqrt(area)*thicknessCircleRatio * ratioAreas), 2); + const auto thicknessLine = intRound(thicknessCircle * thicknessLineRatioWRTCircle); + const auto radius = thicknessCircle / 2; + + // Draw lines + for (auto pair = 0 ; pair < pairs.size() ; pair+=2) + { + const auto index1 = (person * keypoints.getSize(1) + pairs[pair]) * keypoints.getSize(2); + const auto index2 = (person * keypoints.getSize(1) + pairs[pair+1]) * keypoints.getSize(2); + if (keypoints[index1+2] > threshold && keypoints[index2+2] > threshold) + { + const auto colorIndex = pair/2*3; + const cv::Scalar color{colors[colorIndex % numberColors], + colors[(colorIndex+1) % numberColors], + colors[(colorIndex+2) % numberColors]}; + const cv::Point keypoint1{intRound(keypoints[index1]), intRound(keypoints[index1+1])}; + const cv::Point keypoint2{intRound(keypoints[index2]), intRound(keypoints[index2+1])}; + cv::line(frameR, keypoint1, keypoint2, color[0], thicknessLine, lineType, shift); + cv::line(frameG, keypoint1, keypoint2, color[1], thicknessLine, lineType, shift); + cv::line(frameB, keypoint1, keypoint2, color[2], thicknessLine, lineType, shift); + } + } + + // Draw circles + for (auto part = 0 ; part < keypoints.getSize(1) ; part++) + { + const auto faceIndex = (person * keypoints.getSize(1) + part) * keypoints.getSize(2); + if (keypoints[faceIndex+2] > threshold) + { + const auto colorIndex = part*3; + const cv::Scalar color{colors[colorIndex % numberColors], + colors[(colorIndex+1) % numberColors], + colors[(colorIndex+2) % numberColors]}; + const cv::Point center{intRound(keypoints[faceIndex]), intRound(keypoints[faceIndex+1])}; + cv::circle(frameR, center, radius, color[0], thicknessCircle, lineType, shift); + cv::circle(frameG, center, radius, color[1], thicknessCircle, lineType, shift); + cv::circle(frameB, center, radius, color[2], thicknessCircle, lineType, shift); + } + } + } + } + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + } + } + + Rectangle getKeypointsRectangle(const float* keypointPtr, const int numberBodyParts, const float threshold) + { + try + { + if (numberBodyParts < 1) + error("Number body parts must be > 0", __LINE__, __FUNCTION__, __FILE__); + + unsigned int minX = -1; + unsigned int maxX = 0u; + unsigned int minY = -1; + unsigned int maxY = 0u; + for (auto part = 0 ; part < numberBodyParts ; part++) + { + const auto score = keypointPtr[3*part + 2]; + if (score > threshold) + { + const auto x = keypointPtr[3*part]; + const auto y = keypointPtr[3*part + 1]; + // Set X + if (maxX < x) + maxX = x; + if (minX > x) + minX = x; + // Set Y + if (maxY < y) + maxY = y; + if (minY > y) + minY = y; + } + } + return Rectangle{minX, minY, maxX-minX, maxY-minY}; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return Rectangle{}; + } + } + + int getKeypointsArea(const float* keypointPtr, const int numberBodyParts, const float threshold) + { + try + { + return getKeypointsRectangle(keypointPtr, numberBodyParts, threshold).area(); + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return 0; + } + } + + int getBiggestPerson(const Array& keypoints, const float threshold) + { + try + { + if (!keypoints.empty()) + { + const auto numberPeople = keypoints.getSize(0); + const auto numberBodyParts = keypoints.getSize(1); + const auto area = numberBodyParts * keypoints.getSize(2); + auto biggestPoseIndex = -1; + auto biggestArea = -1; + for (auto person = 0 ; person < numberPeople ; person++) + { + const auto newPersonArea = getKeypointsArea(&keypoints[person*area], numberBodyParts, threshold); + if (newPersonArea > biggestArea) + { + biggestArea = newPersonArea; + biggestPoseIndex = person; + } + } + return biggestPoseIndex; + } + else + return -1; + } + catch (const std::exception& e) + { + error(e.what(), __LINE__, __FUNCTION__, __FILE__); + return -1; + } + } +} diff --git a/src/openpose/wrapper/wrapperStructFace.cpp b/src/openpose/wrapper/wrapperStructFace.cpp index 86061a15..9b960193 100644 --- a/src/openpose/wrapper/wrapperStructFace.cpp +++ b/src/openpose/wrapper/wrapperStructFace.cpp @@ -2,11 +2,11 @@ namespace op { - WrapperStructFace::WrapperStructFace(const bool enable_, const Point& netInputSize_, const bool renderOutput_, const float alphaKeypoint_, - const float alphaHeatMap_) : + WrapperStructFace::WrapperStructFace(const bool enable_, const Point& netInputSize_, const RenderMode renderMode_, + const float alphaKeypoint_, const float alphaHeatMap_) : enable{enable_}, netInputSize{netInputSize_}, - renderOutput{renderOutput_}, + renderMode{renderMode_}, alphaKeypoint{alphaKeypoint_}, alphaHeatMap{alphaHeatMap_} { diff --git a/src/openpose/wrapper/wrapperStructPose.cpp b/src/openpose/wrapper/wrapperStructPose.cpp index 5d1a3b0e..6addd113 100644 --- a/src/openpose/wrapper/wrapperStructPose.cpp +++ b/src/openpose/wrapper/wrapperStructPose.cpp @@ -3,7 +3,7 @@ namespace op { WrapperStructPose::WrapperStructPose(const Point& netInputSize_, const Point& outputSize_, const ScaleMode keypointScale_, const int gpuNumber_, - const int gpuNumberStart_, const int scalesNumber_, const float scaleGap_, const bool renderOutput_, + const int gpuNumberStart_, const int scalesNumber_, const float scaleGap_, const RenderMode renderMode_, const PoseModel poseModel_, const bool blendOriginalFrame_, const float alphaKeypoint_, const float alphaHeatMap_, const int defaultPartToRender_, const std::string& modelFolder_, const std::vector& heatMapTypes_, const ScaleMode heatMapScale_) : @@ -14,7 +14,7 @@ namespace op gpuNumberStart{gpuNumberStart_}, scalesNumber{scalesNumber_}, scaleGap{scaleGap_}, - renderOutput{renderOutput_}, + renderMode{renderMode_}, poseModel{poseModel_}, blendOriginalFrame{blendOriginalFrame_}, alphaKeypoint{alphaKeypoint_},