new filters added and all the 3 modules updated

All 3 modules Updated
This commit is contained in:
siddharth 2013-09-03 21:12:05 +05:30
parent ae9b4003ae
commit 56ab1c18e6
14 changed files with 1600 additions and 570 deletions

View File

@ -39,19 +39,21 @@ colorChange
----------- -----------
Given an original color image, two differently colored versions of this image can be mixed seamlessly. 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 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 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 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 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. 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 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 dst: Output image with the same size and type as ``src``.
:param alpha: Value ranges between 0-2. :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 textureFlattening
----------------- -----------------
By retaining only the gradients at edge locations, before integrating with the Poisson solver, one washes out the texture of the selected 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 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 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:** **NOTE:**

90
modules/photo/doc/npr.rst Normal file
View File

@ -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.

View File

@ -68,8 +68,8 @@ enum
enum enum
{ {
RECURSIVE_FILTER = 1, RECURS_FILTER = 1,
NC_FILTER = 2 NORMCONV_FILTER = 2
}; };
//! restores the damaged image areas using one of the available intpainting algorithms //! 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 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 } // cv

View File

@ -57,7 +57,7 @@ double norm(double);
double norm(double E) double norm(double E)
{ {
return (sqrt(pow(E,2))); return (sqrt(pow(E,2)));
} }
void cv::decolor(InputArray _src, OutputArray _dst, OutputArray _boost) 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 ) if(!I.data )
{ {
cout << "Could not open or find the image" << endl ; cout << "Could not open or find the image" << endl ;
return; return;
} }
if(I.channels() !=3) if(I.channels() !=3)
{ {
cout << "Input Color Image" << endl; cout << "Input Color Image" << endl;
return; return;
} }
int maxIter = 15; int maxIter = 15;
int iterCount = 0; int iterCount = 0;
float tol = .0001; float tol = .0001;
double E = 0; double E = 0;
double pre_E = std::numeric_limits<double>::infinity(); double pre_E = std::numeric_limits<double>::infinity();
Decolor obj; Decolor obj;
Mat img; Mat img;
img = Mat(I.size(),CV_32FC3); img = Mat(I.size(),CV_32FC3);
I.convertTo(img,CV_32FC3,1.0/255.0); I.convertTo(img,CV_32FC3,1.0/255.0);
obj.init(); obj.init();
vector <double> Cg; vector <double> Cg;
vector < vector <double> > polyGrad; vector < vector <double> > polyGrad;
vector < vector <double> > bc; vector < vector <double> > bc;
vector < vector < int > > comb; vector < vector < int > > comb;
vector <double> alf; vector <double> alf;
obj.grad_system(img,polyGrad,Cg,comb); obj.grad_system(img,polyGrad,Cg,comb);
obj.weak_order(img,alf); obj.weak_order(img,alf);
Mat Mt = Mat(polyGrad.size(),polyGrad[0].size(), CV_32FC1); Mat Mt = Mat(polyGrad.size(),polyGrad[0].size(), CV_32FC1);
obj.wei_update_matrix(polyGrad,Cg,Mt); obj.wei_update_matrix(polyGrad,Cg,Mt);
vector <double> wei; vector <double> wei;
obj.wei_inti(comb,wei); obj.wei_inti(comb,wei);
//////////////////////////////// main loop starting //////////////////////////////////////// //////////////////////////////// main loop starting ////////////////////////////////////////
while(norm(E-pre_E) > tol) while(norm(E-pre_E) > tol)
{ {
iterCount +=1; iterCount +=1;
pre_E = E; pre_E = E;
vector <double> G_pos; vector <double> G_pos;
vector <double> G_neg; vector <double> G_neg;
vector <double> temp; vector <double> temp;
vector <double> temp1; vector <double> temp1;
double val = 0.0; double val = 0.0;
for(unsigned int i=0;i< polyGrad[0].size();i++) for(unsigned int i=0;i< polyGrad[0].size();i++)
{ {
val = 0.0; val = 0.0;
for(unsigned int j =0;j<polyGrad.size();j++) for(unsigned int j =0;j<polyGrad.size();j++)
val = val + (polyGrad[j][i] * wei[j]); val = val + (polyGrad[j][i] * wei[j]);
temp.push_back(val - Cg[i]); temp.push_back(val - Cg[i]);
temp1.push_back(val + Cg[i]); temp1.push_back(val + Cg[i]);
} }
double ans = 0.0; double ans = 0.0;
double ans1 = 0.0; double ans1 = 0.0;
for(unsigned int i =0;i<alf.size();i++) 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)); 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)); ans1 =((1 - alf[i])/2) * exp((-1.0 * 0.5 * pow(temp1[i],2))/pow(sigma,2));
G_pos.push_back(ans); G_pos.push_back(ans);
G_neg.push_back(ans1); G_neg.push_back(ans1);
} }
vector <double> EXPsum; vector <double> EXPsum;
vector <double> EXPterm; vector <double> EXPterm;
for(unsigned int i = 0;i<G_pos.size();i++) for(unsigned int i = 0;i<G_pos.size();i++)
EXPsum.push_back(G_pos[i]+G_neg[i]); EXPsum.push_back(G_pos[i]+G_neg[i]);
vector <double> temp2;
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<EXPsum.size();i++) for(unsigned int i =0; i < G_pos.size();i++)
{ EXPterm.push_back((G_pos[i] - G_neg[i])/(EXPsum[i] + temp2[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++) double val1 = 0.0;
EXPterm.push_back((G_pos[i] - G_neg[i])/(EXPsum[i] + temp2[i])); vector <double> wei1;
for(unsigned int i=0;i< polyGrad.size();i++)
double val1 = 0.0; {
vector <double> wei1; 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< polyGrad.size();i++) for(unsigned int i =0;i<wei.size();i++)
{ wei[i] = wei1[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); E = obj.energyCalcu(Cg,polyGrad,wei);
if(iterCount > maxIter) if(iterCount > maxIter)
break; break;
G_pos.clear(); G_pos.clear();
G_neg.clear(); G_neg.clear();
temp.clear(); temp.clear();
temp1.clear(); temp1.clear();
EXPsum.clear(); EXPsum.clear();
EXPterm.clear(); EXPterm.clear();
temp2.clear(); temp2.clear();
wei1.clear(); wei1.clear();
} }
Mat Gray = Mat::zeros(img.size(),CV_32FC1); Mat Gray = Mat::zeros(img.size(),CV_32FC1);
obj.grayImContruct(wei, img, Gray); obj.grayImContruct(wei, img, Gray);
Gray.convertTo(dst,CV_8UC1,255); Gray.convertTo(dst,CV_8UC1,255);
/////////////////////////////////// Contrast Boosting ///////////////////////////////// /////////////////////////////////// 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); 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);
int h1 = img.size().height; cvtColor(I,lab,COLOR_BGR2Lab);
int w1 = img.size().width;
for(int i =0;i<h1;i++) int h1 = img.size().height;
for(int j=0;j<w1;j++) int w1 = img.size().width;
{
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 i =0;i<h1;i++)
for(int j=0;j<w1;j++) for(int j=0;j<w1;j++)
{ {
lab.at<uchar>(i,j*3+0) = l.at<uchar>(i,j); l.at<uchar>(i,j) = lab.at<uchar>(i,j*3+0);
lab.at<uchar>(i,j*3+1) = a.at<uchar>(i,j); a.at<uchar>(i,j) = lab.at<uchar>(i,j*3+1);
lab.at<uchar>(i,j*3+2) = b.at<uchar>(i,j); b.at<uchar>(i,j) = lab.at<uchar>(i,j*3+2);
} }
cvtColor(lab,color_boost,COLOR_Lab2BGR); 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);
} }

