viser icon indicating copy to clipboard operation
viser copied to clipboard

The generated image does not match the screen resolution

Open smart4654154 opened this issue 1 year ago • 10 comments

I can provide images of various resolutions to the browser, but my monitor resolution is fixed (1920 * 1080), I have observed that even if the resolution of my photos is high or low, they can always fill the browser When the returned image resolution is small, such as 100 * 100, I know that Viser stretched the photo to fill the browser. Q1:Based on the code that you provided(https://github.com/nerfstudio-project/viser/issues/247), I guess this is stretch code. Can you tell me specifically what 'file' refers to in the getFilmWidth function.may be browser resolution?

// Resize the mesh based on focal length.
const f = camera.getFocalLength();
backgroundMesh.current!.scale.set(
  camera.getFilmWidth() / f,
  camera.getFilmHeight() / f,
  1.0,
);

Q2: When the returned image resolution is high, such as 2000 * 2000 or 3000 * 3000, the results I see in the browser are very clear. Does Viser downsample high-resolution photos to the browser resolution?Because the resolution of the monitor is limited. For example, converting 2000 * 2000 photos to browser resolution and allowing users to view them. 3000 * 3000 photos are also converted to browser resolution for users to view. Can you tell me the specific code? Or is it this code that completes the downsampling task? // Resize the mesh based on focal length. const f = camera.getFocalLength(); backgroundMesh.current!.scale.set( camera.getFilmWidth() / f, camera.getFilmHeight() / f, 1.0, );

Q3: I guess both photos (3000 * 3000) and (2000 * 2000) will be downsampled to the same resolution. My problem is that users can render high-resolution photos, such as 2000 * 2000, 3000 * 3000, and Viser will automatically downsample to the same resolution. Therefore, rendering high-resolution photos is meaningless because the final displayed photo resolution is the same.am I right Thank you very much.

smart4654154 avatar Sep 13 '24 09:09 smart4654154

Hello!

Q1: For getting more information about getFilmWidth / getFilmHeight, your best bet is probably Google. Or, here's the threejs docs page: https://threejs.org/docs/#api/en/cameras/PerspectiveCamera.getFilmHeight

Q2/Q3: There's no explicit image downsampling. But otherwise we just display your image as a texture to fill the browser window, which will either be up- or down-sampled automatically by the WebGL renderer.

rendering high-resolution photos is meaningless because the final displayed photo resolution is the same

Yes, rendering photos that are higher in resolution than the screen/browser has no value!

brentyi avatar Sep 13 '24 16:09 brentyi

Hello!

Q1: For getting more information about getFilmWidth / getFilmHeight, your best bet is probably Google. Or, here's the threejs docs page: https://threejs.org/docs/#api/en/cameras/PerspectiveCamera.getFilmHeight

Q2/Q3: There's no explicit image downsampling. But otherwise we just display your image as a texture to fill the browser window, which will either be up- or down-sampled automatically by the WebGL renderer.

rendering high-resolution photos is meaningless because the final displayed photo resolution is the same

Yes, rendering photos that are higher in resolution than the screen/browser has no value!

Thank you very much. Is there any function that can obtain the resolution of the current browser?

smart4654154 avatar Sep 19 '24 08:09 smart4654154

Is there any function that can obtain the resolution of the current browser?

Unfortunately this isn't exposed right now, you would have to modify the source code. If you have time for a PR I'd also appreciate it!

brentyi avatar Sep 29 '24 02:09 brentyi

Is there any function that can obtain the resolution of the current browser?

Unfortunately this isn't exposed right now, you would have to modify the source code. If you have time for a PR I'd also appreciate it!

image I saw a number using F12, and I guess this number is the resolution of the displayed image. (Because my monitor resolution is 1920 * 1080) Q1Is my guess correct? Q2If correct, can this information be obtained using Python? Because rendering photos that are higher in resolution than the screen/browser has no value! This resolution is the optimal resolution
thankyou

smart4654154 avatar Oct 26 '24 05:10 smart4654154

Q2/Q3: There's no explicit image downsampling. But otherwise we just display your image as a texture to fill the browser window, which will either be up- or down-sampled automatically by the WebGL renderer.

thank you Q2/Q3: There's no explicit image downsampling. But otherwise we just display your image as a texture to fill the browser window, which will either be up- or down-sampled automatically by the WebGL renderer. now,I just want the webpage to render images at the original resolution, for example, with a very low resolution that only occupies the top left corner of the browser. I don't know how to develop webpages, can you help me? Thank you

smart4654154 avatar Apr 02 '25 01:04 smart4654154

@smart4654154 get canvas size img_wh as https://github.com/nerfstudio-project/viser/blob/dc1f02f436f85fcaaaa245f7f0509524e38d3891/examples/04_camera_poses.py#L41

Then, put you render_img to the background_img

  def _viewer_render_fn(self, camera_state, img_wh):
    background_img = np.zeros((img_wh[1], img_wh[0], 3), dtype=np.uint8)
    if render_img is not None:
      y_start = (render_img[1] - rst.shape[0]) // 2
      x_start = (render_img[0] - rst.shape[1]) // 2
      if y_start >= 0 and x_start >= 0:
        background_img[y_start : y_start + render_img.shape[0], x_start : x_start + render_img.shape[1], :] = render_img
    return background_img

zerolover avatar Apr 02 '25 05:04 zerolover

@smart4654154 get canvas size img_wh as

viser/examples/04_camera_poses.py

Line 41 in dc1f02f

f"\tcanvas size: {client.camera.image_width}x{client.camera.image_height}" Then, put you render_img to the background_img

def _viewer_render_fn(self, camera_state, img_wh): background_img = np.zeros((img_wh[1], img_wh[0], 3), dtype=np.uint8) if render_img is not None: y_start = (render_img[1] - rst.shape[0]) // 2 x_start = (render_img[0] - rst.shape[1]) // 2 if y_start >= 0 and x_start >= 0: background_img[y_start : y_start + render_img.shape[0], x_start : x_start + render_img.shape[1], :] = render_img return background_img def _viewer_render_fn(self, camera_state, img_wh): background_img = np.zeros((img_wh[1], img_wh[0], 3), dtype=np.uint8) if render_img is not None: y_start = (render_img[1] - rst.shape[0]) // 2 x_start = (render_img[0] - rst.shape[1]) // 2 if y_start >= 0 and x_start >= 0: background_img[y_start : y_start + render_img.shape[0], x_start : x_start + render_img.shape[1], :] = render_img return background_img

Thank you very much, but I didn't understand what you meant Can you give me an example of the entire code?

smart4654154 avatar Apr 02 '25 07:04 smart4654154

@smart4654154 I use nerfview https://github.com/hangg7/nerfview

img_wh set to actual size by {client.camera.image_width}x{client.camera.image_height} and

def render_fn(
    camera_state: nerfview.CameraState, img_wh: Tuple[int, int]
) -> np.ndarray:
    # Parse camera state for camera-to-world matrix (c2w) and intrinsic (K) as
    # float64 numpy arrays.
    c2w = camera_state.c2w
    K = camera_state.get_K(img_wh)
    render_img = your_rendering_logic(c2w, K)

    background_img = np.zeros((img_wh[1], img_wh[0], 3), dtype=np.uint8)
    if render_img is not None:
      y_start = (render_img[1] - rst.shape[0]) // 2
      x_start = (render_img[0] - rst.shape[1]) // 2
      if y_start >= 0 and x_start >= 0:
        background_img[y_start : y_start + render_img.shape[0], x_start : x_start + render_img.shape[1], :] = render_img
    return background_img

zerolover avatar Apr 02 '25 08:04 zerolover

@smart4654154 I use nerfview https://github.com/hangg7/nerfview

img_wh set to actual size by {client.camera.image_width}x{client.camera.image_height} and

def render_fn( camera_state: nerfview.CameraState, img_wh: Tuple[int, int] ) -> np.ndarray: # Parse camera state for camera-to-world matrix (c2w) and intrinsic (K) as # float64 numpy arrays. c2w = camera_state.c2w K = camera_state.get_K(img_wh) render_img = your_rendering_logic(c2w, K)

background_img = np.zeros((img_wh[1], img_wh[0], 3), dtype=np.uint8)
if render_img is not None:
  y_start = (render_img[1] - rst.shape[0]) // 2
  x_start = (render_img[0] - rst.shape[1]) // 2
  if y_start >= 0 and x_start >= 0:
    background_img[y_start : y_start + render_img.shape[0], x_start : x_start + render_img.shape[1], :] = render_img
return background_img

Thank you very much. I am also using NERFView ( 03_gsplat_rendering.py), which gives the rendered image to Viser, and then the image is enlarged or reduced in the webpage, so I have this problem. Q1:This code is great, did you add it? Y_start=(render_img [1] - rst. shape [0])//2, what is rst? in my understanding width_start = (client.camera.image_width-render_img_width) // 2 Q2:What is the version of Viser you are using? The parameter 'client. camera. image. width' is a new parameter. Do i need to modify the code for nerfview? thank you

smart4654154 avatar Apr 02 '25 08:04 smart4654154

@smart4654154 sorry, this is the final code. I put rst to the middle of img. using the latest main branch

  def _viewer_render_fn(self, camera_state, img_wh):
    img = np.zeros((img_wh[1], img_wh[0], 3), dtype=np.uint8)
    output = self.do_render(camera_state)
    rst = output["rgb"]
    rst = (rst * 255).permute(1, 2, 0).cpu().numpy().astype(np.uint8)

    if rst is not None:
      y_start = (img_wh[1] - rst.shape[0]) // 2
      x_start = (img_wh[0] - rst.shape[1]) // 2
      if y_start >= 0 and x_start >= 0:
        img[y_start : y_start + rst.shape[0], x_start : x_start + rst.shape[1], :] = rst
    return img

zerolover avatar Apr 02 '25 09:04 zerolover