| # Apply Net |
|
|
| `apply_net` is a tool to print or visualize DensePose results on a set of images. |
| It has two modes: `dump` to save DensePose model results to a pickle file |
| and `show` to visualize them on images. |
|
|
| The `image.jpg` file that is used as an example in this doc can be found [here](http://images.cocodataset.org/train2017/000000117508.jpg) |
|
|
| ## Dump Mode |
|
|
| The general command form is: |
| ```bash |
| python apply_net.py dump [-h] [-v] [--output <dump_file>] <config> <model> <input> |
| ``` |
|
|
| There are three mandatory arguments: |
| - `<config>`, configuration file for a given model; |
| - `<model>`, model file with trained parameters |
| - `<input>`, input image file name, pattern or folder |
|
|
| One can additionally provide `--output` argument to define the output file name, |
| which defaults to `output.pkl`. |
|
|
|
|
| Examples: |
|
|
| 1. Dump results of the [R_50_FPN_s1x](https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl) DensePose model for images in a folder `images` to file `dump.pkl`: |
| ```bash |
| python apply_net.py dump configs/densepose_rcnn_R_50_FPN_s1x.yaml \ |
| https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl \ |
| images --output dump.pkl -v |
| ``` |
|
|
| 2. Dump results of the [R_50_FPN_s1x](https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl) DensePose model for images with file name matching a pattern `image*.jpg` to file `results.pkl`: |
| ```bash |
| python apply_net.py dump configs/densepose_rcnn_R_50_FPN_s1x.yaml \ |
| https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl \ |
| "image*.jpg" --output results.pkl -v |
| ``` |
|
|
| If you want to load the pickle file generated by the above command: |
| ``` |
| # make sure DensePose is in your PYTHONPATH, or use the following line to add it: |
| sys.path.append("/your_detectron2_path/detectron2_repo/projects/DensePose/") |
| |
| f = open('/your_result_path/results.pkl', 'rb') |
| data = pickle.load(f) |
| ``` |
|
|
| The file `results.pkl` contains the list of results per image, for each image the result is a dictionary. |
|
|
| **If you use a [IUV model](DENSEPOSE_IUV.md#-model-zoo-and-baselines)**, the dumped data will have the following format: |
|
|
| ``` |
| data: [{'file_name': '/your_path/image1.jpg', |
| 'scores': tensor([0.9884]), |
| 'pred_boxes_XYXY': tensor([[ 69.6114, 0.0000, 706.9797, 706.0000]]), |
| 'pred_densepose': [DensePoseChartResultWithConfidences(labels=tensor(...), uv=tensor(...), sigma_1=None, |
| sigma_2=None, kappa_u=None, kappa_v=None, fine_segm_confidence=None, coarse_segm_confidence=None), |
| DensePoseChartResultWithConfidences, ...] |
| } |
| {'file_name': '/your_path/image2.jpg', |
| 'scores': tensor([0.9999, 0.5373, 0.3991]), |
| 'pred_boxes_XYXY': tensor([[ 59.5734, 7.7535, 579.9311, 932.3619], |
| [612.9418, 686.1254, 612.9999, 704.6053], |
| [164.5081, 407.4034, 598.3944, 920.4266]]), |
| 'pred_densepose': [DensePoseChartResultWithConfidences(labels=tensor(...), uv=tensor(...), sigma_1=None, |
| sigma_2=None, kappa_u=None, kappa_v=None, fine_segm_confidence=None, coarse_segm_confidence=None), |
| DensePoseChartResultWithConfidences, ...] |
| }] |
| ``` |
|
|
| `DensePoseChartResultWithConfidences` contains the following fields: |
| - `labels` - a tensor of size `[H, W]` of type `torch.long` which contains fine segmentation labels (previously called `I`) |
| - `uv` - a tensor of size `[2, H, W]` of type `torch.float` which contains `U` and `V` coordinates |
| - various optional confidence-related fields (`sigma_1`, `sigma_2`, `kappa_u`, `kappa_v`, `fine_segm_confidence`, `coarse_segm_confidence`) |
|
|
|
|
| **If you use a [CSE model](DENSEPOSE_CSE.md#-model-zoo-and-baselines)**, the dumped data will have the following format: |
| ``` |
| data: [{'file_name': '/your_path/image1.jpg', |
| 'scores': tensor([0.9984, 0.9961]), |
| 'pred_boxes_XYXY': tensor([[480.0093, 461.0796, 698.3614, 696.1011], |
| [78.1589, 168.6614, 307.1287, 653.8522]]), |
| 'pred_densepose': DensePoseEmbeddingPredictorOutput(embedding=tensor(...), coarse_segm=tensor(...))} |
| {'file_name': '/your_path/image2.jpg', |
| 'scores': tensor([0.9189, 0.9491]), |
| 'pred_boxes_XYXY': tensor([[734.9685, 534.2003, 287.3923, 254.8859], |
| [434.2853, 765.1219, 132.1029, 867.9283]]), |
| 'pred_densepose': DensePoseEmbeddingPredictorOutput(embedding=tensor(...), coarse_segm=tensor(...))}] |
| ``` |
|
|
| `DensePoseEmbeddingPredictorOutput` contains the following fields: |
| - `embedding` - a tensor of size `[N, D, sz, sz]` of type `torch.float`, which contains embeddings of size `D` of the `N` detections in the image |
| - `coarse_segm` - a tensor of size `[N, 2, sz, sz]` of type `torch.float` which contains segmentation scores of the `N` detections in the image; e.g. a mask can be obtained by `coarse_segm.argmax(dim=1)` |
|
|
| `sz` is a fixed size for the tensors; you can resize them to the size of the bounding box, if needed |
|
|
| We can use the following code, to parse the outputs of the first |
| detected instance on the first image (IUV model). |
| ``` |
| img_id, instance_id = 0, 0 # Look at the first image and the first detected instance |
| bbox_xyxy = data[img_id]['pred_boxes_XYXY'][instance_id] |
| result = data[img_id]['pred_densepose'][instance_id] |
| uv = result.uv |
| ``` |
| The array `bbox_xyxy` contains (x0, y0, x1, y1) of the bounding box. |
|
|
|
|
| ## Visualization Mode |
|
|
| The general command form is: |
| ```bash |
| python apply_net.py show [-h] [-v] [--min_score <score>] [--nms_thresh <threshold>] [--output <image_file>] <config> <model> <input> <visualizations> |
| ``` |
|
|
| There are four mandatory arguments: |
| - `<config>`, configuration file for a given model; |
| - `<model>`, model file with trained parameters |
| - `<input>`, input image file name, pattern or folder |
| - `<visualizations>`, visualizations specifier; currently available visualizations are: |
| * `bbox` - bounding boxes of detected persons; |
| * `dp_segm` - segmentation masks for detected persons; |
| * `dp_u` - each body part is colored according to the estimated values of the |
| U coordinate in part parameterization; |
| * `dp_v` - each body part is colored according to the estimated values of the |
| V coordinate in part parameterization; |
| * `dp_contour` - plots contours with color-coded U and V coordinates; |
| * `dp_iuv_texture` - transfers the texture from a given texture image file to detected instances, in IUV mode; |
| * `dp_vertex` - plots the rainbow visualization of the closest vertices prediction for a given mesh, in CSE mode; |
| * `dp_cse_texture` - transfers the texture from a given list of texture image files (one from each human or animal mesh) to detected instances, in CSE mode |
| |
|
|
| One can additionally provide the following optional arguments: |
| - `--min_score` to only show detections with sufficient scores that are not lower than provided value |
| - `--nms_thresh` to additionally apply non-maximum suppression to detections at a given threshold |
| - `--output` to define visualization file name template, which defaults to `output.png`. |
| To distinguish output file names for different images, the tool appends 1-based entry index, |
| e.g. output.0001.png, output.0002.png, etc... |
| - `--texture_atlas` to define the texture atlas image for IUV texture transfer |
| - `--texture_atlases_map` to define the texture atlas images map (a dictionary `{mesh name: texture atlas image}`) for CSE texture transfer |
|
|
|
|
| The following examples show how to output results of a DensePose model |
| with ResNet-50 FPN backbone using different visualizations for image `image.jpg`: |
|
|
| 1. Show bounding box and segmentation: |
| ```bash |
| python apply_net.py show configs/densepose_rcnn_R_50_FPN_s1x.yaml \ |
| https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl \ |
| image.jpg bbox,dp_segm -v |
| ``` |
|  |
|
|
| 2. Show bounding box and estimated U coordinates for body parts: |
| ```bash |
| python apply_net.py show configs/densepose_rcnn_R_50_FPN_s1x.yaml \ |
| https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl \ |
| image.jpg bbox,dp_u -v |
| ``` |
|  |
|
|
| 3. Show bounding box and estimated V coordinates for body parts: |
| ```bash |
| python apply_net.py show configs/densepose_rcnn_R_50_FPN_s1x.yaml \ |
| https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl \ |
| image.jpg bbox,dp_v -v |
| ``` |
|  |
|
|
| 4. Show bounding box and estimated U and V coordinates via contour plots: |
| ```bash |
| python apply_net.py show configs/densepose_rcnn_R_50_FPN_s1x.yaml \ |
| https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl \ |
| image.jpg dp_contour,bbox -v |
| ``` |
|  |
|
|
| 5. Show bounding box and texture transfer: |
| ```bash |
| python apply_net.py show configs/densepose_rcnn_R_50_FPN_s1x.yaml \ |
| https://dl.fbaipublicfiles.com/densepose/densepose_rcnn_R_50_FPN_s1x/165712039/model_final_162be9.pkl \ |
| image.jpg dp_iuv_texture,bbox --texture_atlas texture_from_SURREAL.jpg -v |
| ``` |
|  |
|
|
| 6. Show bounding box and CSE rainbow visualization: |
| ```bash |
| python apply_net.py show configs/cse/densepose_rcnn_R_50_FPN_s1x.yaml \ |
| https://dl.fbaipublicfiles.com/densepose/cse/densepose_rcnn_R_50_FPN_s1x/251155172/model_final_c4ea5f.pkl \ |
| image.jpg dp_vertex,bbox -v |
| ``` |
|  |
|
|
| 7. Show bounding box and CSE texture transfer: |
| ```bash |
| python apply_net.py show configs/cse/densepose_rcnn_R_50_FPN_s1x.yaml \ |
| https://dl.fbaipublicfiles.com/densepose/cse/densepose_rcnn_R_50_FPN_s1x/251155172/model_final_c4ea5f.pkl \ |
| image.jpg dp_cse_texture,bbox --texture_atlases_map '{"smpl_27554": "smpl_uvSnapshot_colors.jpg"}' -v |
| ``` |
|  |
|
|
| The texture files can be found in the `doc/images` folder |
|
|