[Maya-Python] Playblast from multiple cameras

2,027 views
Skip to first unread message

Marcus Ottosson

unread,
Jan 26, 2016, 11:33:33 AM1/26/16
to python_in...@googlegroups.com
Hi all,

I'm looking to perform a playblast from multiple cameras at once, and they way I was thinking of going at it, was to have four viewports refresh during playback, and capture each viewport into a QPixmap that I line up, such as in a 4x4 grid, within a single widget and save the resulting image as the "playblast".

Does anyone know how to grab a frame from the current viewport? Or know of an existing or more straightforward method to achieve the same result?

Best,
Marcus

--
Marcus Ottosson
konstr...@gmail.com

Marcus Ottosson

unread,
Jan 26, 2016, 11:49:02 AM1/26/16
to python_in...@googlegroups.com
I found this.

- http://stackoverflow.com/a/9417180

..but it doesn't produce anything reliable. Just a black-ish picture; like a dump of an arbitrary location in memory.

Saving to a file works however.

- http://nathanhorne.com/?p=485

But it's not ideal..
--
Marcus Ottosson
konstr...@gmail.com

Marcus Ottosson

unread,
Jan 26, 2016, 12:17:29 PM1/26/16
to python_in...@googlegroups.com
Sorry, this was the Nathan Horne address I meant to post.

- http://nathanhorne.com/?p=261
--
Marcus Ottosson
konstr...@gmail.com

Justin Israel

unread,
Jan 26, 2016, 4:00:02 PM1/26/16
to python_in...@googlegroups.com
Hey Marcus,

The MImage approach was a way I had also used in the past. I had encountered what you mentioned about the issues grabbing from the pixmap. Seemed to always be black for me as well because of the OpenGL viewport that is embedded, I think?

There are a couple options for MImage though. On Linux/OSX there is a shmem/tmpfs location which is a mounted "ram drive". You can write images there and maybe move them elsewhere in a background thread? I don't know what exists for this solution on Windows. Also, MImage can give you back the raw pixel data. Maybe you can make use of it with something like OpenImageIO/ImageMagick/OpenCV, in memory?

Justin

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/CAFRtmOCUY38zYjNMQT7EGRmJTxYQyXi4-FBbi%2BFtRFwSkM1vUA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.

Marcus Ottosson

unread,
Jan 26, 2016, 5:05:33 PM1/26/16
to python_in...@googlegroups.com

Thanks Justin.

I think I got a reasonable version up and running with writing to disk; basically per frame write to disk, read it back in, and grab the resulting viewports laid out in a grid. The performance overhead wasn’t as bad as I had first thought, at least in the expected cases where the majority of time is spent calculating the frame itself.

I’m on Linux though and the memory location sounds like a healthy optimisation, may also bypass any potential permission issues with writing to disk.

The end result at least seems like something many people have been looking for, judging by Googling for a solution, to capture all four viewports at once in a single go. I’ve had a need for it many times in the past, before I knew Python well enough to get it together. I’ll see if I can put something shareable together and perhaps crack that nut once and for all.

Also, MImage can give you back the raw pixel data

I tried making use of that, do you mean the MImage.pixels() method? I got what I assume is a pointer to an array of pixels in memory, but I wasn’t sure how to make use of that through Python. That might allow me to generate a pixmap directly, as opposed to writing it out first.



For more options, visit https://groups.google.com/d/optout.



--
Marcus Ottosson
konstr...@gmail.com

Roy Nieterau

unread,
Jan 27, 2016, 3:24:18 PM1/27/16
to Python Programming for Autodesk Maya
Sorry for hijacking the thread.

Could this also be used to create a playblast in 32 bit with the color management in Maya 2016?

Justin Israel

unread,
Jan 27, 2016, 10:54:27 PM1/27/16
to python_in...@googlegroups.com


On Wed, 27 Jan 2016 11:05 AM Marcus Ottosson <konstr...@gmail.com> wrote:

Thanks Justin.

I think I got a reasonable version up and running with writing to disk; basically per frame write to disk, read it back in, and grab the resulting viewports laid out in a grid. The performance overhead wasn’t as bad as I had first thought, at least in the expected cases where the majority of time is spent calculating the frame itself.

I’m on Linux though and the memory location sounds like a healthy optimisation, may also bypass any potential permission issues with writing to disk.

The end result at least seems like something many people have been looking for, judging by Googling for a solution, to capture all four viewports at once in a single go. I’ve had a need for it many times in the past, before I knew Python well enough to get it together. I’ll see if I can put something shareable together and perhaps crack that nut once and for all.

Also, MImage can give you back the raw pixel data

I tried making use of that, do you mean the MImage.pixels() method? I got what I assume is a pointer to an array of pixels in memory, but I wasn’t sure how to make use of that through Python. That might allow me to generate a pixmap directly, as opposed to writing it out first.


I took a look at python options and I couldn't find any support in OpenImageIO, ImageMagick, or OpenCV bindings that would let you pass a data pointer (you can convert the swig pixels array from MImage using long()) 

I know you could do it from C++

Justin Israel

unread,
Jan 28, 2016, 2:15:48 AM1/28/16
to Python Programming for Autodesk Maya
Hey Marcus,

I did some more searching an found some info about people going from MImage to QImage by passing the pointer. 

Simplified example:

Original post:

Justin

To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Marcus Ottosson
konstr...@gmail.com

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_maya+unsub...@googlegroups.com.

Marcus Ottosson

unread,
Jan 28, 2016, 3:04:43 AM1/28/16
to python_in...@googlegroups.com

Ah, neat. Thanks, I’ll try this out.

One of the problems of the disk-writing approach in practice was that the instant reading and writing of a file is quite unpredictable; as I’m overwriting the same file per frame, sometimes it picks up an older image several frames back. Assuming network caching or such. This should circumvent that.

