Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
O
opencv_contrib
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
opencv_contrib
Commits
eeca8669
Commit
eeca8669
authored
Aug 28, 2014
by
Bellaktris
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
images -> vectors in xphoto/inpainting
parent
a5ba77a0
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
352 additions
and
205 deletions
+352
-205
inpainting.cpp
modules/xphoto/samples/inpainting.cpp
+8
-0
advanced_types.hpp
modules/xphoto/src/advanced_types.hpp
+67
-0
annf.hpp
modules/xphoto/src/annf.hpp
+17
-11
blending.hpp
modules/xphoto/src/blending.hpp
+46
-0
gcgraph.hpp
modules/xphoto/src/gcgraph.hpp
+1
-1
inpainting.cpp
modules/xphoto/src/inpainting.cpp
+108
-30
norm2.hpp
modules/xphoto/src/norm2.hpp
+7
-45
photomontage.hpp
modules/xphoto/src/photomontage.hpp
+98
-118
.DS_Store
...oto/testdata/xphoto/dct_image_denoising/results/.DS_Store
+0
-0
No files found.
modules/xphoto/samples/inpainting.cpp
View file @
eeca8669
...
...
@@ -6,6 +6,8 @@
#include "opencv2/core/utility.hpp"
#include "opencv2/imgproc/types_c.h"
#include <ctime>
#include <iostream>
const
char
*
keys
=
{
...
...
@@ -54,9 +56,15 @@ int main( int argc, const char** argv )
printf
(
"Cannot read image file: %s
\n
"
,
maskFilename
.
c_str
()
);
return
-
1
;
}
cv
::
threshold
(
mask
,
mask
,
128
,
255
,
CV_THRESH_BINARY
|
CV_THRESH_OTSU
);
cv
::
Mat
res
(
src
.
size
(),
src
.
type
());
int
time
=
clock
();
cv
::
xphoto
::
inpaint
(
src
,
mask
,
res
,
cv
::
xphoto
::
INPAINT_SHIFTMAP
);
std
::
cout
<<
"time = "
<<
(
clock
()
-
time
)
/
double
(
CLOCKS_PER_SEC
)
<<
std
::
endl
;
cv
::
cvtColor
(
res
,
res
,
CV_Lab2RGB
);
if
(
outFilename
==
""
)
...
...
modules/xphoto/src/advanced_types.hpp
0 → 100644
View file @
eeca8669
/*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) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// * 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 Intel Corporation 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*/
#ifndef __ADVANCED_TYPES_HPP__
#define __ADVANCED_TYPES_HPP__
#ifdef __cplusplus
#include <opencv2/core.hpp>
/********************* Functions *********************/
namespace
cv
{
template
<
typename
_Tp
,
typename
_Tp2
>
static
inline
cv
::
Size_
<
_Tp
>
operator
*
(
const
_Tp2
x
,
const
cv
::
Size_
<
_Tp
>
&
sz
)
{
return
cv
::
Size_
<
_Tp
>
(
cv
::
saturate_cast
<
_Tp
>
(
x
*
sz
.
width
),
cv
::
saturate_cast
<
_Tp
>
(
x
*
sz
.
height
));
}
template
<
typename
_Tp
,
typename
_Tp2
>
static
inline
cv
::
Size_
<
_Tp
>
operator
/
(
const
cv
::
Size_
<
_Tp
>
&
sz
,
const
_Tp2
x
)
{
return
cv
::
Size_
<
_Tp
>
(
cv
::
saturate_cast
<
_Tp
>
(
sz
.
width
/
x
),
cv
::
saturate_cast
<
_Tp
>
(
sz
.
height
/
x
));
}
}
// cv
#endif
#endif
/* __ADVANCED_TYPES_HPP__ */
\ No newline at end of file
modules/xphoto/src/annf.hpp
View file @
eeca8669
...
...
@@ -40,6 +40,16 @@
#ifndef __ANNF_HPP__
#define __ANNF_HPP__
#include <vector>
#include <stack>
#include <limits>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <fstream>
#include <time.h>
#include <functional>
#include "norm2.hpp"
#include "whs.hpp"
...
...
@@ -170,8 +180,8 @@ updateDist(const int leaf, const int &idx0, int &bestIdx, double &dist)
if
(
abs
(
ny
-
y
)
<
zeroThresh
&&
abs
(
nx
-
x
)
<
zeroThresh
)
continue
;
if
(
nx
>
width
-
1
||
nx
<
1
||
ny
>
height
-
1
||
ny
<
1
)
if
(
nx
>
=
width
-
1
||
nx
<
1
||
ny
>
=
height
-
1
||
ny
<
1
)
continue
;
double
ndist
=
norm2
(
data
[
idx0
],
data
[
idx
[
k
]]);
...
...
@@ -186,11 +196,11 @@ updateDist(const int leaf, const int &idx0, int &bestIdx, double &dist)
/************************** ANNF search **************************/
static
void
dominantTransforms
(
const
cv
::
Mat
&
img
,
std
::
vector
<
cv
::
Matx33f
>
&
transforms
,
static
void
dominantTransforms
(
const
cv
::
Mat
&
img
,
std
::
vector
<
cv
::
Point2i
>
&
transforms
,
const
int
nTransform
,
const
int
psize
)
{
const
int
zeroThresh
=
2
*
psize
;
const
int
leafNum
=
6
3
;
const
int
leafNum
=
6
4
;
/** Walsh-Hadamard Transformation **/
...
...
@@ -222,13 +232,13 @@ static void dominantTransforms(const cv::Mat &img, std::vector <cv::Matx33f> &tr
int
dy
[]
=
{
0
,
1
,
0
},
dx
[]
=
{
0
,
0
,
1
};
for
(
int
k
=
0
;
k
<
int
(
sizeof
(
dy
)
/
sizeof
(
int
)
);
++
k
)
if
(
i
-
dy
[
k
]
>=
0
&&
j
-
dx
[
k
]
>=
0
)
if
(
i
-
dy
[
k
]
>=
0
&&
j
-
dx
[
k
]
>=
0
)
{
int
neighbor
=
(
i
-
dy
[
k
])
*
whs
.
cols
+
(
j
-
dx
[
k
]);
int
leafIdx
=
(
dx
[
k
]
==
0
&&
dy
[
k
]
==
0
)
?
neighbor
:
annf
[
neighbor
]
+
dy
[
k
]
*
whs
.
cols
+
dx
[
k
];
kdTree
.
updateDist
(
leafIdx
,
current
,
annf
[
i
*
whs
.
cols
+
j
],
dist
);
annf
[
i
*
whs
.
cols
+
j
],
dist
);
}
}
...
...
@@ -265,15 +275,11 @@ static void dominantTransforms(const cv::Mat &img, std::vector <cv::Matx33f> &tr
std
::
partial_sort
(
amount
.
begin
(),
amount
.
begin
()
+
nTransform
,
amount
.
end
(),
std
::
greater
<
std
::
pair
<
double
,
int
>
>
()
);
std
::
ofstream
out
(
"C:/Users/Yury/Projects/inpaint/output/log.log"
);
transforms
.
resize
(
nTransform
);
for
(
int
i
=
0
;
i
<
nTransform
;
++
i
)
{
int
idx
=
amount
[
i
].
second
;
transforms
[
i
]
=
cv
::
Matx33f
(
1
,
0
,
float
(
shiftM
[
idx
].
x
),
0
,
1
,
float
(
shiftM
[
idx
].
y
),
0
,
0
,
1
);
out
<<
int
(
shiftM
[
idx
].
x
)
<<
","
<<
int
(
shiftM
[
idx
].
y
)
<<
std
::
endl
;
transforms
[
i
]
=
cv
::
Point2i
(
shiftM
[
idx
].
x
,
shiftM
[
idx
].
y
);
}
}
...
...
modules/xphoto/src/blending.hpp
0 → 100644
View file @
eeca8669
/*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) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009-2011, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// * 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 Intel Corporation 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*/
#ifndef __BLENDING_HPP__
#define __BLENDING_HPP__
#endif
/* __BLENDING_HPP__ */
\ No newline at end of file
modules/xphoto/src/gcgraph.hpp
View file @
eeca8669
...
...
@@ -254,7 +254,7 @@ TWeight GCGraph<TWeight>::maxFlow()
minWeight
=
MIN
(
minWeight
,
weight
);
CV_Assert
(
minWeight
>
0
);
}
weight
=
fabs
(
v
->
weight
);
weight
=
abs
(
TWeight
(
v
->
weight
)
);
minWeight
=
MIN
(
minWeight
,
weight
);
CV_Assert
(
minWeight
>
0
);
}
...
...
modules/xphoto/src/inpainting.cpp
View file @
eeca8669
...
...
@@ -60,59 +60,137 @@
#include "opencv2/highgui.hpp"
namespace
xphotoInternal
{
# include "photomontage.hpp"
# include "annf.hpp"
}
#include "photomontage.hpp"
#include "annf.hpp"
#include "advanced_types.hpp"
namespace
cv
{
namespace
xphoto
{
template
<
typename
Tp
,
unsigned
int
cn
>
static
void
shiftMapInpaint
(
const
Mat
&
src
,
const
Mat
&
mask
,
Mat
&
dst
,
const
int
nTransform
=
60
,
const
int
psize
=
8
)
static
void
shiftMapInpaint
(
const
Mat
&
_src
,
const
Mat
&
_
mask
,
Mat
&
dst
,
const
int
nTransform
=
60
,
const
int
psize
=
8
,
const
cv
::
Point2i
dsize
=
cv
::
Point2i
(
800
,
600
)
)
{
/** Preparing input **/
cv
::
Mat
img
;
cv
::
Mat
src
,
mask
,
img
,
dmask
,
ddmask
;
const
float
ls
=
std
::
max
(
/**/
std
::
min
(
/*...*/
std
::
max
(
_src
.
rows
,
_src
.
cols
)
/
float
(
dsize
.
x
),
std
::
min
(
_src
.
rows
,
_src
.
cols
)
/
float
(
dsize
.
y
)
),
1.0
f
/**/
);
cv
::
resize
(
_mask
,
mask
,
_mask
.
size
()
/
ls
,
0
,
0
,
cv
::
INTER_NEAREST
);
cv
::
resize
(
_src
,
src
,
_src
.
size
()
/
ls
,
0
,
0
,
cv
::
INTER_AREA
);
src
.
convertTo
(
img
,
CV_32F
);
img
.
setTo
(
0
,
255
-
mask
);
cv
::
erode
(
mask
,
dmask
,
cv
::
Mat
(),
cv
::
Point
(
-
1
,
-
1
),
2
);
cv
::
erode
(
dmask
,
ddmask
,
cv
::
Mat
(),
cv
::
Point
(
-
1
,
-
1
),
2
);
std
::
vector
<
Point2i
>
pPath
;
cv
::
Mat_
<
int
>
backref
(
ddmask
.
size
(),
int
(
-
1
)
);
for
(
int
i
=
0
;
i
<
ddmask
.
rows
;
++
i
)
{
uchar
*
dmask_data
=
(
uchar
*
)
ddmask
.
template
ptr
<
uchar
>
(
i
);
int
*
backref_data
=
(
int
*
)
backref
.
template
ptr
<
int
>
(
i
);
for
(
int
j
=
0
;
j
<
ddmask
.
cols
;
++
j
)
if
(
dmask_data
[
j
]
==
0
)
{
backref_data
[
j
]
=
int
(
pPath
.
size
());
pPath
.
push_back
(
cv
::
Point
(
j
,
i
)
);
}
}
/** ANNF computation **/
std
::
vector
<
Matx33f
>
transforms
(
nTransform
);
xphotoInternal
::
dominantTransforms
(
img
,
transforms
,
nTransform
,
psize
);
std
::
vector
<
cv
::
Point2i
>
transforms
(
nTransform
);
dominantTransforms
(
img
,
transforms
,
nTransform
,
psize
);
transforms
.
push_back
(
cv
::
Point2i
(
0
,
0
)
);
/** Warping **/
std
::
vector
<
Mat
>
images
(
nTransform
+
1
);
// source image transformed with transforms
std
::
vector
<
Mat
>
masks
(
nTransform
+
1
);
// definition domain for current shift
std
::
vector
<
std
::
vector
<
cv
::
Vec
<
float
,
cn
>
>
>
pointSeq
(
pPath
.
size
()
);
// source image transformed with transforms
std
::
vector
<
int
>
labelSeq
(
pPath
.
size
()
);
// resulting label sequence
std
::
vector
<
std
::
vector
<
int
>
>
linkIdx
(
pPath
.
size
()
);
// neighbor links for pointSeq elements
std
::
vector
<
std
::
vector
<
unsigned
char
>
>
maskSeq
(
pPath
.
size
()
);
// corresponding mask
Mat_
<
uchar
>
invMask
=
255
-
mask
;
dilate
(
invMask
,
invMask
,
Mat
(),
Point
(
-
1
,
-
1
),
2
);
for
(
size_t
i
=
0
;
i
<
pPath
.
size
();
++
i
)
{
for
(
int
j
=
0
;
j
<
nTransform
+
1
;
++
j
)
{
cv
::
Point2i
u
=
pPath
[
i
]
+
transforms
[
j
];
uchar
xmask
=
dmask
.
template
at
<
uchar
>
(
pPath
[
i
]);
img
.
copyTo
(
images
[
0
]
)
;
mask
.
copyTo
(
masks
[
0
]
)
;
unsigned
char
vmask
=
0
;
cv
::
Vec
<
float
,
cn
>
vimg
=
0
;
for
(
int
i
=
0
;
i
<
nTransform
;
++
i
)
{
warpPerspective
(
images
[
0
],
images
[
i
+
1
],
transforms
[
i
],
images
[
0
].
size
(),
INTER_LINEAR
);
if
(
u
.
y
<
src
.
rows
&&
u
.
y
>=
0
&&
u
.
x
<
src
.
cols
&&
u
.
x
>=
0
)
{
if
(
xmask
==
0
||
j
==
nTransform
)
vmask
=
mask
.
template
at
<
uchar
>
(
u
);
vimg
=
img
.
template
at
<
cv
::
Vec
<
float
,
cn
>
>
(
u
);
}
maskSeq
[
i
].
push_back
(
vmask
);
pointSeq
[
i
].
push_back
(
vimg
);
if
(
vmask
!=
0
)
labelSeq
[
i
]
=
j
;
}
cv
::
Point2i
p
[]
=
{
pPath
[
i
]
+
cv
::
Point2i
(
0
,
+
1
),
pPath
[
i
]
+
cv
::
Point2i
(
+
1
,
0
)
};
warpPerspective
(
masks
[
0
],
masks
[
i
+
1
],
transforms
[
i
],
masks
[
0
].
size
(),
INTER_NEAREST
);
cv
::
imwrite
(
cv
::
format
(
"C:/Users/Yury/Projects/inpaint/output/%d.png"
,
i
),
images
[
i
]);
masks
[
i
+
1
]
&=
invMask
;
for
(
int
j
=
0
;
j
<
sizeof
(
p
)
/
sizeof
(
cv
::
Point2i
);
++
j
)
if
(
p
[
j
].
y
<
src
.
rows
&&
p
[
j
].
y
>=
0
&&
p
[
j
].
x
<
src
.
cols
&&
p
[
j
].
x
>=
0
)
linkIdx
[
i
].
push_back
(
backref
(
p
[
j
])
);
else
linkIdx
[
i
].
push_back
(
-
1
);
}
/** Stitching **/
Mat
photomontageResult
;
xphotoInternal
::
Photomontage
<
cv
::
Vec
<
float
,
cn
>
>
(
images
,
masks
)
.
assignResImage
(
photomontageResult
);
photomontage
(
pointSeq
,
maskSeq
,
linkIdx
,
labelSeq
);
/** Upscaling **/
if
(
ls
!=
1
)
{
// _src.convertTo( img, CV_32F );
//
// for (size_t k = 0; k < pPath.size(); ++k)
// {
// int clabel = labelSeq[k];
// int nearSeam = 0;
//
// for (size_t i = 0; i < linkIdx[k].size(); ++i)
// nearSeam |= linkIdx[k] == -1
// || clabel != labelSeq[linkIdx[k][i]];
//
// if (nearSeam == 0)
// ...
// else
// {
// ...
// }
// }
//
// xphotoInternal::Photomontage < cv::Vec <float, cn> > ( /*...*/
// pointSeq, maskSeq, linkIdx, labelSeq );
}
/** Writing result **/
photomontageResult
.
convertTo
(
dst
,
dst
.
type
()
);
for
(
size_t
i
=
0
;
i
<
labelSeq
.
size
();
++
i
)
{
cv
::
Vec
<
float
,
cn
>
val
=
pointSeq
[
i
][
labelSeq
[
i
]];
img
.
template
at
<
cv
::
Vec
<
float
,
cn
>
>
(
pPath
[
i
])
=
val
;
}
img
.
convertTo
(
dst
,
dst
.
type
()
);
}
template
<
typename
Tp
,
unsigned
int
cn
>
...
...
modules/xphoto/src/norm2.hpp
View file @
eeca8669
...
...
@@ -40,52 +40,13 @@
#ifndef __NORM2_HPP__
#define __NORM2_HPP__
/************************ General template *************************/
template
<
typename
_Tp
>
struct
is_norm2_type
:
std
::
integral_constant
<
bool
,
!
std
::
is_unsigned
<
_Tp
>::
value
&&
!
std
::
is_same
<
_Tp
,
char
>::
value
>
{};
template
<
typename
Tp
>
static
inline
Tp
sqr
(
Tp
x
)
{
return
x
*
x
;
}
template
<
typename
Tp
,
int
cn
>
static
inline
Tp
sqr
(
cv
::
Vec
<
Tp
,
cn
>
x
)
{
return
x
.
dot
(
x
);
}
template
<
typename
Tp
>
static
inline
Tp
norm2
(
const
Tp
&
a
,
const
Tp
&
b
)
{
return
sqr
(
a
-
b
);
}
template
<
typename
Tp
,
int
cn
>
static
inline
Tp
norm2
(
const
cv
::
Vec
<
Tp
,
cn
>
&
a
,
const
cv
::
Vec
<
Tp
,
cn
>
&
b
)
{
return
sqr
(
a
-
b
);
}
/******************* uchar, char, ushort, uint *********************/
static
inline
int
norm2
(
const
uchar
&
a
,
const
uchar
&
b
)
{
return
sqr
(
int
(
a
)
-
int
(
b
));
}
template
<
int
cn
>
static
inline
int
norm2
(
const
cv
::
Vec
<
uchar
,
cn
>
&
a
,
const
cv
::
Vec
<
uchar
,
cn
>
&
b
)
{
return
sqr
(
cv
::
Vec
<
int
,
cn
>
(
a
)
-
cv
::
Vec
<
int
,
cn
>
(
b
)
);
}
static
inline
int
norm2
(
const
char
&
a
,
const
char
&
b
)
{
return
sqr
(
int
(
a
)
-
int
(
b
));
}
template
<
int
cn
>
static
inline
int
norm2
(
const
cv
::
Vec
<
char
,
cn
>
&
a
,
const
cv
::
Vec
<
char
,
cn
>
&
b
)
{
return
sqr
(
cv
::
Vec
<
int
,
cn
>
(
a
)
-
cv
::
Vec
<
int
,
cn
>
(
b
)
);
}
static
inline
short
norm2
(
const
ushort
&
a
,
const
ushort
&
b
)
{
return
sqr
<
short
>
(
short
(
a
)
-
short
(
b
));
}
template
<
int
cn
>
static
inline
short
norm2
(
const
cv
::
Vec
<
ushort
,
cn
>
&
a
,
const
cv
::
Vec
<
ushort
,
cn
>
&
b
)
{
return
sqr
(
cv
::
Vec
<
short
,
cn
>
(
a
)
-
cv
::
Vec
<
short
,
cn
>
(
b
)
);
}
static
inline
int
norm2
(
const
uint
&
a
,
const
uint
&
b
)
{
return
sqr
(
int
(
a
)
-
int
(
b
));
}
template
<
int
cn
>
static
inline
int
norm2
(
const
cv
::
Vec
<
uint
,
cn
>
&
a
,
const
cv
::
Vec
<
uint
,
cn
>
&
b
)
{
return
sqr
(
cv
::
Vec
<
int
,
cn
>
(
a
)
-
cv
::
Vec
<
int
,
cn
>
(
b
)
);
}
template
<
typename
_Tp
,
int
cn
>
static
inline
typename
std
::
enable_if
<
is_norm2_type
<
_Tp
>::
value
,
_Tp
>::
type
norm2
(
cv
::
Vec
<
_Tp
,
cn
>
a
,
cv
::
Vec
<
_Tp
,
cn
>
b
)
{
return
(
a
-
b
).
dot
(
a
-
b
);
}
template
<
typename
_Tp
>
static
inline
typename
std
::
enable_if
<
is_norm2_type
<
_Tp
>::
value
,
_Tp
>::
type
norm2
(
const
_Tp
&
a
,
const
_Tp
&
b
)
{
return
(
a
-
b
)
*
(
a
-
b
);
}
#endif
/* __NORM2_HPP__ */
\ No newline at end of file
modules/xphoto/src/photomontage.hpp
View file @
eeca8669
...
...
@@ -40,13 +40,33 @@
#ifndef __PHOTOMONTAGE_HPP__
#define __PHOTOMONTAGE_HPP__
#include <vector>
#include <stack>
#include <limits>
#include <algorithm>
#include <iterator>
#include <iostream>
#include <fstream>
#include <time.h>
#include <functional>
#include "norm2.hpp"
#include "blending.hpp"
namespace
gcoptimization
{
#include "gcgraph.hpp"
#define GCInfinity 10*1000*1000*1000.0
typedef
float
TWeight
;
typedef
int
labelTp
;
#define GCInfinity 10*1000*1000
#define eps 0.02
template
<
typename
Tp
>
static
int
min_idx
(
std
::
vector
<
Tp
>
vec
)
{
return
int
(
std
::
min_element
(
vec
.
begin
(),
vec
.
end
())
-
vec
.
begin
()
);
...
...
@@ -58,22 +78,17 @@ template <typename Tp> static int min_idx(std::vector <Tp> vec)
template
<
typename
Tp
>
class
Photomontage
{
private
:
const
std
::
vector
<
cv
::
Mat
>
&
images
;
// vector of images for different labels
const
std
::
vector
<
cv
::
Mat
>
&
masks
;
// vector of definition domains for each image
const
std
::
vector
<
std
::
vector
<
Tp
>
>
&
pointSeq
;
// points for stitching
const
std
::
vector
<
std
::
vector
<
uchar
>
>
&
maskSeq
;
// corresponding masks
std
::
vector
<
cv
::
Mat
>
labelings
;
// vector of labelings for different expansions
std
::
vector
<
double
>
distances
;
// vector of max-flow costs for different labeling
const
std
::
vector
<
std
::
vector
<
int
>
>
&
linkIdx
;
// vector of neighbors for pointSeq
const
int
height
;
const
int
width
;
const
int
type
;
const
int
channels
;
const
int
lsize
;
std
::
vector
<
std
::
vector
<
labelTp
>
>
labelings
;
// vector of labelings
std
::
vector
<
TWeight
>
distances
;
// vector of max-flow costs for different labeling
cv
::
Mat
x_i
;
// current best labeling
std
::
vector
<
labelTp
>
&
labelSeq
;
// current best labeling
double
singleExpansion
(
const
int
alpha
);
// single neighbor computing
void
gradientDescent
();
// gradient descent in alpha-expansion topology
TWeight
singleExpansion
(
const
int
alpha
);
// single neighbor computing
class
ParallelExpansion
:
public
cv
::
ParallelLoopBody
{
...
...
@@ -88,121 +103,86 @@ private:
for
(
int
i
=
range
.
start
;
i
<=
range
.
end
-
1
;
++
i
)
main
->
distances
[
i
]
=
main
->
singleExpansion
(
i
);
}
};
}
parallelExpansion
;
void
operator
=
(
const
Photomontage
<
Tp
>&
)
const
{};
protected
:
virtual
double
dist
(
const
Tp
&
l1p1
,
const
Tp
&
l1p2
,
const
Tp
&
l2p1
,
const
Tp
&
l2p2
);
virtual
void
setWeights
(
GCGraph
<
double
>
&
graph
,
const
cv
::
Point
&
pA
,
const
cv
::
Point
&
pB
,
const
int
lA
,
const
int
lB
,
const
int
lX
);
virtual
TWeight
dist
(
const
Tp
&
l1p1
,
const
Tp
&
l1p2
,
const
Tp
&
l2p1
,
const
Tp
&
l2p2
);
virtual
void
setWeights
(
GCGraph
<
TWeight
>
&
graph
,
const
int
idx1
,
const
int
idx2
,
const
int
l1
,
const
int
l2
,
const
int
lx
);
public
:
Photomontage
(
const
std
::
vector
<
cv
::
Mat
>
&
images
,
const
std
::
vector
<
cv
::
Mat
>
&
masks
);
virtual
~
Photomontage
(){};
void
gradientDescent
();
// gradient descent in alpha-expansion topology
void
assignLabeling
(
cv
::
Mat
&
img
);
void
assignResImage
(
cv
::
Mat
&
img
);
Photomontage
(
const
std
::
vector
<
std
::
vector
<
Tp
>
>
&
pointSeq
,
const
std
::
vector
<
std
::
vector
<
uchar
>
>
&
maskSeq
,
const
std
::
vector
<
std
::
vector
<
int
>
>
&
linkIdx
,
std
::
vector
<
labelTp
>
&
labelSeq
);
virtual
~
Photomontage
(){};
};
template
<
typename
Tp
>
inline
double
Photomontage
<
Tp
>::
template
<
typename
Tp
>
inline
TWeight
Photomontage
<
Tp
>::
dist
(
const
Tp
&
l1p1
,
const
Tp
&
l1p2
,
const
Tp
&
l2p1
,
const
Tp
&
l2p2
)
{
return
norm2
(
l1p1
,
l2p1
)
+
norm2
(
l1p2
,
l2p2
);
}
template
<
typename
Tp
>
void
Photomontage
<
Tp
>::
setWeights
(
GCGraph
<
double
>
&
graph
,
const
cv
::
Point
&
pA
,
const
cv
::
Point
&
pB
,
const
int
lA
,
const
int
lB
,
const
int
lX
)
setWeights
(
GCGraph
<
TWeight
>
&
graph
,
const
int
idx1
,
const
int
idx2
,
const
int
l1
,
const
int
l2
,
const
int
lx
)
{
if
(
l
A
==
lB
)
if
(
l
1
==
l2
)
{
/** Link from A to B **/
double
weightAB
=
dist
(
images
[
lA
].
template
at
<
Tp
>
(
pA
),
images
[
lA
].
template
at
<
Tp
>
(
pB
),
images
[
lX
].
template
at
<
Tp
>
(
pA
),
images
[
lX
].
template
at
<
Tp
>
(
pB
)
);
graph
.
addEdges
(
int
(
pA
.
y
*
width
+
pA
.
x
),
int
(
pB
.
y
*
width
+
pB
.
x
),
weightAB
,
weightAB
);
TWeight
weightAB
=
dist
(
pointSeq
[
idx1
][
l1
],
pointSeq
[
idx2
][
l1
],
pointSeq
[
idx1
][
lx
],
pointSeq
[
idx2
][
lx
]
);
graph
.
addEdges
(
idx1
,
idx2
,
weightAB
,
weightAB
);
}
else
{
int
X
=
graph
.
addVtx
();
/** Link from X to sink **/
double
weightXS
=
dist
(
images
[
lA
].
template
at
<
Tp
>
(
pA
),
images
[
lA
].
template
at
<
Tp
>
(
pB
),
images
[
lB
].
template
at
<
Tp
>
(
pA
),
images
[
lB
].
template
at
<
Tp
>
(
pB
)
);
graph
.
addTermWeights
(
X
,
0
,
weightXS
);
TWeight
weightXS
=
dist
(
pointSeq
[
idx1
][
l1
],
pointSeq
[
idx2
][
l1
],
pointSeq
[
idx1
][
l2
],
pointSeq
[
idx2
][
l2
]
);
graph
.
addTermWeights
(
X
,
0
,
weightXS
);
/** Link from A to X **/
double
weightAX
=
dist
(
images
[
lA
].
template
at
<
Tp
>
(
pA
),
images
[
lA
].
template
at
<
Tp
>
(
pB
),
images
[
lX
].
template
at
<
Tp
>
(
pA
),
images
[
lX
].
template
at
<
Tp
>
(
pB
)
);
graph
.
addEdges
(
int
(
pA
.
y
*
width
+
pA
.
x
),
X
,
weightAX
,
weightAX
);
TWeight
weightAX
=
dist
(
pointSeq
[
idx1
][
l1
],
pointSeq
[
idx2
][
l1
],
pointSeq
[
idx1
][
lx
],
pointSeq
[
idx2
][
lx
]
);
graph
.
addEdges
(
idx1
,
X
,
weightAX
,
weightAX
);
/** Link from X to B **/
double
weightXB
=
dist
(
images
[
lX
].
template
at
<
Tp
>
(
pA
),
images
[
lX
].
template
at
<
Tp
>
(
pB
),
images
[
lB
].
template
at
<
Tp
>
(
pA
),
images
[
lB
].
template
at
<
Tp
>
(
pB
)
);
graph
.
addEdges
(
X
,
int
(
pB
.
y
*
width
+
pB
.
x
),
weightXB
,
weightXB
);
TWeight
weightXB
=
dist
(
pointSeq
[
idx1
][
lx
],
pointSeq
[
idx1
][
lx
],
pointSeq
[
idx1
][
l2
],
pointSeq
[
idx1
][
l2
]
);
graph
.
addEdges
(
X
,
idx2
,
weightXB
,
weightXB
);
}
}
template
<
typename
Tp
>
double
Photomontage
<
Tp
>::
template
<
typename
Tp
>
TWeight
Photomontage
<
Tp
>::
singleExpansion
(
const
int
alpha
)
{
int
actualEdges
=
(
height
-
1
)
*
width
+
height
*
(
width
-
1
);
GCGraph
<
double
>
graph
(
actualEdges
+
height
*
width
,
2
*
actualEdges
);
GCGraph
<
TWeight
>
graph
(
3
*
int
(
pointSeq
.
size
()),
4
*
int
(
pointSeq
.
size
())
);
/** Terminal links **/
for
(
int
i
=
0
;
i
<
height
;
++
i
)
{
const
uchar
*
maskAlphaRow
=
masks
[
alpha
].
template
ptr
<
uchar
>
(
i
);
const
int
*
labelRow
=
(
const
int
*
)
x_i
.
template
ptr
<
int
>
(
i
);
for
(
int
j
=
0
;
j
<
width
;
++
j
)
graph
.
addTermWeights
(
graph
.
addVtx
(),
maskAlphaRow
[
j
]
?
0
:
GCInfinity
,
masks
[
labelRow
[
j
]
].
template
at
<
uchar
>
(
i
,
j
)
?
0
:
GCInfinity
);
}
for
(
size_t
i
=
0
;
i
<
maskSeq
.
size
();
++
i
)
graph
.
addTermWeights
(
graph
.
addVtx
(),
maskSeq
[
i
][
alpha
]
?
TWeight
(
0
)
:
TWeight
(
GCInfinity
),
0
);
/** Neighbor links **/
for
(
int
i
=
0
;
i
<
height
-
1
;
++
i
)
{
const
int
*
currentRow
=
(
const
int
*
)
x_i
.
template
ptr
<
int
>
(
i
);
const
int
*
nextRow
=
(
const
int
*
)
x_i
.
template
ptr
<
int
>
(
i
+
1
);
for
(
int
j
=
0
;
j
<
width
-
1
;
++
j
)
{
setWeights
(
graph
,
cv
::
Point
(
j
,
i
),
cv
::
Point
(
j
+
1
,
i
),
currentRow
[
j
],
currentRow
[
j
+
1
],
alpha
);
setWeights
(
graph
,
cv
::
Point
(
j
,
i
),
cv
::
Point
(
j
,
i
+
1
),
currentRow
[
j
],
nextRow
[
j
],
alpha
);
}
setWeights
(
graph
,
cv
::
Point
(
width
-
1
,
i
),
cv
::
Point
(
width
-
1
,
i
+
1
),
currentRow
[
width
-
1
],
nextRow
[
width
-
1
],
alpha
);
}
const
int
*
currentRow
=
(
const
int
*
)
x_i
.
template
ptr
<
int
>
(
height
-
1
);
for
(
int
i
=
0
;
i
<
width
-
1
;
++
i
)
setWeights
(
graph
,
cv
::
Point
(
i
,
height
-
1
),
cv
::
Point
(
i
+
1
,
height
-
1
),
currentRow
[
i
],
currentRow
[
i
+
1
],
alpha
);
for
(
size_t
i
=
0
;
i
<
pointSeq
.
size
();
++
i
)
for
(
size_t
j
=
0
;
j
<
linkIdx
[
i
].
size
();
++
j
)
if
(
linkIdx
[
i
][
j
]
!=
-
1
)
setWeights
(
graph
,
int
(
i
),
linkIdx
[
i
][
j
],
labelSeq
[
i
],
labelSeq
[
linkIdx
[
i
][
j
]],
alpha
);
/** Max-flow computation **/
double
result
=
graph
.
maxFlow
();
TWeight
result
=
graph
.
maxFlow
();
/** Writing results **/
labelings
[
alpha
].
create
(
height
,
width
,
CV_32SC1
);
for
(
int
i
=
0
;
i
<
height
;
++
i
)
{
const
int
*
inRow
=
(
const
int
*
)
x_i
.
template
ptr
<
int
>
(
i
);
int
*
outRow
=
(
int
*
)
labelings
[
alpha
].
template
ptr
<
int
>
(
i
);
for
(
int
j
=
0
;
j
<
width
;
++
j
)
outRow
[
j
]
=
graph
.
inSourceSegment
(
i
*
width
+
j
)
?
inRow
[
j
]
:
alpha
;
}
for
(
size_t
i
=
0
;
i
<
pointSeq
.
size
();
++
i
)
labelings
[
i
][
alpha
]
=
graph
.
inSourceSegment
(
int
(
i
))
?
labelSeq
[
i
]
:
alpha
;
return
result
;
}
...
...
@@ -210,55 +190,55 @@ singleExpansion(const int alpha)
template
<
typename
Tp
>
void
Photomontage
<
Tp
>::
gradientDescent
()
{
double
optValue
=
std
::
numeric_limits
<
double
>::
max
();
TWeight
optValue
=
std
::
numeric_limits
<
TWeight
>::
max
();
for
(
int
num
=
-
1
;
/**/
;
num
=
-
1
)
{
parallel_for_
(
cv
::
Range
(
0
,
lsize
),
ParallelExpansion
(
this
)
);
int
range
=
int
(
pointSeq
[
0
].
size
()
);
parallel_for_
(
cv
::
Range
(
0
,
range
),
parallelExpansion
);
int
minIndex
=
min_idx
(
distances
);
double
minValue
=
distances
[
minIndex
];
TWeight
minValue
=
distances
[
minIndex
];
std
::
cerr
<<
optValue
<<
" "
<<
*
max_element
(
distances
.
begin
(),
distances
.
end
())
<<
std
::
endl
;
if
(
minValue
<
(
1.00
-
eps
)
*
optValue
)
optValue
=
distances
[
num
=
minIndex
];
if
(
num
==
-
1
)
break
;
labelings
[
num
].
copyTo
(
x_i
);
for
(
size_t
i
=
0
;
i
<
labelSeq
.
size
();
++
i
)
labelSeq
[
i
]
=
labelings
[
i
][
num
];
}
}
template
<
typename
Tp
>
void
Photomontage
<
Tp
>::
assignLabeling
(
cv
::
Mat
&
img
)
template
<
typename
Tp
>
Photomontage
<
Tp
>::
Photomontage
(
const
std
::
vector
<
std
::
vector
<
Tp
>
>
&
_pointSeq
,
const
std
::
vector
<
std
::
vector
<
uchar
>
>
&
_maskSeq
,
const
std
::
vector
<
std
::
vector
<
int
>
>
&
_linkIdx
,
std
::
vector
<
labelTp
>
&
_labelSeq
)
:
pointSeq
(
_pointSeq
),
maskSeq
(
_maskSeq
),
linkIdx
(
_linkIdx
),
distances
(
pointSeq
[
0
].
size
()),
labelSeq
(
_labelSeq
),
parallelExpansion
(
this
)
{
x_i
.
setTo
(
0
);
gradientDescent
();
x_i
.
copyTo
(
img
);
size_t
lsize
=
pointSeq
[
0
].
size
(
);
labelings
.
assign
(
pointSeq
.
size
(),
std
::
vector
<
labelTp
>
(
lsize
)
);
}
template
<
typename
Tp
>
void
Photomontage
<
Tp
>::
assignResImage
(
cv
::
Mat
&
img
)
{
cv
::
Mat
optimalLabeling
;
assignLabeling
(
optimalLabeling
);
img
.
create
(
height
,
width
,
type
);
for
(
int
i
=
0
;
i
<
height
;
++
i
)
for
(
int
j
=
0
;
j
<
width
;
++
j
)
{
cv
::
Mat
M
=
images
[
optimalLabeling
.
template
at
<
int
>
(
i
,
j
)];
img
.
template
at
<
Tp
>
(
i
,
j
)
=
M
.
template
at
<
Tp
>
(
i
,
j
);
}
}
template
<
typename
Tp
>
Photomontage
<
Tp
>::
Photomontage
(
const
std
::
vector
<
cv
::
Mat
>
&
_images
,
const
std
::
vector
<
cv
::
Mat
>
&
_masks
)
:
images
(
_images
),
masks
(
_masks
),
labelings
(
images
.
size
()),
distances
(
images
.
size
()),
height
(
int
(
images
[
0
].
rows
)),
width
(
int
(
images
[
0
].
cols
)),
type
(
images
[
0
].
type
()),
channels
(
images
[
0
].
channels
()),
lsize
(
int
(
images
.
size
())),
x_i
(
height
,
width
,
CV_32SC1
){}
template
<
typename
Tp
>
static
inline
void
photomontage
(
const
std
::
vector
<
std
::
vector
<
Tp
>
>
&
pointSeq
,
const
std
::
vector
<
std
::
vector
<
uchar
>
>
&
maskSeq
,
const
std
::
vector
<
std
::
vector
<
int
>
>
&
linkIdx
,
std
::
vector
<
gcoptimization
::
labelTp
>
&
labelSeq
)
{
gcoptimization
::
Photomontage
<
Tp
>
(
pointSeq
,
maskSeq
,
linkIdx
,
labelSeq
).
gradientDescent
();
}
#endif
/* __PHOTOMONTAGE_HPP__ */
modules/xphoto/testdata/xphoto/dct_image_denoising/results/.DS_Store
deleted
100644 → 0
View file @
a5ba77a0
File deleted
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment