Mercurial > hg > octave-image
changeset 582:4355b74e0b17
Slight optimisations in bwlabeln.cc (use linear indices consistently)
author | jordigh |
---|---|
date | Tue, 04 Sep 2012 21:29:27 +0000 |
parents | 56faf308f3d0 |
children | 319cadd33084 |
files | src/bwlabeln.cc |
diffstat | 1 files changed, 69 insertions(+), 51 deletions(-) [+] |
line wrap: on
line diff
--- a/src/bwlabeln.cc +++ b/src/bwlabeln.cc @@ -32,14 +32,6 @@ return true; } -bool in_range (const coord& a, const dim_vector& size_vec) -{ - for(octave_idx_type i = 0; i < a.nelem (); i++) - if (a(i) < 0 or a(i) >= size_vec(i)) - return false; - return true; -} - //Lexicographic order for coords bool operator< (const coord& a, const coord& b) { @@ -61,31 +53,12 @@ return true; } -struct coord_hash -{ - inline size_t operator() (const coord& c) const - { - size_t seed = 0; - for(octave_idx_type i = 0; i < c.nelem (); i++) - { - //Boost's hash - seed ^= c(i) + 0x9e3779b9 + (seed<<6) + (seed>>2); - } - return seed; - } - - inline size_t operator()(size_t s) const - { - return s; - } -}; - // A few basic utility functions //{ inline coord -to_coord(const dim_vector& dv, - octave_idx_type k) +to_coord (const dim_vector& dv, + octave_idx_type k) { octave_idx_type n = dv.length (); coord retval ( dim_vector (n, 1)); @@ -98,6 +71,21 @@ } inline +octave_idx_type +coord_to_pad_idx (const dim_vector& dv, + const coord& c) +{ + octave_idx_type idx = 0; + octave_idx_type mul = 1; + for (octave_idx_type j = 0; j < dv.length (); j++) + { + idx += mul*c(j); + mul *= dv(j) + 2; + } + return idx; +} + +inline coord operator+ (const coord& a, const coord& b) { @@ -139,28 +127,34 @@ } //} -std::set<coord> -populate_neighbours(const boolNDArray& conn_mask) +std::set<octave_idx_type> +populate_neighbours(const boolNDArray& conn_mask, + const dim_vector& size_vec) { + std::set<octave_idx_type> neighbours_idx; std::set<coord> neighbours; dim_vector conn_size = conn_mask.dims (); - coord centre(dim_vector(conn_size.length (), 1), 1); - coord zero(dim_vector(conn_size.length (), 1), 0); + coord centre (dim_vector(conn_size.length (), 1), 1); + coord zero (dim_vector(conn_size.length (), 1), 0); for (octave_idx_type idx = 0; idx < conn_mask.nelem (); idx++) { if (conn_mask(idx)) { - coord aidx = to_coord(conn_size, idx) - centre; + coord aidx = to_coord (conn_size, idx) - centre; + //The zero coordinates are the centre, and the negative ones //are the ones reflected about the centre, and we don't need //to consider those. if( aidx == zero or neighbours.find(-aidx) != neighbours.end() ) continue; + neighbours.insert (aidx); + + neighbours_idx.insert (coord_to_pad_idx(size_vec, aidx)); } } - return neighbours; + return neighbours_idx; } boolNDArray @@ -265,7 +259,22 @@ return boolNDArray (mask_dims, 1); } -#include <iostream> +octave_idx_type +get_padded_index (octave_idx_type r, + const dim_vector& dv) +{ + octave_idx_type mult = 1; + octave_idx_type padded = 0; + for (octave_idx_type j = 0; j < dv.length (); j++) + { + padded += mult*(r % dv(j) + 1); + mult *= dv(j) + 2; + r /= dv(j); + } + return padded; +} + + DEFUN_DLD(bwlabeln, args, , "\ -*- texinfo -*-\n\ @@ -286,7 +295,7 @@ { octave_value_list rval; - union_find<coord, coord_hash> u_f; + union_find<octave_idx_type> u_f; octave_idx_type nargin = args.length (); @@ -350,40 +359,49 @@ if (error_state) return rval; - using std::set; + auto neighbours = populate_neighbours(conn_mask, size_vec); - set<coord> neighbours = populate_neighbours(conn_mask); + // Use temporary array with borders padded with zeros. Labels will + // also go in here eventually. + dim_vector padded_size = size_vec; + for (octave_idx_type j = 0; j < size_vec.length (); j++) + padded_size(j) += 2; - std::cout << "Union-finding..." << std::endl;; + NDArray L (padded_size, 0); - bool* BW_vec = BW.fortran_vec (); - for (octave_idx_type idx = 0; idx < BW.nelem (); idx++) + // L(2:end-1, 2:end, ..., 2:end-1) = BW + L.insert(BW, coord (dim_vector (size_vec.length (), 1), 1)); + + double* L_vec = L.fortran_vec (); + + for (octave_idx_type BWidx = 0; BWidx < BW.nelem (); BWidx++) { - if (BW_vec[idx]) + octave_idx_type Lidx = get_padded_index (BWidx, size_vec); + + if (L_vec[Lidx]) { - coord aidx = to_coord (size_vec, idx); - //Insert this one into its group - u_f.find_id(aidx); + u_f.find_id(Lidx); //Replace this with C++0x range-based for loop later //(implemented in gcc 4.6) for (auto nbr = neighbours.begin (); nbr != neighbours.end (); nbr++) { - coord n = *nbr + aidx; - if (in_range (n,size_vec) and BW(n) ) - u_f.unite (n,aidx); + octave_idx_type n = *nbr + Lidx; + if (L_vec[n] ) + u_f.unite (n, Lidx); } } } - NDArray L (size_vec, 0); + unordered_map<octave_idx_type, octave_idx_type> ids_to_label; octave_idx_type next_label = 1; auto idxs = u_f.get_objects (); //C++0x foreach later + for (auto idx = idxs.begin (); idx != idxs.end (); idx++) { octave_idx_type label; @@ -399,7 +417,7 @@ label = try_label -> second; } - L(idx->first) = label; + L_vec[idx->first] = label; } rval(0) = L;