From 56ab1c18e651bfb466c644437e37a6c8b4f41809 Mon Sep 17 00:00:00 2001
From: siddharth <siddharthkherada27@gmail.com>
Date: Tue, 3 Sep 2013 21:12:05 +0530
Subject: [PATCH] new filters added and all the 3 modules updated

All 3 modules Updated
---
 modules/photo/doc/cloning.rst           |  27 +-
 modules/photo/doc/npr.rst               |  90 +++
 modules/photo/include/opencv2/photo.hpp |  34 +-
 modules/photo/src/contrast_preserve.cpp | 274 ++++---
 modules/photo/src/contrast_preserve.hpp |  30 +-
 modules/photo/src/npr.cpp               | 236 +++++-
 modules/photo/src/npr.hpp               | 953 ++++++++++++++----------
 modules/photo/src/seamless_cloning.cpp  |  58 +-
 modules/photo/src/seamless_cloning.hpp  |  30 +-
 modules/photo/test/test_cloning.cpp     |   4 +-
 modules/photo/test/test_npr.cpp         | 146 ++++
 samples/cpp/cloning.cpp                 |  42 +-
 samples/cpp/cloning_example.cpp         | 243 ++++++
 samples/cpp/npr_demo.cpp                | 107 +++
 14 files changed, 1652 insertions(+), 622 deletions(-)
 create mode 100644 modules/photo/doc/npr.rst
 create mode 100644 modules/photo/test/test_npr.cpp
 create mode 100644 samples/cpp/cloning_example.cpp
 create mode 100644 samples/cpp/npr_demo.cpp

diff --git a/modules/photo/doc/cloning.rst b/modules/photo/doc/cloning.rst
index 740e1ab64b..11e9bce135 100644
--- a/modules/photo/doc/cloning.rst
+++ b/modules/photo/doc/cloning.rst
@@ -39,19 +39,21 @@ colorChange
 -----------
 Given an original color image, two differently colored versions of this image can be mixed seamlessly.
 
-.. ocv:function:: void colorChange( InputArray src, OutputArray dst, float red = 1.0, float green = 1.0, float blue = 1.0)
+.. ocv:function:: void colorChange( InputArray src, InputArray mask, OutputArray dst, float red_mul = 1.0, float green_mul = 1.0, float blue_mul = 1.0)
 
     :param src: Input 8-bit 3-channel image.
 
+    :param mask: Input 8-bit 1 or 3-channel image.
+    
     :param dst: Output image with the same size and type as  ``src`` .
 
-    :param red: R-channel Value
+    :param red_mul: R-channel multiply factor.
     
-    :param green: G-channel Value
+    :param green_mul: G-channel multiply factor.
     
-    :param blue: B-channel Value
+    :param blue_mul: B-channel multiply factor.
 
-RGB values between .5 to 2.5
+Multiplication factor is between .5 to 2.5.
     
 
 illuminationChange
@@ -59,10 +61,12 @@ illuminationChange
 Applying an appropriate non-linear transformation to the gradient field inside the selection and then integrating back with a Poisson
 solver, modifies locally the apparent illumination of an image.
 
-.. ocv:function:: void illuminationChange(InputArray src, OutputArray dst, float alpha = 0.2, float beta = 0.4)
+.. ocv:function:: void illuminationChange(InputArray src, InputArray mask, OutputArray dst, float alpha = 0.2, float beta = 0.4)
 
     :param src: Input 8-bit 3-channel image.
 
+    :param mask: Input 8-bit 1 or 3-channel image.
+    
     :param dst: Output image with the same size and type as  ``src``.
 
     :param alpha: Value ranges between 0-2.
@@ -74,14 +78,21 @@ This is useful to highlight under-exposed foreground objects or to reduce specul
 textureFlattening
 -----------------
 By retaining only the gradients at edge locations, before integrating with the Poisson solver, one washes out the texture of the selected
-region, giving its contents a flat aspect.
+region, giving its contents a flat aspect. Here Canny Edge Detector is used.
 
-.. ocv:function:: void textureFlattening(InputArray src, OutputArray dst)
+.. ocv:function:: void textureFlattening(InputArray src, InputArray mask, OutputArray dst, double low_threshold, double high_threshold, int kernel_size)
 
     :param src: Input 8-bit 3-channel image.
 
+    :param mask: Input 8-bit 1 or 3-channel image.
+    
     :param dst: Output image with the same size and type as  ``src``.
 
+    :param low_threshold: Range from 0 to 100.
+    
+    :param high_threshold: Value > 100.
+    
+    :param kernel_size: The size of the Sobel kernel to be used.
 
 **NOTE:**
 
diff --git a/modules/photo/doc/npr.rst b/modules/photo/doc/npr.rst
new file mode 100644
index 0000000000..db56c6955c
--- /dev/null
+++ b/modules/photo/doc/npr.rst
@@ -0,0 +1,90 @@
+Non-Photorealistic Rendering
+============================
+
+.. highlight:: cpp
+
+edgePreservingFilter
+--------------------
+
+Filtering is the fundamental operation in image and video processing. Edge-preserving smoothing filters are used in many different applications.
+
+.. ocv:function:: void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1, float sigma_s = 60, float sigma_r = 0.4);
+
+    :param src: Input 8-bit 3-channel image.
+
+    :param dst: Output 8-bit 3-channel image.
+    
+    :param flags: Edge preserving filters:
+
+            * **RECURS_FILTER**     
+
+            * **NORMCONV_FILTER**   
+
+    :param sigma_s: Range between 0 to 200.
+    
+    :param sigma_r: Range between 0 to 1.
+
+
+detailEnhance
+-------------
+This filter enhances the details of a particular image.
+
+.. ocv:function:: void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10, float sigma_r = 0.15);
+
+    :param src: Input 8-bit 3-channel image.
+
+    :param dst: Output image with the same size and type as  ``src``.
+
+    :param sigma_s: Range between 0 to 200. 
+    
+    :param sigma_r: Range between 0 to 1.
+    
+
+pencilSketch
+------------
+Pencil-like non-photorealistic line drawing
+
+.. ocv:function:: void pencilSketch(InputArray src, OutputArray dst1, OutputArray dst2, float sigma_s = 60, float sigma_r = 0.07, float shade_factor = 0.02);
+
+    :param src: Input 8-bit 3-channel image.
+
+    :param dst1: Output 8-bit 1-channel image.
+    
+    :param dst2: Output image with the same size and type as  ``src``.
+
+    :param sigma_s: Range between 0 to 200.
+    
+    :param sigma_r: Range between 0 to 1.
+    
+    :param shade_factor: Range between 0 to 0.1.
+
+
+stylization
+-----------
+Stylization aims to produce digital imagery with a wide variety of effects not focused on photorealism. Edge-aware filters are ideal for stylization, as they can abstract regions of low contrast while preserving, or enhancing, high-contrast features.
+
+.. ocv:function:: void stylization(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45);
+
+    :param src: Input 8-bit 3-channel image.
+
+    :param dst: Output image with the same size and type as  ``src``.
+
+    :param sigma_s: Range between 0 to 200.
+    
+    :param sigma_r: Range between 0 to 1.
+
+
+edgeEnhance
+-----------
+Able to suppress low-amplitude details and enhance edges.
+
+.. ocv:function:: void edgeEnhance(InputArray src, OutputArray dst, float sigma_s = 60, float sigma_r = 0.45);
+
+    :param src: Input 8-bit 3-channel image.
+
+    :param dst: Output 8-bit 1-channel image.
+
+    :param sigma_s: Range between 0 to 200.
+    
+    :param sigma_r: Range between 0 to 1.
+
diff --git a/modules/photo/include/opencv2/photo.hpp b/modules/photo/include/opencv2/photo.hpp
index d825c2489e..1eb5ccaab1 100644
--- a/modules/photo/include/opencv2/photo.hpp
+++ b/modules/photo/include/opencv2/photo.hpp
@@ -68,8 +68,8 @@ enum
 
 enum
 {
-	RECURSIVE_FILTER = 1,
-	NC_FILTER = 2
+	RECURS_FILTER = 1,
+	NORMCONV_FILTER = 2
 };
 
 //! restores the damaged image areas using one of the available intpainting algorithms
@@ -301,17 +301,35 @@ public:
 
 CV_EXPORTS_W Ptr<MergeRobertson> createMergeRobertson();
 
-CV_EXPORTS_W void decolor(InputArray src, OutputArray grayscale, OutputArray color_boost);
+CV_EXPORTS_W void decolor( InputArray src, OutputArray grayscale, OutputArray color_boost);
 
-CV_EXPORTS_W void seamlessClone(InputArray src, InputArray dst, InputArray mask, Point p, OutputArray _blend, int flags);
+CV_EXPORTS_W void seamlessClone( InputArray src, InputArray dst, InputArray mask, Point p,
+                                 OutputArray _blend, int flags);
 
-CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, float red = 1.0, float green = 1.0, float blue = 1.0); 
+CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst, float red_mul = 1.0,
+                              float green_mul = 1.0, float blue_mul = 1.0);
 
-CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArray dst, float alpha = 0.2, float beta = 0.4);
+CV_EXPORTS_W void illuminationChange(InputArray src, InputArray mask, OutputArray dst,
+                                     float alpha = 0.2, float beta = 0.4);
 
-CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst);
+CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst,
+                                    double low_threshold, double high_threshold,
+                                    int kernel_size);
 
-CV_EXPORTS_W void edgepreservefilter(InputArray _src, OutputArray _dst, int flags = 1, float sigma_h = 60, float sigma_r = 0.4);
+CV_EXPORTS_W void edgePreservingFilter(InputArray src, OutputArray dst, int flags = 1,
+                                       float sigma_s = 60, float sigma_r = 0.4);
+
+CV_EXPORTS_W void detailEnhance(InputArray src, OutputArray dst, float sigma_s = 10,
+                                float sigma_r = 0.15);
+
+CV_EXPORTS_W void pencilSketch(InputArray src, OutputArray dst, OutputArray dst1,
+                               float sigma_s = 60, float sigma_r = 0.07, float shade_factor = 0.02);
+
+CV_EXPORTS_W void stylization(InputArray src, OutputArray dst, float sigma_s = 60,
+                              float sigma_r = 0.45);
+
+CV_EXPORTS_W void edgeEnhance(InputArray src, OutputArray dst, float sigma_s = 60,
+                              float sigma_r = 0.45);
 
 } // cv
 
diff --git a/modules/photo/src/contrast_preserve.cpp b/modules/photo/src/contrast_preserve.cpp
index 9a659691a8..14ed6ac30f 100644
--- a/modules/photo/src/contrast_preserve.cpp
+++ b/modules/photo/src/contrast_preserve.cpp
@@ -57,7 +57,7 @@ double norm(double);
 
 double norm(double E)
 {
-        return (sqrt(pow(E,2)));
+    return (sqrt(pow(E,2)));
 }
 
 void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost)
@@ -71,170 +71,168 @@ void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost)
 
     if(!I.data )
     {
-		cout <<  "Could not open or find the image" << endl ;
-		return;
-	}
-	if(I.channels() !=3)
-	{
-		cout << "Input Color Image" << endl;
-		return;
-	}
-
-	int maxIter = 15;
-	int iterCount = 0;
+        cout <<  "Could not open or find the image" << endl ;
+        return;
+    }
+    if(I.channels() !=3)
+    {
+        cout << "Input Color Image" << endl;
+        return;
+    }
+
+    int maxIter = 15;
+    int iterCount = 0;
     float tol = .0001;
     double E = 0;
     double pre_E = std::numeric_limits<double>::infinity();
 
-	Decolor obj;
+    Decolor obj;
 
-	Mat img;
+    Mat img;
 
     img = Mat(I.size(),CV_32FC3);
     I.convertTo(img,CV_32FC3,1.0/255.0);
 
     obj.init();
 
-	vector <double> Cg;
-	vector < vector <double> > polyGrad;
-	vector < vector <double> > bc;
-	vector < vector < int > > comb;
+    vector <double> Cg;
+    vector < vector <double> > polyGrad;
+    vector < vector <double> > bc;
+    vector < vector < int > > comb;
 
-	vector <double> alf;
+    vector <double> alf;
 
-	obj.grad_system(img,polyGrad,Cg,comb);
-	obj.weak_order(img,alf);
+    obj.grad_system(img,polyGrad,Cg,comb);
+    obj.weak_order(img,alf);
 
-	Mat Mt = Mat(polyGrad.size(),polyGrad[0].size(), CV_32FC1);
-	obj.wei_update_matrix(polyGrad,Cg,Mt);
+    Mat Mt = Mat(polyGrad.size(),polyGrad[0].size(), CV_32FC1);
+    obj.wei_update_matrix(polyGrad,Cg,Mt);
 
-	vector <double> wei;
-	obj.wei_inti(comb,wei);
+    vector <double> wei;
+    obj.wei_inti(comb,wei);
 
-	//////////////////////////////// main loop starting ////////////////////////////////////////
+    //////////////////////////////// main loop starting ////////////////////////////////////////
 
