source: trunk/src/Detection/areClose.cc @ 744

Last change on this file since 744 was 744, checked in by MatthewWhiting, 14 years ago

Two major changes. We make use of the ObjectGrower? class to handle the growing of the detections, and there are some improvements to the addPixel function in Object2D that result in major speed-ups.

File size: 7.1 KB
Line 
1// -----------------------------------------------------------------------
2// areClose.cc: Determine whether two Detections are close enough to
3//              be merged.
4// -----------------------------------------------------------------------
5// Copyright (C) 2006, Matthew Whiting, ATNF
6//
7// This program is free software; you can redistribute it and/or modify it
8// under the terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 2 of the License, or (at your
10// option) any later version.
11//
12// Duchamp is distributed in the hope that it will be useful, but WITHOUT
13// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15// for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with Duchamp; if not, write to the Free Software Foundation,
19// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
20//
21// Correspondence concerning Duchamp may be directed to:
22//    Internet email: Matthew.Whiting [at] atnf.csiro.au
23//    Postal address: Dr. Matthew Whiting
24//                    Australia Telescope National Facility, CSIRO
25//                    PO Box 76
26//                    Epping NSW 1710
27//                    AUSTRALIA
28// -----------------------------------------------------------------------
29#include <math.h>
30#include <duchamp/Detection/detection.hh>
31#include <duchamp/PixelMap/Scan.hh>
32#include <duchamp/PixelMap/Object3D.hh>
33#include <duchamp/param.hh>
34
35using namespace PixelInfo;
36
37namespace duchamp
38{
39
40  bool areAdj(Object2D &obj1, Object2D &obj2);
41  bool areClose(Object2D &obj1, Object2D &obj2, float threshold);
42
43  bool areClose(Detection &obj1, Detection &obj2, Param &par)
44  {
45
46    /// A Function to test whether object1 and object2 are within the
47    /// spatial and velocity thresholds specified in the parameter set par.
48    /// Returns true if at least one pixel of object1 is close to
49    /// at least one pixel of object2.
50 
51    bool close = false;   // this will be the value returned
52
53    //
54    // First, check to see if the objects are nearby.  We will only do
55    // the pixel-by-pixel comparison if their pixel ranges overlap.
56    // This saves a bit of time if the objects are big and are nowhere
57    // near one another.
58    //
59
60    bool flagAdj = par.getFlagAdjacent();
61    float threshS = par.getThreshS();
62    float threshV = par.getThreshV();
63
64    long gap;
65    if(flagAdj) gap = 1;
66    else gap = long( ceil(threshS) );
67
68    Scan test1,test2;
69
70    // Test X ranges
71    test1.define(0,obj1.getXmin()-gap,obj1.getXmax()-obj1.getXmin()+2*gap+1);
72    test2.define(0,obj2.getXmin(),obj2.getXmax()-obj2.getXmin()+1);
73    bool areNear = overlap(test1,test2);
74
75    // Test Y ranges
76    test1.define(0,obj1.getYmin()-gap,obj1.getYmax()-obj1.getYmin()+2*gap+1);
77    test2.define(0,obj2.getYmin(),obj2.getYmax()-obj2.getYmin()+1);
78    areNear = areNear && overlap(test1,test2);
79 
80    // Test Z ranges
81    gap = long(ceil(threshV));
82    test1.define(0,obj1.getZmin()-gap,obj1.getZmax()-obj1.getZmin()+2*gap+1);
83    test2.define(0,obj2.getZmin(),obj2.getZmax()-obj2.getZmin()+1);
84    areNear = areNear && overlap(test1,test2);
85    //   Scan commonZ = intersect(test1,test2);
86
87    if(areNear){
88      //
89      // If we get to here, the pixel ranges overlap -- so we do a
90      // pixel-by-pixel comparison to make sure they are actually
91      // "close" according to the thresholds.  Otherwise, close=false,
92      // and so don't need to do anything else before returning.
93      //
94
95      std::vector<long> zlist1 = obj1.getChannelList();
96      std::vector<long> zlist2 = obj2.getChannelList();
97
98      for(size_t ct1=0; (!close && (ct1<zlist1.size())); ct1++){
99       
100        for(size_t ct2=0; (!close && (ct2<zlist2.size())); ct2++){
101       
102          if(abs(zlist1[ct1]-zlist2[ct2])<=threshV){
103             
104            Object2D temp1 = obj1.getChanMap(zlist1[ct1]);
105            Object2D temp2 = obj2.getChanMap(zlist2[ct2]);
106
107            if(flagAdj) gap = 1;
108            else gap = long( ceil(threshS) );
109            test1.define(0, temp1.getXmin()-gap,
110                         temp1.getXmax()-temp1.getXmin()+2*gap+1);
111            test2.define(0, temp2.getXmin(),
112                         temp2.getXmax()-temp2.getXmin()+1);
113            areNear = overlap(test1,test2);
114            test1.define(0, temp1.getYmin()-gap,
115                         temp1.getYmax()-temp1.getYmin()+2*gap+1);
116            test2.define(0, temp2.getYmin(),
117                         temp2.getYmax()-temp2.getYmin()+1);
118            areNear = areNear && overlap(test1,test2);
119             
120            if(areNear){
121              if(flagAdj) close = close || areAdj(temp1,temp2);
122              else close = close || areClose(temp1,temp2,threshS);
123            }
124           
125          }
126
127        }
128
129      }
130
131    }
132
133    return close;
134
135  }
136
137  bool areClose(Object2D &obj1, Object2D &obj2, float threshold)
138  {
139    bool close = false;
140
141    long nscan1 = obj1.getNumScan();
142    long nscan2 = obj2.getNumScan();
143
144    Scan temp1(0, obj1.getYmin()-int(threshold),
145               obj1.getYmax()-obj1.getYmin()+1+2*int(threshold));
146    Scan temp2(0, obj2.getYmin(),obj2.getYmax()-obj2.getYmin()+1);
147    Scan Yoverlap = intersect(temp1,temp2);
148     
149      // Yoverlap has the scans that overlap with a padding of width threshold
150      // If two pixels are separated in Y by threshold, but have the same X, then they match.
151      // This is the furthest apart they can be in Y.
152
153    if(Yoverlap.getXlen()>0){
154      // Grow by a pixel in each direction, to take into account the possibility of fractional thresholds (eg. 7.5)
155      Yoverlap.growLeft();
156      Yoverlap.growRight();
157   
158      // Now look at just these scans pixel by pixel
159
160      // Get the scans from object 2 that lie in the overlap region (these haven't been affected by the threshold gap)
161       for(int scanct2=0; (!close && (scanct2<nscan2)); scanct2++){
162        temp2 = obj2.getScan(scanct2);
163        if(Yoverlap.isInScan(temp2.getY(),0)){ // if the scan is in the allowed Y range
164
165          for(int scanct1=0; (!close && (scanct1<nscan1)); scanct1++){
166            temp1 = obj1.getScan(scanct1);
167            if(abs(temp1.getY()-temp2.getY())<threshold){
168
169              close = (minSep(temp1,temp2) < threshold);
170
171            }
172
173          }
174
175        }
176
177       }
178     
179    }
180    return close;
181
182  }
183
184
185  bool areAdj(Object2D &obj1, Object2D &obj2)
186  {
187    bool close = false;
188
189    long nscan1 = obj1.getNumScan();
190    long nscan2 = obj2.getNumScan();
191
192    Scan temp1(0, obj1.getYmin()-1,obj1.getYmax()-obj1.getYmin()+3);
193    Scan temp2(0, obj2.getYmin(),obj2.getYmax()-obj2.getYmin()+1);
194    Scan temp3;
195    Scan commonY = intersect(temp1,temp2);
196    if(commonY.getXlen()>0){
197      commonY.growLeft();
198      commonY.growRight();
199      //    std::cerr << temp1 << " " << temp2 << " " << commonY << "\n";
200
201      for(int scanct1=0;(!close && scanct1 < nscan1);scanct1++){
202        temp1 = obj1.getScan(scanct1);
203        if(commonY.isInScan(temp1.getY(),0)){
204          long y1 = temp1.getY();
205
206          for(int scanct2=0; (!close && scanct2 < nscan2); scanct2++){
207            temp2 = obj2.getScan(scanct2);
208            if(commonY.isInScan(temp2.getY(),0)){     
209              long dy = abs(y1 - temp2.getY());
210
211              if(dy<= 1){
212
213                temp3.define(temp2.getY(),temp1.getX(),temp1.getXlen());
214                if(touching(temp3,temp2)) close = true;
215
216              }
217            }
218          } // end of for loop over scanct2
219     
220        }
221     
222      } // end of for loop over scanct1
223
224    }
225    return close;
226  }
227
228}
Note: See TracBrowser for help on using the repository browser.