1
$\begingroup$

I am using two Viewer nodes to directly access pixel values of the rendering through bpy.data.images['Viewer Node'].pixels.I want to access the outputs of both of these nodes by activating them one by one using Python. However, it seems that I cannot activate them via Python. If I click on either of them the Viewer Node data block is immediately updated as the sum of the pixel values shows. For instance, clicking on Viewer2:

enter image description here

And doing np.array(bpy.data.images['Viewer Node'].pixels[:]).sum() will give me 292007.42460217333

Clicking on Viewer1 and doing np.array(bpy.data.images['Viewer Node'].pixels[:]).sum() will result in a different number. Doing the followings will not activate either of the Viewer nodes and I will always get the same number in the np.sum():

v1 = bpy.context.scene.node_tree.nodes['Viewer']
v2 = bpy.context.scene.node_tree.nodes['Viewer.001']

v1.select = True
v2.select = False

np.array(bpy.data.images['Viewer Node'].pixels[:]).sum()
292007.42460217333`

v1.select = False
v2.select = True

np.array(bpy.data.images['Viewer Node'].pixels[:]).sum()
292007.42460217333`

I also tried bpy.context.scene.node_tree.nodes.active = v1 after v1.select = True and v2.select = False lines but it still does not work.

None of these activate either of the Viewer nodes. It seems that I am doing the same thing as shown in the solutions provided here but I cannot activate the nodes, or update the image block without re-rendering. Another solution that I found is this one. However, it seems that Blender's Python API has changed a little bit for the newer versions of Blender (I am using 2.79) and I cannot use the method provided.

A promising solution seems to be coming from invoking clicking events as shown here but I don't know how I can do it for selecting nodes. So I wonder, does any one know how to activate the Viewer nodes via Python, possibly via invoking LBM events?

$\endgroup$
8
  • $\begingroup$ The link you posted is not invoking clicking events at all, its capturing them. $\endgroup$
    – batFINGER
    Mar 10, 2018 at 22:28
  • $\begingroup$ @batFINGER Sorry I couldn't clearly understand what the problem is there. I thought capturing the invocation means something a different, and relevant to my problem. So actually maybe the most relevant thing would be this $\endgroup$
    – Amir
    Mar 10, 2018 at 22:33
  • $\begingroup$ Sorry, Also the answer in your last link is not relevant as it describes what very simplified logic is behind selecting an object in 3D view. Where the mouse is simulated with another 3D object. Not simulating events at all $\endgroup$
    – J. Bakker
    Mar 11, 2018 at 8:37
  • $\begingroup$ @J.Bakker Well I thought this is the closest thing, not totally relevant. The point is to simulate the mouse in Blender through scripting. $\endgroup$
    – Amir
    Mar 11, 2018 at 9:16
  • 1
    $\begingroup$ I don't see a way to make this work. I expect you will have to render to image. You can mount a tmpfs to keep these renders in ram and eliminate disk IO. To limit the number of files, render one, then read into numpy and append collected info to a data file and delete the render. $\endgroup$
    – sambler
    Mar 11, 2018 at 17:35

2 Answers 2

2
$\begingroup$

Very good question. But The answer at this moment is you can’t. The python interpreter needs to be finished in order to start the compositor recalculation. This is a background job and after it is finished you know for certain that the new image has been updated.

If we would have a possibility in the API to find out if the background job of the compositor is running we would be able to start a python thread or modal window to wait for this to happen and then continue the task you want to do.

Perhaps best solution ATM is to use the file output node to always store those all outputs and when needed read them back.

$\endgroup$
2
  • $\begingroup$ The reason that I do not want to store files is that I am going to get millions of renderings and I cannot store them on disk. The disk will have enough space but will not be able to handle a couple of millions of meta-data files. So I need to store the images in Numpy arrays and store them in chunks on disk. I would really appreciate if you can look more into this problem and offer a solution. $\endgroup$
    – Amir
    Mar 10, 2018 at 9:36
  • $\begingroup$ I updated the question. I think there is a way to do this actually. Let let me know if you can come up with some ideas on how I can invoke clicking events $\endgroup$
    – Amir
    Mar 10, 2018 at 19:38
2
$\begingroup$

I think you'll be a lot better off using a single Viewer node, and then toggling the viewer input with a Switch node:

enter image description here

You can toggle the node with this script:

import bpy
switch = bpy.context.scene.node_tree.nodes['Switch']
switch.check = True
$\endgroup$
1
  • $\begingroup$ Thank you but I'm afraid your solution potentially adds another layer of complexity to the problem :( The thing is I am going to do millions of renderings. If I use one Viewer node I need to do two renderings to update the image buffer. Do you have any ideas on how I can probably simulate clicking on the nodes? $\endgroup$
    – Amir
    Mar 10, 2018 at 21:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.