View File

@ -39,7 +39,6 @@
// //
//M*/ //M*/
#include "precomp.hpp" #include "precomp.hpp"
#include "opencv2/photo.hpp" #include "opencv2/photo.hpp"
#include "opencv2/imgproc.hpp" #include "opencv2/imgproc.hpp"
@ -69,7 +68,7 @@ class Decolor
void add_to_vector_poly(vector < vector <double> > &polyGrad, vector <double> &curGrad); void add_to_vector_poly(vector < vector <double> > &polyGrad, vector <double> &curGrad);
void weak_order(Mat img, vector <double> &alf); void weak_order(Mat img, vector <double> &alf);
void grad_system(Mat img, vector < vector < double > > &polyGrad, 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_update_matrix(vector < vector <double> > &poly, vector <double> &Cg, Mat &X);
void wei_inti(vector < vector <int> > &comb, vector <double> &wei); void wei_inti(vector < vector <int> > &comb, vector <double> &wei);
void grayImContruct(vector <double> &wei, Mat img, Mat &Gray); 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) double Decolor::energyCalcu(vector <double> &Cg, vector < vector <double> > &polyGrad, vector <double> &wei)
{ {
vector <double> P; vector <double> P;
vector <double> temp; vector <double> temp;
vector <double> temp1; vector <double> temp1;
@ -112,8 +110,6 @@ double Decolor::energyCalcu(vector <double> &Cg, vector < vector <double> > &pol
} }
void Decolor::init() void Decolor::init()
{ {
kernel = Mat(1,2, CV_32FC1); kernel = Mat(1,2, CV_32FC1);
@ -123,7 +119,6 @@ void Decolor::init()
kernel1.at<float>(0,0)=1.0; kernel1.at<float>(0,0)=1.0;
kernel1.at<float>(1,0)=-1.0; kernel1.at<float>(1,0)=-1.0;
order = 2; order = 2;
} }
vector<double> Decolor::product(vector < vector<int> > &comb, vector <double> &initRGB) 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(); dest.release();
dest1.release(); dest1.release();
} }
void Decolor::colorGrad(Mat img, vector <double> &Cg) void Decolor::colorGrad(Mat img, vector <double> &Cg)
{ {
@ -222,7 +217,6 @@ void Decolor::colorGrad(Mat img, vector <double> &Cg)
ImL.clear(); ImL.clear();
Ima.clear(); Ima.clear();
Imb.clear(); Imb.clear();
} }
void Decolor::add_vector(vector < vector <int> > &comb, int r,int g,int b) 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); green.at<float>(i,j) = img.at<float>(i,j*3+1);
blue.at<float>(i,j) = img.at<float>(i,j*3+0); blue.at<float>(i,j) = img.at<float>(i,j*3+0);
} }
vector <double> Rg; vector <double> Rg;
vector <double> Gg; vector <double> Gg;
vector <double> Bg; vector <double> Bg;
@ -275,7 +269,7 @@ void Decolor::weak_order(Mat img, vector <double> &alf)
vector <double> t1; vector <double> t1;
vector <double> t2; vector <double> t2;
vector <double> t3; vector <double> t3;
vector <double> tmp1; vector <double> tmp1;
vector <double> tmp2; vector <double> tmp2;
vector <double> tmp3; 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++) for(unsigned int i =0 ;i < Rg.size();i++)
alf[i] -= tmp1[i] * tmp2[i] * tmp3[i]; alf[i] -= tmp1[i] * tmp2[i] * tmp3[i];
double sum =0.0; double sum =0.0;
for(unsigned int i=0;i<alf.size();i++) for(unsigned int i=0;i<alf.size();i++)
sum += abs(alf[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, 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 h = img.size().height;
int w = img.size().width; int w = img.size().width;
double sizefactor; double sizefactor;
if((h + w) > 800) if((h + w) > 800)
{ {
@ -375,7 +368,7 @@ void Decolor::grad_system(Mat img, vector < vector < double > > &polyGrad,
h = img.size().height; h = img.size().height;
w = img.size().width; w = img.size().width;
colorGrad(img,Cg); colorGrad(img,Cg);
Mat curIm = Mat(img.size(),CV_32FC1); Mat curIm = Mat(img.size(),CV_32FC1);
Mat red = Mat(img.size(),CV_32FC1); Mat red = Mat(img.size(),CV_32FC1);
Mat green = 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++) for(int j=0;j<w;j++)
curIm.at<float>(i,j)= curIm.at<float>(i,j)=
pow(red.at<float>(i,j),r)*pow(green.at<float>(i,j),g)* 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; vector <double> curGrad;
gradvector(curIm,curGrad); gradvector(curIm,curGrad);
add_to_vector_poly(polyGrad,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) void Decolor::grayImContruct(vector <double> &wei, Mat img, Mat &Gray)
{ {
int h=img.size().height; int h=img.size().height;
int w=img.size().width; int w=img.size().width;
@ -485,7 +477,7 @@ void Decolor::grayImContruct(vector <double> &wei, Mat img, Mat &Gray)
} }
int kk =0; int kk =0;
for(int r =0;r<=order;r++) for(int r =0;r<=order;r++)
for(int g=0;g<=order;g++) for(int g=0;g<=order;g++)
for(int b=0;b<=order;b++) 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++) for(int j=0;j<w;j++)
Gray.at<float>(i,j)=Gray.at<float>(i,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)* 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; kk=kk+1;
} }
@ -508,7 +500,7 @@ void Decolor::grayImContruct(vector <double> &wei, Mat img, Mat &Gray)
{ {
if(Gray.at<float>(i,j) < minval) if(Gray.at<float>(i,j) < minval)
minval = Gray.at<float>(i,j); minval = Gray.at<float>(i,j);
if(Gray.at<float>(i,j) > maxval) if(Gray.at<float>(i,j) > maxval)
maxval = Gray.at<float>(i,j); maxval = Gray.at<float>(i,j);
} }

View File

@ -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 "precomp.hpp"
#include "opencv2/photo.hpp" #include "opencv2/photo.hpp"
#include "opencv2/highgui.hpp" #include "opencv2/highgui.hpp"
@ -11,7 +52,7 @@
using namespace std; using namespace std;
using namespace cv; 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(); Mat I = _src.getMat();
_dst.create(I.size(), CV_8UC3); _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); 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);
}

