Ali Mohsin
feat: Add virtual try-on system components including DensePose, SMPL, and pix2pixHD models, rendering, and utilities.
5db43ff
| from typing import Tuple | |
| import ctypes | |
| import numpy as np | |
| import OpenGL.EGL as egl | |
| from OpenGL.raw.EGL.EXT.platform_device import EGL_PLATFORM_DEVICE_EXT | |
| from OpenGL.EGL.EXT.device_base import egl_get_devices | |
| from OpenGL import error | |
| from OpenGL.GL import * | |
| def create_initialized_headless_egl_display(): | |
| """Creates an initialized EGL display directly on a device. | |
| """ | |
| for device in egl_get_devices(): | |
| display = egl.eglGetPlatformDisplayEXT( | |
| EGL_PLATFORM_DEVICE_EXT, device, None) | |
| if display != egl.EGL_NO_DISPLAY and egl.eglGetError() == egl.EGL_SUCCESS: | |
| # `eglInitialize` may or may not raise an exception on failure depending | |
| # on how PyOpenGL is configured. We therefore catch a `GLError` and also | |
| # manually check the output of `eglGetError()` here. | |
| try: | |
| initialized = egl.eglInitialize(display, None, None) | |
| except error.GLError: | |
| pass | |
| else: | |
| if initialized == egl.EGL_TRUE and egl.eglGetError() == egl.EGL_SUCCESS: | |
| return display | |
| return egl.EGL_NO_DISPLAY | |
| def create_opengl_context(surface_size: Tuple[int, int]): | |
| """Create offscreen OpenGL context and make it current. | |
| Users are expected to directly use EGL API in case more advanced | |
| context management is required. | |
| Args: | |
| surface_size: (width, height), size of the offscreen rendering surface. | |
| """ | |
| egl_display = create_initialized_headless_egl_display() | |
| if egl_display == egl.EGL_NO_DISPLAY: | |
| raise RuntimeError('Cannot initialize a headless EGL display.') | |
| major, minor = egl.EGLint(), egl.EGLint() | |
| egl.eglInitialize(egl_display, ctypes.pointer( | |
| major), ctypes.pointer(minor)) | |
| config_attribs = [ | |
| egl.EGL_SURFACE_TYPE, egl.EGL_PBUFFER_BIT, egl.EGL_BLUE_SIZE, 8, | |
| egl.EGL_GREEN_SIZE, 8, egl.EGL_RED_SIZE, 8, egl.EGL_DEPTH_SIZE, 24, | |
| egl.EGL_RENDERABLE_TYPE, egl.EGL_OPENGL_BIT, egl.EGL_NONE | |
| ] | |
| config_attribs = (egl.EGLint * len(config_attribs))(*config_attribs) | |
| num_configs = egl.EGLint() | |
| egl_cfg = egl.EGLConfig() | |
| egl.eglChooseConfig(egl_display, config_attribs, ctypes.pointer(egl_cfg), 1, | |
| ctypes.pointer(num_configs)) | |
| width, height = surface_size | |
| pbuffer_attribs = [ | |
| egl.EGL_WIDTH, | |
| width, | |
| egl.EGL_HEIGHT, | |
| height, | |
| egl.EGL_NONE, | |
| ] | |
| pbuffer_attribs = (egl.EGLint * len(pbuffer_attribs))(*pbuffer_attribs) | |
| egl_surf = egl.eglCreatePbufferSurface( | |
| egl_display, egl_cfg, pbuffer_attribs) | |
| egl.eglBindAPI(egl.EGL_OPENGL_API) | |
| egl_context = egl.eglCreateContext( | |
| egl_display, egl_cfg, egl.EGL_NO_CONTEXT, None) | |
| egl.eglMakeCurrent(egl_display, egl_surf, egl_surf, egl_context) | |
| return egl_display, egl_surf, egl_context | |
| def init_frame_buffer(frame_image: np.ndarray, num_samples: int = 16): | |
| """Create an FBO and assign a texture buffer to it for the purpose of offscreen rendering to the texture buffer | |
| """ | |
| samples = min(num_samples, GL_SAMPLES - 1) | |
| width = frame_image.shape[1] | |
| height = frame_image.shape[0] | |
| if frame_image.shape[-1] == 3: | |
| texture_type = GL_RGB | |
| internal_texture_type = GL_RGB8 | |
| elif frame_image.shape[-1] == 4: | |
| texture_type = GL_RGBA | |
| internal_texture_type = GL_RGBA8 | |
| render_texture = glGenTextures(1) | |
| glBindTexture(GL_TEXTURE_2D, render_texture) | |
| glTexImage2D(GL_TEXTURE_2D, 0, internal_texture_type, width, | |
| height, 0, texture_type, GL_UNSIGNED_BYTE, None) | |
| glBindTexture(GL_TEXTURE_2D, 0) | |
| render_frame_object = glGenFramebuffers(1) | |
| glBindFramebuffer(GL_FRAMEBUFFER, render_frame_object) | |
| # Create color render buffer | |
| color_buffer = glGenRenderbuffers(1) | |
| glBindRenderbuffer(GL_RENDERBUFFER, color_buffer) | |
| glRenderbufferStorage( | |
| GL_RENDERBUFFER, internal_texture_type, width, height) | |
| glFramebufferRenderbuffer( | |
| GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color_buffer) | |
| glFramebufferTexture2D( | |
| GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, render_texture, 0) | |
| depth_buffer = glGenRenderbuffers(1) | |
| glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer) | |
| glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height) | |
| glBindRenderbuffer(GL_RENDERBUFFER,0) | |
| glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depth_buffer) | |
| glBindRenderbuffer(GL_RENDERBUFFER, 0) | |
| # Sees if your GPU can handle the FBO configuration defined above | |
| if glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE: | |
| raise RuntimeError( | |
| "Framebuffer binding failed, probably because your GPU does not support this FBO configuration.") | |
| glBindFramebuffer(GL_FRAMEBUFFER, 0) | |
| return render_frame_object | |