-	while(norm(E-pre_E) > tol)
-	{
-		iterCount +=1;
+    while(norm(E-pre_E) > tol)
+    {
+        iterCount +=1;
         pre_E = E;
 
-		vector <double> G_pos;
-		vector <double> G_neg;
-
-		vector <double> temp;
-		vector <double> temp1;
-
-		double val = 0.0;
-		for(unsigned int i=0;i< polyGrad[0].size();i++)
-		{
-			val = 0.0;
-			for(unsigned int j =0;j<polyGrad.size();j++)
-				val = val + (polyGrad[j][i] * wei[j]);
-			temp.push_back(val - Cg[i]);
-			temp1.push_back(val + Cg[i]);
-		}
-
-		double ans = 0.0;
-		double ans1 = 0.0;
-		for(unsigned int i =0;i<alf.size();i++)
-		{
-			ans = ((1 + alf[i])/2) * exp((-1.0 * 0.5 * pow(temp[i],2))/pow(sigma,2));
-			ans1 =((1 - alf[i])/2) * exp((-1.0 * 0.5 * pow(temp1[i],2))/pow(sigma,2));
-			G_pos.push_back(ans);
-			G_neg.push_back(ans1);
-		}
-
-		vector <double> EXPsum;
-		vector <double> EXPterm;
-
-		for(unsigned int i = 0;i<G_pos.size();i++)
-			EXPsum.push_back(G_pos[i]+G_neg[i]);
-
-
-		vector <double> temp2;
-
-		for(unsigned int i=0;i<EXPsum.size();i++)
-		{
-			if(EXPsum[i] == 0)
-				temp2.push_back(1.0);
-			else
-				temp2.push_back(0.0);
-		}
-
-		for(unsigned int i =0; i < G_pos.size();i++)
-			EXPterm.push_back((G_pos[i] - G_neg[i])/(EXPsum[i] + temp2[i]));
-
-		
-		double val1 = 0.0;
-		vector <double> wei1;
-
-		for(unsigned int i=0;i< polyGrad.size();i++)
-		{
-			val1 = 0.0;
-			for(unsigned int j =0;j<polyGrad[0].size();j++)
-			{
-				val1 = val1 + (Mt.at<float>(i,j) * EXPterm[j]);
-			}
-			wei1.push_back(val1);
-		}
-
-		for(unsigned int i =0;i<wei.size();i++)
-			wei[i] = wei1[i];
+        vector <double> G_pos;
+        vector <double> G_neg;
+
+        vector <double> temp;
+        vector <double> temp1;
+
+        double val = 0.0;
+        for(unsigned int i=0;i< polyGrad[0].size();i++)
+        {
+            val = 0.0;
+            for(unsigned int j =0;j<polyGrad.size();j++)
+                val = val + (polyGrad[j][i] * wei[j]);
+            temp.push_back(val - Cg[i]);
+            temp1.push_back(val + Cg[i]);
+        }
+
+        double ans = 0.0;
+        double ans1 = 0.0;
+        for(unsigned int i =0;i<alf.size();i++)
+        {
+            ans = ((1 + alf[i])/2) * exp((-1.0 * 0.5 * pow(temp[i],2))/pow(sigma,2));
+            ans1 =((1 - alf[i])/2) * exp((-1.0 * 0.5 * pow(temp1[i],2))/pow(sigma,2));
+            G_pos.push_back(ans);
+            G_neg.push_back(ans1);
+        }
+
+        vector <double> EXPsum;
+        vector <double> EXPterm;
+
+        for(unsigned int i = 0;i<G_pos.size();i++)
+            EXPsum.push_back(G_pos[i]+G_neg[i]);
+
+        vector <double> temp2;
+
+        for(unsigned int i=0;i<EXPsum.size();i++)
+        {
+            if(EXPsum[i] == 0)
+                temp2.push_back(1.0);
+            else
+                temp2.push_back(0.0);
+        }
+
+        for(unsigned int i =0; i < G_pos.size();i++)
+            EXPterm.push_back((G_pos[i] - G_neg[i])/(EXPsum[i] + temp2[i]));
+
+        double val1 = 0.0;
+        vector <double> wei1;
+
+        for(unsigned int i=0;i< polyGrad.size();i++)
+        {
+            val1 = 0.0;
+            for(unsigned int j =0;j<polyGrad[0].size();j++)
+            {
+                val1 = val1 + (Mt.at<float>(i,j) * EXPterm[j]);
+            }
+            wei1.push_back(val1);
+        }
+
+        for(unsigned int i =0;i<wei.size();i++)
+            wei[i] = wei1[i];
 
         E = obj.energyCalcu(Cg,polyGrad,wei);
 
         if(iterCount > maxIter)
             break;
 
-		G_pos.clear();
-		G_neg.clear();
-		temp.clear();
-		temp1.clear();
-		EXPsum.clear();
-		EXPterm.clear();
-		temp2.clear();
-		wei1.clear();
-	}
+        G_pos.clear();
+        G_neg.clear();
+        temp.clear();
+        temp1.clear();
+        EXPsum.clear();
+        EXPterm.clear();
+        temp2.clear();
+        wei1.clear();
+    }
 
-	Mat Gray = Mat::zeros(img.size(),CV_32FC1);
-	obj.grayImContruct(wei, img, Gray);
+    Mat Gray = Mat::zeros(img.size(),CV_32FC1);
+    obj.grayImContruct(wei, img, Gray);
 
-	Gray.convertTo(dst,CV_8UC1,255);
+    Gray.convertTo(dst,CV_8UC1,255);
 
     ///////////////////////////////////       Contrast Boosting   /////////////////////////////////
-	
-	Mat lab = Mat(img.size(),CV_8UC3);
-	Mat color = Mat(img.size(),CV_8UC3);
-	Mat l = Mat(img.size(),CV_8UC1);
-	Mat a = Mat(img.size(),CV_8UC1);
-	Mat b = Mat(img.size(),CV_8UC1);
-
-	cvtColor(I,lab,COLOR_BGR2Lab);
-
-	int h1 = img.size().height;
-	int w1 = img.size().width;
-
-	for(int i =0;i<h1;i++)
-		for(int j=0;j<w1;j++)
-		{
-			l.at<uchar>(i,j) = lab.at<uchar>(i,j*3+0);
-			a.at<uchar>(i,j) = lab.at<uchar>(i,j*3+1);
-			b.at<uchar>(i,j) = lab.at<uchar>(i,j*3+2);
-		}
-	
-	for(int i =0;i<h1;i++)
-		for(int j=0;j<w1;j++)
-		{
-			l.at<uchar>(i,j) = 255.0*Gray.at<float>(i,j);
-		}
-
-	for(int i =0;i<h1;i++)
-		for(int j=0;j<w1;j++)
-		{
-			lab.at<uchar>(i,j*3+0) = l.at<uchar>(i,j);
-			lab.at<uchar>(i,j*3+1) = a.at<uchar>(i,j);
-			lab.at<uchar>(i,j*3+2) = b.at<uchar>(i,j);
-		}
-
-	cvtColor(lab,color_boost,COLOR_Lab2BGR);
+
+    Mat lab = Mat(img.size(),CV_8UC3);
+    Mat color = Mat(img.size(),CV_8UC3);
+    Mat l = Mat(img.size(),CV_8UC1);
+    Mat a = Mat(img.size(),CV_8UC1);
+    Mat b = Mat(img.size(),CV_8UC1);
+
+    cvtColor(I,lab,COLOR_BGR2Lab);
+
+    int h1 = img.size().height;
+    int w1 = img.size().width;
+
+    for(int i =0;i<h1;i++)
+        for(int j=0;j<w1;j++)
+        {
+            l.at<uchar>(i,j) = lab.at<uchar>(i,j*3+0);
+            a.at<uchar>(i,j) = lab.at<uchar>(i,j*3+1);
+            b.at<uchar>(i,j) = lab.at<uchar>(i,j*3+2);
+        }
+
+    for(int i =0;i<h1;i++)
+        for(int j=0;j<w1;j++)
+        {
+            l.at<uchar>(i,j) = 255.0*Gray.at<float>(i,j);
+        }
+
+    for(int i =0;i<h1;i++)
+        for(int j=0;j<w1;j++)
+        {
+            lab.at<uchar>(i,j*3+0) = l.at<uchar>(i,j);
+            lab.at<uchar>(i,j*3+1) = a.at<uchar>(i,j);
+            lab.at<uchar>(i,j*3+2) = b.at<uchar>(i,j);
+        }
+
+    cvtColor(lab,color_boost,COLOR_Lab2BGR);
 }
diff --git a/modules/photo/src/contrast_preserve.hpp b/modules/photo/src/contrast_preserve.hpp
index 607b494832..c9d75036c2 100644
--- a/modules/photo/src/contrast_preserve.hpp
+++ b/modules/photo/src/contrast_preserve.hpp
@@ -39,7 +39,6 @@
 //
 //M*/
 
-
 #include "precomp.hpp"
 #include "opencv2/photo.hpp"
 #include "opencv2/imgproc.hpp"
@@ -69,7 +68,7 @@ class Decolor
         void add_to_vector_poly(vector < vector <double> > &polyGrad, vector <double> &curGrad);
         void weak_order(Mat img, vector <double> &alf);
         void grad_system(Mat img, vector < vector < double > > &polyGrad,
-                         vector < double > &Cg, vector < vector <int> >& comb);
+                vector < double > &Cg, vector < vector <int> >& comb);
         void wei_update_matrix(vector < vector <double> > &poly, vector <double> &Cg, Mat &X);
         void wei_inti(vector < vector <int> > &comb, vector <double> &wei);
         void grayImContruct(vector <double> &wei, Mat img, Mat &Gray);
@@ -87,7 +86,6 @@ float sigma = .02;
 double Decolor::energyCalcu(vector <double> &Cg, vector < vector <double> > &polyGrad, vector <double> &wei)
 {
     vector <double> P;
-
     vector <double> temp;
     vector <double> temp1;
 
@@ -112,8 +110,6 @@ double Decolor::energyCalcu(vector <double> &Cg, vector < vector <double> > &pol
 
 }
 
-
-
 void Decolor::init()
 {
     kernel = Mat(1,2, CV_32FC1);
@@ -123,7 +119,6 @@ void Decolor::init()
     kernel1.at<float>(0,0)=1.0;
     kernel1.at<float>(1,0)=-1.0;
     order = 2;
-
 }
 
 vector<double> Decolor::product(vector < vector<int> > &comb, vector <double> &initRGB)
@@ -183,7 +178,7 @@ void Decolor::gradvector(const Mat &img, vector <double> &grad)
     dest.release();
     dest1.release();
 }
-    
+
 void Decolor::colorGrad(Mat img, vector <double> &Cg)
 {
 
@@ -222,7 +217,6 @@ void Decolor::colorGrad(Mat img, vector <double> &Cg)
     ImL.clear();
     Ima.clear();
     Imb.clear();
-    
 }
 
 void Decolor::add_vector(vector < vector <int> > &comb, int r,int g,int b)
@@ -267,7 +261,7 @@ void Decolor::weak_order(Mat img, vector <double> &alf)
             green.at<float>(i,j) = img.at<float>(i,j*3+1);
             blue.at<float>(i,j) = img.at<float>(i,j*3+0);
         }
-    
+
     vector <double> Rg;
     vector <double> Gg;
     vector <double> Bg;
@@ -275,7 +269,7 @@ void Decolor::weak_order(Mat img, vector <double> &alf)
     vector <double> t1;
     vector <double> t2;
     vector <double> t3;
-    
+
     vector <double> tmp1;
     vector <double> tmp2;
     vector <double> tmp3;
@@ -333,7 +327,7 @@ void Decolor::weak_order(Mat img, vector <double> &alf)
 
     for(unsigned int i =0 ;i < Rg.size();i++)
         alf[i] -= tmp1[i] * tmp2[i] * tmp3[i];
-    
+
     double sum =0.0;
     for(unsigned int i=0;i<alf.size();i++)
         sum += abs(alf[i]);
@@ -359,12 +353,11 @@ void Decolor::weak_order(Mat img, vector <double> &alf)
 }
 
 void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad,
