Skip to content

Commit

Permalink
Fixing sgm mem issue
Browse files Browse the repository at this point in the history
  • Loading branch information
ScottMcMichael committed Sep 21, 2017
1 parent d2daaba commit 9aba338
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 80 deletions.
File renamed without changes.
18 changes: 0 additions & 18 deletions src/vw/Stereo/CorrelateResearch.cc

This file was deleted.

25 changes: 0 additions & 25 deletions src/vw/Stereo/CorrelateResearch.h

This file was deleted.

4 changes: 2 additions & 2 deletions src/vw/Stereo/CorrelationView.tcc
Original file line number Diff line number Diff line change
Expand Up @@ -685,8 +685,8 @@ prerasterize(BBox2i const& bbox) const {
vw_out() << "Finished writing DEBUG data...\n";
} // End DEBUG

//if (level == 5)
// vw_throw( NoImplErr() << "DEBUG" );
if (level == 2)
vw_throw( NoImplErr() << "DEBUG" );

} // End of the level loop

Expand Down
4 changes: 2 additions & 2 deletions src/vw/Stereo/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ if MAKE_MODULE_STEREO

include_HEADERS = AffineMixtureComponent.h Algorithms.h Correlate.h \
Correlate.tcc Correlation.h CorrelationView.h CorrelationView.tcc \
CorrelateResearch.h CorrelateResearch.tcc CostFunctions.h \
CostFunctions.h \
DisparityMap.h EMSubpixelCorrelatorView.h \
EMSubpixelCorrelatorView.hpp GammaMixtureComponent.h \
GaussianMixtureComponent.h MixtureComponent.h PreFilter.h \
StereoModel.h StereoView.h SubpixelView.h \
UniformMixtureComponent.h SGM.h SGMAssist.h

libvwStereo_la_SOURCES = StereoModel.cc Correlate.cc Correlation.cc \
DisparityMap.cc EMSubpixelCorrelatorView.cc CorrelateResearch.cc SGM.cc
DisparityMap.cc EMSubpixelCorrelatorView.cc SGM.cc

libvwStereo_la_LIBADD = @MODULE_STEREO_LIBS@

Expand Down
39 changes: 34 additions & 5 deletions src/vw/Stereo/SGM.cc
Original file line number Diff line number Diff line change
Expand Up @@ -541,13 +541,41 @@ size_t SemiGlobalMatcher::compute_buffer_length() {

vw_out(DebugMessage, "stereo") << "SGM: Total disparity search area = " << total_offset << std::endl;

const size_t BYTES_PER_MB = 1024*1024;
const size_t total_bytes = total_offset * (sizeof(CostType) + sizeof(AccumCostType));
const size_t total_usage_mb = total_bytes / BYTES_PER_MB;
if (total_offset < 6)
vw_throw( ArgumentErr() << "SGM: Total disparity usage is too low!\n" );

const size_t BYTES_PER_MB = 1024*1024;
const size_t main_buffer_bytes = total_offset * (sizeof(CostType) + sizeof(AccumCostType));

vw_out(DebugMessage, "stereo") << "SGM: Estimating total large buffer size: "
<< main_buffer_bytes/BYTES_PER_MB << " MB\n";

m_buffer_lengths = total_offset; // Record this value


// Verify that allocating the "small" buffers won't put us over the limit.
// - m_buffer_lengths must be set for this to work.
const int PATHS_PER_PASS = 1;
const int NUM_MGM_BUFFERS = 4;
size_t small_buffer_size = 0;
if (m_use_mgm)
// Four vertical buffers and four horizontal buffers.
small_buffer_size = MultiAccumRowBuffer::get_buffer_size(this, PATHS_PER_PASS, true )*NUM_MGM_BUFFERS +
MultiAccumRowBuffer::get_buffer_size(this, PATHS_PER_PASS, false)*NUM_MGM_BUFFERS;
else {
int num_threads = vw_settings().default_num_threads();
small_buffer_size = OneLineBuffer::get_buffer_size(this)*num_threads;
}
size_t small_buffer_size_bytes = small_buffer_size * sizeof(AccumCostType);
vw_out(DebugMessage, "stereo") << "SGM: Estimating total small buffer size: "
<< small_buffer_size_bytes/BYTES_PER_MB << " MB\n";

if (total_usage_mb > m_memory_limit_mb)
vw_throw( ArgumentErr() << "SGM: Required memory usage is "<< total_usage_mb
size_t total_num_bytes = main_buffer_bytes + small_buffer_size_bytes;
if (total_num_bytes/BYTES_PER_MB > m_memory_limit_mb) {
vw_throw( ArgumentErr() << "SGM: Required memory usage is "<< total_num_bytes
<< " MB which is greater than the cap of "<< m_memory_limit_mb <<" MB!\n" );
}


return total_offset;
}
Expand All @@ -570,6 +598,7 @@ void SemiGlobalMatcher::allocate_large_buffers() {
// Allocate the requested memory and init all to zero
m_accum_buffer.reset(new AccumCostType[total_offset]);
memset(m_accum_buffer.get(), 0, accum_buffer_num_bytes);

}


Expand Down
2 changes: 1 addition & 1 deletion src/vw/Stereo/SGM.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ class SemiGlobalMatcher {
// The two main memory buffers that must be allocated.
boost::shared_array<CostType > m_cost_buffer;
boost::shared_array<AccumCostType> m_accum_buffer;
size_t m_buffer_lengths;

/// Image containing the inclusive disparity bounds for each pixel.
/// - Stored as min_col, min_row, max_col, max_row.
Expand Down Expand Up @@ -316,7 +317,6 @@ class SemiGlobalMatcher {
dy = (disp / m_num_disp_x) + m_min_disp_y; // 2D implementation
dx = (disp % m_num_disp_x) + m_min_disp_x;
}


//// Print out a disparity vector
//template <typename T>
Expand Down
97 changes: 74 additions & 23 deletions src/vw/Stereo/SGMAssist.h
Original file line number Diff line number Diff line change
Expand Up @@ -279,34 +279,62 @@ class MultiAccumRowBuffer {
PASS_ONE = 0,
PASS_TWO = 1 };

/// Return the number of elements in the buffer
static size_t get_buffer_size(const SemiGlobalMatcher* parent_ptr,
const int num_paths_in_pass,
const bool vertical) {

size_t line_size = parent_ptr->m_num_output_cols;
if (vertical)
line_size = parent_ptr->m_num_output_rows;

//std::cout << "m_line_size = " << m_line_size << std::endl;

// Instantiate two single-row buffers that will be used to temporarily store
// accumulated cost info until it is no longer needed.
// - Within each buffer, data is indexed in order [col][pass][disparity]
// - The actual data size in the buffer will vary each line, so it is
// initialized to be the maximum possible size.
const size_t buffer_pixel_size = num_paths_in_pass*parent_ptr->m_num_disp;
size_t buffer_size = line_size*buffer_pixel_size;

// No reason for the buffer size to be larger than the entire accumulator!
if (buffer_size > parent_ptr->m_buffer_lengths)
buffer_size = parent_ptr->m_buffer_lengths;

// If the buffer is over 128 MB, reduce its size to a percentage of the
// size of the entire accumulation buffer.
const size_t SAFE_BUFFER_SIZE = (1024*1024*128) / sizeof(SemiGlobalMatcher::AccumCostType);
const double MAX_PERCENTAGE = 0.04;

if (buffer_size > SAFE_BUFFER_SIZE) {
buffer_size = parent_ptr->m_buffer_lengths * MAX_PERCENTAGE;
if (buffer_size < SAFE_BUFFER_SIZE)
buffer_size = SAFE_BUFFER_SIZE; // Buffer can at least be this size
}

return buffer_size;
}

/// Construct the buffers.
/// - num_paths_in_pass must be four (8 directions) or eight (16 directions)
/// - num_paths_in_pass can be 1, four (8 directions), or eight (16 directions)
MultiAccumRowBuffer(const SemiGlobalMatcher* parent_ptr,
const int num_paths_in_pass=4,
const bool vertical=false) {
m_parent_ptr = parent_ptr;
m_num_paths_in_pass = num_paths_in_pass;
m_vertical = vertical;

const int num_cols = m_parent_ptr->m_num_output_cols;
const int num_rows = m_parent_ptr->m_num_output_rows;

m_line_size = num_cols;
m_line_size = m_parent_ptr->m_num_output_cols;
if (vertical)
m_line_size = num_rows;

//std::cout << "m_line_size = " << m_line_size << std::endl;

// Instantiate two single-row buffers that will be used to temporarily store
// accumulated cost info until it is no longer needed.
// - Within each buffer, data is indexed in order [col][pass][disparity]
// - The actual data size in the buffer will vary each line, so it is
// initialized to be the maximum possible size.
const size_t buffer_pixel_size = m_num_paths_in_pass*m_parent_ptr->m_num_disp;
m_buffer_size = m_line_size*buffer_pixel_size;
m_buffer_size = get_buffer_size(parent_ptr, num_paths_in_pass, vertical);
m_buffer_size_bytes = m_buffer_size*sizeof(SemiGlobalMatcher::AccumCostType);

//std::cout << "Allocating buffer: " << m_buffer_size_bytes << std::endl;
vw_out(DebugMessage, "stereo") << "MultiAccumRowBuffer - allocating buffer size (MB): "
<< m_buffer_size_bytes/(1024*1024) << std::endl;

// Allocate buffers that store accumulation scores
m_bufferA.reset(new SemiGlobalMatcher::AccumCostType[m_buffer_size]);
Expand Down Expand Up @@ -560,27 +588,50 @@ class OneLineBuffer{
initialize(parent_ptr);
}

/// Initialize the buffer.
/// - All this really does is allocate a memory buffer of the maximum possible required size.
void initialize(const SemiGlobalMatcher* parent_ptr) {

/// Returns the size it elements of the buffer.
static size_t get_buffer_size(const SemiGlobalMatcher* parent_ptr) {

// Figure out the max possible line length (diagonal line down the center)
const int num_cols = parent_ptr->m_num_output_cols;
const int num_rows = parent_ptr->m_num_output_rows;
int line_size = sqrt(num_cols*num_cols + num_rows*num_rows) + 1;
//std::cout << "m_line_size = " << m_line_size << std::endl;

// Instantiate single-row buffer that will be used to temporarily store
// accumulated cost info until it can be addded to the main SGM class buffer.
// - Within each buffer, data is indexed in order [pixel][disparity]
// - The actual data size in the buffer will vary each line, so it is
// initialized to be the maximum possible size.
size_t buffer_size = line_size*parent_ptr->m_num_disp;

// No reason for the buffer size to be larger than the entire accumulator!
if (buffer_size > parent_ptr->m_buffer_lengths)
buffer_size = parent_ptr->m_buffer_lengths;

// If the buffer is over 64 MB, reduce its size to a percentage of the
// size of the entire accumulation buffer.
const size_t SAFE_BUFFER_SIZE = (1024*1024*64) / sizeof(SemiGlobalMatcher::AccumCostType);
const double MAX_PERCENTAGE = 0.02;

if (buffer_size > SAFE_BUFFER_SIZE) {
buffer_size = parent_ptr->m_buffer_lengths * MAX_PERCENTAGE;
if (buffer_size < SAFE_BUFFER_SIZE)
buffer_size = SAFE_BUFFER_SIZE; // Buffer can at least be this size
}

return buffer_size;
}

/// Initialize the buffer.
/// - All this really does is allocate a memory buffer of the maximum possible required size.
void initialize(const SemiGlobalMatcher* parent_ptr) {

// Determine the buffer size
m_num_disp = parent_ptr->m_num_disp;
m_buffer_size = line_size*m_num_disp;
m_buffer_size = get_buffer_size(parent_ptr);
m_buffer_size_bytes = m_buffer_size*sizeof(SemiGlobalMatcher::AccumCostType);

//std::cout << "OneLineBuffer - allocating buffer size: " << m_buffer_size_bytes << std::endl;
//std::cout << "OneLineBuffer - m_num_disp = " << m_num_disp << std::endl;
vw_out(DebugMessage, "stereo") << "OneLineBuffer - allocating buffer size (MB): "
<< m_buffer_size_bytes/(1024*1024) << std::endl;

// Allocate the accumulation buffer
m_buffer.reset(new SemiGlobalMatcher::AccumCostType[m_buffer_size]);
Expand Down Expand Up @@ -695,7 +746,7 @@ class PixelPassTask : public Task {

// Retrive a memory buffer to work with
size_t buffer_id = m_buffer_manager_ptr->get_free_buffer_id();
OneLineBuffer * buff_ptr = m_buffer_manager_ptr->get_line_buffer(buffer_id);
OneLineBuffer* buff_ptr = m_buffer_manager_ptr->get_line_buffer(buffer_id);
AccumCostType* full_prior_ptr = buff_ptr->get_full_prior_ptr();

// Make a copy of the pixel iterator so we can re-use it for accum buffer addition
Expand Down
13 changes: 9 additions & 4 deletions src/vw/tools/ipfind.cc
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ int main(int argc, char** argv) {
int tile_size, num_threads, print_num_ip;
ImageView<double> integral;
bool no_orientation;
bool opencv_normalize = false;

const float IDEAL_LOG_THRESHOLD = .03;
const float IDEAL_OBALOG_THRESHOLD = .07;
Expand All @@ -153,6 +154,7 @@ int main(int argc, char** argv) {
"Specify the tile size for processing interest points. (Useful when working with large images).")
("lowe,l", "Save the interest points in an ASCII data format that is compatible with the Lowe-SIFT toolchain.")
("normalize", "Normalize the input, use for images that have non standard values such as ISIS cube files.")
("opencv-normalize", "Apply per-tile openCV normalization.")
("debug-image,d", "Write out debug images.")
("print-ip", po::value(&print_num_ip)->default_value(0),
"Print information for this many detected IP")
Expand Down Expand Up @@ -243,6 +245,9 @@ int main(int argc, char** argv) {
exit(0);
}

if ( vm.count("opencv-normalize"))
opencv_normalize = true;

// Iterate over the input files and find interest points in each.
for (size_t i = 0; i < input_file_names.size(); ++i) {

Expand Down Expand Up @@ -307,13 +312,13 @@ int main(int argc, char** argv) {
// Floats don't work here
// TODO: Don't always apply nodata mask.
} else if ( interest_operator == "brisk") {
OpenCvInterestPointDetector detector(OPENCV_IP_DETECTOR_TYPE_BRISK, true, describeInDetect, max_points);
OpenCvInterestPointDetector detector(OPENCV_IP_DETECTOR_TYPE_BRISK, opencv_normalize, describeInDetect, max_points);
ip = detect_interest_points(create_mask(image), detector, max_points);
} else if ( interest_operator == "orb") {
OpenCvInterestPointDetector detector(OPENCV_IP_DETECTOR_TYPE_ORB, true, describeInDetect, max_points);
OpenCvInterestPointDetector detector(OPENCV_IP_DETECTOR_TYPE_ORB, opencv_normalize, describeInDetect, max_points);
ip = detect_interest_points(create_mask(image), detector, max_points);
} else if ( interest_operator == "sift") {
OpenCvInterestPointDetector detector(OPENCV_IP_DETECTOR_TYPE_SIFT, true, describeInDetect, max_points);
OpenCvInterestPointDetector detector(OPENCV_IP_DETECTOR_TYPE_SIFT, opencv_normalize, describeInDetect, max_points);
ip = detect_interest_points(create_mask(image), detector, max_points);
/*
ImageView<PixelGray<unsigned char> > buffer_image;
Expand Down Expand Up @@ -369,7 +374,7 @@ int main(int argc, char** argv) {
*/

} else if ( interest_operator == "surf") {
OpenCvInterestPointDetector detector(OPENCV_IP_DETECTOR_TYPE_SURF, true, describeInDetect, max_points);
OpenCvInterestPointDetector detector(OPENCV_IP_DETECTOR_TYPE_SURF, opencv_normalize, describeInDetect, max_points);
ip = detect_interest_points(create_mask(image), detector, max_points);
}
#else // End OpenCV section
Expand Down

0 comments on commit 9aba338

Please sign in to comment.