diff --git a/apps/specular_estimation/CMakeFiles/specular_estimation.dir/src/specular_estimation.cc.o b/apps/specular_estimation/CMakeFiles/specular_estimation.dir/src/specular_estimation.cc.o
index 219505ab1ce78f01cbbc44762d6040461a33a6fc..1271b541311c20f58f61c6862a9e4ccf72092dfd 100644
Binary files a/apps/specular_estimation/CMakeFiles/specular_estimation.dir/src/specular_estimation.cc.o and b/apps/specular_estimation/CMakeFiles/specular_estimation.dir/src/specular_estimation.cc.o differ
diff --git a/apps/specular_estimation/src/OpenCV.h b/apps/specular_estimation/src/OpenCV.h
index 4534a3d9611ae83321da73d64b748a27c298be2a..7c90b0f8502783a91c9b35ddf8461a78ec97d123 100644
--- a/apps/specular_estimation/src/OpenCV.h
+++ b/apps/specular_estimation/src/OpenCV.h
@@ -26,6 +26,7 @@ void displayTexture(cv::Mat texture, std::string modelPath, bool saveTexture);
 void displayNormalMap(cv::Mat normals, std::string modelPath, bool saveNormalMap);
 void displayHeightMap(cv::Mat Z, std::string modelPath, bool saveHeightMap);
 cv::Mat scaleImageIntensity(cv::Mat image);