-                          vector < double > &Cg, vector < vector <int> >& comb)
+        vector < double > &Cg, vector < vector <int> >& comb)
 {
     int h = img.size().height;
     int w = img.size().width;
 
-
     double sizefactor;
     if((h + w) > 800)
     {
@@ -375,7 +368,7 @@ void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad,
     h = img.size().height;
     w = img.size().width;
     colorGrad(img,Cg);
-    
+
     Mat curIm = Mat(img.size(),CV_32FC1);
     Mat red = Mat(img.size(),CV_32FC1);
     Mat green = Mat(img.size(),CV_32FC1);
@@ -400,7 +393,7 @@ void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad,
                         for(int j=0;j<w;j++)
                             curIm.at<float>(i,j)=
                                 pow(red.at<float>(i,j),r)*pow(green.at<float>(i,j),g)*
-                                    pow(blue.at<float>(i,j),b);
+                                pow(blue.at<float>(i,j),b);
                     vector <double> curGrad;
                     gradvector(curIm,curGrad);
                     add_to_vector_poly(polyGrad,curGrad);
@@ -468,7 +461,6 @@ void Decolor::wei_inti(vector < vector <int> > &comb, vector <double> &wei)
 
 void Decolor::grayImContruct(vector <double> &wei, Mat img, Mat &Gray)
 {
-
     int h=img.size().height;
     int w=img.size().width;
 
@@ -485,7 +477,7 @@ void Decolor::grayImContruct(vector <double> &wei, Mat img, Mat &Gray)
         }
 
     int kk =0;
-    
+
     for(int r =0;r<=order;r++)
         for(int g=0;g<=order;g++)
             for(int b=0;b<=order;b++)
@@ -495,7 +487,7 @@ void Decolor::grayImContruct(vector <double> &wei, Mat img, Mat &Gray)
                         for(int j=0;j<w;j++)
                             Gray.at<float>(i,j)=Gray.at<float>(i,j) +
                                 wei[kk]*pow(red.at<float>(i,j),r)*pow(green.at<float>(i,j),g)*
-                                    pow(blue.at<float>(i,j),b);
+                                pow(blue.at<float>(i,j),b);
 
                     kk=kk+1;
                 }
@@ -508,7 +500,7 @@ void Decolor::grayImContruct(vector <double> &wei, Mat img, Mat &Gray)
         {
             if(Gray.at<float>(i,j) < minval)
                 minval = Gray.at<float>(i,j);
-            
+
             if(Gray.at<float>(i,j) > maxval)
                 maxval = Gray.at<float>(i,j);
         }
diff --git a/modules/photo/src/npr.cpp b/modules/photo/src/npr.cpp
index c2311c8122..54f5ce55ed 100644
--- a/modules/photo/src/npr.cpp
+++ b/modules/photo/src/npr.cpp
@@ -1,3 +1,44 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                           License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//
+//   * The name of the copyright holders may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
 #include "precomp.hpp"
 #include "opencv2/photo.hpp"
 #include "opencv2/highgui.hpp"
@@ -11,7 +52,7 @@
 using namespace std;
 using namespace cv;
 
-void cv::edgepreservefilter(InputArray _src, OutputArray _dst, int flags, float sigma_s, float sigma_r)
+void cv::edgePreservingFilter(InputArray _src, OutputArray _dst, int flags, float sigma_s, float sigma_r)
 {
 	Mat I = _src.getMat();
 	_dst.create(I.size(), CV_8UC3);
@@ -32,3 +73,196 @@ void cv::edgepreservefilter(InputArray _src, OutputArray _dst, int flags, float
 
 	convertScaleAbs(res, dst, 255,0);
 }
+
+void cv::detailEnhance(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r)
+{
+	Mat I = _src.getMat();
+	_dst.create(I.size(), CV_8UC3);
+	Mat dst = _dst.getMat();
+
+	int h = I.size().height;
+	int w = I.size().width;
+	int channel = I.channels();
+	float factor = 3.0;
+
+	Mat img = Mat(I.size(),CV_32FC3);
+	I.convertTo(img,CV_32FC3,1.0/255.0);
+	
+	Mat res = Mat(h,w,CV_32FC3);
+	dst.convertTo(res,CV_32FC3,1.0/255.0);
+
+	Mat result = Mat(img.size(),CV_32FC3);
+	Mat lab = Mat(img.size(),CV_32FC3);
+	Mat l_channel = Mat(img.size(),CV_32FC1);
+	Mat a_channel = Mat(img.size(),CV_32FC1);
+	Mat b_channel = Mat(img.size(),CV_32FC1);
+
+	cvtColor(img,lab,COLOR_BGR2Lab);
+
+	for(int i = 0; i < h; i++)
+		for(int j = 0; j < w; j++)
+		{
+			l_channel.at<float>(i,j) = lab.at<float>(i,j*channel+0);
+			a_channel.at<float>(i,j) = lab.at<float>(i,j*channel+1);
+			b_channel.at<float>(i,j) = lab.at<float>(i,j*channel+2);
+		}
+
+	Mat L = Mat(img.size(),CV_32FC1);
+
+	l_channel.convertTo(L,CV_32FC1,1.0/255.0);
+
+	Domain_Filter obj;
+
+	obj.filter(L, res, sigma_s, sigma_r, 1);
+
+	Mat detail = Mat(h,w,CV_32FC1);
+
+	for(int i = 0; i < h; i++)
+		for(int j = 0; j < w; j++)
+			detail.at<float>(i,j) = L.at<float>(i,j) - res.at<float>(i,j);
+
+	for(int i = 0; i < h; i++)
+		for(int j = 0; j < w; j++)
+			L.at<float>(i,j) = res.at<float>(i,j) + factor*detail.at<float>(i,j);
+
+	L.convertTo(l_channel,CV_32FC1,255);
+
+	for(int i = 0; i < h; i++)
+		for(int j = 0; j < w; j++)
+		{
+			lab.at<float>(i,j*channel+0) = l_channel.at<float>(i,j);
+			lab.at<float>(i,j*channel+1) = a_channel.at<float>(i,j);
+			lab.at<float>(i,j*channel+2) = b_channel.at<float>(i,j);
+		}
+
+	cvtColor(lab,result,COLOR_Lab2BGR);
+	result.convertTo(dst,CV_8UC3,255);
+}
+
+void cv::pencilSketch(InputArray _src, OutputArray _dst, OutputArray _dst1, float sigma_s, float sigma_r, float shade_factor)
+{
+	Mat I = _src.getMat();
+	_dst.create(I.size(), CV_8UC1);
+	Mat dst = _dst.getMat();
+
+	_dst1.create(I.size(), CV_8UC3);
+	Mat dst1 = _dst1.getMat();
+	
+	Mat img = Mat(I.size(),CV_32FC3);
+	I.convertTo(img,CV_32FC3,1.0/255.0);
+
+	Domain_Filter obj;
+
+	Mat sketch = Mat(I.size(),CV_32FC1);
+	Mat color_sketch = Mat(I.size(),CV_32FC3);
+
+	obj.pencil_sketch(img, sketch, color_sketch, sigma_s, sigma_r, shade_factor);
+
+	sketch.convertTo(dst,CV_8UC1,255);
+	color_sketch.convertTo(dst1,CV_8UC3,255);
+
+}
+
+void cv::stylization(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r)
+{
+	Mat I = _src.getMat();
+	_dst.create(I.size(), CV_8UC3);
+	Mat dst = _dst.getMat();
+
+	Mat img = Mat(I.size(),CV_32FC3);
+	I.convertTo(img,CV_32FC3,1.0/255.0);
+
+	int h = img.size().height;
+	int w = img.size().width;
+	int channel = img.channels();
+
+	Mat res = Mat(h,w,CV_32FC3);
+
+	Domain_Filter obj;
+	obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER);
+
+	vector <Mat> planes;
+	split(res, planes);
+
+	Mat magXR = Mat(h, w, CV_32FC1);
+	Mat magYR = Mat(h, w, CV_32FC1);
+
+	Mat magXG = Mat(h, w, CV_32FC1);
+	Mat magYG = Mat(h, w, CV_32FC1);
+
+	Mat magXB = Mat(h, w, CV_32FC1);
+	Mat magYB = Mat(h, w, CV_32FC1);
+
+	Sobel(planes[0], magXR, CV_32FC1, 1, 0, 3);
+	Sobel(planes[0], magYR, CV_32FC1, 0, 1, 3);
+
+	Sobel(planes[1], magXG, CV_32FC1, 1, 0, 3);
+	Sobel(planes[1], magYG, CV_32FC1, 0, 1, 3);
+
+	Sobel(planes[2], magXB, CV_32FC1, 1, 0, 3);
+	Sobel(planes[2], magYB, CV_32FC1, 0, 1, 3);
+
+	Mat magx = Mat(h,w,CV_32FC1);
+	Mat magy = Mat(h,w,CV_32FC1);
+
+	Mat mag1 = Mat(h,w,CV_32FC1);
+	Mat mag2 = Mat(h,w,CV_32FC1);
+	Mat mag3 = Mat(h,w,CV_32FC1);
+
+	magnitude(magXR,magYR,mag1);
+	magnitude(magXG,magYG,mag2);
+	magnitude(magXB,magYB,mag3);
+
+	Mat magnitude = Mat(h,w,CV_32FC1);
+
+	for(int i =0;i < h;i++)
+		for(int j=0;j<w;j++)
+		{
+			magnitude.at<float>(i,j) = mag1.at<float>(i,j) + mag2.at<float>(i,j) + mag3.at<float>(i,j);
+		}
+
+	for(int i =0;i < h;i++)
+		for(int j=0;j<w;j++)
+		{
+			magnitude.at<float>(i,j) = 1.0 -  magnitude.at<float>(i,j);
+		}
+
+	Mat stylized = Mat(h,w,CV_32FC3);
+
+	for(int i =0;i < h;i++)
+		for(int j=0;j<w;j++)
+			for(int c=0;c<channel;c++)
+			{
+				stylized.at<float>(i,j*channel + c) = res.at<float>(i,j*channel + c) * magnitude.at<float>(i,j);
+			}
+
+	stylized.convertTo(dst,CV_8UC3,255);
+}
+
+void cv::edgeEnhance(InputArray _src, OutputArray _dst, float sigma_s, float sigma_r)
+{
+	Mat I = _src.getMat();
+	_dst.create(I.size(), CV_8UC1);
+	Mat dst = _dst.getMat();
+
+	Mat img = Mat(I.size(),CV_32FC3);
+	I.convertTo(img,CV_32FC3,1.0/255.0);
+
+	Mat orig = img.clone();
+
+	int h = img.size().height;
+	int w = img.size().width;
+
+	Mat res = Mat(h,w,CV_32FC3);
+	Mat magnitude = Mat(h,w,CV_32FC1);
+
+	Mat mag8 = Mat(h,w,CV_32FC1);
+
+	Domain_Filter obj;
+
+	obj.filter(img, res, sigma_s, sigma_r, NORMCONV_FILTER);
+
+	obj.find_magnitude(res,magnitude);
+
+	magnitude.convertTo(dst,CV_8UC1,255);
+}
diff --git a/modules/photo/src/npr.hpp b/modules/photo/src/npr.hpp
index 856a4768b6..66638ccbd8 100644
--- a/modules/photo/src/npr.hpp
+++ b/modules/photo/src/npr.hpp
@@ -1,3 +1,44 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                           License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//
+//   * The name of the copyright holders may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
 #include "precomp.hpp"
 #include "opencv2/photo.hpp"
 #include "opencv2/imgproc.hpp"
@@ -13,478 +54,616 @@ double myinf = std::numeric_limits<double>::infinity();
 
 class Domain_Filter
 {
-	public:
-		Mat ct_H, ct_V, horiz, vert, O, O_t, lower_idx, upper_idx;
-		void init(const Mat &img, int flags, float sigma_s, float sigma_r);
-		void getGradientx( const Mat &img, Mat &gx);
-		void getGradienty( const Mat &img, Mat &gy);
-		void diffx(const Mat &img, Mat &temp);
-		void diffy(const Mat &img, Mat &temp);
-		void compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius);
-		void compute_Rfilter(Mat &O, Mat &horiz, float sigma_h);
-		void compute_NCfilter(Mat &O, Mat &horiz, Mat &psketch, float radius);
-		void filter(const Mat &img, Mat &res, float sigma_s, float sigma_r, int flags);
+    public:
+        Mat ct_H, ct_V, horiz, vert, O, O_t, lower_idx, upper_idx;
+        void init(const Mat &img, int flags, float sigma_s, float sigma_r);
+        void getGradientx( const Mat &img, Mat &gx);
+        void getGradienty( const Mat &img, Mat &gy);
+        void diffx(const Mat &img, Mat &temp);
+        void diffy(const Mat &img, Mat &temp);
+        void find_magnitude(Mat &img, Mat &mag);
+        void compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius);
+        void compute_Rfilter(Mat &O, Mat &horiz, float sigma_h);
+        void compute_NCfilter(Mat &O, Mat &horiz, Mat &psketch, float radius);
+        void filter(const Mat &img, Mat &res, float sigma_s, float sigma_r, int flags);
+        void pencil_sketch(const Mat &img, Mat &sketch, Mat &color_res, float sigma_s, float sigma_r, float shade_factor);
+        void Depth_of_field(const Mat &img, Mat &img1, float sigma_s, float sigma_r);
 };
 
 void Domain_Filter::diffx(const Mat &img, Mat &temp)
 {
-	int channel = img.channels();
-
-	for(int i = 0; i < img.size().height; i++)
-		for(int j = 0; j < img.size().width-1; j++)
-		{
-			for(int c =0; c < channel; c++)
-			{
-				temp.at<float>(i,j*channel+c) = 
-					img.at<float>(i,(j+1)*channel+c) - img.at<float>(i,j*channel+c);
-			}
-		}
+    int channel = img.channels();
+
+    for(int i = 0; i < img.size().height; i++)
+        for(int j = 0; j < img.size().width-1; j++)
+        {
+            for(int c =0; c < channel; c++)
+            {
+                temp.at<float>(i,j*channel+c) = 
+                    img.at<float>(i,(j+1)*channel+c) - img.at<float>(i,j*channel+c);
+            }
+        }
 }
 
 void Domain_Filter::diffy(const Mat &img, Mat &temp)
 {
-	int channel = img.channels();
-
-	for(int i = 0; i < img.size().height-1; i++)
-		for(int j = 0; j < img.size().width; j++)
-		{
-			for(int c =0; c < channel; c++)
-			{
-				temp.at<float>(i,j*channel+c) = 
-					img.at<float>((i+1),j*channel+c) - img.at<float>(i,j*channel+c);
-			}
-		}
+    int channel = img.channels();
+
+    for(int i = 0; i < img.size().height-1; i++)
+        for(int j = 0; j < img.size().width; j++)
+        {
+            for(int c =0; c < channel; c++)
+            {
+                temp.at<float>(i,j*channel+c) = 
+                    img.at<float>((i+1),j*channel+c) - img.at<float>(i,j*channel+c);
+            }
+        }
 }
 
 void Domain_Filter::getGradientx( const Mat &img, Mat &gx)
 {
-	int w = img.cols;
-	int h = img.rows;
-	int channel = img.channels();
-
-	for(int i=0;i<h;i++)
-		for(int j=0;j<w;j++)
-			for(int c=0;c<channel;++c)
-			{
-				gx.at<float>(i,j*channel+c) =
-					img.at<float>(i,(j+1)*channel+c) - img.at<float>(i,j*channel+c);
-			}
+    int w = img.cols;
+    int h = img.rows;
+    int channel = img.channels();
+
+    for(int i=0;i<h;i++)
+        for(int j=0;j<w;j++)
+            for(int c=0;c<channel;++c)
+            {
+                gx.at<float>(i,j*channel+c) =
+                    img.at<float>(i,(j+1)*channel+c) - img.at<float>(i,j*channel+c);
+            }
 }
