separate face and head

- Head position is now calculated from the midpoint of points 2 and 14
(sides of head)
- Face position is calculated from point 30 (nose tip)
This commit is contained in:
Epicalert 2021-01-01 16:23:44 +08:00
parent 25ebd7a387
commit 62779b6f78
No known key found for this signature in database
GPG key ID: CAA46F858D0979BD
3 changed files with 114 additions and 71 deletions

View file

@ -11,24 +11,37 @@
#include <graphics.hpp>
GLuint vbo; //vertex buffer
GLuint ebo; //element buffer
GLuint vao; //vertex array (holds shader relations etc to vertex buffer)
//VAOs for different parts
//TODO: make this more modular
GLuint head; //head object
GLuint face; //face object
GLuint shader; //standard shader program used for all elements
GLuint transUniform; //location of the "transMatrix" transformation matrix uniform in the shader
GLuint texHead; //head texture
GLuint texFace; //face texture
glm::mat4 matHead(1.0f); //transformation matrix for head object
glm::mat4 matFace(1.0f); //transformation matrix for face object
void display () {
glClear(GL_COLOR_BUFFER_BIT);
glBindVertexArray(head);
glBindTexture(GL_TEXTURE_2D, texHead);
glUniformMatrix4fv(transUniform, 1, GL_FALSE, glm::value_ptr(matHead));
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glBindVertexArray(face);
glBindTexture(GL_TEXTURE_2D, texFace);
glUniformMatrix4fv(transUniform, 1, GL_FALSE, glm::value_ptr(matFace));
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
glutSwapBuffers();
}
void initBuffers () {
glewInit();
void initBuffers (GLuint* vaoNum) {
//TODO: put quad stuff in header file or something
GLfloat quad[] = {
//vertex UV/texcoord
@ -43,6 +56,73 @@ void initBuffers () {
2, 3, 0
};
glGenVertexArrays(1, vaoNum);
glBindVertexArray(*vaoNum);
GLuint vbo; //vertex buffer
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
//change to GL_DYNAMIC_DRAW when using deformable meshes
glBufferData(GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW);
GLuint ebo; //element buffer
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quadElements), quadElements, GL_STATIC_DRAW);
//tell OpenGL what to put in the input vars
GLuint posAttr = glGetAttribLocation(shader, "position");
glVertexAttribPointer(posAttr, 2, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), 0);
glEnableVertexAttribArray(posAttr);
GLuint uvAttr = glGetAttribLocation(shader, "texcoord");
glVertexAttribPointer(uvAttr, 2, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (void*)(2*sizeof(GLfloat)));
glEnableVertexAttribArray(uvAttr);
}
void initGraphics () {
int argc = 1;
char *argv[1] = {(char*)"fc2d"};
glutInit(&argc, argv);
glutCreateWindow("FaceCam2D");
glutInitWindowSize(512, 512);
glutDisplayFunc(display);
glewInit();
initShader();
initBuffers(&head);
initBuffers(&face);
initTexture(&texHead, "head-base.png");
initTexture(&texFace, "head-face.png");
//enable blending for alpha textures
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
//set background color
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
}
void initTexture (GLuint* texNum, const char* path) {
glGenTextures(1, texNum);
glBindTexture(GL_TEXTURE_2D, *texNum);
int x, y, channels;
GLubyte* pixels = stbi_load(path, &x, &y, &channels, 4);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
}
void initShader() {
const char* vsSrc =
"#version 150\n"
"in vec2 position;"
@ -63,18 +143,6 @@ void initBuffers () {
"color = texture(tex, uv);"
"}";
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);
glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
//change to GL_DYNAMIC_DRAW when using deformable meshes
glBufferData(GL_ARRAY_BUFFER, sizeof(quad), quad, GL_STATIC_DRAW);
glGenBuffers(1, &ebo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(quadElements), quadElements, GL_STATIC_DRAW);
//compile vert shader
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(vs, 1, &vsSrc, NULL);
@ -91,7 +159,6 @@ void initBuffers () {
glGetShaderiv(fs, GL_COMPILE_STATUS, &status);
if (status != GL_TRUE) { std::cout << "fragment shader borked" << std::endl;
printShaderCompileLog(vs); }
//link shaders into a shader program
shader = glCreateProgram();
@ -101,48 +168,9 @@ void initBuffers () {
glLinkProgram(shader);
glUseProgram(shader);
//tell OpenGL what to put in the input vars
GLuint posAttr = glGetAttribLocation(shader, "position");
glVertexAttribPointer(posAttr, 2, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), 0);
glEnableVertexAttribArray(posAttr);
GLuint uvAttr = glGetAttribLocation(shader, "texcoord");
glVertexAttribPointer(uvAttr, 2, GL_FLOAT, GL_FALSE, 4*sizeof(GLfloat), (void*)(2*sizeof(GLfloat)));
glEnableVertexAttribArray(uvAttr);
//set an identity ("do nothing") transformation matrix as default
transUniform = glGetUniformLocation(shader, "transMatrix");
glUniformMatrix4fv(transUniform, 1, GL_FALSE, glm::value_ptr(glm::mat4(1.0f)));
GLuint tex;
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
int x, y, channels;
GLubyte* pixels = stbi_load("face.png", &x, &y, &channels, 4);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//enable blending for alpha textures
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
void initGraphics () {
int argc = 1;
char *argv[1] = {(char*)"fc2d"};
glutInit(&argc, argv);
glutCreateWindow("FaceCam2D");
glutInitWindowSize(512, 512);
glutDisplayFunc(display);
initBuffers();
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
}
void graphicsFrame () {
@ -160,12 +188,11 @@ void initModel () {
}
void updateModel(glm::vec2 headPos) {
//calculate transform
glm::mat4 transMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(headPos.x, headPos.y, 0.0f));
//upload to GPU and put in transMatrix uniform var in shader program
glUniformMatrix4fv(transUniform, 1, GL_FALSE, glm::value_ptr(transMatrix));
void updateModel(glm::vec2 headPos, glm::vec2 facePos) {
//calculate transforms
matHead = glm::translate(glm::mat4(1.0f), glm::vec3(headPos.x, -headPos.y, 0.0f));
matFace = glm::translate(glm::mat4(1.0f), glm::vec3(facePos.x, -facePos.y, 0.0f));
//tell FreeGLUT to schedule a screen update
glutPostRedisplay();
}

View file

@ -8,8 +8,12 @@ void initGraphics ();
void graphicsFrame ();
void initTexture (GLuint* texNum, const char* path);
void initShader();
void printShaderCompileLog(GLuint shader);
void updateModel(glm::vec2 headPos);
void updateModel(glm::vec2 headPos, glm::vec2 facePos);
#endif

View file

@ -43,13 +43,25 @@ int main () {
std::vector<std::vector<cv::Point2f>> landmarks;
if (facemark->fit (frame, faces, landmarks)) {
for (int i = 0; i < landmarks[biggestFace].size(); i++) {
cv::circle (frame, landmarks[biggestFace][i], 2, cv::Scalar (255, 255, 255));
}
//for (int i = 0; i < landmarks[biggestFace].size(); i++) {
// cv::circle (frame, landmarks[biggestFace][i], 2, cv::Scalar (255, 255, 255));
//}
cv::circle(frame, cv::Point2f(
(landmarks[biggestFace][2].x + landmarks[biggestFace][14].x) / 2,
(landmarks[biggestFace][2].y + landmarks[biggestFace][14].y) / 2
), 6, cv::Scalar(0, 0, 255));
cv::circle (frame, landmarks[biggestFace][30], 6, cv::Scalar (0, 255, 255));
//send control information to graphics
updateModel(glm::vec2(
((faces[biggestFace].x + (faces[biggestFace].width / 2)) * 2) / (float)frame.cols - 1,
((faces[biggestFace].y + (faces[biggestFace].height / 2)) * 2) / -(float)frame.rows + 1
(landmarks[biggestFace][2].x + landmarks[biggestFace][14].x) / 2
* 2 / (float)frame.cols - 1,
(landmarks[biggestFace][2].y + landmarks[biggestFace][14].y) / 2
* 2 / (float)frame.rows - 1
),
glm::vec2(
landmarks[biggestFace][30].x * 2 / (float)frame.cols - 1,
landmarks[biggestFace][30].y * 2 / (float)frame.rows - 1
));
}