added keyboard control
This commit is contained in:
parent
e170115ad0
commit
1ed0e44090
@ -63,7 +63,13 @@ enum
|
|||||||
{
|
{
|
||||||
NORMAL_CLONE = 1,
|
NORMAL_CLONE = 1,
|
||||||
MIXED_CLONE = 2,
|
MIXED_CLONE = 2,
|
||||||
FEATURE_EXCHANGE = 3
|
MONOCHROME_TRANSFER = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
RECURSIVE_FILTER = 1,
|
||||||
|
NC_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
|
||||||
@ -303,7 +309,9 @@ CV_EXPORTS_W void colorChange(InputArray src, InputArray mask, OutputArray dst,
|
|||||||
|
|
||||||
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, OutputArray dst);
|
CV_EXPORTS_W void textureFlattening(InputArray src, InputArray mask, OutputArray dst);
|
||||||
|
|
||||||
|
CV_EXPORTS_W void edgepreservefilter(InputArray _src, OutputArray _dst, int flags = 1, float sigma_h = 60, float sigma_r = 0.4);
|
||||||
|
|
||||||
} // cv
|
} // cv
|
||||||
|
|
||||||
|
@ -144,8 +144,12 @@ void cv::colorChange(InputArray _src, InputArray _mask, OutputArray _dst, float
|
|||||||
float blue = b;
|
float blue = b;
|
||||||
|
|
||||||
Mat gray = Mat::zeros(mask.size(),CV_8UC1);
|
Mat gray = Mat::zeros(mask.size(),CV_8UC1);
|
||||||
cvtColor(mask, gray, COLOR_BGR2GRAY);
|
|
||||||
|
|
||||||
|
if(mask.channels() == 3)
|
||||||
|
cvtColor(mask, gray, COLOR_BGR2GRAY );
|
||||||
|
else
|
||||||
|
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;
|
||||||
@ -178,7 +182,11 @@ void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst,
|
|||||||
float beta = b;
|
float beta = b;
|
||||||
|
|
||||||
Mat gray = Mat::zeros(mask.size(),CV_8UC1);
|
Mat gray = Mat::zeros(mask.size(),CV_8UC1);
|
||||||
cvtColor(mask, gray, COLOR_BGR2GRAY);
|
|
||||||
|
if(mask.channels() == 3)
|
||||||
|
cvtColor(mask, gray, COLOR_BGR2GRAY );
|
||||||
|
else
|
||||||
|
gray = mask;
|
||||||
|
|
||||||
Mat cs_mask = Mat::zeros(src.size(),CV_8UC3);
|
Mat cs_mask = Mat::zeros(src.size(),CV_8UC3);
|
||||||
|
|
||||||
@ -200,14 +208,39 @@ void cv::illuminationChange(InputArray _src, InputArray _mask, OutputArray _dst,
|
|||||||
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, OutputArray _dst)
|
|
||||||
|
void cv::textureFlattening(InputArray _src, InputArray _mask, OutputArray _dst)
|
||||||
{
|
{
|
||||||
|
|
||||||
Mat src = _src.getMat();
|
Mat src = _src.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();
|
||||||
|
|
||||||
Cloning obj;
|
Mat gray = Mat::zeros(mask.size(),CV_8UC1);
|
||||||
obj.texture_flatten(src,blend);
|
|
||||||
|
if(mask.channels() == 3)
|
||||||
|
cvtColor(mask, gray, COLOR_BGR2GRAY );
|
||||||
|
else
|
||||||
|
gray = mask;
|
||||||
|
|
||||||
|
Mat cs_mask = Mat::zeros(src.size(),CV_8UC3);
|
||||||
|
|
||||||
|
int channel = 3;
|
||||||
|
for(int i=0;i<mask.size().height;i++)
|
||||||
|
for(int j=0;j<mask.size().width;j++)
|
||||||
|
{
|
||||||
|
if(gray.at<uchar>(i,j) == 255)
|
||||||
|
{
|
||||||
|
for(int c=0;c<channel;c++)
|
||||||
|
{
|
||||||
|
cs_mask.at<uchar>(i,j*channel+c) = src.at<uchar>(i,j*channel+c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Cloning obj;
|
||||||
|
obj.texture_flatten(src,cs_mask,gray,blend);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +76,7 @@ class Cloning
|
|||||||
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, float green, float blue);
|
||||||
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 &final);
|
void texture_flatten(Mat &I, Mat &mask, Mat &wmask, Mat &final);
|
||||||
};
|
};
|
||||||
|
|
||||||
void Cloning::getGradientx( const Mat &img, Mat &gx)
|
void Cloning::getGradientx( const Mat &img, Mat &gx)
|
||||||
@ -782,91 +782,79 @@ void Cloning::illum_change(Mat &I, Mat &mask, Mat &wmask, Mat &final, float alph
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cloning::texture_flatten(Mat &I, Mat &final)
|
|
||||||
|
void Cloning::texture_flatten(Mat &I, Mat &mask, Mat &wmask, Mat &final)
|
||||||
{
|
{
|
||||||
|
init(I,wmask);
|
||||||
|
|
||||||
grx = Mat(I.size(),CV_32FC3);
|
int w = I.size().width;
|
||||||
gry = Mat(I.size(),CV_32FC3);
|
int h = I.size().height;
|
||||||
|
|
||||||
Mat out = Mat(I.size(),CV_8UC1);
|
getGradientx(I,grx);
|
||||||
|
getGradienty(I,gry);
|
||||||
|
|
||||||
getGradientx( I, grx);
|
getGradientx(mask,sgx);
|
||||||
getGradienty( I, gry);
|
getGradienty(mask,sgy);
|
||||||
|
|
||||||
Canny( I, out, 30, 45, 3 );
|
Mat Kernel(Size(3, 3), CV_8UC1);
|
||||||
|
Kernel.setTo(Scalar(1));
|
||||||
|
|
||||||
int channel = I.channels();
|
erode(wmask, wmask, Kernel);
|
||||||
|
erode(wmask, wmask, Kernel);
|
||||||
|
erode(wmask, wmask, Kernel);
|
||||||
|
|
||||||
for(int i=0;i<I.size().height;i++)
|
wmask.convertTo(smask,CV_32FC1,1.0/255.0);
|
||||||
for(int j=0;j<I.size().width;j++)
|
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 );
|
||||||
|
|
||||||
|
int channel = mask.channels();
|
||||||
|
|
||||||
|
for(int i=0;i<mask.size().height;i++)
|
||||||
|
for(int j=0;j<mask.size().width;j++)
|
||||||
for(int c=0;c<channel;c++)
|
for(int c=0;c<channel;c++)
|
||||||
{
|
{
|
||||||
if(out.at<uchar>(i,j) != 255)
|
if(out.at<uchar>(i,j) != 255)
|
||||||
{
|
{
|
||||||
grx.at<float>(i,j*channel+c) = 0.0;
|
sgx.at<float>(i,j*channel+c) = 0.0;
|
||||||
gry.at<float>(i,j*channel+c) = 0.0;
|
sgy.at<float>(i,j*channel+c) = 0.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
r_channel = Mat::zeros(I.size(),CV_8UC1);
|
for(int i=0;i < h; i++)
|
||||||
g_channel = Mat::zeros(I.size(),CV_8UC1);
|
for(int j=0; j < w; j++)
|
||||||
b_channel = Mat::zeros(I.size(),CV_8UC1);
|
for(int c=0;c<channel;++c)
|
||||||
|
{
|
||||||
|
srx32.at<float>(i,j*channel+c) =
|
||||||
|
(sgx.at<float>(i,j*channel+c)*smask.at<float>(i,j));
|
||||||
|
sry32.at<float>(i,j*channel+c) =
|
||||||
|
(sgy.at<float>(i,j*channel+c)*smask.at<float>(i,j));
|
||||||
|
}
|
||||||
|
|
||||||
for(int i=0;i<I.size().height;i++)
|
bitwise_not(wmask,wmask);
|
||||||
for(int j=0;j<I.size().width;j++)
|
|
||||||
{
|
|
||||||
r_channel.at<uchar>(i,j) = I.at<uchar>(i,j*3+0);
|
|
||||||
g_channel.at<uchar>(i,j) = I.at<uchar>(i,j*3+1);
|
|
||||||
b_channel.at<uchar>(i,j) = I.at<uchar>(i,j*3+2);
|
|
||||||
}
|
|
||||||
|
|
||||||
Mat gxx = Mat(I.size(),CV_32FC3);
|
wmask.convertTo(smask1,CV_32FC1,1.0/255.0);
|
||||||
Mat gyy = Mat(I.size(),CV_32FC3);
|
I.convertTo(grx32,CV_32FC3,1.0/255.0);
|
||||||
|
I.convertTo(gry32,CV_32FC3,1.0/255.0);
|
||||||
|
|
||||||
lapx(grx,gxx);
|
for(int i=0;i < h; i++)
|
||||||
lapy(gry,gyy);
|
for(int j=0; j < w; j++)
|
||||||
|
for(int c=0;c<channel;++c)
|
||||||
|
{
|
||||||
|
grx32.at<float>(i,j*channel+c) =
|
||||||
|
(grx.at<float>(i,j*channel+c)*smask1.at<float>(i,j));
|
||||||
|
gry32.at<float>(i,j*channel+c) =
|
||||||
|
(gry.at<float>(i,j*channel+c)*smask1.at<float>(i,j));
|
||||||
|
}
|
||||||
|
|
||||||
rx_channel = Mat(I.size(),CV_32FC1);
|
calc(I,grx32,gry32,srx32,sry32);
|
||||||
gx_channel = Mat(I.size(),CV_32FC1);
|
|
||||||
bx_channel = Mat(I.size(),CV_32FC1);
|
|
||||||
|
|
||||||
for(int i=0;i<I.size().height;i++)
|
for(int i=0;i<h;i++)
|
||||||
for(int j=0;j<I.size().width;j++)
|
for(int j=0;j<w;j++)
|
||||||
{
|
|
||||||
rx_channel.at<float>(i,j) = gxx.at<float>(i,j*3+0);
|
|
||||||
gx_channel.at<float>(i,j) = gxx.at<float>(i,j*3+1);
|
|
||||||
bx_channel.at<float>(i,j) = gxx.at<float>(i,j*3+2);
|
|
||||||
}
|
|
||||||
|
|
||||||
ry_channel = Mat(I.size(),CV_32FC1);
|
|
||||||
gy_channel = Mat(I.size(),CV_32FC1);
|
|
||||||
by_channel = Mat(I.size(),CV_32FC1);
|
|
||||||
|
|
||||||
for(int i=0;i<I.size().height;i++)
|
|
||||||
for(int j=0;j<I.size().width;j++)
|
|
||||||
{
|
|
||||||
ry_channel.at<float>(i,j) = gyy.at<float>(i,j*3+0);
|
|
||||||
gy_channel.at<float>(i,j) = gyy.at<float>(i,j*3+1);
|
|
||||||
by_channel.at<float>(i,j) = gyy.at<float>(i,j*3+2);
|
|
||||||
}
|
|
||||||
|
|
||||||
resultr = Mat(I.size(),CV_8UC1);
|
|
||||||
resultg = Mat(I.size(),CV_8UC1);
|
|
||||||
resultb = Mat(I.size(),CV_8UC1);
|
|
||||||
|
|
||||||
clock_t tic = clock();
|
|
||||||
|
|
||||||
|
|
||||||
poisson_solver(r_channel,rx_channel, ry_channel,resultr);
|
|
||||||
poisson_solver(g_channel,gx_channel, gy_channel,resultg);
|
|
||||||
poisson_solver(b_channel,bx_channel, by_channel,resultb);
|
|
||||||
|
|
||||||
clock_t toc = clock();
|
|
||||||
|
|
||||||
printf("Execution time: %f seconds\n", (double)(toc - tic) / CLOCKS_PER_SEC);
|
|
||||||
|
|
||||||
for(int i=0;i<I.size().height;i++)
|
|
||||||
for(int j=0;j<I.size().width;j++)
|
|
||||||
{
|
{
|
||||||
final.at<uchar>(i,j*3+0) = resultr.at<uchar>(i,j);
|
final.at<uchar>(i,j*3+0) = resultr.at<uchar>(i,j);
|
||||||
final.at<uchar>(i,j*3+1) = resultg.at<uchar>(i,j);
|
final.at<uchar>(i,j*3+1) = resultg.at<uchar>(i,j);
|
||||||
|
@ -164,14 +164,17 @@ TEST(Photo_SeamlessClone_illuminationChange, regression)
|
|||||||
TEST(Photo_SeamlessClone_textureFlattening, regression)
|
TEST(Photo_SeamlessClone_textureFlattening, regression)
|
||||||
{
|
{
|
||||||
string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Texture_Flattening/";
|
string folder = string(cvtest::TS::ptr()->get_data_path()) + "cloning/Texture_Flattening/";
|
||||||
string original_path = folder + "source1.png";
|
string original_path1 = folder + "source1.png";
|
||||||
|
string original_path2 = folder + "mask.png";
|
||||||
|
|
||||||
Mat source = imread(original_path, IMREAD_COLOR);
|
Mat source = imread(original_path1, IMREAD_COLOR);
|
||||||
|
Mat mask = imread(original_path2, IMREAD_COLOR);
|
||||||
|
|
||||||
ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path;
|
ASSERT_FALSE(source.empty()) << "Could not load source image " << original_path1;
|
||||||
|
ASSERT_FALSE(mask.empty()) << "Could not load mask image " << original_path2;
|
||||||
|
|
||||||
Mat result;
|
Mat result;
|
||||||
textureFlattening(source, result);
|
textureFlattening(source, mask, result);
|
||||||
|
|
||||||
imwrite(folder + "cloned.png", result);
|
imwrite(folder + "cloned.png", result);
|
||||||
|
|
||||||
|
@ -6,26 +6,31 @@
|
|||||||
*
|
*
|
||||||
* This tutorial demonstrates how to use OpenCV seamless cloning
|
* This tutorial demonstrates how to use OpenCV seamless cloning
|
||||||
* module.
|
* module.
|
||||||
* Flags:
|
*
|
||||||
* 1- NORMAL_CLONE
|
* 1- Normal Cloning
|
||||||
* 2- MIXED_CLONE
|
* 2- Mixed Cloning
|
||||||
* 3- FEATURE_EXCHANGE
|
* 3- Monochrome Transfer
|
||||||
|
* 4- Color Change
|
||||||
|
* 5- Illumination change
|
||||||
|
* 6- Texture Flattening
|
||||||
|
|
||||||
* The program takes as input a source and a destination image
|
* The program takes as input a source and a destination image (for 1-3 methods)
|
||||||
* and ouputs the cloned image.
|
* and ouputs the cloned image.
|
||||||
|
|
||||||
* Step 1:
|
* Step 1:
|
||||||
* -> In the source image, select the region of interest by left click mouse button. A Polygon ROI will be created by left clicking mouse button.
|
* -> In the source image, select the region of interest by left click mouse button. A Polygon ROI will be created by left clicking mouse button.
|
||||||
* -> To set the Polygon ROI, click the right mouse button.
|
* -> To set the Polygon ROI, click the right mouse button or 'd' key.
|
||||||
* -> To reset the region selected, click the middle mouse button.
|
* -> To reset the region selected, click the middle mouse button or 'r' key.
|
||||||
|
|
||||||
* Step 2:
|
* Step 2:
|
||||||
* -> In the destination image, select the point where you want to place the ROI in the image by left clicking mouse button.
|
* -> In the destination image, select the point where you want to place the ROI in the image by left clicking mouse button.
|
||||||
* -> To get the cloned result, click the right mouse button.
|
* -> To get the cloned result, click the right mouse button or 'c' key.
|
||||||
|
* -> To quit the program, use 'q' key.
|
||||||
|
*
|
||||||
* Result: The cloned image will be displayed.
|
* Result: The cloned image will be displayed.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
#include "opencv2/photo.hpp"
|
#include "opencv2/photo.hpp"
|
||||||
#include "opencv2/imgproc.hpp"
|
#include "opencv2/imgproc.hpp"
|
||||||
#include "opencv2/highgui.hpp"
|
#include "opencv2/highgui.hpp"
|
||||||
@ -47,6 +52,8 @@ Point* pts = new Point[100];
|
|||||||
Point* pts2 = new Point[100];
|
Point* pts2 = new Point[100];
|
||||||
Point* pts_diff = new Point[100];
|
Point* pts_diff = new Point[100];
|
||||||
|
|
||||||
|
char src[50];
|
||||||
|
char dest[50];
|
||||||
|
|
||||||
int var = 0;
|
int var = 0;
|
||||||
int flag = 0;
|
int flag = 0;
|
||||||
@ -57,6 +64,10 @@ int minxd,minyd,maxxd,maxyd,lenxd,lenyd;
|
|||||||
|
|
||||||
int channel,num;
|
int channel,num;
|
||||||
|
|
||||||
|
float alpha,beta;
|
||||||
|
|
||||||
|
float red, green, blue;
|
||||||
|
|
||||||
void source(int event, int x, int y, int, void*)
|
void source(int event, int x, int y, int, void*)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -93,20 +104,20 @@ void source(int event, int x, int y, int, void*)
|
|||||||
pts[i] = point;
|
pts[i] = point;
|
||||||
|
|
||||||
if(var!=0)
|
if(var!=0)
|
||||||
{
|
{
|
||||||
const Point* pts3[1] = {&pts[0]};
|
const Point* pts3[1] = {&pts[0]};
|
||||||
polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0);
|
polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i=0;i<var;i++)
|
for(int i=0;i<var;i++)
|
||||||
{
|
{
|
||||||
minx = min(minx,pts[i].x);
|
minx = min(minx,pts[i].x);
|
||||||
maxx = max(maxx,pts[i].x);
|
maxx = max(maxx,pts[i].x);
|
||||||
miny = min(miny,pts[i].y);
|
miny = min(miny,pts[i].y);
|
||||||
maxy = max(maxy,pts[i].y);
|
maxy = max(maxy,pts[i].y);
|
||||||
}
|
}
|
||||||
lenx = maxx - minx;
|
lenx = maxx - minx;
|
||||||
leny = maxy - miny;
|
leny = maxy - miny;
|
||||||
|
|
||||||
int mid_pointx = minx + lenx/2;
|
int mid_pointx = minx + lenx/2;
|
||||||
int mid_pointy = miny + leny/2;
|
int mid_pointy = miny + leny/2;
|
||||||
@ -117,21 +128,41 @@ void source(int event, int x, int y, int, void*)
|
|||||||
pts_diff[i].y = pts[i].y - mid_pointy;
|
pts_diff[i].y = pts[i].y - mid_pointy;
|
||||||
}
|
}
|
||||||
|
|
||||||
imshow("Source", img1);
|
imshow("Source", img1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event == EVENT_RBUTTONUP)
|
if (event == EVENT_RBUTTONUP)
|
||||||
{
|
{
|
||||||
flag = var;
|
flag = var;
|
||||||
|
|
||||||
final = Mat::zeros(img0.size(),CV_8UC3);
|
final = Mat::zeros(img0.size(),CV_8UC3);
|
||||||
res1 = Mat::zeros(img0.size(),CV_8UC1);
|
res1 = Mat::zeros(img0.size(),CV_8UC1);
|
||||||
const Point* pts4[1] = {&pts[0]};
|
const Point* pts4[1] = {&pts[0]};
|
||||||
|
|
||||||
fillPoly(res1, pts4,&numpts, 1, Scalar(255, 255, 255), 8, 0);
|
fillPoly(res1, pts4,&numpts, 1, Scalar(255, 255, 255), 8, 0);
|
||||||
bitwise_and(img0, img0, final,res1);
|
bitwise_and(img0, img0, final,res1);
|
||||||
|
|
||||||
imshow("Source", img1);
|
imshow("Source", img1);
|
||||||
|
|
||||||
|
if(num == 4)
|
||||||
|
{
|
||||||
|
colorChange(img0,res1,blend,red,green,blue);
|
||||||
|
imshow("Color Change Image", blend);
|
||||||
|
waitKey(0);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(num == 5)
|
||||||
|
{
|
||||||
|
illuminationChange(img0,res1,blend,alpha,beta);
|
||||||
|
imshow("Illum Change Image", blend);
|
||||||
|
waitKey(0);
|
||||||
|
}
|
||||||
|
else if(num == 6)
|
||||||
|
{
|
||||||
|
textureFlattening(img0,res1,blend);
|
||||||
|
imshow("Texture Flattened", blend);
|
||||||
|
waitKey(0);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (event == EVENT_MBUTTONDOWN)
|
if (event == EVENT_MBUTTONDOWN)
|
||||||
@ -194,95 +225,305 @@ void destination(int event, int x, int y, int, void*)
|
|||||||
maxyd = max(maxyd,pts2[i].y);
|
maxyd = max(maxyd,pts2[i].y);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(maxxd > im1.size().width || maxyd > im1.size().height || minxd < 0 || minyd < 0)
|
if(maxxd > im1.size().width || maxyd > im1.size().height || minxd < 0 || minyd < 0)
|
||||||
{
|
{
|
||||||
cout << "Index out of range" << endl;
|
cout << "Index out of range" << endl;
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
final1 = Mat::zeros(img2.size(),CV_8UC3);
|
final1 = Mat::zeros(img2.size(),CV_8UC3);
|
||||||
res = Mat::zeros(img2.size(),CV_8UC1);
|
res = Mat::zeros(img2.size(),CV_8UC1);
|
||||||
for(int i=miny, k=minyd;i<(miny+leny);i++,k++)
|
for(int i=miny, k=minyd;i<(miny+leny);i++,k++)
|
||||||
for(int j=minx,l=minxd ;j<(minx+lenx);j++,l++)
|
for(int j=minx,l=minxd ;j<(minx+lenx);j++,l++)
|
||||||
{
|
{
|
||||||
for(int c=0;c<channel;c++)
|
for(int c=0;c<channel;c++)
|
||||||
{
|
{
|
||||||
final1.at<uchar>(k,l*channel+c) = final.at<uchar>(i,j*channel+c);
|
final1.at<uchar>(k,l*channel+c) = final.at<uchar>(i,j*channel+c);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const Point* pts6[1] = {&pts2[0]};
|
const Point* pts6[1] = {&pts2[0]};
|
||||||
fillPoly(res, pts6, &numpts, 1, Scalar(255, 255, 255), 8, 0);
|
fillPoly(res, pts6, &numpts, 1, Scalar(255, 255, 255), 8, 0);
|
||||||
|
|
||||||
if(num == 1 || num == 2 || num == 3)
|
if(num == 1 || num == 2 || num == 3)
|
||||||
{
|
{
|
||||||
seamlessClone(img0,img2,res1,point,blend,num);
|
seamlessClone(img0,img2,res1,point,blend,num);
|
||||||
imshow("Cloned Image", blend);
|
imshow("Cloned Image", blend);
|
||||||
imwrite("cloned.png",blend);
|
imwrite("cloned.png",blend);
|
||||||
waitKey(0);
|
waitKey(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < flag ; i++)
|
for(int i = 0; i < flag ; i++)
|
||||||
{
|
{
|
||||||
pts2[i].x=0;
|
pts2[i].x=0;
|
||||||
pts2[i].y=0;
|
pts2[i].y=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN;
|
minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN;
|
||||||
}
|
}
|
||||||
|
|
||||||
im1.release();
|
im1.release();
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkfile(char *file)
|
||||||
|
{
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
printf("Enter %s Image: ",file);
|
||||||
|
if(!strcmp(file,"Source"))
|
||||||
|
{
|
||||||
|
cin >> src;
|
||||||
|
if(access( src, F_OK ) != -1 )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Image doesn't exist\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(!strcmp(file,"Destination"))
|
||||||
|
{
|
||||||
|
cin >> dest;
|
||||||
|
|
||||||
|
if(access( dest, F_OK ) != -1 )
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Image doesn't exist\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
cout << endl;
|
||||||
|
cout << "Cloning Module" << endl;
|
||||||
|
cout << "---------------" << endl;
|
||||||
|
cout << "Step 1:" << endl;
|
||||||
|
cout << " -> In the source image, select the region of interest by left click mouse button. A Polygon ROI will be created by left clicking mouse button." << endl;
|
||||||
|
cout << " -> To set the Polygon ROI, click the right mouse button or use 'd' key" << endl;
|
||||||
|
cout << " -> To reset the region selected, click the middle mouse button or use 'r' key." << endl;
|
||||||
|
|
||||||
if (argc != 3)
|
cout << "Step 2:" << endl;
|
||||||
|
cout << " -> In the destination image, select the point where you want to place the ROI in the image by left clicking mouse button." << endl;
|
||||||
|
cout << " -> To get the cloned result, click the right mouse button or use 'c' key." << endl;
|
||||||
|
cout << " -> To quit the program, use 'q' key." << 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: ";
|
||||||
|
cin >> num;
|
||||||
|
cout << endl;
|
||||||
|
|
||||||
|
char s[]="Source";
|
||||||
|
char d[]="Destination";
|
||||||
|
|
||||||
|
minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN;
|
||||||
|
|
||||||
|
minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN;
|
||||||
|
|
||||||
|
if(num == 1 || num == 2 || num == 3)
|
||||||
{
|
{
|
||||||
cout << "usage: " << argv[0] << " <source image>" << " <destination image>" << endl;
|
|
||||||
exit(1);
|
checkfile(s);
|
||||||
|
checkfile(d);
|
||||||
|
|
||||||
|
img0 = imread(src);
|
||||||
|
|
||||||
|
img2 = imread(dest);
|
||||||
|
|
||||||
|
channel = img0.channels();
|
||||||
|
|
||||||
|
res = Mat::zeros(img2.size(),CV_8UC1);
|
||||||
|
res1 = Mat::zeros(img0.size(),CV_8UC1);
|
||||||
|
final = Mat::zeros(img0.size(),CV_8UC3);
|
||||||
|
final1 = Mat::zeros(img2.size(),CV_8UC3);
|
||||||
|
//////////// source image ///////////////////
|
||||||
|
|
||||||
|
namedWindow("Source", 1);
|
||||||
|
setMouseCallback("Source", source, NULL);
|
||||||
|
imshow("Source", img0);
|
||||||
|
|
||||||
|
/////////// destination image ///////////////
|
||||||
|
|
||||||
|
namedWindow("Destination", 1);
|
||||||
|
setMouseCallback("Destination", destination, NULL);
|
||||||
|
imshow("Destination",img2);
|
||||||
|
|
||||||
|
}
|
||||||
|
else if(num == 4)
|
||||||
|
{
|
||||||
|
checkfile(s);
|
||||||
|
|
||||||
|
cout << "Enter RGB values: " << endl;
|
||||||
|
cout << "Red: ";
|
||||||
|
cin >> red;
|
||||||
|
|
||||||
|
cout << "Green: ";
|
||||||
|
cin >> green;
|
||||||
|
|
||||||
|
cout << "Blue: ";
|
||||||
|
cin >> blue;
|
||||||
|
|
||||||
|
img0 = imread(src);
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
checkfile(s);
|
||||||
|
|
||||||
|
cout << "alpha: ";
|
||||||
|
cin >> alpha;
|
||||||
|
|
||||||
|
cout << "beta: ";
|
||||||
|
cin >> beta;
|
||||||
|
|
||||||
|
img0 = imread(src);
|
||||||
|
|
||||||
|
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 == 6)
|
||||||
|
{
|
||||||
|
checkfile(s);
|
||||||
|
|
||||||
|
img0 = imread(src);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
char key = waitKey(0);
|
||||||
|
|
||||||
|
if(key == 'd')
|
||||||
|
{
|
||||||
|
flag1 = 1;
|
||||||
|
img1 = img0.clone();
|
||||||
|
for(int i = var; i < numpts ; i++)
|
||||||
|
pts[i] = point;
|
||||||
|
|
||||||
|
if(var!=0)
|
||||||
|
{
|
||||||
|
const Point* pts3[1] = {&pts[0]};
|
||||||
|
polylines( img1, pts3, &numpts,1, 1, Scalar(0,0,0), 2, 8, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i=0;i<var;i++)
|
||||||
|
{
|
||||||
|
minx = min(minx,pts[i].x);
|
||||||
|
maxx = max(maxx,pts[i].x);
|
||||||
|
miny = min(miny,pts[i].y);
|
||||||
|
maxy = max(maxy,pts[i].y);
|
||||||
|
}
|
||||||
|
lenx = maxx - minx;
|
||||||
|
leny = maxy - miny;
|
||||||
|
|
||||||
|
int mid_pointx = minx + lenx/2;
|
||||||
|
int mid_pointy = miny + leny/2;
|
||||||
|
|
||||||
|
for(int i=0;i<var;i++)
|
||||||
|
{
|
||||||
|
pts_diff[i].x = pts[i].x - mid_pointx;
|
||||||
|
pts_diff[i].y = pts[i].y - mid_pointy;
|
||||||
|
}
|
||||||
|
|
||||||
|
flag = var;
|
||||||
|
|
||||||
|
final = Mat::zeros(img0.size(),CV_8UC3);
|
||||||
|
res1 = Mat::zeros(img0.size(),CV_8UC1);
|
||||||
|
const Point* pts4[1] = {&pts[0]};
|
||||||
|
|
||||||
|
fillPoly(res1, pts4,&numpts, 1, Scalar(255, 255, 255), 8, 0);
|
||||||
|
bitwise_and(img0, img0, final,res1);
|
||||||
|
|
||||||
|
imshow("Source", img1);
|
||||||
|
}
|
||||||
|
else if(key == 'r')
|
||||||
|
{
|
||||||
|
for(int i = 0; i < numpts ; i++)
|
||||||
|
{
|
||||||
|
pts[i].x=0;
|
||||||
|
pts[i].y=0;
|
||||||
|
}
|
||||||
|
var = 0;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
else if ((num == 1 || num == 2 || num == 3) && key == 'c' && flag1 == 1)
|
||||||
|
{
|
||||||
|
seamlessClone(img0,img2,res1,point,blend,num);
|
||||||
|
imshow("Cloned Image", blend);
|
||||||
|
imwrite("cloned.png",blend);
|
||||||
|
}
|
||||||
|
else if (num == 4 && key == 'c' && flag1 == 1)
|
||||||
|
{
|
||||||
|
colorChange(img0,res1,blend,red,green,blue);
|
||||||
|
imshow("Color Change Image", blend);
|
||||||
|
imwrite("cloned.png",blend);
|
||||||
|
}
|
||||||
|
else if (num == 5 && key == 'c' && flag1 == 1)
|
||||||
|
{
|
||||||
|
illuminationChange(img0,res1,blend,alpha,beta);
|
||||||
|
imshow("Illum Change Image", blend);
|
||||||
|
imwrite("cloned.png",blend);
|
||||||
|
}
|
||||||
|
else if (num == 6 && key == 'c' && flag1 == 1)
|
||||||
|
{
|
||||||
|
textureFlattening(img0,res1,blend);
|
||||||
|
imshow("Texture Flattened", blend);
|
||||||
|
imwrite("cloned.png",blend);
|
||||||
|
}
|
||||||
|
else if(key == 'q')
|
||||||
|
exit(0);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Mat src = imread(argv[1]);
|
waitKey(0);
|
||||||
Mat dest = imread(argv[2]);
|
|
||||||
|
|
||||||
cout << "Flags:" << endl;
|
|
||||||
cout << "1- NORMAL_CLONE" << endl;
|
|
||||||
cout << "2- MIXED_CLONE" << endl;
|
|
||||||
cout << "3- FEATURE_EXCHANGE" << endl << endl;
|
|
||||||
|
|
||||||
cout << "Enter Flag:";
|
|
||||||
cin >> num;
|
|
||||||
|
|
||||||
minx = INT_MAX; miny = INT_MAX; maxx = INT_MIN; maxy = INT_MIN;
|
|
||||||
|
|
||||||
minxd = INT_MAX; minyd = INT_MAX; maxxd = INT_MIN; maxyd = INT_MIN;
|
|
||||||
|
|
||||||
img0 = src;
|
|
||||||
img2 = dest;
|
|
||||||
|
|
||||||
channel = img0.channels();
|
|
||||||
|
|
||||||
res = Mat::zeros(img2.size(),CV_8UC1);
|
|
||||||
res1 = Mat::zeros(img0.size(),CV_8UC1);
|
|
||||||
final = Mat::zeros(img0.size(),CV_8UC3);
|
|
||||||
final1 = Mat::zeros(img2.size(),CV_8UC3);
|
|
||||||
//////////// source image ///////////////////
|
|
||||||
|
|
||||||
namedWindow("Source", 1);
|
|
||||||
setMouseCallback("Source", source, NULL);
|
|
||||||
imshow("Source", img0);
|
|
||||||
|
|
||||||
/////////// destination image ///////////////
|
|
||||||
|
|
||||||
namedWindow("Destination", 1);
|
|
||||||
setMouseCallback("Destination", destination, NULL);
|
|
||||||
imshow("Destination",img2);
|
|
||||||
waitKey(0);
|
|
||||||
|
|
||||||
img0.release();
|
|
||||||
img1.release();
|
|
||||||
img2.release();
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user