+
 void Domain_Filter::getGradienty( const Mat &img, Mat &gy)
 {
-	int w = img.cols;
-	int h = img.rows;
-	int channel = img.channels();
-
-	for(int i=0;i<h;i++)
-		for(int j=0;j<w;j++)
-			for(int c=0;c<channel;++c)
-			{
-				gy.at<float>(i,j*channel+c) =
-					img.at<float>(i+1,j*channel+c) - img.at<float>(i,j*channel+c);
-
-			}
+    int w = img.cols;
+    int h = img.rows;
+    int channel = img.channels();
+
+    for(int i=0;i<h;i++)
+        for(int j=0;j<w;j++)
+            for(int c=0;c<channel;++c)
+            {
+                gy.at<float>(i,j*channel+c) =
+                    img.at<float>(i+1,j*channel+c) - img.at<float>(i,j*channel+c);
+
+            }
 }
 
-void Domain_Filter::compute_Rfilter(Mat &output, Mat &hz, float sigma_h)
+void Domain_Filter::find_magnitude(Mat &img, Mat &mag)
 {
 
-	float a;
+    int h = img.rows;
+    int w = img.cols;
+
+    vector <Mat> planes;
+    split(img, planes);
+
+    Mat magXR = Mat(h, w, CV_32FC1);
+    Mat magYR = Mat(h, w, CV_32FC1);
+
+    Mat magXG = Mat(h, w, CV_32FC1);
+    Mat magYG = Mat(h, w, CV_32FC1);
+
+    Mat magXB = Mat(h, w, CV_32FC1);
+    Mat magYB = Mat(h, w, CV_32FC1);
+
+    getGradientx(planes[0], magXR);
+    getGradienty(planes[0], magYR);
+
+    getGradientx(planes[1], magXG);
+    getGradienty(planes[1], magYG);
+
+    getGradientx(planes[2], magXR);
+    getGradienty(planes[2], magYR);
+
+    Mat magx = Mat(h,w,CV_32FC1);
+    Mat magy = Mat(h,w,CV_32FC1);
+
+    Mat mag1 = Mat(h,w,CV_32FC1);
+    Mat mag2 = Mat(h,w,CV_32FC1);
+    Mat mag3 = Mat(h,w,CV_32FC1);
+
+    magnitude(magXR,magYR,mag1);
+    magnitude(magXG,magYG,mag2);
+    magnitude(magXB,magYB,mag3);
 
-	int h = output.rows;
-	int w = output.cols;
-	int channel = output.channels();
+    for(int i =0;i < h;i++)
+        for(int j=0;j<w;j++)
+        {
+            mag.at<float>(i,j) = mag1.at<float>(i,j) + mag2.at<float>(i,j) + mag3.at<float>(i,j);
+        }
 
-	a = exp(-sqrt(2) / sigma_h);
 
-	Mat temp = Mat(h,w,CV_32FC3);
+    for(int i =0;i < h;i++)
+        for(int j=0;j<w;j++)
+        {
+            mag.at<float>(i,j) = 1.0 -  mag.at<float>(i,j);
+        }
 
-	for(int i =0; i < h;i++)
-		for(int j=0;j<w;j++)
-			for(int c=0;c<channel;c++)
-				temp.at<float>(i,j*channel+c) = output.at<float>(i,j*channel+c);
+}
+
+void Domain_Filter::compute_Rfilter(Mat &output, Mat &hz, float sigma_h)
+{
+
+    float a;
+
+    int h = output.rows;
+    int w = output.cols;
+    int channel = output.channels();
+
+    a = exp(-sqrt(2) / sigma_h);
 
+    Mat temp = Mat(h,w,CV_32FC3);
 
-	Mat V = Mat(h,w,CV_32FC1);
+    for(int i =0; i < h;i++)
+        for(int j=0;j<w;j++)
+            for(int c=0;c<channel;c++)
+                temp.at<float>(i,j*channel+c) = output.at<float>(i,j*channel+c);
 
-	for(int i=0;i<h;i++)
-		for(int j=0;j<w;j++)
-			V.at<float>(i,j) = pow(a,hz.at<float>(i,j));
 
+    Mat V = Mat(h,w,CV_32FC1);
 
-	for(int i=0; i<h; i++)
-	{
-		for(int j =1; j < w; j++)
-		{
-			for(int c = 0; c<channel; c++)
-			{
-				temp.at<float>(i,j*channel+c) = temp.at<float>(i,j*channel+c) + 
-					(temp.at<float>(i,(j-1)*channel+c) - temp.at<float>(i,j*channel+c)) * V.at<float>(i,j);
-			}
-		}
-	}
-				
-	for(int i=0; i<h; i++)
-	{
-		for(int j =w-2; j >= 0; j--)
-		{
-			for(int c = 0; c<channel; c++)
-			{
-				temp.at<float>(i,j*channel+c) = temp.at<float>(i,j*channel+c) +
-					(temp.at<float>(i,(j+1)*channel+c) - temp.at<float>(i,j*channel+c))*V.at<float>(i,j+1);
-			}
-		}
-	}
+    for(int i=0;i<h;i++)
+        for(int j=0;j<w;j++)
+            V.at<float>(i,j) = pow(a,hz.at<float>(i,j));
 
 
-	for(int i =0; i < h;i++)
-		for(int j=0;j<w;j++)
-			for(int c=0;c<channel;c++)
-				output.at<float>(i,j*channel+c) = temp.at<float>(i,j*channel+c);
+    for(int i=0; i<h; i++)
+    {
+        for(int j =1; j < w; j++)
+        {
+            for(int c = 0; c<channel; c++)
+            {
+                temp.at<float>(i,j*channel+c) = temp.at<float>(i,j*channel+c) + 
+                    (temp.at<float>(i,(j-1)*channel+c) - temp.at<float>(i,j*channel+c)) * V.at<float>(i,j);
+            }
+        }
+    }
 
-	temp.release();
-	V.release();
+    for(int i=0; i<h; i++)
+    {
+        for(int j =w-2; j >= 0; j--)
+        {
+            for(int c = 0; c<channel; c++)
+            {
+                temp.at<float>(i,j*channel+c) = temp.at<float>(i,j*channel+c) +
+                    (temp.at<float>(i,(j+1)*channel+c) - temp.at<float>(i,j*channel+c))*V.at<float>(i,j+1);
+            }
+        }
+    }
 
 
+    for(int i =0; i < h;i++)
+        for(int j=0;j<w;j++)
+            for(int c=0;c<channel;c++)
+                output.at<float>(i,j*channel+c) = temp.at<float>(i,j*channel+c);
+
+    temp.release();
+    V.release();
 }
 
 void Domain_Filter::compute_boxfilter(Mat &output, Mat &hz, Mat &psketch, float radius)
 {
-	int h = output.rows;
-	int w = output.cols;
-	Mat lower_pos = Mat(h,w,CV_32FC1);
-	Mat upper_pos = Mat(h,w,CV_32FC1);
-
-	for(int i=0;i<h;i++)
-		for(int j=0;j<w;j++)
-		{
-			lower_pos.at<float>(i,j) = hz.at<float>(i,j) - radius;
-			upper_pos.at<float>(i,j) = hz.at<float>(i,j) + radius;
-		}
-
-	lower_idx = Mat::zeros(h,w,CV_32FC1);
-	upper_idx = Mat::zeros(h,w,CV_32FC1);
-
-	Mat domain_row = Mat::zeros(1,w+1,CV_32FC1);
-
-	for(int i=0;i<h;i++)
-	{
-		for(int j=0;j<w;j++)
-			domain_row.at<float>(0,j) = hz.at<float>(i,j);
-		domain_row.at<float>(0,w) = myinf;
-
-		Mat lower_pos_row = Mat::zeros(1,w,CV_32FC1);
-		Mat upper_pos_row = Mat::zeros(1,w,CV_32FC1);
-
-		for(int j=0;j<w;j++)
-		{
-			lower_pos_row.at<float>(0,j) = lower_pos.at<float>(i,j);
-			upper_pos_row.at<float>(0,j) = upper_pos.at<float>(i,j);
-		}
-
-		Mat temp_lower_idx = Mat::zeros(1,w,CV_32FC1);
-		Mat temp_upper_idx = Mat::zeros(1,w,CV_32FC1);
-
-		for(int j=0;j<w;j++)
-		{
-			if(domain_row.at<float>(0,j) > lower_pos_row.at<float>(0,0))
-			{
-				temp_lower_idx.at<float>(0,0) = j;
-				break;
-			}
-		}
-		for(int j=0;j<w;j++)
-		{
-			if(domain_row.at<float>(0,j) > upper_pos_row.at<float>(0,0))
-			{
-				temp_upper_idx.at<float>(0,0) = j;
-				break;
-			}
-		}
-
-		int temp = 0;
-		for(int j=1;j<w;j++)
-		{
-			int count=0;
-			for(int k=temp_lower_idx.at<float>(0,j-1);k<w+1;k++)
-			{
-				if(domain_row.at<float>(0,k) > lower_pos_row.at<float>(0,j))
-				{
-					temp = count;
-					break;
-				}
-				count++;
-			}
-
-			temp_lower_idx.at<float>(0,j) = temp_lower_idx.at<float>(0,j-1) + temp;
-
-			count = 0;
-			for(int k=temp_upper_idx.at<float>(0,j-1);k<w+1;k++)
-			{
-
-
-				if(domain_row.at<float>(0,k) > upper_pos_row.at<float>(0,j))
-				{
-					temp = count;
-					break;
-				}
-				count++;
-			}
-
-			temp_upper_idx.at<float>(0,j) = temp_upper_idx.at<float>(0,j-1) + temp;
-		}
-
-		for(int j=0;j<w;j++)
-		{
-			lower_idx.at<float>(i,j) = temp_lower_idx.at<float>(0,j) + 1;
-			upper_idx.at<float>(i,j) = temp_upper_idx.at<float>(0,j) + 1;
-		}
-
-
-		lower_pos_row.release();
-		upper_pos_row.release();
-		temp_lower_idx.release();
-		temp_upper_idx.release();
-	}
-	for(int i=0;i<h;i++)
-		for(int j=0;j<w;j++)
-			psketch.at<float>(i,j) = upper_idx.at<float>(i,j) - lower_idx.at<float>(i,j);
+    int h = output.rows;
+    int w = output.cols;
+    Mat lower_pos = Mat(h,w,CV_32FC1);
+    Mat upper_pos = Mat(h,w,CV_32FC1);
+
+    for(int i=0;i<h;i++)
+        for(int j=0;j<w;j++)
+        {
+            lower_pos.at<float>(i,j) = hz.at<float>(i,j) - radius;
+            upper_pos.at<float>(i,j) = hz.at<float>(i,j) + radius;
+        }
+
+    lower_idx = Mat::zeros(h,w,CV_32FC1);
+    upper_idx = Mat::zeros(h,w,CV_32FC1);
+
+    Mat domain_row = Mat::zeros(1,w+1,CV_32FC1);
+
+    for(int i=0;i<h;i++)
+    {
+        for(int j=0;j<w;j++)
+            domain_row.at<float>(0,j) = hz.at<float>(i,j);
+        domain_row.at<float>(0,w) = myinf;
+
+        Mat lower_pos_row = Mat::zeros(1,w,CV_32FC1);
+        Mat upper_pos_row = Mat::zeros(1,w,CV_32FC1);
+
+        for(int j=0;j<w;j++)
+        {
+            lower_pos_row.at<float>(0,j) = lower_pos.at<float>(i,j);
+            upper_pos_row.at<float>(0,j) = upper_pos.at<float>(i,j);
+        }
+
+        Mat temp_lower_idx = Mat::zeros(1,w,CV_32FC1);
+        Mat temp_upper_idx = Mat::zeros(1,w,CV_32FC1);
+
+        for(int j=0;j<w;j++)
+        {
+            if(domain_row.at<float>(0,j) > lower_pos_row.at<float>(0,0))
+            {
+                temp_lower_idx.at<float>(0,0) = j;
+                break;
+            }
+        }
+        for(int j=0;j<w;j++)
+        {
+            if(domain_row.at<float>(0,j) > upper_pos_row.at<float>(0,0))
+            {
+                temp_upper_idx.at<float>(0,0) = j;
+                break;
+            }
+        }
+
+        int temp = 0;
+        for(int j=1;j<w;j++)
+        {
+            int count=0;
+            for(int k=temp_lower_idx.at<float>(0,j-1);k<w+1;k++)
+            {
+                if(domain_row.at<float>(0,k) > lower_pos_row.at<float>(0,j))
+                {
+                    temp = count;
+                    break;
+                }
+                count++;
+            }
+
+            temp_lower_idx.at<float>(0,j) = temp_lower_idx.at<float>(0,j-1) + temp;
+
+            count = 0;
+            for(int k=temp_upper_idx.at<float>(0,j-1);k<w+1;k++)
+            {
+
+
+                if(domain_row.at<float>(0,k) > upper_pos_row.at<float>(0,j))
+                {
+                    temp = count;
+                    break;
+                }
+                count++;
+            }
+
+            temp_upper_idx.at<float>(0,j) = temp_upper_idx.at<float>(0,j-1) + temp;
+        }
+
+        for(int j=0;j<w;j++)
+        {
+            lower_idx.at<float>(i,j) = temp_lower_idx.at<float>(0,j) + 1;
+            upper_idx.at<float>(i,j) = temp_upper_idx.at<float>(0,j) + 1;
+        }
+
+        lower_pos_row.release();
+        upper_pos_row.release();
+        temp_lower_idx.release();
+        temp_upper_idx.release();
+    }
+    for(int i=0;i<h;i++)
+        for(int j=0;j<w;j++)
+            psketch.at<float>(i,j) = upper_idx.at<float>(i,j) - lower_idx.at<float>(i,j);
 
 }
 void Domain_Filter::compute_NCfilter(Mat &output, Mat &hz, Mat &psketch, float radius)
 {
 
-	int h = output.rows;
-	int w = output.cols;
-	int channel = output.channels();
-
-	compute_boxfilter(output,hz,psketch,radius);
-
-	Mat box_filter = Mat::zeros(h,w+1,CV_32FC3);
-
-	for(int i = 0; i < h; i++)
-	{
-		box_filter.at<float>(i,1*channel+0) = output.at<float>(i,0*channel+0);
-		box_filter.at<float>(i,1*channel+1) = output.at<float>(i,0*channel+1);
-		box_filter.at<float>(i,1*channel+2) = output.at<float>(i,0*channel+2);
-		for(int j = 2; j < w+1; j++)
-		{
-			for(int c=0;c<channel;c++)
-				box_filter.at<float>(i,j*channel+c) = output.at<float>(i,(j-1)*channel+c) + box_filter.at<float>(i,(j-1)*channel+c);
-		}
-	}
-
-	Mat indices = Mat::zeros(h,w,CV_32FC1);
-	Mat final =   Mat::zeros(h,w,CV_32FC3);
-
-	for(int i=0;i<h;i++)
-		for(int j=0;j<w;j++)
-			indices.at<float>(i,j) = i+1;
-
-	Mat a = Mat::zeros(h,w,CV_32FC1);
-	Mat b = Mat::zeros(h,w,CV_32FC1);
-
-	for(int c=0;c<channel;c++)
-	{
-		Mat flag = Mat::ones(h,w,CV_32FC1);
-		for(int i=0;i<h;i++)
-			for(int j=0;j<w;j++)
-				flag.at<float>(i,j) = (c+1)*flag.at<float>(i,j);
-
-		for(int i=0;i<h;i++)
-			for(int j=0;j<w;j++)
-			{
-				a.at<float>(i,j) = (flag.at<float>(i,j) - 1) * h * (w+1) + (lower_idx.at<float>(i,j) - 1) * h + indices.at<float>(i,j);
-				b.at<float>(i,j) = (flag.at<float>(i,j) - 1) * h * (w+1) + (upper_idx.at<float>(i,j) - 1) * h + indices.at<float>(i,j);
-
-			}
-
-		int p,q,r,rem;
-		int p1,q1,r1,rem1;
-
-		for(int i=0;i<h;i++)
-		{
-			for(int j=0;j<w;j++)
-			{
-
-				r = b.at<float>(i,j)/(h*(w+1));
-				rem = b.at<float>(i,j) - r*h*(w+1);
-				q = rem/h;
-				p = rem - q*h;
-				if(q==0)
-				{
-					p=h;
-					q=w;
-					r=r-1;
-				}
-				if(p==0)
-				{
-					p=h;
-					q=q-1;
-				}
-						
-
-				r1 = a.at<float>(i,j)/(h*(w+1));
-				rem1 = a.at<float>(i,j) - r1*h*(w+1);
-				q1 = rem1/h;
-				p1 = rem1 - q1*h;
-				if(p1==0)
-				{
-					p1=h;
-					q1=q1-1;
-				}
-
-
-				final.at<float>(i,j*channel+2-c) = (box_filter.at<float>(p-1,q*channel+(2-r)) - box_filter.at<float>(p1-1,q1*channel+(2-r1)))
-					/(upper_idx.at<float>(i,j) - lower_idx.at<float>(i,j));
-			}
-		}
-	}
-
-	for(int i=0;i<h;i++)
-		for(int j=0;j<w;j++)
-			for(int c=0;c<channel;c++)
-				output.at<float>(i,j*channel+c) = final.at<float>(i,j*channel+c);
-
+    int h = output.rows;
+    int w = output.cols;
+    int channel = output.channels();
+
+    compute_boxfilter(output,hz,psketch,radius);
+
+    Mat box_filter = Mat::zeros(h,w+1,CV_32FC3);
+
+    for(int i = 0; i < h; i++)
+    {
+        box_filter.at<float>(i,1*channel+0) = output.at<float>(i,0*channel+0);
+        box_filter.at<float>(i,1*channel+1) = output.at<float>(i,0*channel+1);
+        box_filter.at<float>(i,1*channel+2) = output.at<float>(i,0*channel+2);
+        for(int j = 2; j < w+1; j++)
+        {
+            for(int c=0;c<channel;c++)
+                box_filter.at<float>(i,j*channel+c) = output.at<float>(i,(j-1)*channel+c) + box_filter.at<float>(i,(j-1)*channel+c);
+        }
+    }
+
+    Mat indices = Mat::zeros(h,w,CV_32FC1);
+    Mat final =   Mat::zeros(h,w,CV_32FC3);
+
+    for(int i=0;i<h;i++)
+        for(int j=0;j<w;j++)
+            indices.at<float>(i,j) = i+1;
+
+    Mat a = Mat::zeros(h,w,CV_32FC1);
+    Mat b = Mat::zeros(h,w,CV_32FC1);
+
+    for(int c=0;c<channel;c++)
+    {
+        Mat flag = Mat::ones(h,w,CV_32FC1);
+        for(int i=0;i<h;i++)
+            for(int j=0;j<w;j++)
+                flag.at<float>(i,j) = (c+1)*flag.at<float>(i,j);
+
+        for(int i=0;i<h;i++)
+            for(int j=0;j<w;j++)
+            {
+                a.at<float>(i,j) = (flag.at<float>(i,j) - 1) * h * (w+1) + (lower_idx.at<float>(i,j) - 1) * h + indices.at<float>(i,j);
+                b.at<float>(i,j) = (flag.at<float>(i,j) - 1) * h * (w+1) + (upper_idx.at<float>(i,j) - 1) * h + indices.at<float>(i,j);
+
+            }
+
+        int p,q,r,rem;
+        int p1,q1,r1,rem1;
+
+        for(int i=0;i<h;i++)
+        {
+            for(int j=0;j<w;j++)
+            {
+
+                r = b.at<float>(i,j)/(h*(w+1));
+                rem = b.at<float>(i,j) - r*h*(w+1);
+                q = rem/h;
+                p = rem - q*h;
+                if(q==0)
+                {
+                    p=h;
+                    q=w;
+                    r=r-1;
+                }
+                if(p==0)
+                {
+                    p=h;
+                    q=q-1;
+                }
+
+
+                r1 = a.at<float>(i,j)/(h*(w+1));
+                rem1 = a.at<float>(i,j) - r1*h*(w+1);
+                q1 = rem1/h;
+                p1 = rem1 - q1*h;
+                if(p1==0)
+                {
+                    p1=h;
+                    q1=q1-1;
+                }
+
+
+                final.at<float>(i,j*channel+2-c) = (box_filter.at<float>(p-1,q*channel+(2-r)) - box_filter.at<float>(p1-1,q1*channel+(2-r1)))
+                    /(upper_idx.at<float>(i,j) - lower_idx.at<float>(i,j));
+            }
+        }
+    }
+
+    for(int i=0;i<h;i++)
+        for(int j=0;j<w;j++)
+            for(int c=0;c<channel;c++)
+                output.at<float>(i,j*channel+c) = final.at<float>(i,j*channel+c);
 
 }
 void Domain_Filter::init(const Mat &img, int flags, float sigma_s, float sigma_r)
 {
-	int h = img.size().height;
-	int w = img.size().width;
-	int channel = img.channels();
+    int h = img.size().height;
+    int w = img.size().width;
+    int channel = img.channels();
 
-	////////////////////////////////////     horizontal and vertical partial derivatives /////////////////////////////////
+    ////////////////////////////////////     horizontal and vertical partial derivatives /////////////////////////////////
 
-	Mat derivx = Mat::zeros(h,w-1,CV_32FC3);
-	Mat derivy = Mat::zeros(h-1,w,CV_32FC3);
+    Mat derivx = Mat::zeros(h,w-1,CV_32FC3);
+    Mat derivy = Mat::zeros(h-1,w,CV_32FC3);
 
-	diffx(img,derivx);
-	diffy(img,derivy);
+    diffx(img,derivx);
+    diffy(img,derivy);
 
-	Mat distx = Mat::zeros(h,w,CV_32FC1);
-	Mat disty = Mat::zeros(h,w,CV_32FC1);
+    Mat distx = Mat::zeros(h,w,CV_32FC1);
+    Mat disty = Mat::zeros(h,w,CV_32FC1);
 
-	//////////////////////// Compute the l1-norm distance of neighbor pixels ////////////////////////////////////////////////
+    //////////////////////// Compute the l1-norm distance of neighbor pixels ////////////////////////////////////////////////
 
-	for(int i = 0; i < h; i++)
-		for(int j = 0,k=1; j < w-1; j++,k++)
-			for(int c = 0; c < channel; c++)
-			{
-				distx.at<float>(i,k) = 
-					distx.at<float>(i,k) + abs(derivx.at<float>(i,j*channel+c));
-			}
+    for(int i = 0; i < h; i++)
+        for(int j = 0,k=1; j < w-1; j++,k++)
+            for(int c = 0; c < channel; c++)
+            {
+                distx.at<float>(i,k) = 
+                    distx.at<float>(i,k) + abs(derivx.at<float>(i,j*channel+c));
+            }
 
-	for(int i = 0,k=1; i < h-1; i++,k++)
-		for(int j = 0; j < w; j++)
-			for(int c = 0; c < channel; c++)
-			{
-				disty.at<float>(k,j) = 
-					disty.at<float>(k,j) + abs(derivy.at<float>(i,j*channel+c));
-			}
+    for(int i = 0,k=1; i < h-1; i++,k++)
+        for(int j = 0; j < w; j++)
+            for(int c = 0; c < channel; c++)
+            {
+                disty.at<float>(k,j) = 
+                    disty.at<float>(k,j) + abs(derivy.at<float>(i,j*channel+c));
+            }
 
-	////////////////////// Compute the derivatives of the horizontal and vertical domain transforms. /////////////////////////////
+    ////////////////////// Compute the derivatives of the horizontal and vertical domain transforms. /////////////////////////////
 
-	horiz = Mat(h,w,CV_32FC1);
-	vert = Mat(h,w,CV_32FC1);
+    horiz = Mat(h,w,CV_32FC1);
+    vert = Mat(h,w,CV_32FC1);
 
-	Mat final = Mat(h,w,CV_32FC3);
+    Mat final = Mat(h,w,CV_32FC3);
 
-	for(int i = 0; i < h; i++)
-		for(int j = 0; j < w; j++)
-		{
-			horiz.at<float>(i,j) = (float) 1.0 + (sigma_s/sigma_r) * distx.at<float>(i,j);
-			vert.at<float>(i,j) = (float) 1.0 + (sigma_s/sigma_r) * disty.at<float>(i,j);
-		}
+    for(int i = 0; i < h; i++)
+        for(int j = 0; j < w; j++)
+        {
+            horiz.at<float>(i,j) = (float) 1.0 + (sigma_s/sigma_r) * distx.at<float>(i,j);
+            vert.at<float>(i,j) = (float) 1.0 + (sigma_s/sigma_r) * disty.at<float>(i,j);
+        }
 
 
-	O = Mat(h,w,CV_32FC3);
+    O = Mat(h,w,CV_32FC3);
 
-	for(int  i =0;i<h;i++)
-		for(int  j =0;j<w;j++)
-			for(int c=0;c<channel;c++)
-				O.at<float>(i,j*channel+c) =  img.at<float>(i,j*channel+c);
+    for(int  i =0;i<h;i++)
+        for(int  j =0;j<w;j++)
+            for(int c=0;c<channel;c++)
+                O.at<float>(i,j*channel+c) =  img.at<float>(i,j*channel+c);
 
-	O_t = Mat(w,h,CV_32FC3);
+    O_t = Mat(w,h,CV_32FC3);
 
-	if(flags == 2)
-	{
+    if(flags == 2)
+    {
 
-		ct_H = Mat(h,w,CV_32FC1);
-		ct_V = Mat(h,w,CV_32FC1);
+        ct_H = Mat(h,w,CV_32FC1);
+        ct_V = Mat(h,w,CV_32FC1);
 
-		for(int i = 0; i < h; i++)
-		{
-			ct_H.at<float>(i,0) = horiz.at<float>(i,0);
-			for(int j = 1; j < w; j++)
-			{
-				ct_H.at<float>(i,j) = horiz.at<float>(i,j) + ct_H.at<float>(i,j-1);
-			}
-		}
+        for(int i = 0; i < h; i++)
+        {
+            ct_H.at<float>(i,0) = horiz.at<float>(i,0);
+            for(int j = 1; j < w; j++)
+            {
+                ct_H.at<float>(i,j) = horiz.at<float>(i,j) + ct_H.at<float>(i,j-1);
+            }
+        }
 
-		for(int j = 0; j < w; j++)
-		{
-			ct_V.at<float>(0,j) = vert.at<float>(0,j);
-			for(int i = 1; i < h; i++)
-			{
-				ct_V.at<float>(i,j) = vert.at<float>(i,j) + ct_V.at<float>(i-1,j);
-			}
-		}
-	}
+        for(int j = 0; j < w; j++)
+        {
+            ct_V.at<float>(0,j) = vert.at<float>(0,j);
+            for(int i = 1; i < h; i++)
+            {
+                ct_V.at<float>(i,j) = vert.at<float>(i,j) + ct_V.at<float>(i-1,j);
+            }
+        }
+    }
 
 }
