Files
2024-11-12 14:50:29 +08:00

236 lines
8.0 KiB
Python

import glfw
from OpenGL.GL import *
from OpenGL.GL.shaders import compileProgram, compileShader
import numpy as np
import time
import pickle
import cv2
import os
current_dir = os.path.dirname(os.path.abspath(__file__))
vertex_src = """
# version 330
layout(location = 0) in vec2 a_position;
layout(location = 1) in vec3 a_texture;
out vec3 v_TexCoord;
void main()
{
gl_Position = vec4(a_position, 0.0, 1.0);
v_TexCoord = a_texture;
//v_texture = 1 - a_texture; // Flips the texture vertically and horizontally
//v_texture = vec2(a_texture.s, 1 - a_texture.t); // Flips the texture vertically
}
"""
fragment_src = """
# version 330
in vec3 v_TexCoord;
out vec4 fragColor;
uniform sampler2D texture0;
uniform sampler2D texture1;
void main()
{
if (v_TexCoord.z < 0.5)
{
fragColor = texture(texture0, v_TexCoord.xy);
}
else if (v_TexCoord.z < 1.5)
{
fragColor = vec4(0.0, 0.0, 1.0, 1.0);
}
else if (v_TexCoord.z < 2.5)
{
fragColor = vec4(0.0, 1.0, 0.0, 1.0);
}
else
{
fragColor = vec4(0.0, 0.0, 1.0, 1.0);
}
}
"""
# glfw callback functions
def window_resize(window, width, height):
glViewport(0, 0, width, height)
# initializing glfw library
if not glfw.init():
raise Exception("glfw can not be initialized!")
# creating the window
window_size = 384
glfw.window_hint(glfw.VISIBLE, glfw.FALSE)
window = glfw.create_window(window_size, window_size, "My OpenGL window", None, None)
# check if window was created
if not window:
glfw.terminate()
raise Exception("glfw window can not be created!")
# set window's position
glfw.set_window_pos(window, 100, 100)
# set the callback function for window resize
glfw.set_window_size_callback(window, window_resize)
# make the context current
glfw.make_context_current(window)
from obj_utils.utils import generateRenderInfo
render_verts_, render_face_ = generateRenderInfo()
vt_ = render_verts_[:, 3:5].flatten().tolist()
vertices = np.zeros([len(render_verts_), 5], dtype=np.float32).flatten()
indices = np.array(render_face_, dtype=np.uint32)
shader = compileProgram(compileShader(vertex_src, GL_VERTEX_SHADER), compileShader(fragment_src, GL_FRAGMENT_SHADER))
# Step2: 创建并绑定VBO 对象 传送数据
VBO = glGenBuffers(1)
glBindBuffer(GL_ARRAY_BUFFER, VBO)
glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_STATIC_DRAW)
# Step3: 创建并绑定EBO 对象 传送数据
EBO = glGenBuffers(1)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.nbytes, indices, GL_STATIC_DRAW)
# Step4: 指定解析方式 并启用顶点属性
# 顶点位置属性
glEnableVertexAttribArray(0)
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, vertices.itemsize * 5, ctypes.c_void_p(0))
# 顶点纹理属性
glEnableVertexAttribArray(1)
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, vertices.itemsize * 5, ctypes.c_void_p(8))
glActiveTexture(GL_TEXTURE0)
texture = glGenTextures(1)
glBindTexture(GL_TEXTURE_2D, texture)
# Set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
# Set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
image2 = cv2.imread(os.path.join(current_dir, "face_mask.png"), cv2.IMREAD_UNCHANGED)
b, g, r, a = cv2.split(image2)
image2 = cv2.merge([r, g, b, a])
img_data2 = image2.tobytes()
image_height,image_width = image2.shape[:2]
# img_data = np.array(image.getdata(), np.uint8) # second way of getting the raw image data
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_width, image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_data2)
glUseProgram(shader)
# glUniform1i(glGetUniformLocation(shader, "texture0"), 0)
# glUniform1i(glGetUniformLocation(shader, "texture1"), 1)
glClearColor(0, 0.1, 0.1, 1)
glEnable(GL_DEPTH_TEST)
glEnable(GL_BLEND)
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
verts_loc = glGetUniformLocation(shader, "vertArray")
frame_index = 0
INDEX_LEFT_IRIS = [474, 475, 476, 477]
INDEX_RIGHT_IRIS = [469, 470, 471, 472, 469]
glfw.make_context_current(window)
glfw.swap_interval(0)
start_time = time.time()
glActiveTexture(GL_TEXTURE1)
texture1 = glGenTextures(1)
ref_vt = None
def set_ref_texture(vt, ref_image):
global ref_vt
ref_vt = vt
glBindTexture(GL_TEXTURE_2D, texture1)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
# image = cv2.imread(os.path.join(current_dir, "face_mask2.png"), cv2.IMREAD_UNCHANGED)
image = ref_image
img_data = image.tobytes()
image_height, image_width = image.shape[:2]
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image_width, image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, img_data)
def render2cv(pts_array_, w = 384, h = 384):
global verts_loc,VBO,window
if glfw.get_window_size(window)[0] != w:
glfw.set_window_size(window, w, h)
glfw.poll_events()
glEnable(GL_DEPTH_TEST)
glEnable(GL_CULL_FACE)
glClearColor(0, 0, 0, 0)
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
# glClearColor(0,0,0,0)
pts_array = pts_array_.copy()
if len(pts_array) == 478:
# 加入牙齿
pts_array = np.concatenate([pts_array, np.zeros([36, 3])], axis = 0)
else:
assert len(pts_array) == 478 + 36
pts_array = pts_array[:, :2]/ np.array([w, h]) * 2 - 1
glUniform1i(glGetUniformLocation(shader, "texture0"), 0)
# glUniform1i(glGetUniformLocation(shader, "texture1"), 1)
vertices = []
# print("vt_", len(vt_))
for i in range(468):
vertices.extend([pts_array[i, 0], -pts_array[i, 1], vt_[2 * i], 1 - vt_[2 * i + 1], 0])
for i in range(468, 478):
vertices.extend([pts_array[i, 0], -pts_array[i, 1], 0, 0, 1])
for i in range(478, 478 + 18):
vertices.extend([pts_array[i, 0], -pts_array[i, 1], 0, 0, 2])
for i in range(478 + 18, 478 + 18*2):
vertices.extend([pts_array[i, 0], -pts_array[i, 1], 0, 0, 3])
# for i in range(478, 478 + 18):
# vertices.extend([0, 0, 0, 0, 2])
# for i in range(478 + 18, 478 + 18*2):
# vertices.extend([0, 0, 0, 0, 3])
vertices = np.array(vertices, dtype=np.float32)
glUniform2fv(verts_loc, 478 + 36, vertices)
glBindBuffer(GL_ARRAY_BUFFER, VBO)
glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_DYNAMIC_DRAW)
# 绘制第一个矩形
glDrawElements(GL_TRIANGLES, len(indices), GL_UNSIGNED_INT, None)
if w == h*2:
glUniform1i(glGetUniformLocation(shader, "texture0"), 1)
vertices = []
# print("vt_", len(vt_))
for i in range(468):
vertices.extend([pts_array[i, 0] + 1.0, -pts_array[i, 1], ref_vt[i, 0], ref_vt[i, 1], 0])
for i in range(468, 478):
vertices.extend([pts_array[i, 0] + 1.0, -pts_array[i, 1], 0, 0, 1])
# for i in range(478, 478 + 18):
# vertices.extend([pts_array[i, 0] + 1.0, -pts_array[i, 1], 0, 0, 2])
# for i in range(478 + 18, 478 + 18 * 2):
# vertices.extend([pts_array[i, 0] + 1.0, -pts_array[i, 1], 0, 0, 3])
for i in range(478, 478 + 18):
vertices.extend([0, 0, 0, 0, 2])
for i in range(478 + 18, 478 + 18 * 2):
vertices.extend([0, 0, 0, 0, 3])
vertices = np.array(vertices, dtype=np.float32)
glUniform2fv(verts_loc, 478, vertices)
glBindBuffer(GL_ARRAY_BUFFER, VBO)
glBufferData(GL_ARRAY_BUFFER, vertices.nbytes, vertices, GL_DYNAMIC_DRAW)
# 绘制第一个矩形
glDrawElements(GL_TRIANGLES, len(indices), GL_UNSIGNED_INT, None)
glfw.swap_buffers(window)
glReadBuffer(GL_FRONT)
# 从缓冲区中的读出的数据是字节数组
data = glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, outputType=None)
rgba = data.reshape(h, w, -1)
rgba = np.flip(rgba, 0).astype(np.uint8)
return rgba