Skip to content

Commit

Permalink
stereo_gui: Robustness to outliers when displaying images
Browse files Browse the repository at this point in the history
  • Loading branch information
oleg-alexandrov committed Jun 21, 2017
1 parent 7c641a5 commit 34619ce
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 20 deletions.
20 changes: 14 additions & 6 deletions src/asp/GUI/GuiUtilities.cc
Expand Up @@ -365,28 +365,36 @@ void DiskImagePyramidMultiChannel::get_image_clip(double scale_in, vw::BBox2i re
QImage & qimg, double & scale_out, vw::BBox2i & region_out) const{

bool scale_pixels = (m_type == CH1_DOUBLE);

vw::Vector2 bounds;

// Extract the clip, then convert it from VW format to QImage format.
if (m_type == CH1_DOUBLE) {

bounds = m_img_ch1_double.get_approx_bounds();

ImageView<double> clip;
m_img_ch1_double.get_image_clip(scale_in, region_in, clip,
scale_out, region_out);
formQimage(highlight_nodata, scale_pixels, m_img_ch1_double.get_nodata_val(), clip, qimg);
scale_out, region_out);
formQimage(highlight_nodata, scale_pixels, m_img_ch1_double.get_nodata_val(), bounds,
clip, qimg);
} else if (m_type == CH2_UINT8) {
ImageView<Vector<vw::uint8, 2> > clip;
m_img_ch2_uint8.get_image_clip(scale_in, region_in, clip,
scale_out, region_out);
formQimage(highlight_nodata, scale_pixels, m_img_ch2_uint8.get_nodata_val(), clip, qimg);
formQimage(highlight_nodata, scale_pixels, m_img_ch2_uint8.get_nodata_val(), bounds,
clip, qimg);
} else if (m_type == CH3_UINT8) {
ImageView<Vector<vw::uint8, 3> > clip;
m_img_ch3_uint8.get_image_clip(scale_in, region_in, clip,
scale_out, region_out);
formQimage(highlight_nodata, scale_pixels, m_img_ch3_uint8.get_nodata_val(), clip, qimg);
formQimage(highlight_nodata, scale_pixels, m_img_ch3_uint8.get_nodata_val(), bounds,
clip, qimg);
} else if (m_type == CH4_UINT8) {
ImageView<Vector<vw::uint8, 4> > clip;
m_img_ch4_uint8.get_image_clip(scale_in, region_in, clip,
scale_out, region_out);
formQimage(highlight_nodata, scale_pixels, m_img_ch4_uint8.get_nodata_val(), clip, qimg);
formQimage(highlight_nodata, scale_pixels, m_img_ch4_uint8.get_nodata_val(), bounds,
clip, qimg);
}else{
vw_throw(ArgumentErr() << "Unsupported image with " << m_num_channels << " bands\n");
}
Expand Down
38 changes: 24 additions & 14 deletions src/asp/GUI/GuiUtilities.h
Expand Up @@ -122,22 +122,22 @@ namespace vw { namespace gui {
template<class PixelT>
typename boost::enable_if<boost::is_same<PixelT,double>, void>::type
formQimage(bool highlight_nodata, bool scale_pixels, double nodata_val,
ImageView<PixelT> const& clip,
QImage & qimg);
vw::Vector2 const& bounds,
ImageView<PixelT> const& clip, QImage & qimg);

template<class PixelT>
typename boost::enable_if<boost::is_same<PixelT, vw::Vector<vw::uint8, 2> >, void>::type
formQimage(bool highlight_nodata, bool scale_pixels, double nodata_val,
ImageView<PixelT> const& clip,
vw::Vector2 const& bounds, ImageView<PixelT> const& clip,
QImage & qimg);

template<class PixelT>
typename boost::disable_if<boost::mpl::or_< boost::is_same<PixelT,double>,
boost::is_same<PixelT, vw::Vector<vw::uint8, 2> > >, void >::type
formQimage(bool highlight_nodata,
bool scale_pixels, double nodata_val,
ImageView<PixelT> const& clip,
QImage & qimg);
vw::Vector2 const& bounds,
ImageView<PixelT> const& clip, QImage & qimg);

/// Convert a QRect object to a BBox2 object.
inline BBox2 qrect2bbox(QRect const& R){
Expand Down Expand Up @@ -172,6 +172,7 @@ namespace vw { namespace gui {
// pre-defined member functions for an image class. This class
// is not a perfect solution, but there seem to be no easy way
// in ASP to handle images with variable numbers of channels.
// TODO: Add the case when multi-channel images also have float or double pixels
struct DiskImagePyramidMultiChannel{
vw::cartography::GdalWriteOptions m_opt;
vw::mosaic::DiskImagePyramid< double > m_img_ch1_double;
Expand Down Expand Up @@ -271,8 +272,8 @@ namespace vw { namespace gui {
template<class PixelT>
typename boost::enable_if<boost::is_same<PixelT,double>, void>::type
formQimage(bool highlight_nodata, bool scale_pixels, double nodata_val,
ImageView<PixelT> const& clip,
QImage & qimg){
vw::Vector2 const& bounds,
ImageView<PixelT> const& clip, QImage & qimg){

double min_val = std::numeric_limits<double>::max();
double max_val = -std::numeric_limits<double>::max();
Expand All @@ -284,23 +285,31 @@ formQimage(bool highlight_nodata, bool scale_pixels, double nodata_val,
if (clip(col, row) > max_val) max_val = clip(col, row);
}
}

// These bounds may contain outliers, so correct for that
min_val = std::max(min_val, bounds[0]);
max_val = std::min(max_val, bounds[1]);

// A safety measure
if (min_val >= max_val)
max_val = min_val + 1.0;
}

qimg = QImage(clip.cols(), clip.rows(), QImage::Format_ARGB32_Premultiplied);
for (int col = 0; col < clip.cols(); col++){
for (int row = 0; row < clip.rows(); row++){

double v = clip(col, row);
if (scale_pixels)
if (scale_pixels)
v = round(255*(std::max(v, min_val) - min_val)/(max_val-min_val));

// The comparison below is false when nodata_val is NaN

v = std::min(std::max(0.0, v), 255.0);

if (clip(col, row) <= nodata_val || std::isnan(clip(col, row)) ){

if (!highlight_nodata){
// transparent
qimg.setPixel(col, row, QColor(0, 0, 0, 0).rgba());
qimg.setPixel(col, row, Qt::transparent);
}else{
// highlight in red
qimg.setPixel(col, row, qRgb(255, 0, 0));
Expand All @@ -317,8 +326,8 @@ formQimage(bool highlight_nodata, bool scale_pixels, double nodata_val,
template<class PixelT>
typename boost::enable_if<boost::is_same<PixelT, vw::Vector<vw::uint8, 2> >, void>::type
formQimage(bool highlight_nodata, bool scale_pixels, double nodata_val,
ImageView<PixelT> const& clip,
QImage & qimg){
vw::Vector2 const& bounds,
ImageView<PixelT> const& clip, QImage & qimg){

qimg = QImage(clip.cols(), clip.rows(), QImage::Format_ARGB32_Premultiplied);
for (int col = 0; col < clip.cols(); col++){
Expand All @@ -339,6 +348,7 @@ template<class PixelT>
typename boost::disable_if<boost::mpl::or_< boost::is_same<PixelT,double>,
boost::is_same<PixelT, vw::Vector<vw::uint8, 2> > >, void >::type
formQimage(bool highlight_nodata, bool scale_pixels, double nodata_val,
vw::Vector2 const& bounds,
ImageView<PixelT> const& clip, QImage & qimg){

qimg = QImage(clip.cols(), clip.rows(), QImage::Format_ARGB32_Premultiplied);
Expand All @@ -350,7 +360,7 @@ formQimage(bool highlight_nodata, bool scale_pixels, double nodata_val,
else if (v.size() == 3)
qimg.setPixel(col, row, QColor(v[0], v[1], v[2], 255).rgba()); // color
else if (v.size() > 3)
qimg.setPixel(col, row, QColor(v[0], v[1], v[2], 255*(v[3] > 0) ).rgba()); // color or transparent
qimg.setPixel(col, row, QColor(v[0], v[1], v[2], 255*(v[3] > 0) ).rgba()); // transp or color

else
qimg.setPixel(col, row, QColor(v[0], v[0], v[0], 255).rgba()); // grayscale
Expand Down

0 comments on commit 34619ce

Please sign in to comment.