+
 void Domain_Filter::filter(const Mat &img, Mat &res, float sigma_s = 60, float sigma_r = 0.4, int flags = 1)
 {
-	int no_of_iter = 3;
-	int h = img.size().height;
-	int w = img.size().width;
-	float sigma_h = sigma_s;
+    int no_of_iter = 3;
+    int h = img.size().height;
+    int w = img.size().width;
+    float sigma_h = sigma_s;
+
+    init(img,flags,sigma_s,sigma_r);
+
+    if(flags == 1)
+    {
+        Mat vert_t = vert.t();  
+
+        for(int i=0;i<no_of_iter;i++)
+        {
+            sigma_h = sigma_s * sqrt(3) * pow(2.0,(no_of_iter - (i+1))) / sqrt(pow(4.0,no_of_iter) -1);
+
+            compute_Rfilter(O, horiz, sigma_h);
+
+            O_t = O.t();
+
+            compute_Rfilter(O_t, vert_t, sigma_h);
+
+            O = O_t.t();
+
+        }
+    }
+    else if(flags == 2)
+    {
+
+        Mat vert_t = ct_V.t();
+        Mat temp = Mat(h,w,CV_32FC1);
+        Mat temp1 = Mat(w,h,CV_32FC1);
+
+        float radius;
+
+        for(int i=0;i<no_of_iter;i++)
+        {
+            sigma_h = sigma_s * sqrt(3) * pow(2.0,(no_of_iter - (i+1))) / sqrt(pow(4.0,no_of_iter) -1);
+
+            radius = sqrt(3) * sigma_h;
+
+            compute_NCfilter(O, ct_H, temp,radius);
+
+            O_t = O.t();
+
+            compute_NCfilter(O_t, vert_t, temp1, radius);
+
+            O = O_t.t();
+        }
+    }
+
+    res = O.clone();
+}
+
+void Domain_Filter::pencil_sketch(const Mat &img, Mat &sketch, Mat &color_res, float sigma_s, float sigma_r, float shade_factor)
+{
+
+    int no_of_iter = 3;
+    init(img,2,sigma_s,sigma_r);
+    int h = img.size().height;
+    int w = img.size().width;
+    int channel = img.channels();
+
+    /////////////////////// convert to YCBCR model for color pencil drawing //////////////////////////////////////////////////////
+
+    Mat color_sketch = Mat(h,w,CV_32FC3);
+    Mat Y_channel = Mat(h,w,CV_32FC1);
+    Mat U_channel = Mat(h,w,CV_32FC1);
+    Mat V_channel = Mat(h,w,CV_32FC1);
+
+    cvtColor(img,color_sketch,COLOR_BGR2YCrCb);
+
+    Mat vert_t = ct_V.t();
+
+    float sigma_h = sigma_s;
+
+    Mat penx = Mat(h,w,CV_32FC1);
+
+    Mat pen_res = Mat::zeros(h,w,CV_32FC1);
+    Mat peny = Mat(w,h,CV_32FC1);
+
+    Mat peny_t;
 
-	init(img,flags,sigma_s,sigma_r);
+    float radius;
 
-	if(flags == 1)
-	{
+    for(int i=0;i<no_of_iter;i++)
+    {
+        sigma_h = sigma_s * sqrt(3) * pow(2.0,(no_of_iter - (i+1))) / sqrt(pow(4.0,no_of_iter) -1);
 
-		Mat vert_t = vert.t();  
+        radius = sqrt(3) * sigma_h;
 
-		for(int i=0;i<no_of_iter;i++)
-		{
-			sigma_h = sigma_s * sqrt(3) * pow(2.0,(no_of_iter - (i+1))) / sqrt(pow(4.0,no_of_iter) -1);
+        compute_boxfilter(O, ct_H, penx, radius);
 
-			compute_Rfilter(O, horiz, sigma_h);
+        O_t = O.t();
 
-			O_t = O.t();
+        compute_boxfilter(O_t, vert_t, peny, radius);
 
-			compute_Rfilter(O_t, vert_t, sigma_h);
+        O = O_t.t();
 
-			O = O_t.t();
+        peny_t = peny.t();
 
-		}
-	}
-	else if(flags == 2)
-	{
+        for(int k=0;k<h;k++)
+            for(int j=0;j<w;j++)
+                pen_res.at<float>(k,j) = (shade_factor * (penx.at<float>(k,j) + peny_t.at<float>(k,j)));
 
-		Mat vert_t = ct_V.t();
-		Mat temp = Mat(h,w,CV_32FC1);
-		Mat temp1 = Mat(w,h,CV_32FC1);
+        if(i==0)
+        {
+            sketch = pen_res.clone();
 
-		float radius;
+            for(int k = 0; k < h; k++)
+                for(int j = 0; j < w; j++)
+                {
+                    Y_channel.at<float>(k,j) = color_sketch.at<float>(k,j*channel+0);
+                    U_channel.at<float>(k,j) = color_sketch.at<float>(k,j*channel+1);
+                    V_channel.at<float>(k,j) = color_sketch.at<float>(k,j*channel+2);
+                }
 
-		for(int i=0;i<no_of_iter;i++)
-		{
-			sigma_h = sigma_s * sqrt(3) * pow(2.0,(no_of_iter - (i+1))) / sqrt(pow(4.0,no_of_iter) -1);
 
-			radius = sqrt(3) * sigma_h;
+            for(int k=0;k<h;k++)
+                for(int j=0;j<w;j++)
+                    Y_channel.at<float>(k,j) = pen_res.at<float>(k,j);
 
-			compute_NCfilter(O, ct_H, temp,radius);
+            //	cvMerge(Y_channel,U_channel,V_channel,0,color_sketch);
+            for(int k = 0; k < h; k++)
+                for(int j = 0; j < w; j++)
+                {
+                    color_sketch.at<float>(k,j*channel+0) = Y_channel.at<float>(k,j);
+                    color_sketch.at<float>(k,j*channel+1) = U_channel.at<float>(k,j);
+                    color_sketch.at<float>(k,j*channel+2) = V_channel.at<float>(k,j);
+                }
 
-			O_t = O.t();
+            cvtColor(color_sketch,color_res,COLOR_YCrCb2BGR);
 
-			compute_NCfilter(O_t, vert_t, temp1, radius);
+        }
 
-			O = O_t.t();
-		}
-	}
+    }
 
-	res = O.clone();
 }
