Yolact: where is the alpha mask in the png

Created on 15 Jan 2020  路  8Comments  路  Source: dbolya/yolact

Sorry newbie question - I just assumed the saved png has the alpha mask in it (the a of 8 bit each rgba) and it can be accessed in other programs image processing ( photoshop, gimp. pillow) so for instance, in my case, I can set up a process with it to mask out the background and create a new image without the background. Yet when I inspect the outputed png I do not see a transparency 8 bit matte. How does one access the matte as an image file.

Most helpful comment

The default behavior is just to overlay the mask on top of the original image. If you want to output and alpha channel as an image instead, that's a simple change. Just replace this block:
https://github.com/dbolya/yolact/blob/13bb0c6322aa35777b73d3ca6522a080588fef03/eval.py#L189-L209
with

if args.display_masks and cfg.eval_mask_branch and num_dets_to_consider > 0:
        # After this, mask is of size [num_dets, h, w, 1]
        masks = masks[:num_dets_to_consider, :, :, None]
        img_gpu = (masks.sum(dim=0) >= 1).float().expand(-1, -1, 3).contiguous()
    else:
        img_gpu *= 0

and run evaluation with --display_bbox=False and --display_text=False.


But I can do you one better! If you instead replace the block with

if args.display_masks and cfg.eval_mask_branch and num_dets_to_consider > 0:
        # After this, mask is of size [num_dets, h, w, 1]
        masks = masks[:num_dets_to_consider, :, :, None]
        img_gpu *= (masks.sum(dim=0) >= 1).float().expand(-1, -1, 3)
    else:
        img_gpu *= 0

everything will already be masked out for you. Though you probably also want a chroma key so actually that might not be very useful now that I think about it. Yeah it's prob better just to use the mask because you'd need both anyway :/

All 8 comments

The default behavior is just to overlay the mask on top of the original image. If you want to output and alpha channel as an image instead, that's a simple change. Just replace this block:
https://github.com/dbolya/yolact/blob/13bb0c6322aa35777b73d3ca6522a080588fef03/eval.py#L189-L209
with

if args.display_masks and cfg.eval_mask_branch and num_dets_to_consider > 0:
        # After this, mask is of size [num_dets, h, w, 1]
        masks = masks[:num_dets_to_consider, :, :, None]
        img_gpu = (masks.sum(dim=0) >= 1).float().expand(-1, -1, 3).contiguous()
    else:
        img_gpu *= 0

and run evaluation with --display_bbox=False and --display_text=False.


But I can do you one better! If you instead replace the block with

if args.display_masks and cfg.eval_mask_branch and num_dets_to_consider > 0:
        # After this, mask is of size [num_dets, h, w, 1]
        masks = masks[:num_dets_to_consider, :, :, None]
        img_gpu *= (masks.sum(dim=0) >= 1).float().expand(-1, -1, 3)
    else:
        img_gpu *= 0

everything will already be masked out for you. Though you probably also want a chroma key so actually that might not be very useful now that I think about it. Yeah it's prob better just to use the mask because you'd need both anyway :/

Hi, @dbolya thanks for the explanation. In addition to this, I am just trying to mask out all the single instances from the image individually, for example if there are multiple chairs or Tv eetc I will mask out all of them individually or if there are single one of them, I will do the same thing. Every saved image will include one masked object. But it is just doing it for just one object then only gives black frames. My modified version your above code is like this:

if args.display_masks and cfg.eval_mask_branch and num_dets_to_consider > 0:
    masks = masks[:num_dets_to_consider, :, :, None]
    print('maskshape', (masks.shape))
    for i in range(num_dets_to_consider):
        msk = masks[i, :, :, None]
        mask = msk.view(1, 968, 1296, 1)
        print('newmaskshape', (mask.shape))
        img_gpu *= (mask.sum(dim=0) >= 1).float().expand(-1, -1, 3)
        img_numpy = (img_gpu * 255).byte().cpu().numpy()
        cv2.imwrite('.../mask'+str(i)+'.jpg', img_numpy)

Can you see where the problem is?
Thanks...

@bayraktare That's because of img_gpu *= (mask.sum(dim=0) >= 1).float().expand(-1, -1, 3). You're masking the first instance out, saving that back to the image, and then masking the second instance out of the version of the image that was already masked, so only the overlapping region between the two masks remain. You're getting black frames because that overlap doesn't happen usually.

To fix, just change these lines:

        img_gpu *= (mask.sum(dim=0) >= 1).float().expand(-1, -1, 3)
        img_numpy = (img_gpu * 255).byte().cpu().numpy()

to

        img_gpu_masked = img_gpu * (mask.sum(dim=0) >= 1).float().expand(-1, -1, 3)
        img_numpy = (img_gpu_masked * 255).byte().cpu().numpy()

Untested so let me know if it doesn't work.

Yeah @dbolya that runs great. Thanks a lot.
In addition to that, if you add the following line you can also have the background as well.

img_background = img.byte().cpu().numpy() - (img_gpu_masked * 255).byte().cpu().numpy()

Hi @dbolya, could you point out if I can only crop the bounding box? Thanks

Yeah @dbolya that runs great. Thanks a lot.
In addition to that, if you add the following line you can also have the background as well.

img_background = img.byte().cpu().numpy() - (img_gpu_masked * 255).byte().cpu().numpy()

@bayraktare I would like to have the background in green color (greenscreen mimicking) instead of the black one, do you have any insight how can I do that ?

Thanks it worked. Had to change

```
msk = masks[i, :, :, None]
mask = msk.view(1, 968, 1296, 1)


msk = masks[i, :, :, None]
mask = msk.view(1,msk.shape[0], msk.shape[1], 1)
```

To make it work with any input size image

if args.display_masks and cfg.eval_mask_branch and num_dets_to_consider > 0:
    # After this, mask is of size [num_dets, h, w, 1]
    masks = masks[:num_dets_to_consider, :, :, None]
    img_gpu = (masks.sum(dim=0) >= 1).float().expand(-1, -1, 3).contiguous()
    img_gpu = img_gpu*img/255  # Black/White Image * Original Image(Color) / 255
else:
    img_gpu *= 0

I just modified the above code from 189 lines to 209
This is how I get the black background and color human instance image :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

serhatiscan picture serhatiscan  路  5Comments

dlllll-q picture dlllll-q  路  11Comments

noobgrow picture noobgrow  路  4Comments

CzJaewan picture CzJaewan  路  5Comments

abhigoku10 picture abhigoku10  路  6Comments