File diff suppressed because it is too large Load Diff

View File

@ -39,7 +39,6 @@
// //
//M*/ //M*/
#include "precomp.hpp" #include "precomp.hpp"
#include "opencv2/photo.hpp" #include "opencv2/photo.hpp"
#include "opencv2/imgproc.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) void cv::seamlessClone(InputArray _src, InputArray _dst, InputArray _mask, Point p, OutputArray _blend, int flags)
{ {
Mat src = _src.getMat(); Mat src = _src.getMat();
Mat dest = _dst.getMat(); Mat dest = _dst.getMat();
Mat mask = _mask.getMat(); Mat mask = _mask.getMat();
_blend.create(dest.size(), CV_8UC3); _blend.create(dest.size(), CV_8UC3);
Mat blend = _blend.getMat(); Mat blend = _blend.getMat();
int minx = INT_MAX, miny = INT_MAX, maxx = INT_MIN, maxy = INT_MIN; int minx = INT_MAX, miny = INT_MAX, maxx = INT_MIN, maxy = INT_MIN;
int h = mask.size().height; 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) void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float r, float g, float b)
{ {
Mat src = _src.getMat(); Mat src = _src.getMat();
Mat mask = _mask.getMat(); Mat mask = _mask.getMat();
_dst.create(src.size(), src.type()); _dst.create(src.size(), src.type());
Mat blend = _dst.getMat(); Mat blend = _dst.getMat();
float red = r; float red = r;
float green = g; float green = g;
float blue = b; float blue = b;
Mat gray = Mat::zeros(mask.size(),CV_8UC1); 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 ); cvtColor(mask, gray, COLOR_BGR2GRAY );
else else
gray = mask; gray = mask;
Mat cs_mask = Mat::zeros(src.size(),CV_8UC3); Mat cs_mask = Mat::zeros(src.size(),CV_8UC3);
int channel = 3; 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) void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst, float a, float b)
{ {
Mat src = _src.getMat(); Mat src = _src.getMat();
Mat mask = _mask.getMat(); Mat mask = _mask.getMat();
_dst.create(src.size(), src.type()); _dst.create(src.size(), src.type());
Mat blend = _dst.getMat(); Mat blend = _dst.getMat();
float alpha = a; float alpha = a;
float beta = b; float beta = b;
Mat gray = Mat::zeros(mask.size(),CV_8UC1); Mat gray = Mat::zeros(mask.size(),CV_8UC1);
@ -203,19 +202,20 @@ void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst,
} }
} }
Cloning obj; Cloning obj;
obj.illum_change(src,cs_mask,gray,blend,alpha,beta); 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 src = _src.getMat();
Mat mask = _mask.getMat(); Mat mask = _mask.getMat();
_dst.create(src.size(), src.type()); _dst.create(src.size(), src.type());
Mat blend = _dst.getMat(); Mat blend = _dst.getMat();
Mat gray = Mat::zeros(mask.size(),CV_8UC1); Mat gray = Mat::zeros(mask.size(),CV_8UC1);
@ -239,8 +239,8 @@ void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst)
} }
} }
Cloning obj; Cloning obj;
obj.texture_flatten(src,cs_mask,gray,blend); obj.texture_flatten(src,cs_mask,gray,low_threshold,high_threshold,kernel_size,blend);
} }

View File

@ -39,7 +39,6 @@
// //
//M*/ //M*/
#include "precomp.hpp" #include "precomp.hpp"
#include "opencv2/photo.hpp" #include "opencv2/photo.hpp"
#include "opencv2/imgproc.hpp" #include "opencv2/imgproc.hpp"
@ -74,9 +73,9 @@ class Cloning
void transpose(double *mat, double *mat_t,int h,int w); void transpose(double *mat, double *mat_t,int h,int w);
void poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result); 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 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 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) 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); (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) void Cloning::getGradienty( const Mat &img, Mat &gy)
{ {
int w = img.size().width; 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) void Cloning::lapx( const Mat &img, Mat &gxx)
{ {
int w = img.size().width; 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); (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) void Cloning::lapy( const Mat &img, Mat &gyy)
{ {
int w = img.size().width; int w = img.size().width;
@ -242,6 +244,7 @@ void Cloning::transpose(double *mat, double *mat_t,int h,int w)
tmp.release(); tmp.release();
} }
void Cloning::poisson_solver(const Mat &img, Mat &gxx , Mat &gyy, Mat &result) 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); + (int)bound.at<uchar>(i-1,j) + (int)bound.at<uchar>(i+1,j);
} }
Mat diff = Mat(h,w,CV_32FC1); Mat diff = Mat(h,w,CV_32FC1);
for(int i =0;i<h;i++) 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 [] img_d;
delete [] gtest; delete [] gtest;
delete [] f_bp; delete [] f_bp;
} }
void Cloning::init(Mat &I, Mat &wmask) 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) void Cloning::normal_clone(Mat &I, Mat &mask, Mat &wmask, Mat &final, int num)
{ {
init(I,wmask); 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); 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 i=0;i < h; i++)
for(int j=0; j < w; j++) for(int j=0; j < w; j++)
{ {
factor.at<float>(i,j*channel+0) = blue; factor.at<float>(i,j*channel+0) = blue_mul;
factor.at<float>(i,j*channel+1) = green; factor.at<float>(i,j*channel+1) = green_mul;
factor.at<float>(i,j*channel+2) = red; factor.at<float>(i,j*channel+2) = red_mul;
} }
for(int i=0;i < h; i++) for(int i=0;i < h; i++)
for(int j=0; j < w; j++) for(int j=0; j < w; j++)
for(int c=0;c<channel;++c) 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); 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(srx32,CV_32FC3,1.0/255.0);
I.convertTo(sry32,CV_32FC3,1.0/255.0); I.convertTo(sry32,CV_32FC3,1.0/255.0);
Mat out = Mat(mask.size(),CV_8UC1); 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(); int channel = mask.channels();