diff --git a/modules/photo/src/seamless_cloning.cpp b/modules/photo/src/seamless_cloning.cpp
index 92beb02fe8..c67794ed7a 100644
--- a/modules/photo/src/seamless_cloning.cpp
+++ b/modules/photo/src/seamless_cloning.cpp
@@ -39,7 +39,6 @@
 //
 //M*/
 
-
 #include "precomp.hpp"
 #include "opencv2/photo.hpp"
 #include "opencv2/imgproc.hpp"
@@ -55,11 +54,11 @@ using namespace cv;
 
 void cv::seamlessClone(InputArray _src, InputArray _dst, InputArray _mask, Point p, OutputArray _blend, int flags)
 {
-	Mat src  = _src.getMat();
-	Mat dest = _dst.getMat();
-	Mat mask = _mask.getMat();
-	_blend.create(dest.size(), CV_8UC3);
-	Mat blend = _blend.getMat();
+    Mat src  = _src.getMat();
+    Mat dest = _dst.getMat();
+    Mat mask = _mask.getMat();
+    _blend.create(dest.size(), CV_8UC3);
+    Mat blend = _blend.getMat();
 
     int minx = INT_MAX, miny = INT_MAX, maxx = INT_MIN, maxy = INT_MIN;
     int h = mask.size().height;
@@ -134,14 +133,14 @@ void cv::seamlessClone(InputArray _src, InputArray _dst, InputArray _mask, Point
 
 void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float r, float g, float b)
 {
-	Mat src  = _src.getMat();
-	Mat mask  = _mask.getMat();
-	_dst.create(src.size(), src.type());
-	Mat blend = _dst.getMat();
-	
-	float red = r;
-	float green = g;
-	float blue = b;
+    Mat src  = _src.getMat();
+    Mat mask  = _mask.getMat();
+    _dst.create(src.size(), src.type());
+    Mat blend = _dst.getMat();
+
+    float red = r;
+    float green = g;
+    float blue = b;
 
     Mat gray = Mat::zeros(mask.size(),CV_8UC1);
 
@@ -149,7 +148,7 @@ void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float
         cvtColor(mask, gray, COLOR_BGR2GRAY );
     else
         gray = mask;
-    
+
     Mat cs_mask = Mat::zeros(src.size(),CV_8UC3);
 
     int channel = 3;
@@ -174,12 +173,12 @@ void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float
 void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, float a, float b)
 {
 
-	Mat src  = _src.getMat();
-	Mat mask  = _mask.getMat();
-	_dst.create(src.size(), src.type());
-	Mat blend = _dst.getMat();
-	float alpha = a;
-	float beta = b;
+    Mat src  = _src.getMat();
+    Mat mask  = _mask.getMat();
+    _dst.create(src.size(), src.type());
+    Mat blend = _dst.getMat();
+    float alpha = a;
+    float beta = b;
 
     Mat gray = Mat::zeros(mask.size(),CV_8UC1);
 
@@ -203,19 +202,20 @@ void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst,
             }
 
         }
-    
+
     Cloning obj;
     obj.illum_change(src,cs_mask,gray,blend,alpha,beta);
 
 }
 
-void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst)
+void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst,
+                           double low_threshold, double high_threshold, int kernel_size)
 {
 
-	Mat src  = _src.getMat();
-	Mat mask  = _mask.getMat();
-	_dst.create(src.size(), src.type());
-	Mat blend = _dst.getMat();
+    Mat src  = _src.getMat();
+    Mat mask  = _mask.getMat();
+    _dst.create(src.size(), src.type());
+    Mat blend = _dst.getMat();
 
     Mat gray = Mat::zeros(mask.size(),CV_8UC1);
 
@@ -239,8 +239,8 @@ void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst)
             }
 
         }
-	
+
     Cloning obj;
-	obj.texture_flatten(src,cs_mask,gray,blend);
+    obj.texture_flatten(src,cs_mask,gray,low_threshold,high_threshold,kernel_size,blend);
 }
 
diff --git a/modules/photo/src/seamless_cloning.hpp b/modules/photo/src/seamless_cloning.hpp
index a59cb5d16b..f039d2974d 100644
--- a/modules/photo/src/seamless_cloning.hpp
+++ b/modules/photo/src/seamless_cloning.hpp
@@ -39,7 +39,6 @@
 //
 //M*/
 
-
 #include "precomp.hpp"
 #include "opencv2/photo.hpp"
 #include "opencv2/imgproc.hpp"
@@ -74,9 +73,9 @@ class Cloning
         void transpose(double *mat, double *mat_t,int h,int w);
         void poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result);
         void normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num);
-        void local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float red, float green, float blue);
+        void local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float red_mul, float green_mul, float blue_mul);
         void illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alpha, float beta);
-        void texture_flatten(Mat &I, Mat &mask, Mat &wmask, Mat &final);
+        void texture_flatten(Mat &I, Mat &mask, Mat &wmask, double low_threshold, double high_threhold, int kernel_size, Mat &final);
 };
 
 void Cloning::getGradientx( const Mat &img, Mat &gx)
@@ -94,6 +93,7 @@ void Cloning::getGradientx( const Mat &img, Mat &gx)
                     (float)img.at<uchar>(i,(j+1)*channel+c) - (float)img.at<uchar>(i,j*channel+c);
             }
 }
+
 void Cloning::getGradienty( const Mat &img, Mat &gy)
 {
     int w = img.size().width;
@@ -110,6 +110,7 @@ void Cloning::getGradienty( const Mat &img, Mat &gy)
 
             }
 }
+
 void Cloning::lapx( const Mat &img, Mat &gxx)
 {
     int w = img.size().width;
@@ -125,6 +126,7 @@ void Cloning::lapx( const Mat &img, Mat &gxx)
                     (float)img.at<float>(i,(j+1)*channel+c) - (float)img.at<float>(i,j*channel+c);
             }
 }
+
 void Cloning::lapy( const Mat &img, Mat &gyy)
 {
     int w = img.size().width;
@@ -242,6 +244,7 @@ void Cloning::transpose(double *mat, double *mat_t,int h,int w)
     tmp.release();
 
 }
+
 void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result)
 {
 
@@ -275,7 +278,6 @@ void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result)
                 + (int)bound.at<uchar>(i-1,j) + (int)bound.at<uchar>(i+1,j);
         }
 
-
     Mat diff = Mat(h,w,CV_32FC1);
     for(int i =0;i<h;i++)
     {
@@ -391,7 +393,6 @@ void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result)
     delete [] img_d;
     delete [] gtest;
     delete [] f_bp;
-
 }
 
 void Cloning::init(Mat &I, Mat &wmask)
@@ -486,6 +487,7 @@ void Cloning::calc(Mat &I, Mat &gx, Mat &gy, Mat &sx, Mat &sy)
 
 
 }
+
 void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num)
 {
     init(I,wmask);
@@ -609,7 +611,8 @@ void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num)
 
 }
 
-void Cloning::local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float red=1.0, float green=1.0, float blue=1.0)
+void Cloning::local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float red_mul=1.0,
+                                 float green_mul=1.0, float blue_mul=1.0)
 {
     init(I,wmask);
 
@@ -649,13 +652,11 @@ void Cloning::local_color_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, floa
     for(int i=0;i < h; i++)
         for(int j=0; j < w; j++)
         {
-            factor.at<float>(i,j*channel+0) = blue;
-            factor.at<float>(i,j*channel+1) = green;
-            factor.at<float>(i,j*channel+2) = red;
+            factor.at<float>(i,j*channel+0) = blue_mul;
+            factor.at<float>(i,j*channel+1) = green_mul;
+            factor.at<float>(i,j*channel+2) = red_mul;
         }
 
-
-
     for(int i=0;i < h; i++)
         for(int j=0; j < w; j++)
             for(int c=0;c<channel;++c)
@@ -783,7 +784,8 @@ void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alph
 }
 
 
-void Cloning::texture_flatten(Mat &I, Mat &mask, Mat &wmask, Mat &final)
+void Cloning::texture_flatten(Mat &I, Mat &mask, Mat &wmask, double low_threshold,
+        double high_threshold, int kernel_size, Mat &final)
 {
     init(I,wmask);
 
@@ -807,10 +809,8 @@ void Cloning::texture_flatten(Mat &I, Mat &mask, Mat &wmask, Mat &final)
     I.convertTo(srx32,CV_32FC3,1.0/255.0);
     I.convertTo(sry32,CV_32FC3,1.0/255.0);
 
-
-
     Mat out = Mat(mask.size(),CV_8UC1);
-    Canny( mask, out, 30, 45, 3 );
+    Canny(mask,out,low_threshold,high_threshold,kernel_size);
 
     int channel = mask.channels();
 
diff --git a/modules/photo/test/test_cloning.cpp b/modules/photo/test/test_cloning.cpp
index bb62d874aa..e6fbf3e6a3 100644
--- a/modules/photo/test/test_cloning.cpp
+++ b/modules/photo/test/test_cloning.cpp
@@ -100,7 +100,7 @@ TEST(Photo_SeamlessClone_mixed, regression)
 
 TEST(Photo_SeamlessClone_featureExchange, regression)
 {
-    string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Feature_Exchange/";
+    string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Monochrome_Transfer/";
     string original_path1 = folder + "source1.png";
     string original_path2 = folder + "destination1.png";
     string original_path3 = folder + "mask.png";
@@ -174,7 +174,7 @@ TEST(Photo_SeamlessClone_textureFlattening, regression)
     ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path2;
 
     Mat result;
-    textureFlattening(source, mask, result);
+    textureFlattening(source, mask, result, 30, 45, 3);
 
     imwrite(folder + "cloned.png", result);
 
diff --git a/modules/photo/test/test_npr.cpp b/modules/photo/test/test_npr.cpp
new file mode 100644
index 0000000000..0a4b2c56ef
--- /dev/null
+++ b/modules/photo/test/test_npr.cpp
@@ -0,0 +1,146 @@
+/*M///////////////////////////////////////////////////////////////////////////////////////
+//
+//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
+//
+//  By downloading, copying, installing or using the software you agree to this license.
+//  If you do not agree to this license, do not download, install,
+//  copy or use the software.
+//
+//
+//                           License Agreement
+//                For Open Source Computer Vision Library
+//
+// Copyright (C) 2013, OpenCV Foundation, all rights reserved.
+// Third party copyrights are property of their respective owners.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+//   * Redistribution's of source code must retain the above copyright notice,
+//     this list of conditions and the following disclaimer.
+//
+//   * Redistribution's in binary form must reproduce the above copyright notice,
+//     this list of conditions and the following disclaimer in the documentation
+//     and/or other materials provided with the distribution.
+//
+//   * The name of the copyright holders may not be used to endorse or promote products
+//     derived from this software without specific prior written permission.
+//
+// This software is provided by the copyright holders and contributors "as is" and
+// any express or implied warranties, including, but not limited to, the implied
+// warranties of merchantability and fitness for a particular purpose are disclaimed.
+// In no event shall the Intel Corporation or contributors be liable for any direct,
+// indirect, incidental, special, exemplary, or consequential damages
+// (including, but not limited to, procurement of substitute goods or services;
+// loss of use, data, or profits; or business interruption) however caused
+// and on any theory of liability, whether in contract, strict liability,
+// or tort (including negligence or otherwise) arising in any way out of
+// the use of this software, even if advised of the possibility of such damage.
+//
+//M*/
+
+
+#include "test_precomp.hpp"
+#include "opencv2/photo.hpp"
+#include <string>
+
+using namespace cv;
+using namespace std;
+
+
+TEST(Photo_NPR_EdgePreserveSmoothing_RecursiveFilter, regression)
+{
+    string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Smoothing/";
+    string original_path = folder + "test1.png";
+
+    Mat source = imread(original_path, IMREAD_COLOR);
+
+    ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path;
+
+    Mat result;
+    edgePreservingFilter(source,result,1);
+
+    imwrite(folder + "smoothened_RF.png", result);
+
+}
+
+TEST(Photo_NPR_EdgePreserveSmoothing_NormConvFilter, regression)
+{
+    string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Smoothing/";
+    string original_path = folder + "test1.png";
+
+    Mat source = imread(original_path, IMREAD_COLOR);
+
+    ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path;
+
+    Mat result;
+    edgePreservingFilter(source,result,2);
+
+    imwrite(folder + "smoothened_NCF.png", result);
+
+}
+
+TEST(Photo_NPR_DetailEnhance, regression)
+{
+    string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Detail_Enhance/";
+    string original_path = folder + "test1.png";
+
+    Mat source = imread(original_path, IMREAD_COLOR);
+
+    ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path;
+
+    Mat result;
+    detailEnhance(source,result);
+
+    imwrite(folder + "detail_enhanced.png", result);
+
+}
+
+TEST(Photo_NPR_PencilSketch, regression)
+{
+    string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Pencil_Sketch/";
+    string original_path = folder + "test1.png";
+
+    Mat source = imread(original_path, IMREAD_COLOR);
+
+    ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path;
+
+    Mat result,result1;
+    pencilSketch(source,result,result1,10,.1,.03);
+
+    imwrite(folder + "pencil_sketch.png", result);
+    imwrite(folder + "color_pencil_sketch.png", result1);
+
+}
+
+TEST(Photo_NPR_Stylization, regression)
+{
+    string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Stylization/";
+    string original_path = folder + "test1.png";
+
+    Mat source = imread(original_path, IMREAD_COLOR);
+
+    ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path;
+
+    Mat result;
+    stylization(source,result);
+
+    imwrite(folder + "stylized.png", result);
+
+}
+
+TEST(Photo_NPR_EdgeEnhance, regression)
+{
+    string folder = string(cvtest::TS::ptr()->get_data_path()) + "npr/Edge_Enhance/";
+    string original_path = folder + "test1.png";
+
+    Mat source = imread(original_path, IMREAD_COLOR);
+
+    ASSERT_FALSE(source.empty()) << "Could not load input image " << original_path;
+
+    Mat result;
+    edgeEnhance(source,result);
+
+    imwrite(folder + "edge_enhanced.png", result);
+
+}
diff --git a/samples/cpp/cloning.cpp b/samples/cpp/cloning.cpp
index 9a41ce229b..84458fd4fe 100644
--- a/samples/cpp/cloning.cpp
+++ b/samples/cpp/cloning.cpp
@@ -56,18 +56,19 @@ char src[50];
 char dest[50];
 
 int var = 0;
-int flag = 0;
-int flag1 = 0;
+int flag = 0, flag1 = 0, flag4 = 0;
 
-int minx,miny,maxx,maxy,lenx,leny;
-int minxd,minyd,maxxd,maxyd,lenxd,lenyd;
+int minx, miny, maxx, maxy, lenx, leny;
+int minxd, minyd, maxxd, maxyd, lenxd, lenyd;
 
-int channel,num;
+int channel, num, kernel_size;
 
 float alpha,beta;
 
 float red, green, blue;
 
+double low_t, high_t;
+
 void source(int event, int x, int y, int, void*)
 {
 
@@ -159,7 +160,7 @@ void source(int event, int x, int y, int, void*)
         }
         else if(num == 6)
         {
-            textureFlattening(img0,res1,blend);
+            textureFlattening(img0,res1,blend,low_t,high_t,kernel_size);
             imshow("Texture Flattened", blend);
             waitKey(0);
         }
@@ -176,11 +177,12 @@ void source(int event, int x, int y, int, void*)
 		flag1 = 0;
 		minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN;
 		imshow("Source", img0);
+        if(num == 1 || num == 2 || num == 3)
+            imshow("Destination",img2);
 		drag = 0;
 	}
 }
 
