vil_flood_fill.h
Go to the documentation of this file.
1 #ifndef vil_flood_fill_h_
2 #define vil_flood_fill_h_
3 //:
4 // \file
5 // \brief Fills a connected region with a given value.
6 // \author Tim Cootes
7 
8 #include <vector>
9 #include <utility>
10 #include <vil/vil_image_view.h>
11 #ifdef _MSC_VER
12 # include <vcl_msvc_warnings.h>
13 #endif
14 #include <vil/vil_chord.h>
15 
16 //: Search along i direction either side for limits of pixels matching v
17 // Fills in all such pixels with new_v. Returns limits in ilo and ihi
18 // \relatesalso vil_image_view
19 template<class T>
21  unsigned i, unsigned j,
22  T v, T new_v,
23  unsigned& ilo, unsigned& ihi)
24 {
25  T* row=image.top_left_ptr() + j*image.jstep();
26  unsigned ni1=image.ni()-1;
27  std::ptrdiff_t istep=image.istep();
28  ilo=i;
29  T* p=row+(i-1)*istep;
30  while (ilo>0 && *p==v) { ilo--; *p=new_v; p-=istep; }
31  ihi=i;
32  p=row+(i+1)*istep;
33  while (ihi<ni1 && *p==v) { ihi++; *p=new_v; p+=istep;}
34 }
35 
36 //: Flood fill on a 4-connected region
37 // Find every point in 4-connected region with values image(i,j)==v
38 // containing (seed_i,seed_j), and change their values to new_v
39 //
40 // Note, currently uses inefficient (x,y) access to image. Could be improved
41 // using fast pointer access to work along the rows.
42 // \relatesalso vil_image_view
43 template<class T>
45  unsigned seed_i, unsigned seed_j,
46  T v, T new_v)
47 {
48  unsigned ni1=image.ni()-1;
49  unsigned nj1=image.nj()-1;
50  std::vector<std::pair<unsigned,unsigned> > q; // List of points to visit
51  if (seed_i>ni1 || seed_j>nj1) return; // Seed outside image
52 
53  // Initialise the queue with the seed
54  q.emplace_back(seed_i,seed_j);
55 
56  unsigned k=0;
57  while (k<q.size())
58  {
59  unsigned i=q[k].first, j=q[k].second;
60  if (image(i,j)==v)
61  {
62  image(i,j)=new_v;
63  // Search to left and right for limit of this line
64  unsigned ilo,ihi;
65  vil_flood_fill_row(image,i,j,v,new_v,ilo,ihi);
66 
67  if (j>0)
68  {
69  // Consider row above
70  for (unsigned i1=ilo;i1<=ihi;++i1)
71  if (image(i1,j-1)==v)
72  q.emplace_back(i1,j-1);
73  }
74  if (j<nj1)
75  {
76  // Consider row below
77  for (unsigned i1=ilo;i1<=ihi;++i1)
78  if (image(i1,j+1)==v)
79  q.emplace_back(i1,j+1);
80  }
81  }
82  k++;
83  }
84 }
85 
86 //: Flood fill on a 4-connected region, and record region
87 // Find every point in 4-connected region with values image(i,j)==v
88 // containing (seed_i,seed_j), and change their values to new_v
89 //
90 // On exit region is filled with a set of image chords which cover the
91 // region.
92 //
93 // Note, currently uses inefficient (x,y) access to image. Could be improved
94 // using fast pointer access to work along the rows.
95 // \relatesalso vil_image_view
96 template<class T>
98  unsigned seed_i, unsigned seed_j,
99  T v, T new_v,
100  std::vector<vil_chord>& region)
101 {
102  region.resize(0);
103  unsigned ni1=image.ni()-1;
104  unsigned nj1=image.nj()-1;
105  std::vector<std::pair<unsigned,unsigned> > q; // List of points to visit
106  if (seed_i>ni1 || seed_j>nj1) return; // Seed outside image
107 
108  // Initialise the queue with the seed
109  q.emplace_back(seed_i,seed_j);
110 
111  unsigned k=0;
112  while (k<q.size())
113  {
114  unsigned i=q[k].first, j=q[k].second;
115  if (image(i,j)==v)
116  {
117  image(i,j)=new_v;
118  // Search to left and right for limit of this line
119  unsigned ilo,ihi;
120  vil_flood_fill_row(image,i,j,v,new_v,ilo,ihi);
121 
122  region.emplace_back(ilo,ihi,j);
123 
124  if (j>0)
125  {
126  // Consider row above
127  for (unsigned i1=ilo;i1<=ihi;++i1)
128  if (image(i1,j-1)==v)
129  q.emplace_back(i1,j-1);
130  }
131  if (j<nj1)
132  {
133  // Consider row below
134  for (unsigned i1=ilo;i1<=ihi;++i1)
135  if (image(i1,j+1)==v)
136  q.emplace_back(i1,j+1);
137  }
138  }
139  k++;
140  }
141 }
142 
143 
144 //: Flood fill on a 8-connected region
145 // Find every point in 8-connected region with values image(i,j)==v
146 // containing (seed_i,seed_j), and change their values to new_v
147 //
148 // Note, currently uses inefficient (x,y) access to image. Could be improved
149 // using fast pointer access to work along the rows.
150 // \relatesalso vil_image_view
151 template<class T>
153  unsigned seed_i, unsigned seed_j,
154  T v, T new_v)
155 {
156  unsigned ni1=image.ni()-1;
157  unsigned nj1=image.nj()-1;
158  std::vector<std::pair<unsigned,unsigned> > q; // List of points to visit
159  if (seed_i>ni1 || seed_j>nj1) return; // Seed outside image
160 
161  // Initialise the queue with the seed
162  q.emplace_back(seed_i,seed_j);
163 
164  unsigned k=0;
165  while (k<q.size())
166  {
167  unsigned i=q[k].first, j=q[k].second;
168  if (image(i,j)==v)
169  {
170  image(i,j)=new_v;
171  // Search to left and right for limit of this line
172  unsigned ilo,ihi;
173  vil_flood_fill_row(image,i,j,v,new_v,ilo,ihi);
174 
175  // Expand by one to allow all 8 neighbours to be examined
176  if (ilo>0) ilo--;
177  if (ihi<ni1) ihi++;
178  if (j>0)
179  {
180  // Consider row above
181  for (unsigned i1=ilo;i1<=ihi;++i1)
182  if (image(i1,j-1)==v)
183  q.emplace_back(i1,j-1);
184  }
185  if (j<nj1)
186  {
187  // Consider row below
188  for (unsigned i1=ilo;i1<=ihi;++i1)
189  if (image(i1,j+1)==v)
190  q.emplace_back(i1,j+1);
191  }
192  }
193  k++;
194  }
195 }
196 
197 //: Flood fill on a 8-connected region, and record region
198 // Find every point in 8-connected region with values image(i,j)==v
199 // containing (seed_i,seed_j), and change their values to new_v
200 //
201 // On exit region is filled with a set of image chords which cover the
202 // region.
203 //
204 // Note, currently uses inefficient (x,y) access to image. Could be improved
205 // using fast pointer access to work along the rows.
206 // \relatesalso vil_image_view
207 template<class T>
209  unsigned seed_i, unsigned seed_j,
210  T v, T new_v,
211  std::vector<vil_chord>& region)
212 {
213  region.resize(0);
214  unsigned ni1=image.ni()-1;
215  unsigned nj1=image.nj()-1;
216  std::vector<std::pair<unsigned,unsigned> > q; // List of points to visit
217  if (seed_i>ni1 || seed_j>nj1) return; // Seed outside image
218 
219  // Initialise the queue with the seed
220  q.emplace_back(seed_i,seed_j);
221 
222  unsigned k=0;
223  while (k<q.size())
224  {
225  unsigned i=q[k].first, j=q[k].second;
226  if (image(i,j)==v)
227  {
228  image(i,j)=new_v;
229  // Search to left and right for limit of this line
230  unsigned ilo,ihi;
231  vil_flood_fill_row(image,i,j,v,new_v,ilo,ihi);
232 
233  region.emplace_back(ilo,ihi,j);
234 
235  // Expand by one to allow all 8 neighbours to be examined
236  if (ilo>0) ilo--;
237  if (ihi<ni1) ihi++;
238  if (j>0)
239  {
240  // Consider row above
241  for (unsigned i1=ilo;i1<=ihi;++i1)
242  if (image(i1,j-1)==v)
243  q.emplace_back(i1,j-1);
244  }
245  if (j<nj1)
246  {
247  // Consider row below
248  for (unsigned i1=ilo;i1<=ihi;++i1)
249  if (image(i1,j+1)==v)
250  q.emplace_back(i1,j+1);
251  }
252  }
253  k++;
254  }
255 }
256 
257 #endif // vil_flood_fill_h_
void vil_flood_fill4(vil_image_view< T > &image, unsigned seed_i, unsigned seed_j, T v, T new_v)
Flood fill on a 4-connected region.
Concrete view of image data of type T held in memory.
Definition: vil_fwd.h:13
std::ptrdiff_t jstep() const
Add this to your pixel pointer to get next j pixel.
unsigned ni() const
Width.
unsigned nj() const
Height.
#define v
void vil_flood_fill_row(vil_image_view< T > &image, unsigned i, unsigned j, T v, T new_v, unsigned &ilo, unsigned &ihi)
Search along i direction either side for limits of pixels matching v.
A base class reference-counting view of some image data.
T * top_left_ptr()
Pointer to the first (top left in plane 0) pixel.
Object to store information about position of a row of pixels.
void vil_flood_fill8(vil_image_view< T > &image, unsigned seed_i, unsigned seed_j, T v, T new_v)
Flood fill on a 8-connected region.
std::ptrdiff_t istep() const
Add this to your pixel pointer to get next i pixel.