Пример #1
0
T* wiener_filter(const T &src, size_t region_size, double noise_variance)
{
    if ((region_size < 1) || (region_size > std::min(src.nrows(), src.ncols())))
        throw std::out_of_range("niblack_threshold: region_size out of range");
    
    // Compute regional statistics.
    const FloatImageView* means = mean_filter(src, region_size);
    const FloatImageView* variances = variance_filter(src, *means, region_size);

    // Compute noise variance if needed.
    if (noise_variance < 0) {
        FloatImageData* orderedVariancesData 
            = new FloatImageData(variances->size(), variances->origin());
        FloatImageView* orderedVariances 
            = new FloatImageView(*orderedVariancesData);        
        std::copy(variances->vec_begin(),
                  variances->vec_end(),
                  orderedVariances->vec_begin());
        size_t area = orderedVariances->nrows() * orderedVariances->ncols();
        std::nth_element(orderedVariances->vec_begin(),
                         orderedVariances->vec_begin() + (area - 1) / 2,
                         orderedVariances->vec_end());
        noise_variance 
            = (double)*(orderedVariances->vec_begin() + (area - 1) / 2);
        delete orderedVariancesData;
        delete orderedVariances;
    }

    typedef typename T::value_type value_type;
    typedef typename ImageFactory<T>::data_type data_type;
    typedef typename ImageFactory<T>::view_type view_type;
    data_type* data = new data_type(src.size(), src.origin());
    view_type* view = new view_type(*data);

    for (coord_t y = 0; y < src.nrows(); ++y) {
        for (coord_t x = 0; x < src.ncols(); ++x) {
            double mean = (double)means->get(Point(x, y));
            double variance = (double)variances->get(Point(x, y));
            // The estimate of noise variance will never be perfect, but in
            // theory, it would be impossible for any region to have a local
            // variance less than it. The following check eliminates that
            // theoretical impossibility and has a side benefit of preventing
            // division by zero.
            if (variance < noise_variance) {
                view->set(Point(x, y), (value_type)mean);
            } else {
                double multiplier = (variance - noise_variance) / variance;
                double value = (double)src.get(Point(x, y));
                view->set(Point(x, y),
                          (value_type)(mean + multiplier * (value - mean)));
            }
        }
    }

    delete means->data(); delete means;
    delete variances->data(); delete variances;
    return view;
}
Пример #2
0
FloatImageView* variance_filter(const T &src,
                                const FloatImageView &means,
                                size_t region_size) 
{
    if ((region_size < 1) || (region_size > std::min(src.nrows(), src.ncols())))
        throw std::out_of_range("variance_filter: region_size out of range");
     if (src.size() != means.size())
        throw std::invalid_argument("variance_filter: sizes must match");
 
    size_t half_region_size = region_size / 2;

    // Compute squares of each element. This step avoid repeating the squaring
    // operation for overlapping regions.
    FloatImageData* squaredData = new FloatImageData(src.size(), src.origin());
    FloatImageView* squares = new FloatImageView(*squaredData);

    transform(src.vec_begin(), 
              src.vec_end(), 
              squares->vec_begin(), 
              double_squared<typename T::value_type>());
  
    FloatImageData* data = new FloatImageData(src.size(), src.origin());
    FloatImageView* view = new FloatImageView(*data);  

    for (coord_t y = 0; y < src.nrows(); ++y) {
        for (coord_t x = 0; x < src.ncols(); ++x) {
            // Define the region.
            Point ul((coord_t)std::max(0, (int)x - (int)half_region_size),
                     (coord_t)std::max(0, (int)y - (int)half_region_size));
            Point lr((coord_t)std::min(x + half_region_size, src.ncols() - 1),
                     (coord_t)std::min(y + half_region_size, src.nrows() - 1));
            squares->rect_set(ul, lr);
            // Compute the variance.
            FloatPixel sum
                = std::accumulate(squares->vec_begin(), 
                                  squares->vec_end(), 
                                  (FloatPixel)0);
            size_t area = squares->nrows() * squares->ncols();
            FloatPixel mean = means.get(Point(x,y));
            view->set(Point(x, y), sum / area - mean * mean);
        }
    }
    
    delete squaredData;
    delete squares;
    return view;
}
Пример #3
0
// -----------------------------------------------------------------------------
PyObject* graph_create_minimum_spanning_tree_unique_distances(GraphObject* so, 
      PyObject* images, PyObject* uniq_dists) {

   PyObject* images_seq = PySequence_Fast(images, "images must be iteratable");
   if (images_seq == NULL)
      return NULL;

   static PyTypeObject* imagebase = 0;
   if (imagebase == 0) {
      PyObject* mod = PyImport_ImportModule(CHAR_PTR_CAST "gamera.gameracore");
      if (mod == 0) {
         PyErr_SetString(PyExc_RuntimeError, "Unable to load gameracore.\n");
         Py_DECREF(images_seq);
         return 0;
      }
      PyObject* dict = PyModule_GetDict(mod);
      if (dict == 0) {
         PyErr_SetString(PyExc_RuntimeError, "Unable to get module dictionary\n");
         Py_DECREF(images_seq);
         return 0;
      }
      imagebase = (PyTypeObject*)PyDict_GetItemString(dict, "Image");
   }

   // get the matrix
   if (!PyObject_TypeCheck(uniq_dists, imagebase)
         || get_pixel_type(uniq_dists) != Gamera::FLOAT) {
      PyErr_SetString(PyExc_TypeError, "uniq_dists must be a float image.");
      Py_DECREF(images_seq);
      return 0;
   }
   FloatImageView* dists = (FloatImageView*)((RectObject*)uniq_dists)->m_x;
   if (dists->nrows() != dists->ncols()) {
      PyErr_SetString(PyExc_TypeError, "image must be symmetric.");
      Py_DECREF(images_seq);
      return 0;
   }

   // get the graph ready
   so->_graph->remove_all_edges();
   GRAPH_UNSET_FLAG(so->_graph, FLAG_CYCLIC);

   // make the list for sorting
   typedef std::vector<std::pair<size_t, size_t> > index_vec_type;
   index_vec_type indexes(((dists->nrows() * dists->nrows()) - dists->nrows()) / 2);
   size_t row, col, index = 0;
   for (row = 0; row < dists->nrows(); ++row) {
      for (col = row + 1; col < dists->nrows(); ++col) {
         indexes[index].first = row;
         indexes[index++].second = col;
      }
   }
   std::sort(indexes.begin(), indexes.end(), DistsSorter(dists));

   // Add the nodes to the graph and build our map for later
   int images_len = PySequence_Fast_GET_SIZE(images_seq);
   std::vector<Node*> nodes(images_len);
   int i;
   for (i = 0; i < images_len; ++i) {
      GraphDataPyObject* obj = new GraphDataPyObject(PySequence_Fast_GET_ITEM(images_seq, i));
      nodes[i] = so->_graph->add_node_ptr(obj);
      assert(nodes[i] != NULL);
   }
   Py_DECREF(images_seq);

   // create the mst using kruskal
   i = 0;
   while (i < int(indexes.size()) && (int(so->_graph->get_nedges()) 
            < (images_len - 1))) {

      size_t row = indexes[i].first;
      size_t col = indexes[i].second;
      cost_t weight = dists->get(Point(col, row));
      so->_graph->add_edge(nodes[row], nodes[col], weight);
      ++i;
   }

   RETURN_VOID();
}