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:
parent
25ebd7a387
commit
62779b6f78
157
src/graphics.cpp
157
src/graphics.cpp
|
@ -11,24 +11,37 @@
|
||||||
|
|
||||||
#include <graphics.hpp>
|
#include <graphics.hpp>
|
||||||
|
|
||||||
GLuint vbo; //vertex buffer
|
//VAOs for different parts
|
||||||
GLuint ebo; //element buffer
|
//TODO: make this more modular
|
||||||
GLuint vao; //vertex array (holds shader relations etc to vertex buffer)
|
GLuint head; //head object
|
||||||
|
GLuint face; //face object
|
||||||
|
|
||||||
GLuint shader; //standard shader program used for all elements
|
GLuint shader; //standard shader program used for all elements
|
||||||
GLuint transUniform; //location of the "transMatrix" transformation matrix uniform in the shader
|
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 () {
|
void display () {
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
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);
|
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
|
||||||
|
|
||||||
glutSwapBuffers();
|
glutSwapBuffers();
|
||||||
}
|
}
|
||||||
|
|
||||||
void initBuffers () {
|
void initBuffers (GLuint* vaoNum) {
|
||||||
glewInit();
|
|
||||||
|
|
||||||
//TODO: put quad stuff in header file or something
|
//TODO: put quad stuff in header file or something
|
||||||
GLfloat quad[] = {
|
GLfloat quad[] = {
|
||||||
//vertex UV/texcoord
|
//vertex UV/texcoord
|
||||||
|
@ -43,6 +56,73 @@ void initBuffers () {
|
||||||
2, 3, 0
|
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 =
|
const char* vsSrc =
|
||||||
"#version 150\n"
|
"#version 150\n"
|
||||||
"in vec2 position;"
|
"in vec2 position;"
|
||||||
|
@ -63,18 +143,6 @@ void initBuffers () {
|
||||||
"color = texture(tex, uv);"
|
"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
|
//compile vert shader
|
||||||
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
|
GLuint vs = glCreateShader(GL_VERTEX_SHADER);
|
||||||
glShaderSource(vs, 1, &vsSrc, NULL);
|
glShaderSource(vs, 1, &vsSrc, NULL);
|
||||||
|
@ -92,7 +160,6 @@ void initBuffers () {
|
||||||
if (status != GL_TRUE) { std::cout << "fragment shader borked" << std::endl;
|
if (status != GL_TRUE) { std::cout << "fragment shader borked" << std::endl;
|
||||||
printShaderCompileLog(vs); }
|
printShaderCompileLog(vs); }
|
||||||
|
|
||||||
|
|
||||||
//link shaders into a shader program
|
//link shaders into a shader program
|
||||||
shader = glCreateProgram();
|
shader = glCreateProgram();
|
||||||
glAttachShader(shader, vs);
|
glAttachShader(shader, vs);
|
||||||
|
@ -101,48 +168,9 @@ void initBuffers () {
|
||||||
glLinkProgram(shader);
|
glLinkProgram(shader);
|
||||||
glUseProgram(shader);
|
glUseProgram(shader);
|
||||||
|
|
||||||
|
//set an identity ("do nothing") transformation matrix as default
|
||||||
//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);
|
|
||||||
|
|
||||||
transUniform = glGetUniformLocation(shader, "transMatrix");
|
transUniform = glGetUniformLocation(shader, "transMatrix");
|
||||||
glUniformMatrix4fv(transUniform, 1, GL_FALSE, glm::value_ptr(glm::mat4(1.0f)));
|
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 () {
|
void graphicsFrame () {
|
||||||
|
@ -160,12 +188,11 @@ void initModel () {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateModel(glm::vec2 headPos) {
|
void updateModel(glm::vec2 headPos, glm::vec2 facePos) {
|
||||||
//calculate transform
|
//calculate transforms
|
||||||
glm::mat4 transMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(headPos.x, headPos.y, 0.0f));
|
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));
|
||||||
//upload to GPU and put in transMatrix uniform var in shader program
|
|
||||||
glUniformMatrix4fv(transUniform, 1, GL_FALSE, glm::value_ptr(transMatrix));
|
|
||||||
|
|
||||||
|
//tell FreeGLUT to schedule a screen update
|
||||||
glutPostRedisplay();
|
glutPostRedisplay();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,8 +8,12 @@ void initGraphics ();
|
||||||
|
|
||||||
void graphicsFrame ();
|
void graphicsFrame ();
|
||||||
|
|
||||||
|
void initTexture (GLuint* texNum, const char* path);
|
||||||
|
|
||||||
|
void initShader();
|
||||||
|
|
||||||
void printShaderCompileLog(GLuint shader);
|
void printShaderCompileLog(GLuint shader);
|
||||||
|
|
||||||
void updateModel(glm::vec2 headPos);
|
void updateModel(glm::vec2 headPos, glm::vec2 facePos);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
22
src/main.cpp
22
src/main.cpp
|
@ -43,13 +43,25 @@ int main () {
|
||||||
std::vector<std::vector<cv::Point2f>> landmarks;
|
std::vector<std::vector<cv::Point2f>> landmarks;
|
||||||
|
|
||||||
if (facemark->fit (frame, faces, landmarks)) {
|
if (facemark->fit (frame, faces, landmarks)) {
|
||||||
for (int i = 0; i < landmarks[biggestFace].size(); i++) {
|
//for (int i = 0; i < landmarks[biggestFace].size(); i++) {
|
||||||
cv::circle (frame, landmarks[biggestFace][i], 2, cv::Scalar (255, 255, 255));
|
// 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
|
//send control information to graphics
|
||||||
updateModel(glm::vec2(
|
updateModel(glm::vec2(
|
||||||
((faces[biggestFace].x + (faces[biggestFace].width / 2)) * 2) / (float)frame.cols - 1,
|
(landmarks[biggestFace][2].x + landmarks[biggestFace][14].x) / 2
|
||||||
((faces[biggestFace].y + (faces[biggestFace].height / 2)) * 2) / -(float)frame.rows + 1
|
* 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
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue