Example #1
0
LabelImage RandomForestImage::predict(const RGBDImage& image,
         cuv::ndarray<float, cuv::host_memory_space>* probabilities, const bool onGPU, bool useDepthImages) const {

    LabelImage prediction(image.getWidth(), image.getHeight());

    const LabelType numClasses = getNumClasses();

    if (treeData.size() != ensemble.size()) {
        throw std::runtime_error((boost::format("tree data size: %d, ensemble size: %d. histograms normalized?")
                % treeData.size() % ensemble.size()).str());
    }

    cuv::ndarray<float, cuv::host_memory_space> hostProbabilities(
            cuv::extents[numClasses][image.getHeight()][image.getWidth()],
            m_predictionAllocator);

    if (onGPU) {
        cuv::ndarray<float, cuv::dev_memory_space> deviceProbabilities(
                cuv::extents[numClasses][image.getHeight()][image.getWidth()],
                m_predictionAllocator);
        cudaSafeCall(cudaMemset(deviceProbabilities.ptr(), 0, static_cast<size_t>(deviceProbabilities.size() * sizeof(float))));

        {
            utils::Profile profile("classifyImagesGPU");
            for (const boost::shared_ptr<const TreeNodes>& data : treeData) {
                classifyImage(treeData.size(), deviceProbabilities, image, numClasses, data, useDepthImages);
            }
        }

        normalizeProbabilities(deviceProbabilities);

        cuv::ndarray<LabelType, cuv::dev_memory_space> output(image.getHeight(), image.getWidth(),
                m_predictionAllocator);
        determineMaxProbabilities(deviceProbabilities, output);

        hostProbabilities = deviceProbabilities;
        cuv::ndarray<LabelType, cuv::host_memory_space> outputHost(image.getHeight(), image.getWidth(),
                m_predictionAllocator);

        outputHost = output;

        {
            utils::Profile profile("setLabels");
            for (int y = 0; y < image.getHeight(); ++y) {
                for (int x = 0; x < image.getWidth(); ++x) {
                    prediction.setLabel(x, y, static_cast<LabelType>(outputHost(y, x)));
                }
            }
        }
    } else {
        utils::Profile profile("classifyImagesCPU");

        tbb::parallel_for(tbb::blocked_range<size_t>(0, image.getHeight()),
                [&](const tbb::blocked_range<size_t>& range) {
                    for(size_t y = range.begin(); y != range.end(); y++) {
                        for(int x=0; x < image.getWidth(); x++) {

                            for (LabelType label = 0; label < numClasses; label++) {
                                hostProbabilities(label, y, x) = 0.0f;
                            }

                            for (const auto& tree : ensemble) {
                                const auto& t = tree->getTree();
                                PixelInstance pixel(&image, 0, x, y);
                                const auto& hist = t->classifySoft(pixel);
                                assert(hist.size() == numClasses);
                                for(LabelType label = 0; label<hist.size(); label++) {
                                    hostProbabilities(label, y, x) += hist[label];
                                }
                            }

                            double sum = 0.0f;
                            for (LabelType label = 0; label < numClasses; label++) {
                                sum += hostProbabilities(label, y, x);
                            }
                            float bestProb = -1.0f;
                            for (LabelType label = 0; label < numClasses; label++) {
                                hostProbabilities(label, y, x) /= sum;
                                float prob = hostProbabilities(label, y, x);
                                if (prob > bestProb) {
                                    prediction.setLabel(x, y, label);
                                    bestProb = prob;
                                }
                            }
                        }
                    }
                });
    }

    if (probabilities) {
        *probabilities = hostProbabilities;
    }

    return prediction;
}
//------------------------------------------------------------------------------
InstancePlacer::InstancePlacer(unsigned layer_num,
                               const TerrainDataClient * terrain_data,
                               const std::vector<bbm::DetailTexInfo> & tex_info) :
    cur_camera_cell_x_(-1000),
    cur_camera_cell_z_(-1000),
    terrain_(terrain_data),
    instances_per_cell_(0),
    layer_num_(layer_num)
{
    cos_threshold_steepness_ = cosf(deg2Rad(s_params.get<float>("instances.threshold_steepness")));
    unsigned num_layers = s_params.get<unsigned>("instances.num_layers");
    
    if (s_params.get<std::vector<float> >("instances.density_factor").size() != num_layers)
    {
        throw Exception("density factor not specified for all layers.");
    }
    
    cell_resolution_ = s_params.get<unsigned>("instances.cell_resolution");
    cell_size_       = s_params.get<float>   ("instances.base_draw_distance")*(layer_num+1) / cell_resolution_;
    
    if (!PlacedInstance::dummy_desc_.get())
    {
        PlacedInstance::dummy_desc_.reset(new InstancedGeometryDescription("dummy"));
    }
    
    assert(cell_resolution_);
    cell_resolution_ |= 1; // Make sure we always have an odd number of cells

    instance_probability_.resize(tex_info.size());
    instance_prototype_.  resize(tex_info.size());



    


    
    // The maximum density determines the number of instances allocated
    float max_density = std::numeric_limits<float>::min();
    for (unsigned terrain_type=0; terrain_type<tex_info.size(); ++terrain_type)
    {
        max_density = std::max(max_density, tex_info[terrain_type].grass_density_);

        // Copy probabilities...
        instance_probability_[terrain_type].resize(tex_info[terrain_type].zone_info_.size());
        for (unsigned t=0; t < instance_probability_[terrain_type].size(); ++t)
        {
            instance_probability_[terrain_type][t] = tex_info[terrain_type].zone_info_[t].probability_;
        }



        // Load model prototypes
        instance_prototype_[terrain_type].resize(tex_info[terrain_type].zone_info_.size());
        for (unsigned obj=0; obj<instance_prototype_[terrain_type].size(); ++obj)
        {
            osg::ref_ptr<InstanceProxy> proxy;
            try
            {
                proxy = dynamic_cast<InstanceProxy*>(
                    ReaderWriterBbm::loadModel(tex_info[terrain_type].zone_info_[obj].model_).get());
                if (!proxy.get())
                {
                    Exception e("Error loading automatically placed object \"");
                    e << tex_info[terrain_type].zone_info_[obj].model_
                      << "\". Perhaps it's not instanced?";
                    throw e;
                }
            } catch (Exception & e)
            {
                e.addHistory("InstancePlacer::InstancePlacer()");
                throw e;
            }
            
            instance_prototype_[terrain_type][obj] = proxy;
        }
    }                                          


                                          

    // Depending on the layer we are in, we want to have a different
    // instance density. max_density is the maximum density in
    // instances/m^2 specified for any terrain type and determines the
    // number of prototypes we have to allocate per cell. Terrain
    // types with smaller density have some prototypes unused
    // (probability doesn't sum up to one).

    // convert density to instances per cell,
    // adjust for layer number.
    instances_per_cell_ =
        (unsigned)(cell_size_*cell_size_ * max_density *
                   s_params.get<std::vector<float> >("instances.density_factor")[layer_num_]*
                   s_params.get<float>("instances.user_density"));

    // Perhaps there are no instances in this level, or user chose
    // zero density
    if (instances_per_cell_ == 0) return;
    
    
    normalizeProbabilities(instance_probability_, max_density, tex_info);

    
    initCells();

    s_scheduler.addTask(PeriodicTaskCallback(this, &InstancePlacer::update),
                        s_params.get<float>("instances.update_dt"),
                        "InstancePlacer::update",
                        &fp_group_);
}