Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
dlib
Commits
5b30b06d
Commit
5b30b06d
authored
Oct 21, 2011
by
Davis King
Browse files
merged
parents
e4ae6686
2e1927cd
Changes
37
Show whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
1246 additions
and
3 deletions
+1246
-3
dlib/algs.h
dlib/algs.h
+5
-0
dlib/array2d/array2d_kernel_1.h
dlib/array2d/array2d_kernel_1.h
+8
-0
dlib/disjoint_subsets.h
dlib/disjoint_subsets.h
+11
-0
dlib/disjoint_subsets/disjoint_subsets.h
dlib/disjoint_subsets/disjoint_subsets.h
+142
-0
dlib/disjoint_subsets/disjoint_subsets_abstract.h
dlib/disjoint_subsets/disjoint_subsets_abstract.h
+99
-0
dlib/geometry.h
dlib/geometry.h
+1
-0
dlib/geometry/border_enumerator.h
dlib/geometry/border_enumerator.h
+100
-0
dlib/geometry/border_enumerator_abstract.h
dlib/geometry/border_enumerator_abstract.h
+113
-0
dlib/image_transforms.h
dlib/image_transforms.h
+2
-0
dlib/image_transforms/equalize_histogram.h
dlib/image_transforms/equalize_histogram.h
+6
-0
dlib/image_transforms/equalize_histogram_abstract.h
dlib/image_transforms/equalize_histogram_abstract.h
+2
-0
dlib/image_transforms/label_connected_blobs_abstract.h
dlib/image_transforms/label_connected_blobs_abstract.h
+1
-1
dlib/image_transforms/randomly_color_image.h
dlib/image_transforms/randomly_color_image.h
+71
-0
dlib/image_transforms/randomly_color_image_abstract.h
dlib/image_transforms/randomly_color_image_abstract.h
+41
-0
dlib/image_transforms/segment_image.h
dlib/image_transforms/segment_image.h
+279
-0
dlib/image_transforms/segment_image_abstract.h
dlib/image_transforms/segment_image_abstract.h
+51
-0
dlib/image_transforms/spatial_filtering_abstract.h
dlib/image_transforms/spatial_filtering_abstract.h
+2
-2
dlib/is_kind.h
dlib/is_kind.h
+13
-0
dlib/matrix.h
dlib/matrix.h
+1
-0
dlib/matrix/matrix_conv.h
dlib/matrix/matrix_conv.h
+298
-0
No files found.
dlib/algs.h
View file @
5b30b06d
...
...
@@ -384,6 +384,11 @@ namespace dlib
{
static
const
bool
value
=
true
;
};
template
<
typename
T
>
struct
is_const_type
<
const
T
&>
{
static
const
bool
value
=
true
;
};
// ----------------------------------------------------------------------------------------
...
...
dlib/array2d/array2d_kernel_1.h
View file @
5b30b06d
...
...
@@ -487,6 +487,14 @@ namespace dlib
}
}
// ----------------------------------------------------------------------------------------
template
<
typename
T
,
typename
MM
>
struct
is_array2d
<
array2d
<
T
,
MM
>
>
{
const
static
bool
value
=
true
;
};
// ----------------------------------------------------------------------------------------
}
...
...
dlib/disjoint_subsets.h
0 → 100644
View file @
5b30b06d
// Copyright (C) 2011 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_DISJOINt_SUBSETS_
#define DLIB_DISJOINt_SUBSETS_
#include "disjoint_subsets/disjoint_subsets.h"
#endif // DLIB_DISJOINt_SUBSETS_
dlib/disjoint_subsets/disjoint_subsets.h
0 → 100644
View file @
5b30b06d
// Copyright (C) 2011 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_DISJOINT_SUBsETS_H__
#define DLIB_DISJOINT_SUBsETS_H__
#include "disjoint_subsets_abstract.h"
#include <vector>
#include "../algs.h"
namespace
dlib
{
// ----------------------------------------------------------------------------------------
class
disjoint_subsets
{
public:
void
clear
(
)
{
items
.
clear
();
}
void
set_size
(
unsigned
long
new_size
)
{
items
.
resize
(
new_size
);
for
(
unsigned
long
i
=
0
;
i
<
items
.
size
();
++
i
)
{
items
[
i
].
parent
=
i
;
items
[
i
].
rank
=
0
;
}
}
unsigned
long
size
(
)
const
{
return
items
.
size
();
}
unsigned
long
find_set
(
unsigned
long
item
)
const
{
// make sure requires clause is not broken
DLIB_ASSERT
(
item
<
size
(),
"
\t
unsigned long disjoint_subsets::find_set()"
<<
"
\n\t
item must be less than size()"
<<
"
\n\t
item: "
<<
item
<<
"
\n\t
size(): "
<<
size
()
<<
"
\n\t
this: "
<<
this
);
if
(
items
[
item
].
parent
==
item
)
{
return
item
;
}
else
{
// find root of item
unsigned
long
x
=
item
;
do
{
x
=
items
[
x
].
parent
;
}
while
(
items
[
x
].
parent
!=
x
);
// do path compression
const
unsigned
long
root
=
x
;
x
=
item
;
while
(
items
[
x
].
parent
!=
x
)
{
const
unsigned
long
prev
=
x
;
x
=
items
[
x
].
parent
;
items
[
prev
].
parent
=
root
;
}
return
root
;
}
}
unsigned
long
merge_sets
(
unsigned
long
a
,
unsigned
long
b
)
{
// make sure requires clause is not broken
DLIB_ASSERT
(
a
!=
b
&&
a
<
size
()
&&
b
<
size
()
&&
find_set
(
a
)
==
a
&&
find_set
(
b
)
==
b
,
"
\t
unsigned long disjoint_subsets::merge_sets(a,b)"
<<
"
\n\t
invalid arguments were given to this function"
<<
"
\n\t
a: "
<<
a
<<
"
\n\t
b: "
<<
b
<<
"
\n\t
size(): "
<<
size
()
<<
"
\n\t
find_set(a): "
<<
find_set
(
a
)
<<
"
\n\t
find_set(b): "
<<
find_set
(
b
)
<<
"
\n\t
this: "
<<
this
);
if
(
items
[
a
].
rank
>
items
[
b
].
rank
)
{
items
[
b
].
parent
=
a
;
return
a
;
}
else
{
items
[
a
].
parent
=
b
;
if
(
items
[
a
].
rank
==
items
[
b
].
rank
)
{
items
[
b
].
rank
=
items
[
b
].
rank
+
1
;
}
return
b
;
}
}
private:
/*
See the book Introduction to Algorithms by Cormen, Leiserson, Rivest and Stein
for a discussion of how this algorithm works.
*/
struct
data
{
unsigned
long
rank
;
unsigned
long
parent
;
};
mutable
std
::
vector
<
data
>
items
;
};
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_DISJOINT_SUBsETS_H__
dlib/disjoint_subsets/disjoint_subsets_abstract.h
0 → 100644
View file @
5b30b06d
// Copyright (C) 2011 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_DISJOINT_SUBsETS_ABSTRACT_H__
#ifdef DLIB_DISJOINT_SUBsETS_ABSTRACT_H__
#include <vector>
#include "../algs.h"
namespace
dlib
{
// ----------------------------------------------------------------------------------------
class
disjoint_subsets
{
/*!
INITIAL VALUE
- size() == 0
WHAT THIS OBJECT REPRESENTS
This object represents a set of integers which is partitioned into
a number of disjoint subsets. It supports the two fundamental operations
of finding which subset a particular integer belongs to as well as
merging subsets.
!*/
public:
void
clear
(
);
/*!
ensures
- #size() == 0
- returns this object to its initial value
!*/
void
set_size
(
unsigned
long
new_size
);
/*!
ensures
- #size() == new_size
- for all valid i:
- #find_set(i) == i
(i.e. this object contains new_size subsets, each containing exactly one element)
!*/
unsigned
long
size
(
)
const
;
/*!
ensures
- returns the total number of integer elements represented
by this object.
!*/
unsigned
long
find_set
(
unsigned
long
item
)
const
;
/*!
requires
- item < size()
ensures
- Each disjoint subset can be represented by any of its elements (since
the sets are all disjoint). In particular, for each subset we define
a special "representative element" which is used to represent it.
Therefore, this function returns the representative element for the
set which contains item.
- find_set(find_set(item)) == find_set(item)
- Note that if A and B are both elements of the same subset then we always
have find_set(A) == find_set(B).
!*/
unsigned
long
merge_sets
(
unsigned
long
a
,
unsigned
long
b
)
/*!
requires
- a != b
- a < size()
- b < size()
- find_set(a) == a
(i.e. a is the representative element of some set)
- find_set(b) == b
(i.e. b is the representative element of some set)
ensures
- #find_set(a) == #find_set(b)
(i.e. merges the set's containing a and b)
- returns #find_set(a)
!*/
};
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_DISJOINT_SUBsETS_ABSTRACT_H__
dlib/geometry.h
View file @
5b30b06d
...
...
@@ -5,6 +5,7 @@
#include "geometry/rectangle.h"
#include "geometry/vector.h"
#include "geometry/border_enumerator.h"
#endif // DLIB_GEOMETRy_HEADER
...
...
dlib/geometry/border_enumerator.h
0 → 100644
View file @
5b30b06d
// Copyright (C) 2011 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_BORDER_EnUMERATOR_H_
#define DLIB_BORDER_EnUMERATOR_H_
#include "border_enumerator_abstract.h"
#include "rectangle.h"
namespace
dlib
{
// ----------------------------------------------------------------------------------------
class
border_enumerator
{
public:
border_enumerator
(
)
{
}
border_enumerator
(
const
rectangle
&
rect_
,
unsigned
long
border_size
)
:
rect
(
rect_
),
inner_rect
(
shrink_rect
(
rect_
,
border_size
))
{
reset
();
}
void
reset
(
)
{
p
=
rect
.
tl_corner
();
p
.
x
()
-=
1
;
}
bool
at_start
(
)
const
{
point
temp
=
rect
.
tl_corner
();
temp
.
x
()
-=
1
;
return
temp
==
p
;
}
bool
current_element_valid
(
)
const
{
return
rect
.
contains
(
p
)
&&
!
inner_rect
.
contains
(
p
);
}
bool
move_next
()
{
p
.
x
()
+=
1
;
if
(
p
.
x
()
>
rect
.
right
())
{
p
.
y
()
+=
1
;
p
.
x
()
=
rect
.
left
();
}
else
if
(
inner_rect
.
contains
(
p
))
{
p
.
x
()
=
inner_rect
.
right
()
+
1
;
}
return
current_element_valid
();
}
unsigned
long
size
(
)
const
{
return
rect
.
area
()
-
inner_rect
.
area
();
}
const
point
&
element
(
)
const
{
// make sure requires clause is not broken
DLIB_ASSERT
(
current_element_valid
(),
"
\t
point border_enumerator::element()"
<<
"
\n\t
This function can't be called unless the element is valid."
<<
"
\n\t
this: "
<<
this
);
return
p
;
}
private:
point
p
;
rectangle
rect
;
rectangle
inner_rect
;
// the non-border regions of rect
};
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BORDER_EnUMERATOR_H_
dlib/geometry/border_enumerator_abstract.h
0 → 100644
View file @
5b30b06d
// Copyright (C) 2011 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_BORDER_EnUMERATOR_ABSTRACT_H_
#ifdef DLIB_BORDER_EnUMERATOR_ABSTRACT_H_
#include "rectangle_abstract.h"
namespace
dlib
{
// ----------------------------------------------------------------------------------------
class
border_enumerator
{
/*!
POINTERS AND REFERENCES TO INTERNAL DATA
All operations on this object other than calling element() invalidate
pointers and references to internal data.
WHAT THIS OBJECT REPRESENTS
This object is an enumerator over the border points of a rectangle.
!*/
public:
border_enumerator
(
);
/*!
ensures
- #move_next() == false
(i.e. this object is "empty" and won't enumerate anything)
- current_element_valid() == false
- at_start() == true
- size() == 0
!*/
border_enumerator
(
const
rectangle
&
rect
,
unsigned
long
border_size
);
/*!
ensures
- This object will enumerate over the border points which are inside rect
but within border_size of the edge. For example, if border_size == 1
then it enumerates over the single point wide strip of points all around
the interior edge of rect.
- current_element_valid() == false
- at_start() == true
- size() == rect.area() - shrink_rect(rect,border_size).area()
(i.e. the number of points in the border area of rect)
!*/
bool
at_start
(
)
const
;
/*!
ensures
- returns true if *this represents one position before the first point
(this would also make the current element invalid) else returns false
!*/
void
reset
(
);
/*!
ensures
- #current_element_valid() == false
- #at_start() == true
!*/
bool
current_element_valid
(
)
const
;
/*!
ensures
- returns true if we are currently at a valid element else
returns false
!*/
bool
move_next
(
);
/*!
ensures
- moves to the next element. i.e. #element() will now
return the next border point.
- the return value will be equal to #current_element_valid()
- #at_start() == false
- returns true if there is another element
- returns false if there are no more elements in the container
!*/
unsigned
long
size
(
)
const
;
/*!
ensures
- returns the number of border points
!*/
const
point
&
element
(
)
const
;
/*!
requires
- current_element_valid() == true
ensures
- returns the current border point
!*/
};
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BORDER_EnUMERATOR_ABSTRACT_H_
dlib/image_transforms.h
View file @
5b30b06d
...
...
@@ -13,6 +13,8 @@
#include "image_transforms/integral_image.h"
#include "image_transforms/image_pyramid.h"
#include "image_transforms/label_connected_blobs.h"
#include "image_transforms/randomly_color_image.h"
#include "image_transforms/segment_image.h"
#endif // DLIB_IMAGE_TRANSFORMs_
dlib/image_transforms/equalize_histogram.h
View file @
5b30b06d
...
...
@@ -27,6 +27,9 @@ namespace dlib
{
COMPILE_TIME_ASSERT
(
pixel_traits
<
typename
in_image_type
::
type
>::
is_unsigned
==
true
);
typedef
typename
pixel_traits
<
typename
in_image_type
::
type
>::
basic_pixel_type
in_image_basic_pixel_type
;
COMPILE_TIME_ASSERT
(
sizeof
(
in_image_basic_pixel_type
)
<
sizeof
(
long
));
// make sure hist is the right size
if
(
R
==
1
)
hist
.
set_size
(
1
,
pixel_traits
<
typename
in_image_type
::
type
>::
max
()
+
1
);
...
...
@@ -64,6 +67,9 @@ namespace dlib
COMPILE_TIME_ASSERT
(
pixel_traits
<
typename
in_image_type
::
type
>::
is_unsigned
==
true
);
COMPILE_TIME_ASSERT
(
pixel_traits
<
typename
out_image_type
::
type
>::
is_unsigned
==
true
);
typedef
typename
pixel_traits
<
typename
in_image_type
::
type
>::
basic_pixel_type
in_image_basic_pixel_type
;
COMPILE_TIME_ASSERT
(
sizeof
(
in_image_basic_pixel_type
)
<
sizeof
(
long
));
typedef
typename
in_image_type
::
type
in_pixel_type
;
typedef
typename
out_image_type
::
type
out_pixel_type
;
...
...
dlib/image_transforms/equalize_histogram_abstract.h
View file @
5b30b06d
...
...
@@ -27,6 +27,7 @@ namespace dlib
- pixel_traits<typename out_image_type::type>::has_alpha == false
- pixel_traits<typename in_image_type::type>::is_unsigned == true
- pixel_traits<typename out_image_type::type>::is_unsigned == true
- pixel_traits<typename in_image_type::type>::max() < std::numeric_limits<long>::max()
ensures
- #out_img == the histogram equalized version of in_img
- #out_img.nc() == in_img.nc()
...
...
@@ -49,6 +50,7 @@ namespace dlib
requires
- in_image_type == is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<typename in_image_type::type>::is_unsigned == true
- pixel_traits<typename in_image_type::type>::max() < std::numeric_limits<long>::max()
- hist must be capable of representing a column vector of length
pixel_traits<typename in_image_type>::max(). I.e. if R and C are nonzero
then they must be values that don't conflict with the previous sentence.
...
...
dlib/image_transforms/label_connected_blobs_abstract.h
View file @
5b30b06d
...
...
@@ -177,7 +177,7 @@ namespace dlib
- else
- #label_img[r][c] != 0
- if (img.size() != 0) then
- returns max(array_to_matrix(label_img))+1
- returns max(array_to_matrix(
#
label_img))+1
(i.e. returns a number one greater than the maximum blob id number,
this is the number of blobs found.)
- else
...
...
dlib/image_transforms/randomly_color_image.h
0 → 100644
View file @
5b30b06d
// Copyright (C) 2011 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_RANDOMLY_COlOR_IMAGE_H__
#define DLIB_RANDOMLY_COlOR_IMAGE_H__
#include "randomly_color_image_abstract.h"
#include "../hash.h"
#include "../pixel.h"
#include "../matrix.h"
namespace
dlib
{
// ----------------------------------------------------------------------------------------
template
<
typename
T
>
struct
op_randomly_color_image
:
does_not_alias
{
op_randomly_color_image
(
const
T
&
img_
)
:
img
(
img_
){}
const
T
&
img
;
const
static
long
cost
=
7
;
const
static
long
NR
=
0
;
const
static
long
NC
=
0
;
typedef
rgb_pixel
type
;
typedef
const
rgb_pixel
const_ret_type
;
typedef
typename
T
::
mem_manager_type
mem_manager_type
;
typedef
row_major_layout
layout_type
;
const_ret_type
apply
(
long
r
,
long
c
)
const
{
const
unsigned
long
gray
=
get_pixel_intensity
(
img
[
r
][
c
]);
if
(
gray
!=
0
)
{
const
uint32
h
=
murmur_hash3
(
&
gray
,
sizeof
(
gray
));
rgb_pixel
pix
;
pix
.
red
=
static_cast
<
unsigned
char
>
(
h
)
%
200
+
55
;
pix
.
green
=
static_cast
<
unsigned
char
>
(
h
>>
8
)
%
200
+
55
;
pix
.
blue
=
static_cast
<
unsigned
char
>
(
h
>>
16
)
%
200
+
55
;
return
pix
;
}
else
{
// keep black pixels black
return
rgb_pixel
(
0
,
0
,
0
);
}
}
long
nr
()
const
{
return
img
.
nr
();
}
long
nc
()
const
{
return
img
.
nc
();
}
};
template
<
typename
image_type
>
const
matrix_op
<
op_randomly_color_image
<
image_type
>
>
randomly_color_image
(
const
image_type
&
img
)
{
typedef
op_randomly_color_image
<
image_type
>
op
;
return
matrix_op
<
op
>
(
op
(
img
));
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_RANDOMLY_COlOR_IMAGE_H__
dlib/image_transforms/randomly_color_image_abstract.h
0 → 100644
View file @
5b30b06d
// Copyright (C) 2011 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_RANDOMLY_COlOR_IMAGE_ABSTRACT_H__
#ifdef DLIB_RANDOMLY_COlOR_IMAGE_ABSTRACT_H__
#include "randomly_color_image_abstract.h"
#include "../hash.h"
#include "../pixel.h"
#include "../matrix.h"
namespace
dlib
{
// ----------------------------------------------------------------------------------------
template
<
typename
image_type
>
const
matrix_exp
randomly_color_image
(
const
image_type
&
img
);
/*!
requires
- image_type is an implementation of array2d/array2d_kernel_abstract.h
- pixel_traits<image_type::type> must be defined
ensures
- randomly generates a mapping from gray level pixel values
to the RGB pixel space and then uses this mapping to create
a colored version of img. Returns a matrix which represents
this colored version of img.
- black pixels in img will remain black in the output image.
- The returned matrix will have the same dimensions as img.
!*/
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_RANDOMLY_COlOR_IMAGE_ABSTRACT_H__
dlib/image_transforms/segment_image.h
0 → 100644
View file @
5b30b06d
// Copyright (C) 2011 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_SEGMENT_ImAGE_H__
#define DLIB_SEGMENT_ImAGE_H__
#include "segment_image_abstract.h"
#include "../algs.h"
#include <vector>
#include "../geometry.h"
#include "../disjoint_subsets.h"
namespace
dlib
{
// ----------------------------------------------------------------------------------------
namespace
impl
{
struct
graph_image_segmentation_data
{
graph_image_segmentation_data
()
:
component_size
(
1
),
internal_diff
(
0
)
{}
unsigned
long
component_size
;
unsigned
short
internal_diff
;
};
template
<
typename
T
>
inline
T
edge_diff
(
const
T
&
a
,
const
T
&
b
)
{
if
(
a
>
b
)
return
a
-
b
;
else
return
b
-
a
;
}
struct
segment_image_edge_data
{
segment_image_edge_data
(){}
segment_image_edge_data
(
const
rectangle
&
rect
,
const
point
&
p1
,
const
point
&
p2
,
const
unsigned
short
&
diff_
)
:
idx1
(
p1
.
y
()
*
rect
.
width
()
+
p1
.
x
()),
idx2
(
p2
.
y
()
*
rect
.
width
()
+
p2
.
x
()),
diff
(
diff_
)
{}
unsigned
long
idx1
;
unsigned
long
idx2
;
unsigned
short
diff
;
};
}
// ----------------------------------------------------------------------------------------
template
<
typename
in_image_type
,
typename
out_image_type
>
void
segment_image
(
const
in_image_type
&
in_img
,
out_image_type
&
out_img
,
const
unsigned
long
k
=
200
,
const
unsigned
long
min_diff
=
0
)
{
using
namespace
dlib
::
impl
;
typedef
typename
in_image_type
::
type
ptype
;
// make sure requires clause is not broken
DLIB_ASSERT
(
is_same_object
(
in_img
,
out_img
)
==
false
,
"
\t
void segment_image()"
<<
"
\n\t
The input images can't be the same object."
);
COMPILE_TIME_ASSERT
(
is_unsigned_type
<
ptype
>::
value
&&
sizeof
(
ptype
)
<=
2
);
COMPILE_TIME_ASSERT
(
is_unsigned_type
<
typename
out_image_type
::
type
>::
value
);
out_img
.
set_size
(
in_img
.
nr
(),
in_img
.
nc
());
// don't bother doing anything if the image is too small
if
(
in_img
.
nr
()
<
2
||
in_img
.
nc
()
<
2
)
{
assign_all_pixels
(
out_img
,
0
);
return
;
}
disjoint_subsets
sets
;
sets
.
set_size
(
in_img
.
size
());
std
::
vector
<
graph_image_segmentation_data
>
data
(
in_img
.
size
());
std
::
vector
<
unsigned
long
>
counts
(
std
::
numeric_limits
<
ptype
>::
max
()
+
1
,
0
);
border_enumerator
be
(
get_rect
(
in_img
),
1
);
// we are going to do a radix sort on the edge weights. So the first step
// is to accumulate them into count.
const
rectangle
area
=
get_rect
(
in_img
);
while
(
be
.
move_next
())
{
const
long
r
=
be
.
element
().
y
();
const
long
c
=
be
.
element
().
x
();
const
ptype
pix
=
in_img
[
r
][
c
];
if
(
area
.
contains
(
c
-
1
,
r
))
counts
[
edge_diff
(
pix
,
in_img
[
r
][
c
-
1
])]
+=
1
;
if
(
area
.
contains
(
c
+
1
,
r
))
counts
[
edge_diff
(
pix
,
in_img
[
r
][
c
+
1
])]
+=
1
;
if
(
area
.
contains
(
c
-
1
,
r
-
1
))
counts
[
edge_diff
(
pix
,
in_img
[
r
-
1
][
c
-
1
])]
+=
1
;
if
(
area
.
contains
(
c
,
r
-
1
))
counts
[
edge_diff
(
pix
,
in_img
[
r
-
1
][
c
])]
+=
1
;
if
(
area
.
contains
(
c
+
1
,
r
-
1
))
counts
[
edge_diff
(
pix
,
in_img
[
r
-
1
][
c
+
1
])]
+=
1
;
if
(
area
.
contains
(
c
-
1
,
r
+
1
))
counts
[
edge_diff
(
pix
,
in_img
[
r
+
1
][
c
-
1
])]
+=
1
;
if
(
area
.
contains
(
c
,
r
+
1
))
counts
[
edge_diff
(
pix
,
in_img
[
r
+
1
][
c
])]
+=
1
;
if
(
area
.
contains
(
c
+
1
,
r
+
1
))
counts
[
edge_diff
(
pix
,
in_img
[
r
+
1
][
c
+
1
])]
+=
1
;
}
for
(
long
r
=
1
;
r
+
1
<
in_img
.
nr
();
++
r
)
{
for
(
long
c
=
1
;
c
+
1
<
in_img
.
nc
();
++
c
)
{
const
ptype
pix
=
in_img
[
r
][
c
];
counts
[
edge_diff
(
pix
,
in_img
[
r
][
c
-
1
])]
+=
1
;
counts
[
edge_diff
(
pix
,
in_img
[
r
][
c
+
1
])]
+=
1
;
counts
[
edge_diff
(
pix
,
in_img
[
r
-
1
][
c
-
1
])]
+=
1
;
counts
[
edge_diff
(
pix
,
in_img
[
r
-
1
][
c
])]
+=
1
;
counts
[
edge_diff
(
pix
,
in_img
[
r
-
1
][
c
+
1
])]
+=
1
;
counts
[
edge_diff
(
pix
,
in_img
[
r
+
1
][
c
-
1
])]
+=
1
;
counts
[
edge_diff
(
pix
,
in_img
[
r
+
1
][
c
])]
+=
1
;
counts
[
edge_diff
(
pix
,
in_img
[
r
+
1
][
c
+
1
])]
+=
1
;
}
}
const
unsigned
long
num_edges
=
shrink_rect
(
area
,
1
).
area
()
*
8
+
in_img
.
nr
()
*
2
*
5
-
8
+
(
in_img
.
nc
()
-
2
)
*
2
*
5
;
std
::
vector
<
segment_image_edge_data
>
sorted_edges
(
num_edges
);
// integrate counts. The idea is to have sorted_edges[counts[i]] be the location that edges
// with an edge_diff of i go. So counts[0] == 0, counts[1] == number of 0 edge diff edges, etc.
unsigned
long
prev
=
counts
[
0
];
for
(
unsigned
long
i
=
1
;
i
<
counts
.
size
();
++
i
)
{
const
unsigned
long
temp
=
counts
[
i
];
counts
[
i
]
+=
counts
[
i
-
1
];
counts
[
i
-
1
]
-=
prev
;
prev
=
temp
;
}
counts
[
counts
.
size
()
-
1
]
-=
prev
;
// now build a sorted list of all the edges
be
.
reset
();
while
(
be
.
move_next
())
{
const
long
r
=
be
.
element
().
y
();
const
long
c
=
be
.
element
().
x
();
const
point
p
(
c
,
r
);
const
ptype
pix
=
in_img
[
r
][
c
];
if
(
area
.
contains
(
c
-
1
,
r
))
{
const
ptype
diff
=
edge_diff
(
pix
,
in_img
[
r
][
c
-
1
]);
sorted_edges
[
counts
[
diff
]
++
]
=
segment_image_edge_data
(
area
,
p
,
point
(
c
-
1
,
r
),
diff
);
}
if
(
area
.
contains
(
c
+
1
,
r
))
{
const
ptype
diff
=
edge_diff
(
pix
,
in_img
[
r
][
c
+
1
]);
sorted_edges
[
counts
[
diff
]
++
]
=
segment_image_edge_data
(
area
,
p
,
point
(
c
+
1
,
r
),
diff
);
}
if
(
area
.
contains
(
c
-
1
,
r
-
1
))
{
const
ptype
diff
=
edge_diff
(
pix
,
in_img
[
r
-
1
][
c
-
1
]);
sorted_edges
[
counts
[
diff
]
++
]
=
segment_image_edge_data
(
area
,
p
,
point
(
c
-
1
,
r
-
1
),
diff
);
}
if
(
area
.
contains
(
c
,
r
-
1
))
{
const
ptype
diff
=
edge_diff
(
pix
,
in_img
[
r
-
1
][
c
]);
sorted_edges
[
counts
[
diff
]
++
]
=
segment_image_edge_data
(
area
,
p
,
point
(
c
,
r
-
1
),
diff
);
}
if
(
area
.
contains
(
c
+
1
,
r
-
1
))
{
const
ptype
diff
=
edge_diff
(
pix
,
in_img
[
r
-
1
][
c
+
1
]);
sorted_edges
[
counts
[
diff
]
++
]
=
segment_image_edge_data
(
area
,
p
,
point
(
c
+
1
,
r
-
1
),
diff
);
}
if
(
area
.
contains
(
c
-
1
,
r
+
1
))
{
const
ptype
diff
=
edge_diff
(
pix
,
in_img
[
r
+
1
][
c
-
1
]);
sorted_edges
[
counts
[
diff
]
++
]
=
segment_image_edge_data
(
area
,
p
,
point
(
c
-
1
,
r
+
1
),
diff
);
}
if
(
area
.
contains
(
c
,
r
+
1
))
{
const
ptype
diff
=
edge_diff
(
pix
,
in_img
[
r
+
1
][
c
]);
sorted_edges
[
counts
[
diff
]
++
]
=
segment_image_edge_data
(
area
,
p
,
point
(
c
,
r
+
1
),
diff
);
}
if
(
area
.
contains
(
c
+
1
,
r
+
1
))
{
const
ptype
diff
=
edge_diff
(
pix
,
in_img
[
r
+
1
][
c
+
1
]);
sorted_edges
[
counts
[
diff
]
++
]
=
segment_image_edge_data
(
area
,
p
,
point
(
c
+
1
,
r
+
1
),
diff
);
}
}
// same thing as the above loop but now we do it on the interior of the image and therefore
// don't have to include the boundary checking if statements used above.
for
(
long
r
=
1
;
r
+
1
<
in_img
.
nr
();
++
r
)
{
for
(
long
c
=
1
;
c
+
1
<
in_img
.
nc
();
++
c
)
{
const
point
p
(
c
,
r
);
const
ptype
pix
=
in_img
[
r
][
c
];
ptype
diff
;
diff
=
edge_diff
(
pix
,
in_img
[
r
][
c
-
1
]);
sorted_edges
[
counts
[
diff
]
++
]
=
segment_image_edge_data
(
area
,
p
,
point
(
c
-
1
,
r
),
diff
);
diff
=
edge_diff
(
pix
,
in_img
[
r
][
c
+
1
]);
sorted_edges
[
counts
[
diff
]
++
]
=
segment_image_edge_data
(
area
,
p
,
point
(
c
+
1
,
r
),
diff
);
diff
=
edge_diff
(
pix
,
in_img
[
r
-
1
][
c
-
1
]);
sorted_edges
[
counts
[
diff
]
++
]
=
segment_image_edge_data
(
area
,
p
,
point
(
c
-
1
,
r
-
1
),
diff
);
diff
=
edge_diff
(
pix
,
in_img
[
r
-
1
][
c
]);
sorted_edges
[
counts
[
diff
]
++
]
=
segment_image_edge_data
(
area
,
p
,
point
(
c
,
r
-
1
),
diff
);
diff
=
edge_diff
(
pix
,
in_img
[
r
-
1
][
c
+
1
]);
sorted_edges
[
counts
[
diff
]
++
]
=
segment_image_edge_data
(
area
,
p
,
point
(
c
+
1
,
r
-
1
),
diff
);
diff
=
edge_diff
(
pix
,
in_img
[
r
+
1
][
c
-
1
]);
sorted_edges
[
counts
[
diff
]
++
]
=
segment_image_edge_data
(
area
,
p
,
point
(
c
-
1
,
r
+
1
),
diff
);
diff
=
edge_diff
(
pix
,
in_img
[
r
+
1
][
c
]);
sorted_edges
[
counts
[
diff
]
++
]
=
segment_image_edge_data
(
area
,
p
,
point
(
c
,
r
+
1
),
diff
);
diff
=
edge_diff
(
pix
,
in_img
[
r
+
1
][
c
+
1
]);
sorted_edges
[
counts
[
diff
]
++
]
=
segment_image_edge_data
(
area
,
p
,
point
(
c
+
1
,
r
+
1
),
diff
);
}
}
// now start connecting blobs together to make a minimum spanning tree.
for
(
unsigned
long
i
=
0
;
i
<
sorted_edges
.
size
();
++
i
)
{
const
unsigned
long
idx1
=
sorted_edges
[
i
].
idx1
;
const
unsigned
long
idx2
=
sorted_edges
[
i
].
idx2
;
unsigned
long
set1
=
sets
.
find_set
(
idx1
);
unsigned
long
set2
=
sets
.
find_set
(
idx2
);
if
(
set1
!=
set2
)
{
const
ptype
diff
=
sorted_edges
[
i
].
diff
;
const
ptype
tau1
=
k
/
data
[
set1
].
component_size
;
const
ptype
tau2
=
k
/
data
[
set2
].
component_size
;
const
ptype
mint
=
std
::
min
(
data
[
set1
].
internal_diff
+
tau1
,
data
[
set2
].
internal_diff
+
tau2
);
if
(
diff
<=
std
::
max
<
ptype
>
(
mint
,
min_diff
))
{
const
unsigned
long
new_set
=
sets
.
merge_sets
(
set1
,
set2
);
data
[
new_set
].
component_size
=
data
[
set1
].
component_size
+
data
[
set2
].
component_size
;
data
[
new_set
].
internal_diff
=
diff
;
}
}
}
unsigned
long
idx
=
0
;
for
(
long
r
=
0
;
r
<
out_img
.
nr
();
++
r
)
{
for
(
long
c
=
0
;
c
<
out_img
.
nc
();
++
c
)
{
out_img
[
r
][
c
]
=
sets
.
find_set
(
idx
++
);
}
}
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_SEGMENT_ImAGE_H__
dlib/image_transforms/segment_image_abstract.h
0 → 100644
View file @
5b30b06d
// Copyright (C) 2011 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_SEGMENT_ImAGE_ABSTRACT_H__
#ifdef DLIB_SEGMENT_ImAGE_ABSTRACT_H__
namespace
dlib
{
// ----------------------------------------------------------------------------------------
template
<
typename
in_image_type
,
typename
out_image_type
>
void
segment_image
(
const
in_image_type
&
in_img
,
out_image_type
&
out_img
,
const
unsigned
long
k
=
200
,
const
unsigned
long
min_diff
=
0
);
/*!
requires
- in_image_type == an implementation of array2d/array2d_kernel_abstract.h
- out_image_type == an implementation of array2d/array2d_kernel_abstract.h
- in_image_type::type == an unsigned 8-bit or 16bit integer type.
- out_image_type::type == unsigned integer type
- is_same_object(in_img, out_img) == false
ensures
- Attempts to segment in_img into regions which have some visual consistency to them.
In particular, this function implements the algorithm described in the paper:
Efficient Graph-Based Image Segmentation by Felzenszwalb and Huttenlocher.
- #out_img.nr() == in_img.nr()
- #out_img.nc() == in_img.nc()
- for all valid r and c:
- #out_img[r][c] == an integer value indicating the identity of the segment
containing the pixel in_img[r][c].
- The k parameter is a measure used to influence how large the segment regions will
be. Larger k generally results in larger segments being produced. For a deeper
discussion of the k parameter you should consult the above referenced paper.
- Any neighboring segments with an edge between them with a pixel difference <= min_diff
will always be merged. So making min_diff bigger makes this algorithm more eager
to merge neighboring segments.
!*/
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_SEGMENT_ImAGE_ABSTRACT_H__
dlib/image_transforms/spatial_filtering_abstract.h
View file @
5b30b06d
...
...
@@ -36,8 +36,8 @@ namespace dlib
- filter.nr() % 2 == 1 (i.e. must be odd)
- filter.nc() % 2 == 1 (i.e. must be odd)
ensures
- Applies the given spatial filter to in_img and stores the result in out_img
. Also
divides each resulting pixel by scale.
- Applies the given spatial filter to in_img and stores the result in out_img
(i.e.
cross-correlates in_img with filter). Also
divides each resulting pixel by scale.
- The intermediate filter computations will be carried out using variables of type EXP::type.
This is whatever scalar type is used inside the filter matrix.
- Pixel values are stored into out_img using the assign_pixel() function and therefore
...
...
dlib/is_kind.h
View file @
5b30b06d
...
...
@@ -59,6 +59,19 @@ namespace dlib
ASSERT_ARE_SAME_TYPE
(
helper
,
void
);
};
// ----------------------------------------------------------------------------------------
template
<
typename
T
>
struct
is_array2d
:
public
default_is_kind_value
{
/*!
- if (T is an implementation of array2d/array2d_kernel_abstract.h) then
- is_array2d<T>::value == true
- else
- is_array2d<T>::value == false
!*/
};
// ----------------------------------------------------------------------------------------
template
<
typename
T
>
...
...
dlib/matrix.h
View file @
5b30b06d
...
...
@@ -10,6 +10,7 @@
#include "matrix/matrix_assign.h"
#include "matrix/matrix_la.h"
#include "matrix/symmetric_matrix_cache.h"
#include "matrix/matrix_conv.h"
#ifdef DLIB_USE_BLAS
#include "matrix/matrix_blas_bindings.h"
...
...
dlib/matrix/matrix_conv.h
0 → 100644
View file @
5b30b06d
// Copyright (C) 2011 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_MATRIx_CONV_H__
#define DLIB_MATRIx_CONV_H__
#include "matrix_conv_abstract.h"
#include "matrix.h"
namespace
dlib
{
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template
<
typename
M1
,
typename
M2
,
bool
flip_m2
=
false
>
struct
op_conv
{
op_conv
(
const
M1
&
m1_
,
const
M2
&
m2_
)
:
m1
(
m1_
),
m2
(
m2_
),
nr_
(
m1
.
nr
()
+
m2
.
nr
()
-
1
),
nc_
(
m1
.
nc
()
+
m2
.
nc
()
-
1
)
{
if
(
nr_
<
0
||
m1
.
size
()
==
0
||
m2
.
size
()
==
0
)
nr_
=
0
;
if
(
nc_
<
0
||
m1
.
size
()
==
0
||
m2
.
size
()
==
0
)
nc_
=
0
;
}
const
M1
&
m1
;
const
M2
&
m2
;
long
nr_
;
long
nc_
;
const
static
long
cost
=
(
M1
::
cost
+
M2
::
cost
)
*
10
;
const
static
long
NR
=
(
M1
::
NR
*
M2
::
NR
==
0
)
?
(
0
)
:
(
M1
::
NR
+
M2
::
NR
-
1
);
const
static
long
NC
=
(
M1
::
NC
*
M2
::
NC
==
0
)
?
(
0
)
:
(
M1
::
NC
+
M2
::
NC
-
1
);
typedef
typename
M1
::
type
type
;
typedef
type
const_ret_type
;
typedef
typename
M1
::
mem_manager_type
mem_manager_type
;
typedef
typename
M1
::
layout_type
layout_type
;
const_ret_type
apply
(
long
r
,
long
c
)
const
{
type
temp
=
0
;
const
long
min_rr
=
std
::
max
<
long
>
(
r
-
m2
.
nr
()
+
1
,
0
);
const
long
max_rr
=
std
::
min
<
long
>
(
m1
.
nr
()
-
1
,
r
);
const
long
min_cc
=
std
::
max
<
long
>
(
c
-
m2
.
nc
()
+
1
,
0
);
const
long
max_cc
=
std
::
min
<
long
>
(
m1
.
nc
()
-
1
,
c
);
for
(
long
rr
=
min_rr
;
rr
<=
max_rr
;
++
rr
)
{
for
(
long
cc
=
min_cc
;
cc
<=
max_cc
;
++
cc
)
{
if
(
flip_m2
)
temp
+=
m1
(
rr
,
cc
)
*
m2
(
m2
.
nr
()
-
r
+
rr
-
1
,
m2
.
nc
()
-
c
+
cc
-
1
);
else
temp
+=
m1
(
rr
,
cc
)
*
m2
(
r
-
rr
,
c
-
cc
);
}
}
return
temp
;
}
long
nr
()
const
{
return
nr_
;
}
long
nc
()
const
{
return
nc_
;
}
template
<
typename
U
>
bool
aliases
(
const
matrix_exp
<
U
>&
item
)
const
{
return
m1
.
aliases
(
item
)
||
m2
.
aliases
(
item
);
}
template
<
typename
U
>
bool
destructively_aliases
(
const
matrix_exp
<
U
>&
item
)
const
{
return
m1
.
aliases
(
item
)
||
m2
.
aliases
(
item
);
}
};
template
<
typename
M1
,
typename
M2
>
const
matrix_op
<
op_conv
<
M1
,
M2
>
>
conv
(
const
matrix_exp
<
M1
>&
m1
,
const
matrix_exp
<
M2
>&
m2
)
{
COMPILE_TIME_ASSERT
((
is_same_type
<
typename
M1
::
type
,
typename
M2
::
type
>::
value
==
true
));
typedef
op_conv
<
M1
,
M2
>
op
;
return
matrix_op
<
op
>
(
op
(
m1
.
ref
(),
m2
.
ref
()));
}
template
<
typename
M1
,
typename
M2
>
const
matrix_op
<
op_conv
<
M1
,
M2
,
true
>
>
xcorr
(
const
matrix_exp
<
M1
>&
m1
,
const
matrix_exp
<
M2
>&
m2
)
{
COMPILE_TIME_ASSERT
((
is_same_type
<
typename
M1
::
type
,
typename
M2
::
type
>::
value
==
true
));
typedef
op_conv
<
M1
,
M2
,
true
>
op
;
return
matrix_op
<
op
>
(
op
(
m1
.
ref
(),
m2
.
ref
()));
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template
<
typename
M1
,
typename
M2
,
bool
flip_m2
=
false
>
struct
op_conv_same
{
op_conv_same
(
const
M1
&
m1_
,
const
M2
&
m2_
)
:
m1
(
m1_
),
m2
(
m2_
),
nr_
(
m1
.
nr
()),
nc_
(
m1
.
nc
())
{
if
(
m1
.
size
()
==
0
||
m2
.
size
()
==
0
)
nr_
=
0
;
if
(
m1
.
size
()
==
0
||
m2
.
size
()
==
0
)
nc_
=
0
;
}
const
M1
&
m1
;
const
M2
&
m2
;
long
nr_
;
long
nc_
;
const
static
long
cost
=
(
M1
::
cost
+
M2
::
cost
)
*
10
;
const
static
long
NR
=
M1
::
NR
;
const
static
long
NC
=
M1
::
NC
;
typedef
typename
M1
::
type
type
;
typedef
type
const_ret_type
;
typedef
typename
M1
::
mem_manager_type
mem_manager_type
;
typedef
typename
M1
::
layout_type
layout_type
;
const_ret_type
apply
(
long
r
,
long
c
)
const
{
r
+=
m2
.
nr
()
/
2
;
c
+=
m2
.
nc
()
/
2
;
type
temp
=
0
;
const
long
min_rr
=
std
::
max
<
long
>
(
r
-
m2
.
nr
()
+
1
,
0
);
const
long
max_rr
=
std
::
min
<
long
>
(
m1
.
nr
()
-
1
,
r
);
const
long
min_cc
=
std
::
max
<
long
>
(
c
-
m2
.
nc
()
+
1
,
0
);
const
long
max_cc
=
std
::
min
<
long
>
(
m1
.
nc
()
-
1
,
c
);
for
(
long
rr
=
min_rr
;
rr
<=
max_rr
;
++
rr
)
{
for
(
long
cc
=
min_cc
;
cc
<=
max_cc
;
++
cc
)
{
if
(
flip_m2
)
temp
+=
m1
(
rr
,
cc
)
*
m2
(
m2
.
nr
()
-
r
+
rr
-
1
,
m2
.
nc
()
-
c
+
cc
-
1
);
else
temp
+=
m1
(
rr
,
cc
)
*
m2
(
r
-
rr
,
c
-
cc
);
}
}
return
temp
;
}
long
nr
()
const
{
return
nr_
;
}
long
nc
()
const
{
return
nc_
;
}
template
<
typename
U
>
bool
aliases
(
const
matrix_exp
<
U
>&
item
)
const
{
return
m1
.
aliases
(
item
)
||
m2
.
aliases
(
item
);
}
template
<
typename
U
>
bool
destructively_aliases
(
const
matrix_exp
<
U
>&
item
)
const
{
return
m1
.
aliases
(
item
)
||
m2
.
aliases
(
item
);
}
};
template
<
typename
M1
,
typename
M2
>
const
matrix_op
<
op_conv_same
<
M1
,
M2
>
>
conv_same
(
const
matrix_exp
<
M1
>&
m1
,
const
matrix_exp
<
M2
>&
m2
)
{
COMPILE_TIME_ASSERT
((
is_same_type
<
typename
M1
::
type
,
typename
M2
::
type
>::
value
==
true
));
typedef
op_conv_same
<
M1
,
M2
>
op
;
return
matrix_op
<
op
>
(
op
(
m1
.
ref
(),
m2
.
ref
()));
}
template
<
typename
M1
,
typename
M2
>
const
matrix_op
<
op_conv_same
<
M1
,
M2
,
true
>
>
xcorr_same
(
const
matrix_exp
<
M1
>&
m1
,
const
matrix_exp
<
M2
>&
m2
)
{
COMPILE_TIME_ASSERT
((
is_same_type
<
typename
M1
::
type
,
typename
M2
::
type
>::
value
==
true
));
typedef
op_conv_same
<
M1
,
M2
,
true
>
op
;
return
matrix_op
<
op
>
(
op
(
m1
.
ref
(),
m2
.
ref
()));
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template
<
typename
M1
,
typename
M2
,
bool
flip_m2
=
false
>
struct
op_conv_valid
{
op_conv_valid
(
const
M1
&
m1_
,
const
M2
&
m2_
)
:
m1
(
m1_
),
m2
(
m2_
),
nr_
(
m1
.
nr
()
-
m2
.
nr
()
+
1
),
nc_
(
m1
.
nc
()
-
m2
.
nc
()
+
1
)
{
if
(
nr_
<
0
||
nc_
<=
0
||
m1
.
size
()
==
0
||
m2
.
size
()
==
0
)
nr_
=
0
;
if
(
nc_
<
0
||
nr_
<=
0
||
m1
.
size
()
==
0
||
m2
.
size
()
==
0
)
nc_
=
0
;
}
const
M1
&
m1
;
const
M2
&
m2
;
long
nr_
;
long
nc_
;
const
static
long
cost
=
(
M1
::
cost
+
M2
::
cost
)
*
10
;
const
static
long
NR
=
(
M1
::
NR
*
M2
::
NR
==
0
)
?
(
0
)
:
(
M1
::
NR
-
M2
::
NR
+
1
);
const
static
long
NC
=
(
M1
::
NC
*
M2
::
NC
==
0
)
?
(
0
)
:
(
M1
::
NC
-
M2
::
NC
+
1
);
typedef
typename
M1
::
type
type
;
typedef
type
const_ret_type
;
typedef
typename
M1
::
mem_manager_type
mem_manager_type
;
typedef
typename
M1
::
layout_type
layout_type
;
const_ret_type
apply
(
long
r
,
long
c
)
const
{
r
+=
m2
.
nr
()
-
1
;
c
+=
m2
.
nc
()
-
1
;
type
temp
=
0
;
const
long
min_rr
=
std
::
max
<
long
>
(
r
-
m2
.
nr
()
+
1
,
0
);
const
long
max_rr
=
std
::
min
<
long
>
(
m1
.
nr
()
-
1
,
r
);
const
long
min_cc
=
std
::
max
<
long
>
(
c
-
m2
.
nc
()
+
1
,
0
);
const
long
max_cc
=
std
::
min
<
long
>
(
m1
.
nc
()
-
1
,
c
);
for
(
long
rr
=
min_rr
;
rr
<=
max_rr
;
++
rr
)
{
for
(
long
cc
=
min_cc
;
cc
<=
max_cc
;
++
cc
)
{
if
(
flip_m2
)
temp
+=
m1
(
rr
,
cc
)
*
m2
(
m2
.
nr
()
-
r
+
rr
-
1
,
m2
.
nc
()
-
c
+
cc
-
1
);
else
temp
+=
m1
(
rr
,
cc
)
*
m2
(
r
-
rr
,
c
-
cc
);
}
}
return
temp
;
}
long
nr
()
const
{
return
nr_
;
}
long
nc
()
const
{
return
nc_
;
}
template
<
typename
U
>
bool
aliases
(
const
matrix_exp
<
U
>&
item
)
const
{
return
m1
.
aliases
(
item
)
||
m2
.
aliases
(
item
);
}
template
<
typename
U
>
bool
destructively_aliases
(
const
matrix_exp
<
U
>&
item
)
const
{
return
m1
.
aliases
(
item
)
||
m2
.
aliases
(
item
);
}
};
template
<
typename
M1
,
typename
M2
>
const
matrix_op
<
op_conv_valid
<
M1
,
M2
>
>
conv_valid
(
const
matrix_exp
<
M1
>&
m1
,
const
matrix_exp
<
M2
>&
m2
)
{
COMPILE_TIME_ASSERT
((
is_same_type
<
typename
M1
::
type
,
typename
M2
::
type
>::
value
==
true
));
typedef
op_conv_valid
<
M1
,
M2
>
op
;
return
matrix_op
<
op
>
(
op
(
m1
.
ref
(),
m2
.
ref
()));
}
template
<
typename
M1
,
typename
M2
>
const
matrix_op
<
op_conv_valid
<
M1
,
M2
,
true
>
>
xcorr_valid
(
const
matrix_exp
<
M1
>&
m1
,
const
matrix_exp
<
M2
>&
m2
)
{
COMPILE_TIME_ASSERT
((
is_same_type
<
typename
M1
::
type
,
typename
M2
::
type
>::
value
==
true
));
typedef
op_conv_valid
<
M1
,
M2
,
true
>
op
;
return
matrix_op
<
op
>
(
op
(
m1
.
ref
(),
m2
.
ref
()));
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_MATRIx_CONV_H__
Prev
1
2
Next
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