2

TL;DR: is there a way to scale down both UV map and texture without losing the quality of the produced result?

Full story:

I'm trying to develop a simple rendering engine which would take UV map from .EXR file, put a texture on it and serve to the client. Whole process looks like this:

from PIL import Image
import numpy as np

texture = Image.open("texture.png")
texture_array = np.asarray(txt).transpose(1, 0, 2) 

# assume reading EXR file and grabbing only R and G channels from it
uv = read_exr()
# scale indexes to texture size
uv[..., 0] *= texture.size[0]
uv[..., 1] *= texture.size[1]
map = uv.astype('uint16')
# use numpy indexing to produce the result
result = texture_array[map[..., 0], map[..., 1]]

# downsample for smoother image
image = Image.fromarray(result, "RGB").resize((2048, 2048), Image.LANCZOS)

Produced image is a shirt and texture is in fact a fabric scan. The UV is actually composed from several files since each part of the shirt may have different options.

Everything works fine on high resolution but I thought of making a "preview" version to show on the webpage. Now the problem is when I try to scale the UV and texture down the result only looks decent for fabric with big patterns. E.g. fabric with a lot of thin lines produces moire-like effects. Below are examples of high resolution result scaled down by browser (this is acceptable): High resolution scaled down

and result composed of UV and texture which were scaled down programmatically (this is no way): Built from resized UV and texture

Here's how I scale both texture and UV:

from scipy.ndimage.interpolation import zoom

uv = zoom(uv, [0.25, 0.25, 1], order=1) # higher order produces negative values
texture = texture.resize((1024, 1024), Image.LANCZOS)

I also tried using cv2 for UV scaling but it gives the same result.

It's critical to be able to build this thumbnail version, since compose of high resolution version takes few seconds and thumbnail builds in a split second. Unfortunately I can't prerender all the possible combinations due to high amount of different options.

I wonder if there're some tricks to make the low resolution result look better, ideally to look the same as the downsampled "original" image. I would really appreciate any ideas, since I don't know much about image processing and couldn't find any decent solution so far.

Here's what I tried with no luck already:

  1. Blur the texture a little bit of gaussian blur + UnsharpMask. Helps with moire, but kills the tone of fabric:

blur

  1. Use original-sized texture (no downsample): result looks too sharp and also has moire-like effect; looks awful for lot of other fabrics

enter image description here

  • 1
    No guarantees, but my first attempt would probably to be to try `im.thumbnail(size, Image.ANTIALIAS)` as [discussed in this question](http://stackoverflow.com/questions/273946/how-do-i-resize-an-image-using-pil-and-maintain-its-aspect-ratio). Anti-aliasing should help with the moiré I would think. – Lukas Graf Aug 25 '16 at 19:52
  • 1
    Are you looking effectively for [Anti-Aliasing](https://en.wikipedia.org/wiki/Anti-aliasing_filter) perhaps? – Aaron Aug 25 '16 at 19:56
  • Also, something that's not quite clear to me from the question yet: Can you isolate the issue from 3D graphics at all? In other words, could your question maybe be reduced to "How to avoid moiré when downsampling an image using PIL / numpy"? Or are you getting additional moiré artefacts *as a result* of the 3D rendering process? – Lukas Graf Aug 25 '16 at 19:56
  • @LukasGraf brings up a good point.. I might add that AA filtering is typically a post rendering operation – Aaron Aug 25 '16 at 20:00
  • @LukasGraf yeah I already downsample image once: my sources (both UV and texture) are in 4096x4096 and I resize render result to 2048x2048 to get smoother edges/transitions and the resulting image looks nice. But this render takes a lot of time so my goal now is to resize sources to 1024x1024 so I can get 512x512 image after downsampling. Surely if I'd take 2048x2048 image and just resize it to 512x512 I would get perfect results, but this way I'd still have to build high resolution image and it's expensive. And using low resolution sources gives bad result, although I don't understand why... – Arseniy Panfilov Aug 25 '16 at 23:14
  • I think it's worth to mention that I don't work with any 3D models, I only receive prepared UV map from some third party and use different textures to create different types of shirts. So, given is: high resolution UV and texture and goal is: downsample both to achieve faster rendering of thumbnail. – Arseniy Panfilov Aug 25 '16 at 23:18

0 Answers0