Added an option to weight the features from a hashed_feature_image

relative to the number of times they occur in an image.  I also set
the new default behavior to use this relative weighting and changed
the serialization format to accommodate this.
This commit is contained in:
Davis King 2013-08-06 00:03:24 -04:00
parent 712c65779c
commit 615b3cf6a0
2 changed files with 133 additions and 10 deletions

View File

@ -68,6 +68,15 @@ namespace dlib
inline long get_num_dimensions (
) const;
void use_relative_feature_weights (
);
void use_uniform_feature_weights (
);
bool uses_uniform_feature_weights (
) const;
inline const descriptor_type& operator() (
long row,
long col
@ -111,6 +120,8 @@ namespace dlib
array2d<unsigned long> feats;
feature_extractor fe;
hash_function_type phash;
std::vector<float> feat_counts;
bool uniform_feature_weights;
// This is a transient variable. It is just here so it doesn't have to be
@ -127,9 +138,13 @@ namespace dlib
std::ostream& out
)
{
int version = 1;
serialize(version, out);
serialize(item.feats, out);
serialize(item.fe, out);
serialize(item.phash, out);
serialize(item.feat_counts, out);
serialize(item.uniform_feature_weights, out);
}
template <typename T>
@ -138,9 +153,16 @@ namespace dlib
std::istream& in
)
{
int version = 0;
deserialize(version, in);
if (version != 1)
throw serialization_error("Unexpected version found while deserializing a dlib::hashed_feature_image object.");
deserialize(item.feats, in);
deserialize(item.fe, in);
deserialize(item.phash, in);
deserialize(item.feat_counts, in);
deserialize(item.uniform_feature_weights, in);
}
// ----------------------------------------------------------------------------------------
@ -157,6 +179,7 @@ namespace dlib
hashed_feature_image (
)
{
clear();
hash_feats.resize(1);
}
@ -173,6 +196,8 @@ namespace dlib
fe.clear();
phash = hash_function_type();
feats.clear();
feat_counts.clear();
uniform_feature_weights = false;
}
// ----------------------------------------------------------------------------------------
@ -229,6 +254,7 @@ namespace dlib
{
fe.copy_configuration(item.fe);
phash = item.phash;
uniform_feature_weights = item.uniform_feature_weights;
}
// ----------------------------------------------------------------------------------------
@ -250,11 +276,26 @@ namespace dlib
if (fe.size() != 0)
{
feats.set_size(fe.nr(), fe.nc());
for (long r = 0; r < feats.nr(); ++r)
feat_counts.assign(phash.num_hash_bins(),1);
if (uniform_feature_weights)
{
for (long c = 0; c < feats.nc(); ++c)
for (long r = 0; r < feats.nr(); ++r)
{
feats[r][c] = phash(fe(r,c));
for (long c = 0; c < feats.nc(); ++c)
{
feats[r][c] = phash(fe(r,c));
}
}
}
else
{
for (long r = 0; r < feats.nr(); ++r)
{
for (long c = 0; c < feats.nc(); ++c)
{
feats[r][c] = phash(fe(r,c));
feat_counts[feats[r][c]]++;
}
}
}
}
@ -263,6 +304,18 @@ namespace dlib
feats.set_size(0,0);
}
if (!uniform_feature_weights)
{
// use the inverse frequency as the scale for each feature. We also scale
// these counts so that they are invariant to the size of the image (we scale
// them so they all look like they come from a 500x400 images).
const double scale = img.size()/(500.0*400.0);
for (unsigned long i = 0; i < feat_counts.size(); ++i)
{
feat_counts[i] = scale/feat_counts[i];
}
}
fe.unload();
}
@ -318,6 +371,45 @@ namespace dlib
return phash.num_hash_bins();
}
// ----------------------------------------------------------------------------------------
template <
typename feature_extractor,
typename hash_function_type
>
void hashed_feature_image<feature_extractor,hash_function_type>::
use_relative_feature_weights (
)
{
uniform_feature_weights = false;
}
// ----------------------------------------------------------------------------------------
template <
typename feature_extractor,
typename hash_function_type
>
void hashed_feature_image<feature_extractor,hash_function_type>::
use_uniform_feature_weights (
)
{
uniform_feature_weights = true;
}
// ----------------------------------------------------------------------------------------
template <
typename feature_extractor,
typename hash_function_type
>
bool hashed_feature_image<feature_extractor,hash_function_type>::
uses_uniform_feature_weights (
) const
{
return uniform_feature_weights;
}
// ----------------------------------------------------------------------------------------
template <
@ -342,7 +434,7 @@ namespace dlib
<< "\n\t this: " << this
);
hash_feats[0] = std::make_pair(feats[row][col],1);
hash_feats[0] = std::make_pair(feats[row][col],feat_counts[feats[row][col]]);
return hash_feats;
}

View File

@ -28,14 +28,15 @@ namespace dlib
INITIAL VALUE
- size() == 0
- uses_uniform_feature_weights() == false
WHAT THIS OBJECT REPRESENTS
This object is a tool for performing image feature extraction. In
particular, it wraps another image feature extractor and converts
the wrapped image feature vectors into sparse indicator vectors. It does
this by hashing each feature vector into the range [0, get_num_dimensions()-1]
and then returns a new vector which is zero everywhere except for
the position determined by the hash.
particular, it wraps another image feature extractor and converts the
wrapped image feature vectors into sparse indicator vectors. It does this
by hashing each feature vector into the range [0, get_num_dimensions()-1]
and then returns a new vector which is zero everywhere except for the
position determined by the hash.
THREAD SAFETY
@ -153,6 +154,30 @@ namespace dlib
In this case, this is the number of hash bins. That is, get_hash().num_hash_bins()
!*/
void use_relative_feature_weights (
);
/*!
ensures
- #uses_uniform_feature_weights() == false
!*/
void use_uniform_feature_weights (
);
/*!
ensures
- #uses_uniform_feature_weights() == true
!*/
bool uses_uniform_feature_weights (
) const;
/*!
ensures
- returns true if this object weights each feature with a value of 1 and
false if it uses a weighting of 1/N where N is the number of occurrences
of the feature in an image (note that we normalize N so that it is
invariant to the size of the image given to load()).
!*/
const descriptor_type& operator() (
long row,
long col
@ -169,7 +194,13 @@ namespace dlib
- To be precise, this function returns a sparse vector V such that:
- V.size() == 1
- V[0].first == get_hash()(BASE_FE(row,col))
- V[0].second == 1
- if (uses_uniform_feature_weights()) then
- V[0].second == 1
- else
- V[0].second == 1/N where N is the number of times a feature in
hash bin V[0].first was observed in the image given to load().
Note that we scale all the counts so that they are invariant to
the size of the image.
!*/
const rectangle get_block_rect (