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 b6aa8bee2599dffe58502ea20650860108c1b484..2428848c59b758eb062b70652ea7aedcc06192a1 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/Ceres.h b/apps/specular_estimation/src/Ceres.h
index 9b75b07ae495c80ef5b31d998149de25a19b0a06..32f8a27e66572ad49fa1d013f24214c39fe4c6bb 100644
--- a/apps/specular_estimation/src/Ceres.h
+++ b/apps/specular_estimation/src/Ceres.h
@@ -17,17 +17,19 @@ using ceres::Problem;
 using ceres::Solver;
 using ceres::Solve;*/
 
-void specularMinimisation(double& SpecularIntensity, double& SpecularPower, double residualValue, cv::Vec3d residual, double totalResidual, cv::Mat residualImage, glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int width, int height, int numberOfLights, GLuint SpecularIntensityID, GLuint SpecularPowerID, GLuint programID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint MatrixID, glm::mat4 ModelMatrix, glm::mat4 MVP, glm::mat4 ViewMatrix, glm::mat4 depthBiasMVP, std::vector<glm::vec3> lightInvDirs, std::vector<cv::Mat> textureImages);
-void outputToFile(double specularIntensity, double specularPower, double resiudal);
+void specularMinimisation(double& SpecularIntensity, double& SpecularPower, double& Gain, double& Bias, double residualValue, cv::Vec3d residual, double totalResidual, cv::Mat residualImage, glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, double width, int height, int numberOfLights, GLuint SpecularIntensityID, GLuint SpecularPowerID, GLuint programID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint MatrixID, glm::mat4 ModelMatrix, glm::mat4 MVP, glm::mat4 ViewMatrix, glm::mat4 depthBiasMVP, std::vector<glm::vec3> lightInvDirs, std::vector<cv::Mat> textureImages);
+void outputToFile(double specularIntensity, double specularPower, double gain, double bias, double resiudal);
 
 class MyScalarCostFunctor {
 	public:
 		MyScalarCostFunctor(double residualValue, cv::Vec3d residual, double totalResidual, cv::Mat residualImage, glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int width, int height, int numberOfLights, GLuint SpecularIntensityID, GLuint SpecularPowerID, GLuint programID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint MatrixID, glm::mat4 ModelMatrix, glm::mat4 MVP, glm::mat4 ViewMatrix, glm::mat4 depthBiasMVP, std::vector<glm::vec3> lightInvDirs, std::vector<cv::Mat> textureImages):residualValue_(residualValue), residual_(residual), totalResidual_(totalResidual), residualImage_(residualImage), depthProjectionMatrix_(depthProjectionMatrix), depthViewMatrix_(depthViewMatrix), width_(width), height_(height), numberOfLights_(numberOfLights), SpecularIntensityID_(SpecularIntensityID), SpecularPowerID_(SpecularPowerID), programID_(programID), ModelMatrixID_(ModelMatrixID), ViewMatrixID_(ViewMatrixID), DepthBiasID_(DepthBiasID), lightInvDirID_(lightInvDirID), Texture_(Texture), TextureID_(TextureID), depthTexture_(depthTexture), ShadowMapID_(ShadowMapID), vertexbuffer_(vertexbuffer), uvbuffer_(uvbuffer), normalbuffer_(normalbuffer), elementbuffer_(elementbuffer), indices_(indices), MatrixID_(MatrixID), ModelMatrix_(ModelMatrix), MVP_(MVP), ViewMatrix_(ViewMatrix), depthBiasMVP_(depthBiasMVP), lightInvDirs_(lightInvDirs), textureImages_(textureImages){}
 
-		bool operator()(const double* const SpecularIntensity, const double* const SpecularPower, double* residualValue) const {
+		bool operator()(const double* const SpecularIntensity, const double* const SpecularPower, const double* const Gain, const double* const Bias, double* residualValue) const {
 			
 			double specularIntensity = double(SpecularIntensity[0]);
 			double specularPower     = double(SpecularPower[0]);
+			double gain 			 = double(Gain[0]);
+			double bias     		 = double(Bias[0]);
 			
 			double sum = 0;
 			
@@ -36,8 +38,8 @@ class MyScalarCostFunctor {
 				// Render the polygons
 				renderPolygons(width_, height_, programID_, lightInvDirs_[i], MatrixID_, ModelMatrixID_, ViewMatrixID_, DepthBiasID_, lightInvDirID_, Texture_, TextureID_, depthTexture_, ShadowMapID_, vertexbuffer_, uvbuffer_, normalbuffer_, elementbuffer_, indices_, MVP_, ModelMatrix_, ViewMatrix_, depthBiasMVP_, SpecularIntensityID_, specularIntensity, SpecularPowerID_, specularPower);
 				
-				meanSquaredError(i, height_, width_, textureImages_, sum);
-				//structuralSimilarityIndex(i, height_, width_, textureImages_, sum);
+				meanSquaredError(i, height_, width_, textureImages_, sum, gain, bias);
+				//structuralSimilarityIndex(i, height_, width_, textureImages_, sum, gain, bias);
 				
 				// Swap buffers
 				glfwSwapBuffers(window);
@@ -45,7 +47,7 @@ class MyScalarCostFunctor {
 			}
 
 			//std::cout << "Specular Intensity = " << specularIntensity << ", Specular Power = " << specularPower << ", Residual = " << (sum/numberOfLights_) << ", SSD = " << (sum/numberOfLights_)*(sum/numberOfLights_) << std::endl;
-			//std::cout << specularIntensity << "\t" << specularPower << "\t" << (sum/numberOfLights_) << std::endl;
+			std::cout << specularIntensity << "\t" << specularPower << "\t" << gain << "\t" << bias << "\t" << (sum/numberOfLights_) << std::endl;
 
 			//outputToFile(specularIntensity, specularPower, (sum/numberOfLights_));
 			
@@ -91,25 +93,31 @@ class MyScalarCostFunctor {
 		std::vector<cv::Mat> textureImages_;
 };
 
-void specularMinimisation(double& SpecularIntensity, double& SpecularPower, double residualValue, cv::Vec3d residual, double totalResidual, cv::Mat residualImage, glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int width, int height, int numberOfLights, GLuint SpecularIntensityID, GLuint SpecularPowerID, GLuint programID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint MatrixID, glm::mat4 ModelMatrix, glm::mat4 MVP, glm::mat4 ViewMatrix, glm::mat4 depthBiasMVP, std::vector<glm::vec3> lightInvDirs, std::vector<cv::Mat> textureImages) {
+void specularMinimisation(double& SpecularIntensity, double& SpecularPower, double& Gain, double& Bias, double residualValue, cv::Vec3d residual, double totalResidual, cv::Mat residualImage, glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int width, int height, int numberOfLights, GLuint SpecularIntensityID, GLuint SpecularPowerID, GLuint programID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint MatrixID, glm::mat4 ModelMatrix, glm::mat4 MVP, glm::mat4 ViewMatrix, glm::mat4 depthBiasMVP, std::vector<glm::vec3> lightInvDirs, std::vector<cv::Mat> textureImages) {
 	
 	// The variable to solve for with its initial value. It will be mutated in place by the solver.
 	const double initialSpecularIntensity = SpecularIntensity;
 	const double initialSpecularPower     = SpecularPower;
+	const double initialGain 			  = Gain;
+	const double initialBias     		  = Bias;
 
 	// Build the problem.
 	ceres::Problem problem;
 
 	// Set up the only cost function (also known as residual). This uses auto-differentiation to obtain the derivative (jacobian).
 	// AutoDiffCostFunction<CostFunctor, (Dimensions of Residual), (Dimensions of Variables)>
-	ceres::CostFunction* cost_function = new NumericDiffCostFunction<MyScalarCostFunctor, CENTRAL, 1, 1, 1>(new MyScalarCostFunctor(residualValue, residual, totalResidual, residualImage, depthProjectionMatrix, depthViewMatrix, width, height, numberOfLights, SpecularIntensityID, SpecularPowerID, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, ModelMatrix, MVP, ViewMatrix, depthBiasMVP, lightInvDirs, textureImages));
+	ceres::CostFunction* cost_function = new NumericDiffCostFunction<MyScalarCostFunctor, CENTRAL, 1, 1, 1, 1, 1>(new MyScalarCostFunctor(residualValue, residual, totalResidual, residualImage, depthProjectionMatrix, depthViewMatrix, width, height, numberOfLights, SpecularIntensityID, SpecularPowerID, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, ModelMatrix, MVP, ViewMatrix, depthBiasMVP, lightInvDirs, textureImages));
 	std::vector<ceres::ResidualBlockId> residual_block_ids;
-	ceres::ResidualBlockId block_id = problem.AddResidualBlock(cost_function, NULL, &SpecularIntensity, &SpecularPower);
+	ceres::ResidualBlockId block_id = problem.AddResidualBlock(cost_function, NULL, &SpecularIntensity, &SpecularPower, &Gain, &Bias);
 	residual_block_ids.push_back(block_id);
 
 	problem.SetParameterLowerBound(&SpecularIntensity, 0, 0);
 	problem.SetParameterUpperBound(&SpecularIntensity, 0, 1);
-	problem.SetParameterLowerBound(&SpecularPower, 0, 0.1);
+	problem.SetParameterLowerBound(&SpecularPower, 0, 1);
+	problem.SetParameterLowerBound(&Gain, 0, 0);
+	problem.SetParameterUpperBound(&Gain, 0, 2);
+	problem.SetParameterLowerBound(&Bias, 0, -255);
+	problem.SetParameterUpperBound(&Bias, 0, 255);
 
 	// Run the solver!
 	Solver::Options options;
@@ -129,14 +137,16 @@ void specularMinimisation(double& SpecularIntensity, double& SpecularPower, doub
 	//std::cout << summary.FullReport() << std::endl;
 	std::cout << "Specular Intensity: " << initialSpecularIntensity << " -> " << SpecularIntensity << std::endl;
 	std::cout << "Specular Power: "     << initialSpecularPower     << " -> " << SpecularPower     << std::endl;
+	std::cout << "Gain: "     			<< initialGain			    << " -> " << Gain     		   << std::endl;
+	std::cout << "Bias: "     			<< initialBias     			<< " -> " << Bias     		   << std::endl;
 }
 
-void outputToFile(double specularIntensity, double specularPower, double resiudal) {
+void outputToFile(double specularIntensity, double specularPower, double gain, double bias, double resiudal) {
 	
 	std::ofstream outputFile("results.txt", std::ios::app);
 
 	if (outputFile.is_open()) {
-		outputFile << specularIntensity << "\t" << specularPower << "\t" << resiudal << std::endl;
+		outputFile << specularIntensity << "\t" << specularPower << "\t" << gain << "\t" << bias << "\t" << resiudal << std::endl;
 		outputFile.close();
 	}
 }
diff --git a/apps/specular_estimation/src/OpenCV.h b/apps/specular_estimation/src/OpenCV.h
index c2f93b17de06618d47062e0bbb3c64c4c31e14a9..f7d645c66911b2d3e71953cf436b11a8ca7c0e8b 100644
--- a/apps/specular_estimation/src/OpenCV.h
+++ b/apps/specular_estimation/src/OpenCV.h
@@ -46,6 +46,19 @@ double psnr(cv::Mat& img_src, cv::Mat& img_compressed, int block_size);
 double ssim(cv::Mat& img_src, cv::Mat& img_compressed, int block_size, bool show_progress);
 void compute_quality_metrics(char * file1, char * file2, int block_size);
 double getMSSIM(const cv::Mat& i1, const cv::Mat& i2);
+cv::Mat contrastBrightness(cv::Mat image, double gain, double bias);
+
+cv::Mat contrastBrightness(cv::Mat image, double gain = 1.0, double bias = 0.0) {
+	cv::Mat new_image = cv::Mat::zeros( image.size(), image.type() );
+    for ( int y = 0; y < image.rows; y++ ) {
+        for ( int x = 0; x < image.cols; x++ ) {
+            for ( int c = 0; c < image.channels(); c++ ) {
+                new_image.at<cv::Vec3b>(y,x)[c] = cv::saturate_cast<uchar>( gain*image.at<cv::Vec3b>(y,x)[c] + bias );
+            }
+        }
+    }
+	return new_image;
+}
 
 inline unsigned char Clamp(int n)
 {
diff --git a/apps/specular_estimation/src/OpenGL.h b/apps/specular_estimation/src/OpenGL.h
index 799d5b60120ff818c959e083a47347fce88fba50..4869438cdc251d1bac08ccd0c9a8b672f8be0fc8 100644
--- a/apps/specular_estimation/src/OpenGL.h
+++ b/apps/specular_estimation/src/OpenGL.h
@@ -52,7 +52,8 @@ void renderPolygons(int windowWidth, int windowHeight, GLuint programID, glm::ve
 void renderShadows(GLuint FramebufferName, int shadowResolution, GLuint depthProgramID, glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, GLuint depthMatrixID, GLuint vertexbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, glm::mat4 depthModelMatrix, glm::mat4 depthMVP);
 void renderShadowMap(GLuint quad_programID, GLuint depthTexture, GLuint texID, GLuint quad_vertexbuffer);
 //void meanSquaredError(int imageNumber, int windowHeight, int windowWidth, std::string modelPath, std::vector < cv::Mat > textureImages, cv::Mat& residual, cv::Vec3d& residuals, double& sum, double SpecularIntensity, double SpecularPower);
-void meanSquaredError(int imageNumber, int windowHeight, int windowWidth, std::vector<cv::Mat> textureImages, double& sum);
+void meanSquaredError(int imageNumber, int windowHeight, int windowWidth, std::vector<cv::Mat> textureImages, double& sum, double gain, double bias);
+void structuralSimilarityIndex(int imageNumber, int windowHeight, int windowWidth, std::vector<cv::Mat> textureImages, double& sum, double gain, int bias);
 double returnResidual(int imageNumber, int windowHeight, int windowWidth, std::vector<cv::Mat> textureImages, cv::Mat& residual, cv::Vec3d& residuals, double SpecularIntensity, double SpecularPower);
 //void computeResiduals(cv::Vec3d& residual, std::vector< cv::Vec3d >& residuals, double& totalResidual, cv::Mat& residualImage, bool calculateResidual, glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int width, int height, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::vec3& lightInvDir, cv::Mat lightDirections, std::vector<cv::Mat> textureImages, int lightNumber, int numberOfLights, GLuint& SpecularIntensityID, double& SpecularIntensity, GLuint& SpecularPowerID, double& SpecularPower, GLuint programID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint MatrixID, std::string modelPath);
 void viewModel(cv::Vec3d& residual, double& totalResidual, cv::Mat& residualImage, bool calculateResidual, glm::mat4 depthProjectionMatrix, glm::mat4 depthViewMatrix, int width, int height, glm::vec3& position, float& horizontalAngle, float& verticalAngle, float& FoV, glm::vec3& lightInvDir, cv::Mat lightDirections, std::vector<cv::Mat> textureImages, int lightNumber, int numberOfLights, GLuint& SpecularIntensityID, double& SpecularIntensity, GLuint& SpecularPowerID, double& SpecularPower, GLuint programID, GLuint ModelMatrixID, GLuint ViewMatrixID, GLuint DepthBiasID, GLuint lightInvDirID, GLuint Texture, GLuint TextureID, GLuint depthTexture, GLuint ShadowMapID, GLuint vertexbuffer, GLuint uvbuffer, GLuint normalbuffer, GLuint elementbuffer, std::vector<unsigned int> indices, GLuint MatrixID, std::string modelPath);
@@ -555,7 +556,7 @@ void renderPolygons(int windowWidth, int windowHeight, GLuint programID, glm::ve
 	//std::cout << "Image " << imageNumber << ", average sum of squared differences: R = " << sum << ", specular intensity = " << SpecularIntensity << ", specular power = " << SpecularPower << std::endl;
 }*/
 
-void meanSquaredError(int imageNumber, int windowHeight, int windowWidth, std::vector<cv::Mat> textureImages, double& sum) {
+void meanSquaredError(int imageNumber, int windowHeight, int windowWidth, std::vector<cv::Mat> textureImages, double& sum, double gain, double bias) {
 	
 	// Create an empty Mat the same size as the image
 	cv::Mat temp = cv::Mat(windowHeight, windowWidth, CV_8UC3);
@@ -569,6 +570,9 @@ void meanSquaredError(int imageNumber, int windowHeight, int windowWidth, std::v
 	cv::flip(temp, temp, 0);
 
 	//temp = addNoise(temp, 0.001);
+
+	temp = contrastBrightness(temp, gain, bias);
+	//cv::Mat textureImage = contrastBrightness(textureImages[imageNumber], gain, bias);
 	
 	/*cv::Mat texture = textureImages[imageNumber];
 	cv::cvtColor(texture, texture, CV_BGR2GRAY);
@@ -576,6 +580,7 @@ void meanSquaredError(int imageNumber, int windowHeight, int windowWidth, std::v
 
 	// Calculate the absolute differences between the model and the photograph
 	cv::absdiff(temp, textureImages[imageNumber], residual);
+	//cv::absdiff(temp, textureImage, residual);
 	
 	// Square each element
 	multiply(residual, residual, sumOfSquaredDifferences);
@@ -589,7 +594,7 @@ void meanSquaredError(int imageNumber, int windowHeight, int windowWidth, std::v
 	//sum += (cv::sum(sumOfSquaredDifferences)[0] + cv::sum(sumOfSquaredDifferences)[1] + cv::sum(sumOfSquaredDifferences)[2]);
 }
 
-void structuralSimilarityIndex(int imageNumber, int windowHeight, int windowWidth, std::vector<cv::Mat> textureImages, double& sum) {
+void structuralSimilarityIndex(int imageNumber, int windowHeight, int windowWidth, std::vector<cv::Mat> textureImages, double& sum, double gain, int bias) {
 	
 	// Create an empty Mat the same size as the image
 	cv::Mat temp = cv::Mat(windowHeight, windowWidth, CV_8UC3);
@@ -602,6 +607,8 @@ void structuralSimilarityIndex(int imageNumber, int windowHeight, int windowWidt
 	// 3D models have the origin in the bottom-left corner, while images have the origin in the top-left corner. The image is flipped to convert between the two.
 	cv::flip(temp, temp, 0);
 	
+	temp = contrastBrightness(temp, gain, bias);
+
 	sum += 3 - getMSSIM(temp, textureImages[imageNumber]);
 }
 
@@ -739,8 +746,9 @@ void viewModel(cv::Vec3d& residual, double& totalResidual, cv::Mat& residualImag
 		//void renderShadowMap(GLuint quad_programID, GLuint depthTexture, GLuint texID, GLuint quad_vertexbuffer);
 				
 		if (calculateResidual) {
-			double sum = 0;
-			meanSquaredError(lightNumber, height, width, textureImages, sum);
+			double sum = 0, gain = 0;
+			int bias = 0;
+			meanSquaredError(lightNumber, height, width, textureImages, sum, gain, bias);
 			//computeResiduals(residual, residuals, totalResidual, residualImage, calculateResidual, depthProjectionMatrix, depthViewMatrix, width, height, position, horizontalAngle, verticalAngle, FoV, lightInvDir, lightDirections, textureImages, lightNumber, numberOfLights, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, modelPath);
 			std::cout << "Light number: " << lightNumber << ", per-pixel residual = " << totalResidual << ", specular intensity = " << SpecularIntensity << ", specular power = " << SpecularPower << std::endl;
 		}
@@ -2876,8 +2884,9 @@ void viewModelCT(cv::Vec3d& residual, double& totalResidual, cv::Mat& residualIm
 		//void renderShadowMap(GLuint quad_programID, GLuint depthTexture, GLuint texID, GLuint quad_vertexbuffer);
 				
 		if (calculateResidual) {
-			double sum = 0;
-			meanSquaredError(lightNumber, height, width, textureImages, sum);
+			double sum = 0, gain = 0;
+			int bias = 0;
+			meanSquaredError(lightNumber, height, width, textureImages, sum, gain, bias);
 			//computeResiduals(residual, residuals, totalResidual, residualImage, calculateResidual, depthProjectionMatrix, depthViewMatrix, width, height, position, horizontalAngle, verticalAngle, FoV, lightInvDir, lightDirections, textureImages, lightNumber, numberOfLights, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, modelPath);
 			std::cout << "Light number: " << lightNumber << ", per-pixel residual = " << totalResidual << ", specular intensity = " << SpecularIntensity << ", specular power = " << SpecularPower << std::endl;
 		}
diff --git a/apps/specular_estimation/src/specular_estimation.cc b/apps/specular_estimation/src/specular_estimation.cc
index 5a248f4ca5676114b292f6f524bcac3959036250..6d3e43782533dc7f4f1b5f443dda481c0131c2c1 100644
--- a/apps/specular_estimation/src/specular_estimation.cc
+++ b/apps/specular_estimation/src/specular_estimation.cc
@@ -11,6 +11,19 @@ int main(int argc, char** argv) {
 	cv::Mat black = cv::Mat(windowHeight, windowWidth, CV_8UC3, cv::Scalar::all(0));
 	calibrateLights(windowWidth, windowHeight, black);*/
 
+	/*int windowWidth = 1092, windowHeight = 728;
+	cv::Mat image = cv::imread("/home/thomas/Documents/2018-09-05/uniformAlbedo/uniformAlbedo.albedo (another copy).png");
+	for (double i = 0; i < 3; i += 0.1) {
+		for (double j = -100; j < 100; j+=10) {
+			cv::Mat textureImage = contrastBrightness(image, i, j);
+			cv::imshow("image", textureImage);
+			std::cout << "Gain: " << i << ", Bias: " << j << std::endl;
+			cv::waitKey(0);
+		}
+	}*/
+	
+
+
 	// Required for the Ceres solver
 	google::InitGoogleLogging(argv[0]);
 	
@@ -277,8 +290,9 @@ void renderSynthetic(std::string imageName, std::string calibration, double Spec
 	RenderSynthetic(depthProjectionMatrix, depthViewMatrix, width, height, position, horizontalAngle, verticalAngle, FoV, lightInvDir, lightDirections, textureImages, numberOfLights, SpecularIntensityID, SpecularIntensitySynthetic, SpecularPowerID, SpecularPowerSynthetic, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, modelPath);
 	
 	//SpecularIntensity = 0.5, SpecularPower = 2;
+	double Gain = 1.0, Bias = 0;
 
-	specularMinimisation(SpecularIntensity, SpecularPower, residualValue, residual, totalResidual, residualImage, depthProjectionMatrix, depthViewMatrix, width, height, numberOfLights, SpecularIntensityID, SpecularPowerID, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, ModelMatrix, MVP, ViewMatrix, depthBiasMVP, lightInvDirs, textureImages);
+	specularMinimisation(SpecularIntensity, SpecularPower, Gain, Bias, residualValue, residual, totalResidual, residualImage, depthProjectionMatrix, depthViewMatrix, width, height, numberOfLights, SpecularIntensityID, SpecularPowerID, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, ModelMatrix, MVP, ViewMatrix, depthBiasMVP, lightInvDirs, textureImages);
 
 	//viewModel(residual, totalResidual, residualImage, calculateResidual, depthProjectionMatrix, depthViewMatrix, width, height, position, horizontalAngle, verticalAngle, FoV, lightInvDir, lightDirections, textureImages, lightNumber, numberOfLights, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, modelPath);
 	
@@ -294,7 +308,7 @@ void specularEstimation(std::string imageName, std::string calibration, double S
 	//const std::string imagesPath	  = "/media/tw00275/ESD-USB/";
 	//const std::string sourcePath	  = "/home/thomas/Documents/Minimisation/apps/specular_estimation/src/vboindexer.cpp";
 	const std::string imagesPath	  = "/home/thomas/Documents/";
-	const std::string folderPath	  = "2018-09-05";
+	const std::string folderPath	  = "2018-08-31";
 	const std::string modelPath       = imagesPath + folderPath + "/" + imageName   + "/" + imageName   + ".";
 	//const std::string calibrationPath = imagesPath + folderPath + "/" + calibration + "/" + calibration + ".";
 	const std::string calibrationPath = imagesPath + "2017-12-04" + "/" + calibration + "/" + calibration + ".";
@@ -501,7 +515,9 @@ void specularEstimation(std::string imageName, std::string calibration, double S
 	
 	initialiseOpenGL(heightMap, normalMap, texture, lightDirections, width, height, depthProjectionMatrix, depthViewMatrix, position, horizontalAngle, verticalAngle, FoV, lightInvDir, programID, MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, depthProgramID, quad_programID, FramebufferName, quad_vertexbuffer, VertexArrayID, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower, numberOfLights, calculateResidual, depthMVP, depthModelMatrix, MVP, ProjectionMatrix, ViewMatrix, ModelMatrix, depthBiasMVP, biasMatrix);
 	
-	specularMinimisation(SpecularIntensity, SpecularPower, residualValue, residual, totalResidual, residualImage, depthProjectionMatrix, depthViewMatrix, width, height, numberOfLights, SpecularIntensityID, SpecularPowerID, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, ModelMatrix, MVP, ViewMatrix, depthBiasMVP, lightInvDirs, textureImages);
+	double Gain = 1.0, Bias = 0;
+
+	specularMinimisation(SpecularIntensity, SpecularPower, Gain, Bias, residualValue, residual, totalResidual, residualImage, depthProjectionMatrix, depthViewMatrix, width, height, numberOfLights, SpecularIntensityID, SpecularPowerID, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, ModelMatrix, MVP, ViewMatrix, depthBiasMVP, lightInvDirs, textureImages);
 
 	//viewModel(residual, totalResidual, residualImage, calculateResidual, depthProjectionMatrix, depthViewMatrix, width, height, position, horizontalAngle, verticalAngle, FoV, lightInvDir, lightDirections, textureImages, lightNumber, numberOfLights, SpecularIntensityID, SpecularIntensity, SpecularPowerID, SpecularPower, programID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MatrixID, modelPath);
 	
@@ -599,7 +615,7 @@ void denseSample(std::string imageName, std::string calibration, double Specular
 	cv::Vec3d residual;
 	int lightNumber = 0;
 	bool calculateResidual = false, perspectiveProjection, shadowControl;
-	double totalResidual, residualValue;
+	double totalResidual, residualValue, gain = 1.0, bias = 0;
 	cv::Mat residualImage;
 
 	//cv::Mat lightDirectionsInverted;
@@ -627,7 +643,7 @@ void denseSample(std::string imageName, std::string calibration, double Specular
 				// Render the polygons
 				renderPolygons(width, height, programID, lightInvDirs[i], MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MVP, ModelMatrix, ViewMatrix, depthBiasMVP, SpecularIntensityID, specularIntensity, SpecularPowerID, specularPower);
 				
-				meanSquaredError(i, height, width, textureImages, sum);
+				meanSquaredError(i, height, width, textureImages, sum, gain, bias);
 				
 				// Swap buffers
 				glfwSwapBuffers(window);
@@ -688,7 +704,7 @@ void denseSyntheticSample(std::string imageName, std::string calibration, double
 	cv::Vec3d residual;
 	int lightNumber = 0;
 	bool calculateResidual = false, perspectiveProjection, shadowControl;
-	double totalResidual, residualValue;
+	double totalResidual, residualValue, gain = 1.0, bias = 0;
 	cv::Mat residualImage, albedo = cv::imread(albedoPath), normalMap = cv::imread(normalPath), heightMap = cv::Mat::zeros(albedo.size(), CV_8U);
 	std::vector<cv::Mat> textureImages;;
 
@@ -724,7 +740,7 @@ void denseSyntheticSample(std::string imageName, std::string calibration, double
 				// Render the polygons
 				renderPolygons(width, height, programID, lightInvDirs[i], MatrixID, ModelMatrixID, ViewMatrixID, DepthBiasID, lightInvDirID, Texture, TextureID, depthTexture, ShadowMapID, vertexbuffer, uvbuffer, normalbuffer, elementbuffer, indices, MVP, ModelMatrix, ViewMatrix, depthBiasMVP, SpecularIntensityID, specularIntensity, SpecularPowerID, specularPower);
 				
-				meanSquaredError(i, height, width, textureImages, sum);
+				meanSquaredError(i, height, width, textureImages, sum, gain, bias);
 				
 				// Swap buffers
 				glfwSwapBuffers(window);
diff --git a/bin/specular_estimation b/bin/specular_estimation
index 1970896bb6a1733e85e36fa87ad7c8c540bc0e4f..9dc1995e964149367f6fcc9341e2a26af1b92226 100755
Binary files a/bin/specular_estimation and b/bin/specular_estimation differ