Could this also be used to create a playblast in 32 bit with the color management in Maya 2016?

Dunno, it would depend on the capabilities of both MImage, the framegrabbing mechanism and whether 32-bits of pixels are actually stored in the framebuffer. It’s the latter where I’m sceptical.


To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Marcus Ottosson
konstr...@gmail.com

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python_inside_maya/3699754a-eafa-4e14-b6f6-6bc3837be222%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Marcus Ottosson
konstr...@gmail.com

Marcus Ottosson

unread,
Jan 29, 2016, 10:24:15 AM1/29/16
to python_in...@googlegroups.com
Haha, this works great. Performance-wise I couldn't pick up any difference, though I haven't run through enough tests to be conclusive. The local disks here are rather quick, but likely it would make more of a difference in a fully networked environment, or where disks were slow.

The obvious upside is I no longer have to access the disk for intermediate storage and that's a big win.

---

The next problem is capturing the image without having to worry about whether something is obscuring the viewport. Like in the good old days (on Windows and current days on Linux) grabbing the framebuffer also grabs whatever is in front of the viewport at the time, which means you'll practically have to give up your machine for the duration of the playblast.

An off-screen option would be ideal, but I'm not sure if that's an option in this case.

This command needs to somehow access the viewport, without having actually have it visible; and ideally with cmds.refresh(suspend=True) in action.

image = api.MImage()
view.readColorBuffer(image, True)

- http://nathanhorne.com/?p=261

Any ideas?


--
Marcus Ottosson
konstr...@gmail.com

Marcus Ottosson

unread,
Feb 1, 2016, 9:02:05 AM2/1/16
to python_in...@googlegroups.com
Ok, I think I'm onto something.

Turns out, that the M3dView object has a refresh() method taking an argument "offscreen" along with a buffer in which to write the pixels. I think this should properly grab the viewport even though windows are overlapping.

However, the buffer argument must be an instance of MPxGlBuffer and I'm not sure how to instantiate it, or how to fetch the pixels out of there once filled in.

The documentation also says that this class is used for this purpose (on Linux, but assuming it would still work on Windows).

- https://knowledge.autodesk.com/search-result/caas/CloudHelp/cloudhelp/2016/ENU/Maya-SDK/cpp-ref/class-m-px-gl-buffer-html.html

Here's what I've got so far.
import maya.OpenMayaUI as apiUI
view = apiUI.M3dView.active3dView()
buffer = # MPxGlBuffer somehow..
view.refresh(buffer, True)
Now how can I create that buffer, and retrieve pixels from it?
--
Marcus Ottosson
konstr...@gmail.com

Marcus Ottosson

unread,
Feb 1, 2016, 1:00:35 PM2/1/16
to python_in...@googlegroups.com
Here's a working example illustrating the problem.

Put the script editor infront of the currently active viewport before running this.
On Windows, replace subprocess command "eog" with "start", or just comment it out and open the file manually.

```python
import subprocess
import maya.api.OpenMaya as api
import maya.api.OpenMayaUI as apiUI

view = apiUI.M3dView.active3dView()

cmds.refresh()

image = api.MImage()
view.readColorBuffer(
    image,
    True  # BGRA -> RGBA
)

fname = "/usr/tmp/myfile.jpg"
image.writeToFile(fname, "jpg")
subprocess.Popen(["eog", fname])
```
--
Marcus Ottosson
konstr...@gmail.com

Marcus Ottosson

unread,
Feb 9, 2016, 9:24:29 AM2/9/16
to python_in...@googlegroups.com
Found an alternative approach; basically altering the window manager such that overlapping windows aren't captured in the colorbuffer to begin with.

On CentOS 6, Gnome 2;

```bash
gconftool-2 --type bool --set /apps/metacity/general/compositing_manager true
```
--
Marcus Ottosson
konstr...@gmail.com

Kumaran M

unread,
Feb 10, 2016, 1:55:44 PM2/10/16
to Python Programming for Autodesk Maya
How about using this...

https://github.com/mottosso/maya-capture

Regards,
Kumar

Kumaran M

unread,
Feb 10, 2016, 1:55:44 PM2/10/16
to Python Programming for Autodesk Maya
Sorry, here is the correct repo... might want to try this out.

https://github.com/mottosso/maya-multicapture


On Tuesday, January 26, 2016 at 10:03:33 PM UTC+5:30, Marcus Ottosson wrote:

Justin Israel

unread,
Feb 10, 2016, 1:59:49 PM2/10/16
to Python Programming for Autodesk Maya


On Thu, 11 Feb 2016 7:55 AM Kumaran M <atv....@gmail.com> wrote:

I believe you just linked Marcus to his own repo ;-) 
Not only that, but this is recent and probably what he came up with to solve his problem from this thread. 

--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.
Message has been deleted

Justin Israel

unread,
Feb 10, 2016, 10:18:34 PM2/10/16
to python_in...@googlegroups.com


On Thu, Feb 11, 2016 at 4:09 PM Kumaran M <atv....@gmail.com> wrote:
oops sorry, my mistake.

Hah no worries. Was just funny is all. 
 


On Tuesday, January 26, 2016 at 10:03:33 PM UTC+5:30, Marcus Ottosson wrote:
--
You received this message because you are subscribed to the Google Groups "Python Programming for Autodesk Maya" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python_inside_m...@googlegroups.com.

Marcus Ottosson

unread,
Feb 11, 2016, 4:54:36 AM2/11/16
to python_in...@googlegroups.com
Justin is right, but thanks for the tip! :)


For more options, visit https://groups.google.com/d/optout.



--
Marcus Ottosson
konstr...@gmail.com

Reply all
Reply to author
Forward
0 new messages