+void loadSurfaceNormals(cv::Mat lightDirections, int width, int height, int imageScale, std::string modelPath, cv::Mat& normals, cv::Mat& Z, std::vector< cv::Mat > modelImages);
 
 void photometricStereo(std::string imageName, std::string calibration, std::string modelPath, int imageScale, int cropping, bool showTexture, cv::Mat& Z, cv::Mat& normals, cv::Mat& texture, cv::Mat& lightDirections, cv::Mat& lightDirectionsPerspective, std::vector< cv::Mat > & textureImages, std::vector< cv::Mat > & modelImages, std::vector< cv::Mat > calibrationImages, cv::Rect calibrationBoundingBox, int& width, int& height, std::vector< cv::Vec3d > rvecs, std::vector< cv::Vec3d > tvecs) {
 	
@@ -44,6 +45,53 @@ void photometricStereo(std::string imageName, std::string calibration, std::stri
 
 	texture = createTexture(modelPath, imageScale, textureImages, width, height);
 
+	//loadSurfaceNormals(lightDirections, width, height, imageScale, modelPath, normals, Z, modelImages);
+	
+	normals = cv::Mat(height, width, CV_32FC3, cv::Scalar(0,0,1));
+	Z = cv::Mat(height, width, CV_32FC2, cv::Scalar::all(0));
+	
+	cv::GaussianBlur(Z, Z, cv::Size(3, 3), 0, 0);
+	//cv::resize(Z, Z, cv::Size(), 0.5, 0.5, cv::INTER_LINEAR);
+	//cv::resize(Z, Z, cv::Size(), 2, 2, cv::INTER_LINEAR);
+
+	//flip(Z, Z, 0);
+
+	// Show the mesh, texture, normal map and height map.
+	// Setting the last argument to true writes these images to the image folder.
+	// displayTexture needs to be executed before displayMesh if there is not already a texture file.
+	//displayTexture(texture, modelPath, showTexture);
+	//displayNormalMap(normals, modelPath, true);
+	//displayHeightMap(Z, modelPath, true);
+	//displayMesh(width, height, -Z, lightDirections, imageName, modelPath, texturePath, true, showTexture);
+
+	// Wait for a keystroke before closing the window
+	//cv::waitKey(0);
+}
+
+void loadImages(std::string imageName, std::string calibration, int& width, int& height, int imageScale, std::vector< cv::Mat > & textureImages, std::string calibrationPath, std::vector< cv::Mat > & calibrationImages, std::string modelPath, std::vector< cv::Mat > & modelImages, cv::Rect & calibrationBoundingBox) {
+
+	// Obtain the height and width of the images prior to resizing
+	int originalHeight;
+	int originalWidth;
+
+	cv::Mat calibrationMask = loadCalibrationMask(calibrationPath, originalHeight, originalWidth);
+	//cv::Mat modelMask = loadModelMask(modelPath, imageScale, originalHeight, originalWidth);
+
+	// Obtain the height and width of the images
+	height = calibrationMask.rows / imageScale;
+	width  = calibrationMask.cols / imageScale;
+
+	// Obtain the bounding box that contains the chrome sphere. Removing unnecessary space reduces the computation required to determine the incident light direction in each image
+	calibrationBoundingBox = getBoundingBox(calibrationMask);
+
+	//cropImages(modelBoundingBox, modelMask, croppedHeight, croppedWidth, cropping, modelPath, imageScale);
+
+	//loadImages(calibrationImages, modelImages, textureImages, calibrationPath, modelPath, imageScale, modelMask, modelBoundingBox, originalWidth, originalHeight, width, height, croppedWidth, croppedHeight);
+	loadCalibrationImages(calibrationImages, calibrationPath, originalWidth, originalHeight);
+	loadModelImages(modelImages, textureImages, modelPath, imageScale, originalWidth, originalHeight, width, height);
+}
+
+void loadSurfaceNormals(cv::Mat lightDirections, int width, int height, int imageScale, std::string modelPath, cv::Mat& normals, cv::Mat& Z, std::vector< cv::Mat > modelImages) {
 	// Create Mats to store the light directions, surface normals, and p, q gradients
 	cv::Mat lightDirectionsInverted;
 	cv::invert(lightDirections, lightDirectionsInverted, cv::DECOMP_SVD);
@@ -67,7 +115,8 @@ void photometricStereo(std::string imageName, std::string calibration, std::stri
 	std::string scale = stm.str();
 	
 	std::string normalMapName = modelPath + "normalMap" + scale + ".yml";
-	std::string globalHeightsName = modelPath + "globalHeights" + scale + ".yml";
+	std::string pGradientsName = modelPath + "pGradients" + scale + ".yml";
+	std::string qGradientsName = modelPath + "qGradients" + scale + ".yml";
 
 
 	cv::FileStorage storageRead;
@@ -75,42 +124,49 @@ void photometricStereo(std::string imageName, std::string calibration, std::stri
 	storageRead["normals"] >> normals;
 	storageRead.release();
 	/*
-	storageRead.open(globalHeightsName, cv::FileStorage::READ);
-	storageRead["globalHeights"] >> globalHeights;
+	storageRead.open(pGradientsName, cv::FileStorage::READ);
+	storageRead["pGradients"] >> Z.at<cv::Vec2f>[0];
 	storageRead.release();
-	*/
 	
+	storageRead.open(qGradientsName, cv::FileStorage::READ);
+	storageRead["qGradients"] >> Z.at<cv::Vec2f>[1];
+	storageRead.release();
+	*/
 	cv::FileStorage storageWrite;
 	
-	if (!normals.data) {
-		storageWrite.open(normalMapName, cv::FileStorage::WRITE);
-		
+	if (!normals.data) {		
 		normals = cv::Mat(height, width, CV_32FC3, cv::Scalar::all(0));
 		// Estimate the surface normals and p, q gradients
 		getSurfaceNormals(normals, pGradients, qGradients, lightDirectionsInverted, modelImages);
 		std::cout << "Surface normals have been estimated.\n\n";
 		
+		storageWrite.open(normalMapName, cv::FileStorage::WRITE);
 		storageWrite << "normals" << normals;
 		storageWrite.release();
 	}
 	/*
 	if (!Z.data) {
-		storageWrite.open(globalHeightsName, cv::FileStorage::WRITE);
-		
 		Z = cv::Mat(height, width, CV_32FC2, cv::Scalar::all(0));
 		// global integration of surface normals
 		Z = globalHeights(pGradients, qGradients);
 		std::cout << "Height map has been created.\n\n";
 		
-		storageWrite << "globalHeights" << Z;
+		storageWrite.open(pGradientsName, cv::FileStorage::WRITE);
+		storageWrite << "pGradients" << Z.at<cv::Vec2f>[0];
+		storageWrite.release();
+		
+		storageWrite.open(qGradientsName, cv::FileStorage::WRITE);
+		storageWrite << "qGradients" << Z.at<cv::Vec2f>[1];
 		storageWrite.release();
 	}
 	*/
+	
 	Z = cv::Mat(height, width, CV_32FC2, cv::Scalar::all(0));
 	// global integration of surface normals
 	Z = globalHeights(pGradients, qGradients);
 	std::cout << "Height map has been created.\n\n";
-
+	
+	
 	/*
 	normals = cv::imread(modelPath + "normalMap" + scale + ".png");
 
@@ -124,9 +180,6 @@ void photometricStereo(std::string imageName, std::string calibration, std::stri
 		cv::imwrite(modelPath + "normalMap" + scale + ".png", normals);
 	}
 
-
-	cv::FileStorage file("globalHeights" + scale + ".xml", cv::FileStorage::WRITE);
-
 	Z = cv::imread(modelPath + "globalHeights" + scale + ".png");
 
 	if (!Z.data) {
@@ -139,45 +192,6 @@ void photometricStereo(std::string imageName, std::string calibration, std::stri
 		cv::imwrite(modelPath + "globalHeights" + scale + ".png", Z);
 	}
 	*/
-	cv::GaussianBlur(Z, Z, cv::Size(3, 3), 0, 0);
-	//cv::resize(Z, Z, cv::Size(), 0.5, 0.5, cv::INTER_LINEAR);
-	//cv::resize(Z, Z, cv::Size(), 2, 2, cv::INTER_LINEAR);
-
-	//flip(Z, Z, 0);
-
-	// Show the mesh, texture, normal map and height map.
-	// Setting the last argument to true writes these images to the image folder.
-	// displayTexture needs to be executed before displayMesh if there is not already a texture file.
-	//displayTexture(texture, modelPath, showTexture);
-	//displayNormalMap(normals, modelPath, true);
-	//displayHeightMap(Z, modelPath, true);
-	//displayMesh(width, height, -Z, lightDirections, imageName, modelPath, texturePath, true, showTexture);
-
-	// Wait for a keystroke before closing the window
-	//cv::waitKey(0);
-}
-
-void loadImages(std::string imageName, std::string calibration, int& width, int& height, int imageScale, std::vector< cv::Mat > & textureImages, std::string calibrationPath, std::vector< cv::Mat > & calibrationImages, std::string modelPath, std::vector< cv::Mat > & modelImages, cv::Rect & calibrationBoundingBox) {
-
-	// Obtain the height and width of the images prior to resizing
-	int originalHeight;
-	int originalWidth;
-
-	cv::Mat calibrationMask = loadCalibrationMask(calibrationPath, originalHeight, originalWidth);
-	//cv::Mat modelMask = loadModelMask(modelPath, imageScale, originalHeight, originalWidth);
-
-	// Obtain the height and width of the images
-	height = calibrationMask.rows / imageScale;
-	width  = calibrationMask.cols / imageScale;
-
-	// Obtain the bounding box that contains the chrome sphere. Removing unnecessary space reduces the computation required to determine the incident light direction in each image
-	calibrationBoundingBox = getBoundingBox(calibrationMask);
-
-	//cropImages(modelBoundingBox, modelMask, croppedHeight, croppedWidth, cropping, modelPath, imageScale);
-
-	//loadImages(calibrationImages, modelImages, textureImages, calibrationPath, modelPath, imageScale, modelMask, modelBoundingBox, originalWidth, originalHeight, width, height, croppedWidth, croppedHeight);
-	loadCalibrationImages(calibrationImages, calibrationPath, originalWidth, originalHeight);
-	loadModelImages(modelImages, textureImages, modelPath, imageScale, originalWidth, originalHeight, width, height);
 }
 
 // Return an image comprised of the median intensities
diff --git a/bin/specular_estimation b/bin/specular_estimation
index 980789a48a5aa611d99b2b3aac9006fd506f5bc4..31576dcf5d950b2f11c22dbea51204b7969e0313 100755
Binary files a/bin/specular_estimation and b/bin/specular_estimation differ