Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP, ENH: frame number via compositor #28

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

tylerjereddy
Copy link
Contributor

[ci skip]

I'm assuming that there was also some desire to screen capture blf-placed labels as well and get them into the render in some roundabout way, but the current approach is even cruder and just produces empty images with frame numbers at the bottom using an external lib.

For still images, it seems more resilient to changes in focal length:

Focal length 110:

image

Focal length 80:

image

Focal length 10:

image

* Based on discussion in yuxuanzhuang#27, and as an alternative to
 yuxuanzhuang#14, this is a demo for using external image generation
 followed by a compositor step to overlay the image that
 contains nothing but the frame number in it.

* Predictably, as recently noted at yuxuanzhuang#21 (comment)
  this ablates the background coloring that also uses the compositor.
  It seemed fairly obvious to me that this would happen even as
  non-expert, if we just naively use the compositor for isolated
  purposes that try to ignore each other. I guess I can't escape the
  node connection reality under the hood as much as I'd like to.

[ci skip]
width=resolution[0],
height=resolution[1],
text=f"frame: {self.frame_number}")
_composit_frame_label(img_path=img_path)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that this won't work for movies yet--some/all of the infrastructure may need to be migrated to _update_frame(), which is a bit annoying for design perhaps.

text: str):
img = Image.new('RGBA', (width, height), (0, 0, 0, 0))
draw = ImageDraw.Draw(img)
font = ImageFont.truetype("/System/Library/Fonts/Geneva.ttf", 80)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is obviously not portable. Also, to make matters worse, using the default built-in font from PIL doesn't allow custom font size: python-pillow/Pillow#2695

And, of course, the font size may need to be tuned in some cases unless we scale it "automatically" somehow.

scene.use_nodes = True
tree = scene.node_tree
links = tree.links
tree.nodes.clear()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

presumably this is what ablates the background composition

text_height = text_bbox[3] - text_bbox[1]
x = (width - text_width) // 2
y = height - text_height - 40
draw.text((x, y), text, font=font, fill=(255, 255, 255, 255))
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would probably need a way for user to specify the color of the font, especially if they are also specifying the color of the background

@PardhavMaradani
Copy link

PardhavMaradani commented Mar 7, 2025

I don't think we would need Blender's compositor here. PIL could be much simpler even if composition is really required (for example, in the case of video). Alternatively, we could possibly draw over the render image directly for simple use cases.

Here is a snippet from existing code where the viewport and annotations images are composited. If the alpha image is regular (ie., not pre-multiplied), the conversion step is also not needed:

    .....
    bg = Image.open(viewport_image)
    fg = Image.open(annotations_image)
    fg = Image.frombytes("RGBa", fg.size, fg.tobytes()).convert("RGBA")
    bg.paste(fg, (0, 0), fg)
    display(bg)
    .....

PIL's alpha_composite is another alternative to simple pasting.

I'm assuming that there was also some desire to screen capture blf-placed labels as well and get them into the render in some roundabout way

Currently, it is the same code that is used for viewport display using blf and gpu modules that runs in the render case as well - there is no screen capture, instead of the screen buffer, they are rendered to an off-screen buffer from which the image is generated. In a pure headless mode, the text/drawings will have to be drawn onto a PIL image directly.

* Based on reviewer feedback, avoid the need to write
image files to disk when compositing in frame numbers. Instead,
keep the pixel data in memory and pass directly into
Blender compositor workflow.
* Use a pre-render handler to allow compositing
of frame numbers into Blender movies.

[ci skip]
@tylerjereddy
Copy link
Contributor Author

tylerjereddy commented Mar 7, 2025

even if composition is really required (for example, in the case of video)

Maybe there is some confusion, but I'm generally adding features for both at the same time--I only use the image samples for fast iteration/sharing. I've pushed in a commit to use a pre-render handler to allow the composition to propagate to the movie renders as well now. Here is sample movie generated from this branch using a reference (https://github.com/tylerjereddy/render_north_star) render script: https://youtube.com/shorts/uwDHh-y9uBw?feature=share

The cross-interference with the background color composition remains, but the frame number insertion seems to be working "ok" now. The other caveats from above remain alongside one additional observation, which is a bit of "bouncing" in the text placement I think. Maybe the math that does the positioning of the text could compensate for that.

PIL could be much simpler

That I think I agree on, though the only simplification I've been able to make so far is to stop writing temporary image files and just keep them in memory, which is a nice clean up. I suspect we agree the compositor is more or less needed for both image and video support at this point. Also, I'd be a bit hesitant to treat image and movie generation separately unless there's a really good reason for that--it would be nice if the image could serve as a reliable preview for the movie frames, which may break down a bit if we use separate text placement approaches for both.

@tylerjereddy
Copy link
Contributor Author

Frame number placement also seems "ok" in movies when focal length is varied on this branch, as intended. Most of the other caveats/issues above still apply though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants