Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Added a ErodeView.

This is used to erase blobs that were detected with BlobIndexThreaded. This is applied because after stereo's filtering (which removes high gradients), there are left a whole bunch of little islands of valid data. This data is probably not correct and it's best to remove them. By default stereo deletes islands with an area of 1000 px.

At the moment ErodeView is a little slow. It needs an R-Tree or something similar to speed up it's seaching through blobs.
  • Loading branch information...
commit e37d6d034925a31cb70312b10e1d156a65fa93ec 1 parent aac629c
@zmoratto zmoratto authored
View
1  configure.ac
@@ -433,6 +433,7 @@ AC_CONFIG_FILES([ \
src/Makefile \
src/asp/Makefile \
src/asp/Core/Makefile \
+ src/asp/Core/tests/Makefile \
src/asp/SpiceIO/Makefile \
src/asp/IsisIO/Makefile \
src/asp/IsisIO/tests/Makefile \
View
20 src/asp/Core/BlobIndexThreaded.h
@@ -20,6 +20,7 @@
#include <vw/Core/ThreadPool.h>
#include <vw/Core/Stopwatch.h>
#include <vw/Image/Algorithms.h> // include Boost::Graph
+#include <vw/Image/Manipulation.h>
// BlobIndex (Multi) Threaded
///////////////////////////////////////
@@ -402,11 +403,22 @@ class BlobIndexThreaded {
m_c_blob[index].decompress(output);
}
blob::BlobCompressed const& compressed_blob( vw::uint32 const& index ) const {
- return m_c_blob[index];
- }
+ return m_c_blob[index]; }
+ typedef std::vector<blob::BlobCompressed>::iterator blob_iterator;
+ typedef std::vector<blob::BlobCompressed>::const_iterator const_blob_iterator;
+ blob_iterator begin() { return m_c_blob.begin(); }
+ const_blob_iterator begin() const { return m_c_blob.begin(); }
+ blob_iterator end() { return m_c_blob.end(); }
+ const_blob_iterator end() const { return m_c_blob.end(); }
+
vw::BBox2i const& blob_bbox( vw::uint32 const& index ) const {
- return m_blob_bbox[index];
- }
+ return m_blob_bbox[index]; }
+ typedef std::vector<vw::BBox2i>::iterator bbox_iterator;
+ typedef std::vector<vw::BBox2i>::const_iterator const_bbox_iterator;
+ bbox_iterator bbox_begin() { return m_blob_bbox.begin(); }
+ const_bbox_iterator bbox_begin() const { return m_blob_bbox.begin(); }
+ bbox_iterator bbox_end() { return m_blob_bbox.end(); }
+ const_bbox_iterator bbox_end() const { return m_blob_bbox.end(); }
};
#endif//__BLOB_INDEX_THREADED_H__
View
85 src/asp/Core/ErodeView.h
@@ -0,0 +1,85 @@
+// __BEGIN_LICENSE__
+// Copyright (C) 2006-2009 United States Government as represented by
+// the Administrator of the National Aeronautics and Space Administration.
+// All Rights Reserved.
+// __END_LICENSE__
+
+
+/// \file ErodeView.h
+///
+
+#ifndef __ASP_CORE_ERODE_VIEW_H__
+#define __ASP_CORE_ERODE_VIEW_H__
+
+// Standard
+#include <vector>
+
+// VW
+#include <vw/Image/Algorithms.h>
+#include <vw/Image/ImageViewBase.h>
+
+// ASP
+#include <asp/Core/BlobIndexThreaded.h>
+
+// Erode View
+// This takes in an image and invalidates spots based on the blobs detected
+// by blobindexthreaded
+template <class ViewT>
+class ErodeView : public vw::ImageViewBase<ErodeView<ViewT> > {
+
+ vw::ImageViewBase<ViewT> const& m_child;
+ std::vector<vw::BBox2i> m_bboxes;
+ std::vector<blob::BlobCompressed> m_blobs;
+
+ public:
+ typedef typename ViewT::pixel_type pixel_type;
+ typedef typename ViewT::pixel_type result_type; // Have to copy
+ typedef vw::ProceduralPixelAccessor<ErodeView<ViewT> > pixel_accessor;
+
+ ErodeView( vw::ImageViewBase<ViewT> const& image,
+ BlobIndexThreaded const& bindex ) :
+ m_child(image), m_bboxes(bindex.num_blobs()), m_blobs(bindex.num_blobs()) {
+ std::copy(bindex.begin(),bindex.end(),m_blobs.begin());
+ std::copy(bindex.bbox_begin(),bindex.bbox_end(),m_bboxes.begin());
+ }
+
+ inline vw::int32 cols() const { return m_child.impl().cols(); }
+ inline vw::int32 rows() const { return m_child.impl().rows(); }
+ inline vw::int32 planes() const { return 1; } // Not allowed .
+
+ inline pixel_accessor origin() const { return pixel_accessor(*this,0,0); }
+
+ inline result_type operator()( vw::int32 i, vw::int32 j, vw::int32 /*p*/=0 ) const {
+ // Ideally this should be an R-tree.
+
+ vw::Vector2i lookup(i,j);
+ std::vector<blob::BlobCompressed>::const_iterator blob = m_blobs.begin();
+ for ( std::vector<vw::BBox2i>::const_iterator bbox = m_bboxes.begin();
+ bbox != m_bboxes.end(); bbox++ ) {
+ if ( bbox->contains(lookup) ) {
+ // Determing now if the compressed blob really does contain this point
+ vw::Vector2i local = lookup - bbox->min();
+ typedef std::list<vw::int32>::const_iterator inner_iter;
+ for ( inner_iter start = blob->start(local.y()).begin(),
+ end = blob->end(local.y()).begin();
+ start != blob->start(local.y()).end();
+ start++, end++ ) {
+ if ( local.x() >= *start && local.x() < *end )
+ return result_type(); // zero or invalid
+ }
+ }
+ blob++;
+ }
+ return m_child.impl()(i,j);
+ }
+
+ typedef ErodeView<ViewT> prerasterize_type;
+ inline prerasterize_type prerasterize( vw::BBox2i const& /*bbox*/ ) const { return *this; }
+ template <class DestT>
+ inline void rasterize( DestT const& dest, vw::BBox2i const& bbox ) const {
+ vw::rasterize( prerasterize(bbox), dest, bbox );
+ }
+
+};
+
+#endif//__INPAINT_H__
View
4 src/asp/Core/Makefile.am
@@ -20,7 +20,7 @@ endif
include_HEADERS = BlobIndexThreaded.h StereoSettings.h SparseView.h \
InpaintView.h MedianFilter.h OrthoRasterizer.h \
- SoftwareRenderer.h $(ba_headers)
+ SoftwareRenderer.h ErodeView.h $(ba_headers)
libaspCore_la_SOURCES = BlobIndexThreaded.cc SoftwareRenderer.cc \
StereoSettings.cc $(ba_sources)
@@ -38,7 +38,7 @@ endif
AM_CPPFLAGS = @ASP_CPPFLAGS@
AM_LDFLAGS = @ASP_LDFLAGS@ -version-info @LIBTOOL_VERSION@
-SUBDIRS = .
+SUBDIRS = . tests
includedir = $(prefix)/include/asp/Core
View
1  src/asp/Core/StereoSettings.cc
@@ -125,6 +125,7 @@ StereoSettings::StereoSettings() {
ASSOC_INT("SUBPIXEL_PYRAMID_LEVELS", subpixel_pyramid_levels, 3, "Number of pyramid levels for EMSubpixelCorrelator");
// Filtering Options
+ ASSOC_INT("ERODE_MAX_SIZE", erode_max_size, 1000, "max size of islands that should be removed");
ASSOC_INT("FILL_HOLES", fill_holes, 1, "fill holes using an inpainting method");
ASSOC_INT("FILL_HOLE_MAX_SIZE", fill_hole_max_size, 100000, "max size in pixels that should be filled");
ASSOC_INT("RM_H_HALF_KERN", rm_h_half_kern, 5, "low conf pixel removal kernel half size");
View
3  src/asp/Core/StereoSettings.h
@@ -80,11 +80,12 @@ class StereoSettings {
int rm_threshold; /* rm_treshold < disp[n]-disp[m] reject pxl */
int rm_cleanup_passes; /* number of times to perform cleanup
in the post-processing phase */
+ int erode_max_size; /* Max island size in pixels that it'll remove*/
int fill_holes;
int fill_hole_max_size; /* Maximum hole size in pixels that we'll attempt
to fill */
int mask_flatfield; /* Masks pixels in the input images that are less
- than 0. (For use with apollo metric camera...) */
+ than 0. (For use with apollo metric camera...) */
// Triangulation Options
float near_universe_radius; /* radius of the universe in meters */
View
30 src/asp/Core/tests/Makefile.am
@@ -0,0 +1,30 @@
+# __BEGIN_LICENSE__
+# Copyright (C) 2006-2009 United States Government as represented by
+# the Administrator of the National Aeronautics and Space Administration.
+# All Rights Reserved.
+# __END_LICENSE__
+
+
+########################################################################
+# sources
+########################################################################
+
+if MAKE_MODULE_CORE
+
+TestErodeView_SOURCES = TestErodeView.cxx
+
+TESTS = TestErodeView
+
+endif
+
+########################################################################
+# general
+########################################################################
+
+AM_CPPFLAGS = @ASP_CPPFLAGS@
+AM_LDFLAGS = @ASP_LDFLAGS@ @PKG_CORE_LIBS@
+
+check_PROGRAMS = $(TESTS)
+
+include $(top_srcdir)/config/rules.mak
+include $(top_srcdir)/config/tests.am
View
32 src/asp/Core/tests/TestErodeView.cxx
@@ -0,0 +1,32 @@
+// __BEGIN_LICENSE__
+// Copyright (C) 2006-2009 United States Government as represented by
+// the Administrator of the National Aeronautics and Space Administration.
+// All Rights Reserved.
+// __END_LICENSE__
+
+#include <gtest/gtest.h>
+
+#include <vw/Image/ImageViewRef.h>
+#include <asp/Core/ErodeView.h>
+
+using namespace vw;
+
+TEST(ErodeView, basic_test) {
+ ImageView<PixelMask<uint8> > test(3,3);
+ EXPECT_EQ( PixelMask<uint8>(), test(0,0) );
+ EXPECT_FALSE( is_valid(test(0,0)) );
+ test(1,1) = PixelMask<uint8>(100);
+ EXPECT_TRUE( is_valid(test(1,1)) );
+
+ BlobIndexThreaded bindex( test, 100 );
+ EXPECT_EQ( 1, bindex.num_blobs() );
+
+ ImageViewRef<PixelMask<uint8> > erode_ref =
+ ErodeView<ImageView<PixelMask<uint8> > >( test, bindex );
+ EXPECT_FALSE( is_valid(erode_ref(1,1)) );
+ EXPECT_FALSE( is_valid(erode_ref(0,0)) );
+ ImageView<PixelMask<uint8> > eroded = erode_ref;
+ EXPECT_FALSE( is_valid(eroded(0,0) ) );
+ EXPECT_FALSE( is_valid(eroded(1,1) ) );
+ EXPECT_EQ( 0, eroded(1,1).child() );
+}
View
75 src/asp/Tools/stereo.cc
@@ -683,49 +683,51 @@ int main(int argc, char* argv[]) {
// Applying additional clipping from the edge. We make new
// mask files to avoid a weird and tricky segfault due to
// ownership issues.
- {
- DiskImageView<vw::uint8> left_mask( out_prefix+"-lMask.tif" );
- DiskImageView<vw::uint8> right_mask( out_prefix+"-rMask.tif" );
- int mask_buffer = std::max( stereo_settings().subpixel_h_kern,
- stereo_settings().subpixel_v_kern );
- ImageViewRef<vw::uint8> Lmaskmore, Rmaskmore;
- Lmaskmore = apply_mask(edge_mask(left_mask,0,mask_buffer));
- Rmaskmore = apply_mask(edge_mask(right_mask,0,mask_buffer));
- DiskImageResourceGDAL l_mask_rsrc( out_prefix+"-lMaskMore.tif",
- Lmaskmore.format(),
- raster_tile_size,
- gdal_options );
- DiskImageResourceGDAL r_mask_rsrc( out_prefix+"-rMaskMore.tif",
- Rmaskmore.format(),
- raster_tile_size,
- gdal_options );
- block_write_image(l_mask_rsrc, Lmaskmore,
- TerminalProgressCallback("asp", "\t Reduce LMask: "));
- block_write_image(r_mask_rsrc, Rmaskmore,
- TerminalProgressCallback("asp", "\t Reduce RMask: "));
- }
- DiskImageView<vw::uint8> left_mask( out_prefix+"-lMaskMore.tif" );
- DiskImageView<vw::uint8> right_mask( out_prefix+"-rMaskMore.tif" );
+ DiskImageView<vw::uint8> left_mask( out_prefix+"-lMask.tif" );
+ DiskImageView<vw::uint8> right_mask( out_prefix+"-rMask.tif" );
+ int mask_buffer = std::max( stereo_settings().subpixel_h_kern,
+ stereo_settings().subpixel_v_kern );
+ ImageViewRef<vw::uint8> Lmaskmore, Rmaskmore;
+ Lmaskmore = apply_mask(edge_mask(left_mask,0,mask_buffer));
+ Rmaskmore = apply_mask(edge_mask(right_mask,0,mask_buffer));
+ DiskCacheImageView<vw::uint8>
+ left_red_mask(Lmaskmore, "tif",
+ TerminalProgressCallback("asp","\t Reduce LMask:"),
+ stereo_settings().cache_dir);
+ DiskCacheImageView<vw::uint8>
+ right_red_mask(Rmaskmore, "tif",
+ TerminalProgressCallback("asp","\t Reduce RMask:"),
+ stereo_settings().cache_dir);
disparity_map = stereo::disparity_mask( disparity_map,
- left_mask, right_mask );
+ left_red_mask, right_red_mask );
+
+ DiskCacheImageView<PixelMask<Vector2f> >
+ filtered_disp(disparity_map, "tif",
+ TerminalProgressCallback("asp","\t Intermediate:"),
+ stereo_settings().cache_dir);
vw_out() << "\t--> Rasterizing filtered disparity map to disk. \n";
- DiskImageResourceGDAL filtered_disparity_map_rsrc( out_prefix+"-FTemp.tif", disparity_map.format(),
- raster_tile_size,
- gdal_options );
- block_write_image( filtered_disparity_map_rsrc, disparity_map,
- TerminalProgressCallback("asp", "\t--> Writing: ") );
-
- // Removing extra masks
- std::string lmask = out_prefix+"-lMaskMore.tif",
- rmask = out_prefix+"-rMaskMore.tif";
- unlink( lmask.c_str() );
- unlink( rmask.c_str() );
+ BlobIndexThreaded bindex( filtered_disp,
+ stereo_settings().erode_max_size );
+ vw_out() << "\t * Eroding " << bindex.num_blobs() << " islands\n";
+ ImageViewRef<PixelMask<Vector2f> > erode_disp_map;
+ erode_disp_map = ErodeView<DiskCacheImageView<PixelMask<Vector2f> > >(filtered_disp, bindex );
+ //erode_disp_map = filtered_disp;
+ DiskImageResourceGDAL erode_map_rsrc(out_prefix+"-FTemp.tif",
+ erode_disp_map.format(),
+ raster_tile_size,
+ gdal_options );
+ block_write_image( erode_map_rsrc, erode_disp_map,
+ TerminalProgressCallback("asp", "\t--> Eroding: "));
+ }
+
+ { // Erode away small islands of good data. (They're probably mistakes)
}
+
DiskImageView<PixelMask<Vector2f> > filtered_disparity_map( out_prefix+"-FTemp.tif" );
- {
+ { // Write Good Pixel Map
vw_out() << "\t--> Creating \"Good Pixel\" image: "
<< (out_prefix + "-GoodPixelMap.tif") << "\n";
{
@@ -762,6 +764,7 @@ int main(int argc, char* argv[]) {
}
}
+ // Fill Holes
ImageViewRef<PixelMask<Vector2f> > hole_filled_disp_map;
if(stereo_settings().fill_holes) {
vw_out() << "\t--> Filling holes with Inpainting method.\n";
View
1  src/asp/Tools/stereo.h
@@ -36,6 +36,7 @@ namespace fs = boost::filesystem;
#include <asp/Core/MedianFilter.h>
#include <asp/Core/BlobIndexThreaded.h>
#include <asp/Core/InpaintView.h>
+#include <asp/Core/ErodeView.h>
// Support for ISIS image files
#if defined(ASP_HAVE_PKG_ISIS) && ASP_HAVE_PKG_ISIS == 1
Please sign in to comment.
Something went wrong with that request. Please try again.