-
 void destination(int event, int x, int y, int, void*)
 {
 
@@ -190,6 +192,7 @@ void destination(int event, int x, int y, int, void*)
 	im1 = img2.clone();
 	if (event == EVENT_LBUTTONDOWN)
 	{
+        flag4 = 1;
 		if(flag1 == 1)
 		{
 			point = Point(x, y);
@@ -386,14 +389,12 @@ int main(int argc, char **argv)
         res1 = Mat::zeros(img0.size(),CV_8UC1);
         final = Mat::zeros(img0.size(),CV_8UC3);
 
-
         //////////// source image ///////////////////
 
         namedWindow("Source", 1);
         setMouseCallback("Source", source, NULL);
         imshow("Source", img0);
 
-
     }
     else if(num == 5)
     {
@@ -416,12 +417,20 @@ int main(int argc, char **argv)
         setMouseCallback("Source", source, NULL);
         imshow("Source", img0);
 
-
     }
     else if(num == 6)
     {
         checkfile(s);
 
+        cout << "low_threshold: ";
+        cin >> low_t;
+
+        cout << "high_threshold: ";
+        cin >> high_t;
+        
+        cout << "kernel_size: ";
+        cin >> kernel_size;
+        
         img0 = imread(src);
 
         res1 = Mat::zeros(img0.size(),CV_8UC1);
@@ -434,13 +443,16 @@ int main(int argc, char **argv)
         imshow("Source", img0);
     }
     
+    int flag3 = 0;
+    
     while(true)
     {
         char key = waitKey(0);
 
-        if(key == 'd')
+        if(key == 'd' && flag3 == 0)
         {
             flag1 = 1;
+            flag3 = 1;
             img1 = img0.clone();
             for(int i = var; i < numpts ; i++)
                 pts[i] = point;
@@ -490,13 +502,15 @@ int main(int argc, char **argv)
             }
             var = 0;
             flag1 = 0;
+            flag3 = 0;
+            flag4 = 0;
             minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN;
             imshow("Source", img0);
             if(num == 1 || num == 2 || num == 3)
                 imshow("Destination",img2);
             drag = 0;
         }
-        else if ((num == 1 || num == 2 || num == 3) && key == 'c' && flag1 == 1)
+        else if ((num == 1 || num == 2 || num == 3) && key == 'c' && flag1 == 1 && flag4 == 1)
         {
             seamlessClone(img0,img2,res1,point,blend,num);
             imshow("Cloned Image", blend);
@@ -516,14 +530,12 @@ int main(int argc, char **argv)
         }
         else if (num == 6 && key == 'c' && flag1 == 1)
         {
-            textureFlattening(img0,res1,blend);
+            textureFlattening(img0,res1,blend,low_t,high_t,kernel_size);
             imshow("Texture Flattened", blend);
             imwrite("cloned.png",blend);
         }
         else if(key == 'q')
             exit(0);
-
     }
-
     waitKey(0);
 }
diff --git a/samples/cpp/cloning_example.cpp b/samples/cpp/cloning_example.cpp
new file mode 100644
index 0000000000..6c31d2f44e
--- /dev/null
+++ b/samples/cpp/cloning_example.cpp
@@ -0,0 +1,243 @@
+/*
+* cloning.cpp
+*
+* Author:
+* Siddharth Kherada <siddharthkherada27[at]gmail[dot]com>
+*
+* This tutorial demonstrates how to use OpenCV seamless cloning
+* module without GUI.
+*
+* 1- Normal Cloning
+* 2- Mixed Cloning
+* 3- Monochrome Transfer
+* 4- Color Change
+* 5- Illumination change
+* 6- Texture Flattening
+
+* The program takes as input a source and a destination image (for 1-3 methods)
+* and ouputs the cloned image.
+*/
+
+#include "opencv2/photo.hpp"
+#include "opencv2/imgproc.hpp"
+#include "opencv2/highgui.hpp"
+#include "opencv2/core.hpp"
+#include <iostream>
+#include <stdlib.h>
+
+using namespace std;
+using namespace cv;
+
+int main(int argc, char **argv)
+{
+    cout << endl;
+    cout << "Cloning Module" << endl;
+    cout << "---------------" << endl;
+    cout << "Options: " << endl;
+    cout << endl;
+    cout << "1) Normal Cloning " << endl;
+    cout << "2) Mixed Cloning " << endl;
+    cout << "3) Monochrome Transfer " << endl;
+    cout << "4) Local Color Change " << endl;
+    cout << "5) Local Illumination Change " << endl;
+    cout << "6) Texture Flattening " << endl;
+    cout << endl;
+    cout << "Press number 1-6 to choose from above techniques: ";
+    int num;
+    cin >> num;
+    cout << endl;
+    
+    if(num == 1)
+    {
+        string folder =  "cloning/Normal_Cloning/";
+        string original_path1 = folder + "source1.png";
+        string original_path2 = folder + "destination1.png";
+        string original_path3 = folder + "mask.png";
+        
+        Mat source = imread(original_path1, IMREAD_COLOR);
+        Mat destination = imread(original_path2, IMREAD_COLOR);
+        Mat mask = imread(original_path3, IMREAD_COLOR);
+
+        if(source.empty())
+        {
+            cout << "Could not load source image " << original_path1 << endl;
+            exit(0);
+        }
+        if(destination.empty()) 
+        {
+            cout << "Could not load destination image " << original_path2 << endl;
+            exit(0);
+        }
+        if(mask.empty())
+        {
+            cout << "Could not load mask image " << original_path3 << endl;
+            exit(0);
+        }
+
+        Mat result;
+        Point p;
+        p.x = 400;
+        p.y = 100;
+        
+        seamlessClone(source, destination, mask, p, result, 1);
+        
+        imshow("Output",result);
+        imwrite(folder + "cloned.png", result);
+    }
+    else if(num == 2)
+    { 
+        string folder = "cloning/Mixed_Cloning/";
+        string original_path1 = folder + "source1.png";
+        string original_path2 = folder + "destination1.png";
+        string original_path3 = folder + "mask.png";
+        
+        Mat source = imread(original_path1, IMREAD_COLOR);
+        Mat destination = imread(original_path2, IMREAD_COLOR);
+        Mat mask = imread(original_path3, IMREAD_COLOR);
+
+        if(source.empty()) 
+        {
+            cout << "Could not load source image " << original_path1 << endl;
+            exit(0);
+        }
+        if(destination.empty())
+        {
+            cout << "Could not load destination image " << original_path2 << endl;
+            exit(0);
+        }
+        if(mask.empty()) 
+        {
+            cout << "Could not load mask image " << original_path3 << endl;
+            exit(0);
+        }
+
+        Mat result;
+        Point p;
+        p.x = destination.size().width/2;
+        p.y = destination.size().height/2;
+        
+        seamlessClone(source, destination, mask, p, result, 2);
+
+        imshow("Output",result);
+        imwrite(folder + "cloned.png", result);
+    }
+    else if(num == 3)
+    {
+        string folder = "cloning/Monochrome_Transfer/";
+        string original_path1 = folder + "source1.png";
+        string original_path2 = folder + "destination1.png";
+        string original_path3 = folder + "mask.png";
+
+        Mat source = imread(original_path1, IMREAD_COLOR);
+        Mat destination = imread(original_path2, IMREAD_COLOR);
+        Mat mask = imread(original_path3, IMREAD_COLOR);
+
+        if(source.empty())
+        {
+            cout << "Could not load source image " << original_path1 << endl;
+            exit(0);
+        }
+        if(destination.empty()) 
+        {
+            cout << "Could not load destination image " << original_path2 << endl;
+            exit(0);
+        }
+        if(mask.empty()) 
+        {
+            cout << "Could not load mask image " << original_path3 << endl;
+            exit(0);
+        }
+
+        Mat result;
+        Point p;
+        p.x = destination.size().width/2;
+        p.y = destination.size().height/2;
+        
+        seamlessClone(source, destination, mask, p, result, 3);
+
+        imshow("Output",result);
+        imwrite(folder + "cloned.png", result);
+    }
+    else if(num == 4)
+    {
+        string folder = "cloning/Color_Change/";
+        string original_path1 = folder + "source1.png";
+        string original_path2 = folder + "mask.png";
+
+        Mat source = imread(original_path1, IMREAD_COLOR);
+        Mat mask = imread(original_path2, IMREAD_COLOR);
+
+        if(source.empty())
+        {
+            cout << "Could not load source image " << original_path1 << endl;
+            exit(0);
+        }
+        if(mask.empty())
+        {
+            cout << "Could not load mask image " << original_path2 << endl;
+            exit(0);
+        }
+
+        Mat result;
+        
+        colorChange(source, mask, result, 1.5, .5, .5);
+
+        imshow("Output",result);
+        imwrite(folder + "cloned.png", result);
+    }
+    else if(num == 5)
+    {
+        string folder = "cloning/Illumination_Change/";
+        string original_path1 = folder + "source1.png";
+        string original_path2 = folder + "mask.png";
+
+        Mat source = imread(original_path1, IMREAD_COLOR);
+        Mat mask = imread(original_path2, IMREAD_COLOR);
+
+        if(source.empty()) 
+        {
+            cout << "Could not load source image " << original_path1 << endl;
+            exit(0);
+        }
+        if(mask.empty())
+        {
+            cout << "Could not load mask image " << original_path2 << endl;
+            exit(0);
+        }
+
+        Mat result;
+        
+        illuminationChange(source, mask, result, .2, .4);
+
+        imshow("Output",result);
+        imwrite(folder + "cloned.png", result);
+    }
+    else if(num == 6)
+    {
+        string folder = "cloning/Texture_Flattening/";
+        string original_path1 = folder + "source1.png";
+        string original_path2 = folder + "mask.png";
+
+        Mat source = imread(original_path1, IMREAD_COLOR);
+        Mat mask = imread(original_path2, IMREAD_COLOR);
+
+        if(source.empty())
+        {
+            cout << "Could not load source image " << original_path1 << endl;
+            exit(0);
+        }
+        if(mask.empty())
+        {
+            cout << "Could not load mask image " << original_path2 << endl;
+            exit(0);
+        }
+
+        Mat result;
+        
+        textureFlattening(source, mask, result, 30, 45, 3);
+
+        imshow("Output",result);
+        imwrite(folder + "cloned.png", result);
+    }
+    waitKey(0);
+}
diff --git a/samples/cpp/npr_demo.cpp b/samples/cpp/npr_demo.cpp
new file mode 100644
index 0000000000..871fd32405
--- /dev/null
+++ b/samples/cpp/npr_demo.cpp
@@ -0,0 +1,107 @@
+/*
+* npr_demo.cpp
+*
+* Author:
+* Siddharth Kherada <siddharthkherada27[at]gmail[dot]com>
+*
+* This tutorial demonstrates how to use OpenCV Non-Photorealistic Rendering Module.
+* 1) Edge Preserve Smoothing
+*    -> Using Normalized convolution Filter
+*    -> Using Recursive Filter
+* 2) Detail Enhancement
+* 3) Pencil sketch/Color Pencil Drawing
+* 4) Stylization
+* 5) Edge Enhancement
+*
+*/
+
+#include <signal.h>
+#include "opencv2/photo.hpp"
+#include "opencv2/imgproc.hpp"
+#include "opencv2/highgui.hpp"
+#include "opencv2/core.hpp"
+#include <iostream>
+#include <stdlib.h>
+
+using namespace std;
+using namespace cv;
+
+int main(int argc, char* argv[])
+{
+    int num,type;
+
+    int flag = 0;
+
+    Mat I = imread(argv[1]);
+
+
+    if(argc < 2)
+    {
+        cout << "usage: " << argv[0] << " <Input image> "  << endl;
+        exit(0);
+    }
+
+    if(!I.data)
+    {
+        cout <<  "Image not found" << endl;
+        exit(0);
+    }
+
+    cout << endl;
+    cout << " Edge Preserve Filter" << endl;
+    cout << "----------------------" << endl;
+
+    cout << "Options: " << endl;
+    cout << endl;
+
+    cout << "1) Edge Preserve Smoothing" << endl;
+    cout << "   -> Using Normalized convolution Filter" << endl;
+    cout << "   -> Using Recursive Filter" << endl;
+    cout << "2) Detail Enhancement" << endl;
+    cout << "3) Pencil sketch/Color Pencil Drawing" << endl;
+    cout << "4) Stylization" << endl;
+    cout << "5) Edge Enhancement" << endl;
+    cout << endl;
+
+    cout << "Press number 1-5 to choose from above techniques: ";
+
+    cin >> num;
+
+    Mat img;
+
+    if(num == 1)
+    {
+        cout << endl;
+        cout << "Press 1 for Normalized Convolution Filter and 2 for Recursive Filter: ";
+
+        cin >> type;
+
+        edgePreservingFilter(I,img,type);
+        imshow("Edge Preserve Smoothing",img);
+
+    }
+    else if(num == 2)
+    {
+        detailEnhance(I,img);
+        imshow("Detail Enhanced",img);
+    }
+    else if(num == 3)
+    {
+        Mat img1;
+        pencilSketch(I,img1, img, 10 ,.1,.03);
+        imshow("Pencil Sketch",img1);
+        imshow("Color Pencil Sketch",img);
+    }
+    else if(num == 4)
+    {
+        stylization(I,img);
+        imshow("Stylization",img);
+    }
+    else if(num == 5)
+    {
+        edgeEnhance(I,img);
+        imshow("Edge Enhance",img);
+    }
+
+    waitKey(0);
+}
-- 
2.18.0