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
RevLine 
[300]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// -----------------------------------------------------------------------
[3]29#include <math.h>
[393]30#include <duchamp/Detection/detection.hh>
31#include <duchamp/PixelMap/Scan.hh>
32#include <duchamp/PixelMap/Object3D.hh>
33#include <duchamp/param.hh>
[3]34
[258]35using namespace PixelInfo;
36
[378]37namespace duchamp
[3]38{
[221]39
[378]40  bool areAdj(Object2D &obj1, Object2D &obj2);
41  bool areClose(Object2D &obj1, Object2D &obj2, float threshold);
[221]42
[378]43  bool areClose(Detection &obj1, Detection &obj2, Param &par)
44  {
45
[528]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.
[3]50 
[378]51    bool close = false;   // this will be the value returned
[3]52
[378]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    //
[3]59
[378]60    bool flagAdj = par.getFlagAdjacent();
61    float threshS = par.getThreshS();
62    float threshV = par.getThreshV();
[3]63
[378]64    long gap;
65    if(flagAdj) gap = 1;
66    else gap = long( ceil(threshS) );
[258]67
[378]68    Scan test1,test2;
[258]69
[378]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);
[3]74
[378]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);
[3]79 
[378]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);
[3]86
[378]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      //
[3]94
[570]95      std::vector<long> zlist1 = obj1.getChannelList();
96      std::vector<long> zlist2 = obj2.getChannelList();
[3]97
[623]98      for(size_t ct1=0; (!close && (ct1<zlist1.size())); ct1++){
[258]99       
[623]100        for(size_t ct2=0; (!close && (ct2<zlist2.size())); ct2++){
[258]101       
[570]102          if(abs(zlist1[ct1]-zlist2[ct2])<=threshV){
[258]103             
[570]104            Object2D temp1 = obj1.getChanMap(zlist1[ct1]);
105            Object2D temp2 = obj2.getChanMap(zlist2[ct2]);
[505]106
[378]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);
[258]119             
[378]120            if(areNear){
121              if(flagAdj) close = close || areAdj(temp1,temp2);
122              else close = close || areClose(temp1,temp2,threshS);
[258]123            }
[505]124           
[378]125          }
[3]126
[258]127        }
128
[378]129      }
130
[3]131    }
132
[378]133    return close;
134
[3]135  }
136
[378]137  bool areClose(Object2D &obj1, Object2D &obj2, float threshold)
138  {
139    bool close = false;
[258]140
[378]141    long nscan1 = obj1.getNumScan();
142    long nscan2 = obj2.getNumScan();
[258]143
[378]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);
[505]147    Scan Yoverlap = intersect(temp1,temp2);
148     
[744]149      // Yoverlap has the scans that overlap with a padding of width threshold
[505]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.
[258]152
[505]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
[258]159
[505]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
[258]164
[505]165          for(int scanct1=0; (!close && (scanct1<nscan1)); scanct1++){
166            temp1 = obj1.getScan(scanct1);
[744]167            if(abs(temp1.getY()-temp2.getY())<threshold){
[258]168
[505]169              close = (minSep(temp1,temp2) < threshold);
[258]170
[505]171            }
[258]172
[505]173          }
[258]174
[505]175        }
[258]176
[505]177       }
178     
179    }
180    return close;
[258]181
[378]182  }
[258]183
[505]184
[378]185  bool areAdj(Object2D &obj1, Object2D &obj2)
186  {
187    bool close = false;
[258]188
[378]189    long nscan1 = obj1.getNumScan();
190    long nscan2 = obj2.getNumScan();
[258]191
[378]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";
[258]200
[378]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();
[258]205
[378]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());
[258]210
[378]211              if(dy<= 1){
[258]212
[378]213                temp3.define(temp2.getY(),temp1.getX(),temp1.getXlen());
214                if(touching(temp3,temp2)) close = true;
[258]215
[378]216              }
[258]217            }
[378]218          } // end of for loop over scanct2
[258]219     
[378]220        }
[258]221     
[378]222      } // end of for loop over scanct1
[258]223
[378]224    }
225    return close;
[258]226  }
[378]227
[258]228}
Note: See TracBrowser for help on using the repository browser.