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);
 | 
				
			||||||
| 
						 | 
					@ -91,7 +159,6 @@ void initBuffers () {
 | 
				
			||||||
	glGetShaderiv(fs, GL_COMPILE_STATUS, &status);
 | 
						glGetShaderiv(fs, GL_COMPILE_STATUS, &status);
 | 
				
			||||||
	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();
 | 
				
			||||||
| 
						 | 
					@ -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