View File

@ -100,7 +100,7 @@ TEST(Photo_SeamlessClone_mixed, regression)
TEST(Photo_SeamlessClone_featureExchange, 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_path1 = folder + "source1.png";
string original_path2 = folder + "destination1.png"; string original_path2 = folder + "destination1.png";
string original_path3 = folder + "mask.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; ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path2;
Mat result; Mat result;
textureFlattening(source, mask, result); textureFlattening(source, mask, result, 30, 45, 3);
imwrite(folder + "cloned.png", result); imwrite(folder + "cloned.png", result);

View File

@ -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);
}

View File

@ -56,18 +56,19 @@ char src[50];
char dest[50]; char dest[50];
int var = 0; int var = 0;
int flag = 0; int flag = 0, flag1 = 0, flag4 = 0;
int flag1 = 0;
int minx,miny,maxx,maxy,lenx,leny; int minx, miny, maxx, maxy, lenx, leny;
int minxd,minyd,maxxd,maxyd,lenxd,lenyd; int minxd, minyd, maxxd, maxyd, lenxd, lenyd;
int channel,num; int channel, num, kernel_size;
float alpha,beta; float alpha,beta;
float red, green, blue; float red, green, blue;
double low_t, high_t;
void source(int event, int x, int y, int, void*) 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) else if(num == 6)
{ {
textureFlattening(img0,res1,blend); textureFlattening(img0,res1,blend,low_t,high_t,kernel_size);
imshow("Texture Flattened", blend); imshow("Texture Flattened", blend);
waitKey(0); waitKey(0);
} }
@ -176,11 +177,12 @@ void source(int event, int x, int y, int, void*)
flag1 = 0; flag1 = 0;
minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN;
imshow("Source", img0); imshow("Source", img0);
if(num == 1 || num == 2 || num == 3)
imshow("Destination",img2);
drag = 0; drag = 0;
} }
} }
void destination(int event, int x, int y, int, void*) 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(); im1 = img2.clone();
if (event == EVENT_LBUTTONDOWN) if (event == EVENT_LBUTTONDOWN)
{ {
flag4 = 1;
if(flag1 == 1) if(flag1 == 1)
{ {
point = Point(x, y); point = Point(x, y);
@ -386,14 +389,12 @@ int main(int argc, char **argv)
res1 = Mat::zeros(img0.size(),CV_8UC1); res1 = Mat::zeros(img0.size(),CV_8UC1);
final = Mat::zeros(img0.size(),CV_8UC3); final = Mat::zeros(img0.size(),CV_8UC3);
//////////// source image /////////////////// //////////// source image ///////////////////
namedWindow("Source", 1); namedWindow("Source", 1);
setMouseCallback("Source", source, NULL); setMouseCallback("Source", source, NULL);
imshow("Source", img0); imshow("Source", img0);
} }
else if(num == 5) else if(num == 5)
{ {
@ -416,12 +417,20 @@ int main(int argc, char **argv)
setMouseCallback("Source", source, NULL); setMouseCallback("Source", source, NULL);
imshow("Source", img0); imshow("Source", img0);
} }
else if(num == 6) else if(num == 6)
{ {
checkfile(s); checkfile(s);
cout << "low_threshold: ";
cin >> low_t;
cout << "high_threshold: ";
cin >> high_t;
cout << "kernel_size: ";
cin >> kernel_size;
img0 = imread(src); img0 = imread(src);
res1 = Mat::zeros(img0.size(),CV_8UC1); res1 = Mat::zeros(img0.size(),CV_8UC1);
@ -434,13 +443,16 @@ int main(int argc, char **argv)
imshow("Source", img0); imshow("Source", img0);
} }
int flag3 = 0;
while(true) while(true)
{ {
char key = waitKey(0); char key = waitKey(0);
if(key == 'd') if(key == 'd' && flag3 == 0)
{ {
flag1 = 1; flag1 = 1;
flag3 = 1;
img1 = img0.clone(); img1 = img0.clone();
for(int i = var; i < numpts ; i++) for(int i = var; i < numpts ; i++)
pts[i] = point; pts[i] = point;
@ -490,13 +502,15 @@ int main(int argc, char **argv)
} }
var = 0; var = 0;
flag1 = 0; flag1 = 0;
flag3 = 0;
flag4 = 0;
minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN; minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN;
imshow("Source", img0); imshow("Source", img0);
if(num == 1 || num == 2 || num == 3) if(num == 1 || num == 2 || num == 3)
imshow("Destination",img2); imshow("Destination",img2);
drag = 0; 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); seamlessClone(img0,img2,res1,point,blend,num);
imshow("Cloned Image", blend); imshow("Cloned Image", blend);
@ -516,14 +530,12 @@ int main(int argc, char **argv)
} }
else if (num == 6 && key == 'c' && flag1 == 1) 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); imshow("Texture Flattened", blend);
imwrite("cloned.png",blend); imwrite("cloned.png",blend);
} }
else if(key == 'q') else if(key == 'q')
exit(0); exit(0);
} }
waitKey(0); waitKey(0);
} }

View File

@ -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);
}

107
samples/cpp/npr_demo.cpp Normal file
View File

@ -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);
}