def main(): current_dir = realpath(dirname(__file__)) exr_files = sorted(glob.glob(join(current_dir, 'refs', '*_ref_*.exr'))) images = [] for f in exr_files: if (os.path.basename(f) == 'result.exr'): continue images.append(np.array(Bitmap(f))) images_np = np.stack(images, axis=-1) s = images_np.shape h = s[0] w = s[1] images_np = np.swapaxes(images_np, 2, 3) print(f"images_np.shape: {images_np.shape}") images_np = np.swapaxes(images_np, 0, 2) images_np = np.swapaxes(images_np, 1, 2) print(f"images_np.shape: {images_np.shape}") n_cols = 4 n_rows = len(images) // n_cols images_np = np.reshape(images_np, [n_rows, n_cols, h, w, 3]) images_np = np.swapaxes(images_np, 1, 2) images_np = np.reshape(images_np, [h * n_rows, w * n_cols, 3]) # images_np = np.reshape(images_np, [h * 12, w * 2, 3]) print(f"images_np.shape: {images_np.shape}") Bitmap(images_np).write('result.exr')
def check_finite_difference(test_name, make_scene, get_diff_params, diff_integrator=diff_integrator_default, diff_spp=4, diff_passes=10, ref_integrator=ref_integrator_default, ref_spp=128, ref_passes=10, ref_eps=0.001): from mitsuba.core import Bitmap, Struct from mitsuba.python.autodiff import render # Render groundtruth image and gradients (using finite difference) img_ref, grad_ref = compute_groundtruth(make_scene, ref_integrator, ref_spp, ref_passes, ref_eps) ek.cuda_malloc_trim() scene = make_scene(diff_integrator, diff_spp, 0.0) fsize = scene.sensors()[0].film().size() img, grad = render_gradient(scene, diff_passes, get_diff_params(scene)) error_img = np.abs(img_ref - img).mean() error_grad = np.abs(grad_ref - grad).mean() if error_img > 0.1: print("error_img:", error_img) Bitmap(img_ref).write('%s_img_ref.exr' % test_name) Bitmap(img).write('%s_img.exr' % test_name) assert False if error_grad > 0.1: print("error_grad:", error_grad) scale = np.abs(grad_ref).max() write_gradient_image(grad_ref / scale, '%s_grad_ref' % test_name) write_gradient_image(grad / scale, '%s_grad' % test_name) Bitmap(img_ref).write('%s_img_ref.exr' % test_name) Bitmap(img).write('%s_img.exr' % test_name) assert False
def test_convert_rgb_y(tmpdir): # Tests RGBA(float64) -> Y (float32) conversion b1 = Bitmap(Bitmap.PixelFormat.RGBA, Struct.Type.Float64, [3, 1]) b2 = np.array(b1, copy=False) b2[:] = [[[1, 0, 0, 1], [0, 1, 0, 0.5], [0, 0, 1, 0]]] b3 = np.array(b1.convert(Bitmap.PixelFormat.Y, Struct.Type.Float32, False)).ravel() assert np.allclose(b3, [0.212671, 0.715160, 0.072169])
def test_finite_difference(test_name, make_scene, diff_integrator, diff_spp, diff_passes, fd_integrator, fd_spp, fd_passes, fd_eps): print("Running test:", test_name) path = "output/" + test_name + "/" if not os.path.isdir(path): os.makedirs(path) print("Rendering finite differences...") scene_fd0 = make_scene(fd_integrator, fd_spp, 0) scene_fd1 = make_scene(fd_integrator, fd_spp, fd_eps) fsize = scene_fd0.sensors()[0].film().size() for i in range(fd_passes): print("pass:"******"Writing " + path + 'radiance_fd0.exr') Bitmap(values_fd0).write(path + 'radiance_fd0.exr') print("Writing " + path + 'radiance_fd1.exr') Bitmap(values_fd1).write(path + 'radiance_fd1.exr') gradient_fd = (values_fd1 - values_fd0) / fd_eps gradient_fd = gradient_fd[:, :, [0]] scale = np.abs(gradient_fd).max() write_gradient_image(gradient_fd / scale, path + 'gradient_fd', fsize) del scene_fd0, scene_fd1, values_fd0, values_fd1, channels, gradient_fd print("Rendering gradients... ({} spp, {} passes)".format( diff_spp, diff_passes)) scene = make_scene(diff_integrator, diff_spp, None) assert scene is not None params = traverse(scene) params.keep(['SDF.data']) gradient_rp_np = render_gradient(scene, diff_spp, diff_passes, scale, path, params, fd_eps)
def test_read_write_hdr(tmpdir): np.random.seed(12345) b = Bitmap(Bitmap.PixelFormat.RGB, Struct.Type.Float32, [10, 20]) ref = np.float32(np.random.random((20, 10, 3))) np.array(b, copy=False)[:] = ref[...] tmp_file = os.path.join(str(tmpdir), "out.hdr") b.write(tmp_file) b2 = Bitmap(tmp_file) assert np.abs(np.mean(np.array(b2) - ref)) < 1e-2 os.remove(tmp_file)
def test_read_write_ppm(tmpdir): np.random.seed(12345) b = Bitmap(Bitmap.PixelFormat.RGB, Struct.Type.UInt8, [10, 20]) ref = np.uint8(np.random.random((20, 10, 3)) * 255) np.array(b, copy=False)[:] = ref[...] tmp_file = os.path.join(str(tmpdir), "out.ppm") b.write(tmp_file) b2 = Bitmap(tmp_file) assert np.abs(np.mean(np.array(b2) - ref)) == 0 os.remove(tmp_file)
def test15_test_dither(): from mitsuba.core import Bitmap import numpy.linalg as la b = Bitmap(Bitmap.PixelFormat.Y, Struct.Type.Float32, [10, 256]) value = np.linspace(0, 1 / 255.0, 10) np.array(b, copy=False)[:, :, 0] = np.tile(value, (256, 1)) b = b.convert(Bitmap.PixelFormat.Y, Struct.Type.UInt8, False) b = b.convert(Bitmap.PixelFormat.Y, Struct.Type.Float32, False) err = la.norm(np.mean(np.array(b, copy=False), axis=(0, 2)) - value) assert(err < 5e-4)
def render(scene, write_to): from mitsuba.core import Bitmap, Struct success = scene.integrator().render(scene, scene.sensors()[0]) assert success film = scene.sensors()[0].film() bitmap = film.bitmap(raw=False) if not bitmap.pixel_format() == Bitmap.PixelFormat.MultiChannel: bitmap.convert(Bitmap.PixelFormat.RGB, Struct.Type.UInt8, True).write(write_to) elif bitmap.channel_count() == 16: # Stokes output, rather specialized for 'integrator_stokes_cbox' scene atm. data_np = np.array(bitmap, copy=False).astype(np.float) s0 = data_np[:, :, 4] z = np.zeros(s0.shape) s1 = np.dstack([ np.maximum(0, -data_np[:, :, 7]), np.maximum(0, data_np[:, :, 7]), z ]) s2 = np.dstack([ np.maximum(0, -data_np[:, :, 10]), np.maximum(0, data_np[:, :, 10]), z ]) s3 = np.dstack([ np.maximum(0, -data_np[:, :, 13]), np.maximum(0, data_np[:, :, 13]), z ]) Bitmap(s0).convert(Bitmap.PixelFormat.RGB, Struct.Type.UInt8, True).write(write_to) Bitmap(s1).convert(Bitmap.PixelFormat.RGB, Struct.Type.UInt8, True).write(write_to.replace('.jpg', '_s1.jpg')) Bitmap(s3).convert(Bitmap.PixelFormat.RGB, Struct.Type.UInt8, True).write(write_to.replace('.jpg', '_s3.jpg')) Bitmap(s2).convert(Bitmap.PixelFormat.RGB, Struct.Type.UInt8, True).write(write_to.replace('.jpg', '_s2.jpg')) else: for name, b in bitmap.split(): if name == '<root>': continue # normalize depth map if name == 'depth.y': data_np = np.array(b, copy=False) min_val = np.min(data_np) max_val = np.max(data_np) data_np = (data_np - min_val) / (max_val - min_val) b = Bitmap(data_np, Bitmap.PixelFormat.Y) pixel_format = b.pixel_format() if not pixel_format == Bitmap.PixelFormat.XYZ: pixel_format = Bitmap.PixelFormat.RGB f_name = write_to if name == 'image' else write_to.replace( '.jpg', '_%s.jpg' % name) b.convert(pixel_format, Struct.Type.UInt8, True).write(f_name)
def __init__(self, render_ctx): super(InternalBufferDisplay, self).__init__() self.ctx = render_ctx self.film = self.ctx.scene.getFilm() self.size = self.film.getSize() self.bitmap = Bitmap(Bitmap.ERGBA, Bitmap.EFloat32, self.size) self.bitmap.clear() self.buffer = None self.fast_buffer = True self.do_cancel = False self.time = 0 self.delay = .5 self.ctx.queue.registerListener(self)
def time_errors(method, scene_idx): scene_name = scene_names[scene_idx] crop_s = 80 crop_1_x, crop_1_y, crop_2_x, crop_2_y = scene_crops[scene_idx] path = "results_{}".format(scene_name) N = 20 times = 10**np.linspace(0, 4, N) images = [] for i in range(len(times)): img = np.array(Bitmap("{}/{}_time_{}.exr".format(path, method, i))) crops = (img[crop_1_y:crop_1_y+crop_s, crop_1_x:crop_1_x+crop_s], img[crop_2_y:crop_2_y+crop_s, crop_2_x:crop_2_x+crop_s], img) images.append(crops) ref_1, ref_2, ref_full = images[-1] error_1 = []; error_2 = []; error_full = [] for i in range(N-1): cur_1, cur_2, cur_full = images[i] error_1.append(error(ref_1, cur_1)) error_2.append(error(ref_2, cur_2)) error_full.append(error(ref_full, cur_full)) return error_1, error_2, error_full
def get_bitmap_buffer(self, passes=1): bitmap_clone = self.bitmap.clone() bitmap_clone.flipVertically() if passes == 1: return bitmap_clone.buffer() if self.buffer is None: self.buffer = Bitmap( Bitmap.ERGBA, Bitmap.EFloat32, Vector2i(self.size[0], self.size[1] * passes)) self.buffer.clear() self.buffer.copyFrom(bitmap_clone) return self.buffer.buffer()
def gauss_normalmap(alpha_x, alpha_y, res, scale, num_waves=1000, name=None, noise=0.0, encoding_yan16=False, seed=1): np.random.seed(seed) U1 = np.random.rand(num_waves) U2 = np.random.rand(num_waves) U3 = np.random.rand(num_waves) factor = np.sqrt(2 / num_waves) phi = 2 * np.pi * U1 theta = 2 * np.pi * U2 r = np.sqrt(-np.log(1.0 - U3)) fx = r * np.cos(theta) * alpha_x fy = r * np.sin(theta) * alpha_y def height(pos): return factor * np.sum(np.cos(phi + pos[0] * fx + pos[1] * fy)) def slope(pos): tmp = np.sin(phi + pos[0] * fx + pos[1] * fy) res_x = np.sum(-fx * tmp) res_y = np.sum(-fy * tmp) return factor * np.array([res_x, res_y]) def normal(pos, noise): s = slope(pos) n = np.array([ -s[0] + noise * np.random.uniform(-1, 1), -s[1] + noise * np.random.uniform(-1, 1), 1.0 ]) return n / np.sqrt(n[0]**2 + n[1]**2 + n[2]**2) xx = np.linspace(0, scale, res) yy = np.linspace(0, scale, res) normalmap = np.zeros((res, res, 3)) for j, x in enumerate(xx): print("Generate \"%s\": %.2f%%" % (name, 100 * j / (res - 1)), end="\r") for i, y in enumerate(yy): n = normal(np.array([x, y]), noise) if encoding_yan16: normalmap[i, j, 0] = n[0] normalmap[i, j, 1] = n[1] normalmap[i, j, 2] = n[2] else: normalmap[i, j, 0] = 0.5 * (n[0] + 1.0) normalmap[i, j, 1] = 0.5 * (n[1] + 1.0) normalmap[i, j, 2] = 0.5 * (n[2] + 1.0) Bitmap(normalmap).convert(Bitmap.PixelFormat.RGB, Struct.Type.Float32, False).write("textures/{}.exr".format(name)) print("")
def write_bitmap(filename, data, resolution, write_async=True): """ Write the linearized RGB image in `data` to a PNG/EXR/.. file with resolution `resolution`. """ import numpy as np from mitsuba.core import Bitmap, Struct if type(data).__name__ == 'Tensor': data = data.detach().cpu() data = np.array(data.numpy()) data = data.reshape(*resolution, -1) bitmap = Bitmap(data) if filename.endswith('.png') or \ filename.endswith('.jpg') or \ filename.endswith('.jpeg'): bitmap = bitmap.convert(Bitmap.PixelFormat.RGB, Struct.Type.UInt8, True) quality = 0 if filename.endswith('png') else -1 if write_async: bitmap.write_async(filename, quality=quality) else: bitmap.write(filename, quality=quality)
def test_read_write_png(tmpdir): np.random.seed(12345) tmp_file = os.path.join(str(tmpdir), "out.png") b = Bitmap(Bitmap.PixelFormat.Y, Struct.Type.UInt8, [10, 10]) ref = np.uint8(np.random.random((10, 10)) * 255) np.array(b, copy=False)[:] = ref[..., np.newaxis] b.write(tmp_file) b2 = Bitmap(tmp_file) assert np.sum(np.abs(np.float32(np.array(b2)[:, :, 0]) - ref)) == 0 b = Bitmap(Bitmap.PixelFormat.RGBA, Struct.Type.UInt8, [10, 10]) ref = np.uint8(np.random.random((10, 10, 4)) * 255) np.array(b, copy=False)[:] = ref b.write(tmp_file) b2 = Bitmap(tmp_file) assert np.sum(np.abs(np.float32(np.array(b2)) - ref)) == 0 os.remove(tmp_file)
def write_gradient_image(grad, name, fsize): # print("grad min", grad.min()) # print("grad max", grad.max()) # Compute RGB channels for .exr image (no grad = black) grad_R = grad.copy() grad_R[grad_R < 0] = 0.0 grad_B = grad.copy() grad_B[grad_B > 0] = 0.0 grad_B *= -1.0 grad_G = grad.copy() * 0.0 grad_np = np.concatenate((grad_R, grad_G, grad_B), axis=2) print('Writing', name + ".exr") Bitmap(grad_np).write(name + ".exr") # Compute RGB channels for .png image (no grad = white) grad_clamped = grad.copy() grad_clamped *= 3.0 # Arbitrary, for visualization grad_clamped[grad_clamped > 1] = 1 grad_clamped[grad_clamped < -1] = -1 grad_R = grad_clamped.copy() grad_G = grad_clamped.copy() grad_B = grad_clamped.copy() pos = grad_clamped >= 0 neg = grad_clamped < 0 grad_R[neg] = (1.0 + grad_clamped)[neg] grad_R[pos] = 1.0 grad_G[neg] = (1.0 + grad_clamped)[neg] grad_G[pos] = (1.0 - grad_clamped)[pos] grad_B[neg] = 1.0 grad_B[pos] = (1.0 - grad_clamped)[pos] grad_np = np.concatenate((grad_R, grad_G, grad_B), axis=2) print('Writing', name + ".png") Bitmap(((np.clip(grad_np, a_min=0.0, a_max=1.0)) * 255).astype( np.uint8)).write(name + ".png")
def test_read_write_jpeg(tmpdir): np.random.seed(12345) tmp_file = os.path.join(str(tmpdir), "out.jpg") b = Bitmap(Bitmap.PixelFormat.Y, Struct.Type.UInt8, [10, 10]) ref = np.uint8(np.random.random((10, 10)) * 255) np.array(b, copy=False)[:] = ref[..., np.newaxis] b.write(tmp_file, quality=50) b2 = Bitmap(tmp_file) assert np.sum(np.abs(np.float32(np.array(b2)[:, :, 0]) - ref)) / (10 * 10 * 255) < 0.07 b = Bitmap(Bitmap.PixelFormat.RGB, Struct.Type.UInt8, [10, 10]) ref = np.uint8(np.random.random((10, 10, 3)) * 255) np.array(b, copy=False)[:] = ref b.write(tmp_file, quality=100) b2 = Bitmap(tmp_file) assert np.sum( np.abs(np.float32(np.array(b2)) - ref)) / (3 * 10 * 10 * 255) < 0.2 os.remove(tmp_file)
def test_convert_rgb_y_gamma(tmpdir): def to_srgb(value): if value <= 0.0031308: return 12.92 * value return 1.055 * (value**(1.0 / 2.4)) - 0.055 # Tests RGBA(float64) -> Y (uint8_t, linear) conversion b1 = Bitmap(Bitmap.PixelFormat.RGBA, Struct.Type.Float64, [3, 1]) b2 = np.array(b1, copy=False) b2[:] = [[[1, 0, 0, 1], [0, 1, 0, 0.5], [0, 0, 1, 0]]] b3 = np.array(b1.convert(Bitmap.PixelFormat.Y, Struct.Type.UInt8, False)).ravel() assert np.allclose(b3, [0.212671 * 255, 0.715160 * 255, 0.072169 * 255], atol=1) # Tests RGBA(float64) -> Y (uint8_t, gamma) conversion b1 = Bitmap(Bitmap.PixelFormat.RGBA, Struct.Type.Float64, [3, 1]) b2 = np.array(b1, copy=False) b2[:] = [[[1, 0, 0, 1], [0, 1, 0, 0.5], [0, 0, 1, 0]]] b3 = np.array(b1.convert(Bitmap.PixelFormat.Y, Struct.Type.UInt8, True)).ravel() assert np.allclose(b3, [ to_srgb(0.212671) * 255, to_srgb(0.715160) * 255, to_srgb(0.072169) * 255 ], atol=1)
def get_bitmap_buffer(self, passes=1): bitmap_clone = self.bitmap.clone() bitmap_clone.flipVertically() if passes == 1: return bitmap_clone.buffer() if self.buffer is None: self.buffer = Bitmap(Bitmap.ERGBA, Bitmap.EFloat32, Vector2i(self.size[0], self.size[1] * passes)) self.buffer.clear() self.buffer.copyFrom(bitmap_clone) return self.buffer.buffer()
def test_premultiply_alpha(tmpdir): # Tests RGBA(float64) -> Y (float32) conversion b1 = Bitmap(Bitmap.PixelFormat.RGBA, Struct.Type.Float64, [3, 1]) assert b1.premultiplied_alpha() b1.set_premultiplied_alpha(False) assert not b1.premultiplied_alpha() b2 = np.array(b1, copy=False) b2[:] = [[[1, 0, 0, 1], [0, 1, 0, 0.5], [0, 0, 1, 0]]] # Premultiply b3 = np.array( b1.convert(Bitmap.PixelFormat.RGBA, Struct.Type.Float32, False, Bitmap.AlphaTransform.Premultiply)).ravel() assert np.allclose( b3, [1.0, 0.0, 0.0, 1.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0]) # Unpremultiply b1.set_premultiplied_alpha(True) b3 = np.array( b1.convert(Bitmap.PixelFormat.RGBA, Struct.Type.Float32, False, Bitmap.AlphaTransform.Unpremultiply)).ravel() assert np.allclose( b3, [1.0, 0.0, 0.0, 1.0, 0.0, 2, 0.0, 0.5, 0.0, 0.0, 0.0, 0.0])
def run_rendering(xml, save_name): scene = load_file(xml) sensor = scene.sensors()[0] scene.integrator().render(scene, sensor) film = sensor.film() result = film.bitmap(raw=False) result = np.array(result, copy=False).astype(np.float) image = np.stack([result[:, :, 2], result[:, :, 1], result[:, :, 0]], axis=-1) image = np.array( Bitmap(image, Bitmap.PixelFormat.RGB).convert(Bitmap.PixelFormat.RGB, Struct.Type.UInt8, srgb_gamma=True)) cv2.imwrite(dataset_output_dir + save_name, image) cv2.waitKey()
def test_read_convert_yc(tmpdir): # Tests reading & upsampling a luminance/chroma image b = Bitmap(find_resource('resources/data/tests/bitmap/XYZ_YC.exr')) # Tests float16 XYZ -> float32 RGBA conversion b = b.convert(Bitmap.PixelFormat.RGBA, Struct.Type.Float32, False) ref = [0.36595437, 0.27774358, 0.11499051, 1.] # Tests automatic Bitmap->NumPy conversion assert np.allclose(np.mean(b, axis=(0, 1)), ref, atol=1e-3) tmp_file = os.path.join(str(tmpdir), "out.exr") # Tests bitmap resampling filters rfilter = mitsuba.core.xml.load_string( "<rfilter version='2.0.0' type='box'/>") b = b.resample( [1, 1], rfilter, (FilterBoundaryCondition.Zero, FilterBoundaryCondition.Zero)) # Tests OpenEXR bitmap writing b.write(tmp_file) b = Bitmap(tmp_file) os.remove(tmp_file) assert np.allclose(np.mean(b, axis=(0, 1)), ref, atol=1e-3)
def render_gradient(scene, spp, pass_count, scale, path, params, eps): sensor = scene.sensors()[0] fsize = sensor.film().size() for i in range(pass_count): print("grad:", i, end='\r') set_requires_gradient(params['SDF.data']) y_i = render(scene) set_gradient(params['SDF.data'], np.sign(eps), backward=False) Float32.forward() #i == pass_count - 1 nb_channels = len(y_i) // (fsize[1] * fsize[0]) grad_i = gradient(y_i).numpy().reshape(fsize[1], fsize[0], nb_channels) grad_i = grad_i[:, :, 0] grad_i[grad_i != grad_i] = 0 if i == 0: y = y_i.numpy() y[y != y] = 0 grad = grad_i else: temp = detach(y_i).numpy() temp[temp != temp] = 0 y += temp del y_i grad += grad_i grad /= pass_count y /= pass_count if (scale == 0.0): scale = np.abs(grad).max() grad = grad.reshape(fsize[1], fsize[0], 1) write_gradient_image(grad / scale, path + 'gradient', fsize) y_np = y.reshape(fsize[1], fsize[0], nb_channels) print('Writing ' + path + 'radiance.exr') Bitmap(y_np).write(path + 'radiance.exr') return grad
def test_read_write_complex_exr(tmpdir): # Tests reading and writing of complex multi-channel images with custom properties b1 = Bitmap(Bitmap.PixelFormat.MultiChannel, Struct.Type.Float32, [4, 5], 6) a = b1.struct_() for i in range(6): a[i].name = "my_ch_%i" % i b2 = np.array(b1, copy=False) meta = b1.metadata() meta["str_prop"] = "value" meta["int_prop"] = 15 meta["dbl_prop"] = 30.0 meta["vec3_prop"] = [1.0, 2.0, 3.0] # meta["mat_prop"] = np.arange(16, dtype=float_dtype).reshape((4, 4)) + np.eye(4, dtype=float_dtype) # TODO py::implicitly_convertible<py::array, Transform4f>() doesn't seem to work in transform_v.cpp assert b2.shape == (5, 4, 6) assert b2.dtype == np.float32 b2[:] = np.arange(4 * 5 * 6).reshape((5, 4, 6)) tmp_file = os.path.join(str(tmpdir), "out.exr") b1.write(tmp_file) b3 = Bitmap(tmp_file) os.remove(tmp_file) meta = b3.metadata() meta.remove_property("generatedBy") meta.remove_property("pixelAspectRatio") meta.remove_property("screenWindowWidth") assert b3 == b1 b2[0, 0, 0] = 3 assert b3 != b1 b2[0, 0, 0] = 0 assert b3 == b1 assert str(b3) == str(b1) meta["str_prop"] = "value2" assert b3 != b1 assert str(b3) != str(b1)
def test_render(variants_all, scene_fname): from mitsuba.core import Bitmap, Struct, Thread scene_dir = dirname(scene_fname) if os.path.split(scene_dir)[1] in EXCLUDE_FOLDERS: pytest.skip(f"Skip rendering scene {scene_fname}") Thread.thread().file_resolver().append(scene_dir) ref_fname = get_ref_fname(scene_fname) assert os.path.exists(ref_fname) scene = mitsuba.core.xml.load_file(scene_fname, parameters=[('spp', str(32))]) scene.integrator().render(scene, scene.sensors()[0]) film = scene.sensors()[0].film() cur_bitmap = film.bitmap(raw=True).convert(Bitmap.PixelFormat.RGB, Struct.Type.Float32, False) cur_image = np.array(cur_bitmap, copy=False) ref_bitmap = Bitmap(ref_fname).convert(Bitmap.PixelFormat.RGB, Struct.Type.Float32, False) ref_image = np.array(ref_bitmap, copy=False) error = np.mean(np.mean(np.abs(ref_image - cur_image))) threshold = 0.5 * np.mean(np.mean(ref_image)) success = error < threshold if not success: print("Failed. error: {} // threshold: {}".format(error, threshold)) # Write rendered image to a file cur_fname = os.path.splitext( scene_fname)[0] + '_render_' + mitsuba.variant() + '.exr' cur_bitmap.write(cur_fname) print('Saved rendered image to: ' + cur_fname) assert False
def write_gradient_image(grad, name): """Convert signed floats to blue/red gradient exr image""" from mitsuba.core import Bitmap convert_to_rgb = True if convert_to_rgb: # Compute RGB channels for .exr image (no grad = black) grad_R = grad.copy() grad_R[grad_R < 0] = 0.0 grad_B = grad.copy() grad_B[grad_B > 0] = 0.0 grad_B *= -1.0 grad_G = grad.copy() * 0.0 grad_np = np.concatenate((grad_R, grad_G, grad_B), axis=2) else: grad_np = np.concatenate((grad, grad, grad), axis=2) print('Writing', name + ".exr") Bitmap(grad_np).write(name + ".exr")
def _get_film_ensure_initialized(self, job): """ Ensure that all internal data structure are set up to deal with the given rendering job """ film = job.getScene().getFilm() size = film.getSize() if self.size != size: self.size = size # Round the buffer size to the next power of 4 to ensure 32-bit # aligned scanlines in the underlying buffer. This is needed so # that QtGui.QImage and mitsuba.Bitmap have exactly the same # in-memory representation. bufsize = Vector2i((size.x + 3) // 4 * 4, (size.y + 3) // 4 * 4) # Create an 8-bit Mitsuba bitmap that will store tonemapped pixels self.bitmap = Bitmap(Bitmap.ERGB, Bitmap.EUInt8, bufsize) self.bitmap.clear() # Create a QImage that is backed by the Mitsuba Bitmap instance # (i.e. without doing unnecessary bitmap copy operations) self.qimage = QImage(self.bitmap.getNativeBuffer(), self.size.x, self.size.y, QImage.Format_RGB888) self.callback(MitsubaRenderBuffer.GEOMETRY_CHANGED) return film
def imaging(blocks, film_size, aovs=False, invalid_sample=False): """Imaging result with aovs""" label = ['result'] if aovs: label.append('scatter') label.append('non_scatter') if invalid_sample: label.append('invalid') for i in label: xyzaw_np = np.array(blocks[i].data()).reshape( [film_size[1], film_size[0], 5]) bmp = Bitmap(xyzaw_np, Bitmap.PixelFormat.XYZAW) bmp = bmp.convert(Bitmap.PixelFormat.RGB, Struct.Type.Float32, srgb_gamma=False) bmp.write(i + '.exr') bmp.convert(Bitmap.PixelFormat.RGB, Struct.Type.UInt8, srgb_gamma=True).write(i + '.jpg')
def run(prefix): img= cv2.imread(dataset_output_dir + prefix + 'mask_2x.png') img_i = cv2.bitwise_not(img) cv2.imwrite(output_dir + 'graycode_01.png', img_i) copyfile(dataset_output_dir + prefix + 'rho_2x.png', output_dir + 'graycode_02.png') tree = et.parse('img_gen.xml') root = tree.getroot() for i in range(1, 21): r = root.find('shape/emitter/texture/string') r.set('value', graycode_dir + 'graycode_'+ str(i) +'.png') r = root.findall('sensor/film/integer') [rr.set('value', '1024') for rr in r] tree.write('img_gen.xml') scene = load_file("img_gen.xml") sensor = scene.sensors()[0] scene.integrator().render(scene, sensor) film = sensor.film() result = film.bitmap(raw=False) result = np.array(result, copy=False).astype(np.float) image = np.stack([result[:, :, 2], result[:, :, 1], result[:, :, 0]], axis=-1) image = np.array(Bitmap(image, Bitmap.PixelFormat.RGB).convert(Bitmap.PixelFormat.RGB, Struct.Type.UInt8, srgb_gamma=True)) #cv2.imshow("image", image) cv2.imwrite(output_dir + 'graycode_'+ str(f'{i+2:02d}') +'.png',image) cv2.waitKey() f_run() copyfile('flow_gen/flow/flow.flo', dataset_output_dir + prefix + 'flow_2x.flo') copyfile('flow_gen/flow/flow.png', dataset_output_dir + prefix + 'flow_2x.png')
sample3=0) # Intersect rays with the scene geometry surface_interaction = scene.ray_intersect(rays) # Given intersection, compute the final pixel values as the depth t # of the sampled surface interaction result = surface_interaction.t # Set to zero if no intersection was found result[~surface_interaction.is_valid()] = 0 block = ImageBlock(film.crop_size(), channel_count=5, filter=film.reconstruction_filter(), border=False) block.clear() # ImageBlock expects RGB values (Array of size (n, 3)) block.put(position_sample, rays.wavelengths, Vector3f(result, result, result), 1) # Write out the result from the ImageBlock # Internally, ImageBlock stores values in XYZAW format # (color XYZ, alpha value A and weight W) xyzaw_np = block.data().reshape([film_size[1], film_size[0], 5]) # We then create a Bitmap from these values and save it out as EXR file bmp = Bitmap(xyzaw_np, Bitmap.PixelFormat.XYZAW) bmp = bmp.convert(Bitmap.PixelFormat.Y, Struct.Type.Float32, srgb_gamma=False) bmp.write('depth.exr')
class MitsubaRenderBuffer(RenderListener): """ Implements the Mitsuba callback interface to capture notifications about rendering progress. Partially completed image blocks are efficiently tonemapped into a local 8-bit Mitsuba Bitmap instance and exposed as a QImage. """ RENDERING_FINISHED = 0 RENDERING_CANCELLED = 1 RENDERING_UPDATED = 2 GEOMETRY_CHANGED = 3 def __init__(self, queue, callback): super(MitsubaRenderBuffer, self).__init__() self.bitmap = self.qimage = None self.callback = callback self.time = 0 self.size = Vector2i(0, 0) queue.registerListener(self) def workBeginEvent(self, job, wu, thr): """ Callback: a worker thread started rendering an image block. Draw a rectangle to highlight this """ _ = self._get_film_ensure_initialized(job) self.bitmap.drawWorkUnit(wu.getOffset(), wu.getSize(), thr) self._potentially_send_update() def workEndEvent(self, job, wr, cancelled): """ Callback: a worker thread finished rendering an image block. Tonemap the associated pixels and store them in 'self.bitmap' """ film = self._get_film_ensure_initialized(job) film.develop(wr.getOffset(), wr.getSize(), wr.getOffset(), self.bitmap) self._potentially_send_update() def refreshEvent(self, job): """ Callback: the entire image changed (some rendering techniques do this occasionally). Hence, tonemap the full film. """ film = self._get_film_ensure_initialized(job) film.develop(Point2i(0), self.size, Point2i(0), self.bitmap) self._potentially_send_update() def finishJobEvent(self, job, cancelled): """ Callback: the rendering job has finished or was cancelled. Re-develop the image once more for the final result. """ film = self._get_film_ensure_initialized(job) film.develop(Point2i(0), self.size, Point2i(0), self.bitmap) self.callback(MitsubaRenderBuffer.RENDERING_CANCELLED if cancelled else MitsubaRenderBuffer.RENDERING_FINISHED) def _get_film_ensure_initialized(self, job): """ Ensure that all internal data structure are set up to deal with the given rendering job """ film = job.getScene().getFilm() size = film.getSize() if self.size != size: self.size = size # Round the buffer size to the next power of 4 to ensure 32-bit # aligned scanlines in the underlying buffer. This is needed so # that QtGui.QImage and mitsuba.Bitmap have exactly the same # in-memory representation. bufsize = Vector2i((size.x + 3) // 4 * 4, (size.y + 3) // 4 * 4) # Create an 8-bit Mitsuba bitmap that will store tonemapped pixels self.bitmap = Bitmap(Bitmap.ERGB, Bitmap.EUInt8, bufsize) self.bitmap.clear() # Create a QImage that is backed by the Mitsuba Bitmap instance # (i.e. without doing unnecessary bitmap copy operations) self.qimage = QImage(self.bitmap.getNativeBuffer(), self.size.x, self.size.y, QImage.Format_RGB888) self.callback(MitsubaRenderBuffer.GEOMETRY_CHANGED) return film def _potentially_send_update(self): """ Send an update request to any attached widgets, but not too often """ now = time.time() if now - self.time > .25: self.time = now self.callback(MitsubaRenderBuffer.RENDERING_UPDATED)
def test_accumulate(): # ----- Accumulate the whole bitmap b1 = Bitmap(Bitmap.PixelFormat.RGB, Struct.Type.UInt8, [10, 10]) n = b1.height() * b1.width() # 0, 1, 2, ..., 99 np.array(b1, copy=False)[:] = np.arange(n).reshape(b1.height(), b1.width(), 1) b2 = Bitmap(Bitmap.PixelFormat.RGB, Struct.Type.UInt8, [10, 10]) # 100, 99, ..., 1 np.array(b2, copy=False)[:] = np.arange(n, 0, -1).reshape(b2.height(), b2.width(), 1) b1.accumulate(b2) assert np.all(np.array(b1, copy=False) == n) # ----- Accumulate only a sub-frame np.array(b1, copy=False)[:] = np.arange(n).reshape(b1.height(), b1.width(), 1) ref = np.array(b1) ref[1:6, 3:4, :] += np.array(b2, copy=False)[3:8, 5:6, :] # Recall that positions are specified as (x, y) in Mitsuba convention, # but (row, column) in arrays. b1.accumulate(b2, [5, 3], [3, 1], [1, 5]) assert np.all(np.array(b1, copy=False) == ref)
def test_read_tga(): b1 = Bitmap( find_resource('resources/data/tests/bitmap/tga_uncompressed.tga')) b2 = Bitmap( find_resource('resources/data/tests/bitmap/tga_compressed.tga')) assert b1 == b2
def test_read_bmp(): b = Bitmap(find_resource('resources/data/common/textures/flower.bmp')) ref = [136.50910448, 134.07641791, 85.67253731] assert np.allclose(np.mean(b, axis=(0, 1)), ref)
class InternalBufferDisplay(RenderListener): ''' Class to monitor rendering and update blender render result ''' def __init__(self, render_ctx): super(InternalBufferDisplay, self).__init__() self.ctx = render_ctx self.film = self.ctx.scene.getFilm() self.size = self.film.getSize() self.bitmap = Bitmap(Bitmap.ERGBA, Bitmap.EFloat32, self.size) self.bitmap.clear() self.buffer = None self.fast_buffer = True self.do_cancel = False self.time = 0 self.delay = .5 self.ctx.queue.registerListener(self) def get_offset_size(self, wu): offset = wu.getOffset() size = wu.getSize() end = offset + size offset.x = max(0, offset.x) offset.y = max(0, offset.y) end.x = min(self.size.x, end.x) end.y = min(self.size.y, end.y) size = end - offset return offset, size def workBeginEvent(self, job, wu, thr): offset, size = self.get_offset_size(wu) self.bitmap.drawWorkUnit(offset, size, thr) self.timed_update_result() def workEndEvent(self, job, wr, cancelled): offset, size = self.get_offset_size(wr) self.film.develop(offset, size, offset, self.bitmap) self.timed_update_result() def refreshEvent(self, job): self.film.develop(Point2i(0), self.size, Point2i(0), self.bitmap) self.update_result() def finishJobEvent(self, job, cancelled): MtsLog('Render Job Finished') self.film.develop(Point2i(0), self.size, Point2i(0), self.bitmap) self.update_result(render_end=True) def get_bitmap_buffer(self, passes=1): bitmap_clone = self.bitmap.clone() bitmap_clone.flipVertically() if passes == 1: return bitmap_clone.buffer() if self.buffer is None: self.buffer = Bitmap(Bitmap.ERGBA, Bitmap.EFloat32, Vector2i(self.size[0], self.size[1] * passes)) self.buffer.clear() self.buffer.copyFrom(bitmap_clone) return self.buffer.buffer() def get_bitmap_list(self): self.delay = 1.5 bitmap_list = numpy.ndarray((self.size[0] * self.size[1], 4), buffer=self.get_bitmap_buffer(), dtype='float32') # .tolist() return bitmap_list def timed_update_result(self): now = time.time() if now - self.time > self.delay: self.time = now self.update_result() def update_result(self, render_end=False): if self.ctx.test_break(): return try: render_result = self.ctx.render_engine.begin_result(0, 0, self.size[0], self.size[1]) if render_result is None: err_msg = 'ERROR: Cannot not load render result: begin_result() returned None.' self.do_cancel = True raise Exception(err_msg) if self.fast_buffer: passes = len(render_result.layers[0].passes) bitmap_buffer = self.get_bitmap_buffer(passes) render_result.layers[0].passes.foreach_set('rect', bitmap_buffer) else: bitmap_buffer = self.get_bitmap_list() render_result.layers[0].passes[0].rect = bitmap_buffer self.ctx.render_engine.end_result(render_result, 0) except Exception as err: MtsLog('%s' % err) if self.fast_buffer: self.fast_buffer = False else: self.do_cancel = True if self.do_cancel: self.ctx.render_cancel()