00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include <ipPic/mitkIpPicTypeMultiplex.h>
00019 #include <ANN/ANN.h>
00020 #include "ipSegmentation.h"
00021
00022
00023
00024 static ANNkd_tree *annTree;
00025 static ANNpoint queryPt;
00026 static ANNidxArray nnIdx;
00027 static ANNdistArray dists;
00028
00029
00030
00031
00032 #define QUERY_DIST(qOfs) \
00033 queryPt[0] = (float)(qOfs % line) + 0.5; \
00034 queryPt[1] = (float)(qOfs / line) + 0.5; \
00035 annTree->annkSearch( queryPt, 1, nnIdx, dists );
00036
00037
00038 #define PROCESS_PIXEL \
00039 histVal = *((mitkIpUInt2_t*)history->data+testOfs); \
00040 segVal = *((mitkIpUInt1_t*)seg->data+testOfs); \
00041 if ( segVal > 0 && histVal <= maxHist && testOfs!=oldOfs ) { \
00042 grad = ipMITKSegmentationGetDistGradient( testOfs, seg ); \
00043 QUERY_DIST(testOfs) \
00044 if (grad<minGrad) { \
00045 minGrad = grad; \
00046 gradCand = testOfs; \
00047 } \
00048 if (dists[0] > maxDist) { \
00049 maxDist = dists[0]; \
00050 candOfs = testOfs; \
00051 } \
00052 }
00053
00054
00055 float ipMITKSegmentationGetDistGradient( int ofs, mitkIpPicDescriptor *seg )
00056 {
00057 mitkIpUInt4_t unsignedOfs = ofs < 0 ? seg->n[0]*seg->n[1] - seg->n[0] : ofs;
00058 if (unsignedOfs < seg->n[0] || unsignedOfs >= seg->n[0]*seg->n[1] - seg->n[0])
00059 {
00060 return 1.0;
00061 }
00062 float x = (float)(ofs % seg->n[0]) + 0.5;
00063 float y = (float)(ofs / seg->n[0]) + 0.5;
00064 mitkIpUInt1_t segVal = 0;
00065
00066 queryPt[0] = x+1; queryPt[1] = y;
00067 annTree->annkSearch( queryPt, 1, nnIdx, dists );
00068 float d1 = sqrt( dists[0] );
00069 segVal = *((mitkIpUInt1_t*)seg->data+ofs+1);
00070 if (!segVal) d1 = -10.0;
00071 queryPt[0] = x-1; queryPt[1] = y;
00072 annTree->annkSearch( queryPt, 1, nnIdx, dists );
00073 float d2 = sqrt( dists[0] );
00074 segVal = *((mitkIpUInt1_t*)seg->data+ofs-1);
00075 if (!segVal) d2 = -10.0;
00076 queryPt[0] = x; queryPt[1] = y+1;
00077 annTree->annkSearch( queryPt, 1, nnIdx, dists );
00078 float d3 = sqrt( dists[0] );
00079 segVal = *((mitkIpUInt1_t*)seg->data+ofs+seg->n[0]);
00080 if (!segVal) d3 = -10.0;
00081 queryPt[0] = x; queryPt[1] = y-1;
00082 annTree->annkSearch( queryPt, 1, nnIdx, dists );
00083 float d4 = sqrt( dists[0] );
00084 segVal = *((mitkIpUInt1_t*)seg->data+ofs-seg->n[0]);
00085 if (!segVal) d4 = -10.0;
00086 float res = 0.5*(float)sqrt( (d1-d2)*(d1-d2) + (d3-d4)*(d3-d4) );
00087 return res;
00088 }
00089
00090
00091
00092 tCutResult ipMITKSegmentationGetCutPoints( mitkIpPicDescriptor *seg, mitkIpPicDescriptor *history, int ofs )
00093 {
00094 bool debug(false);
00095 tCutResult res;
00096 int resContourSize = 5000;
00097 res.traceline = (float*)malloc( resContourSize*sizeof(float)*2 );
00098 res.onGradient = (bool*)malloc( resContourSize*sizeof(bool) );
00099 res.numPoints = 0;
00100 res.absMin = 0;
00101 res.cutIt = false;
00102 res.deleteCurve = 0;
00103
00104 if (!history) return res;
00105 if (*((mitkIpUInt2_t*)history->data + ofs) == 0) return res;
00106
00107
00108 mitkIpUInt1_t *ptr = (mitkIpUInt1_t*)seg->data + ofs;
00109 int endLine = ((ofs / seg->n[0]) + 1) * seg->n[0] -1;
00110 int contourOfs = ofs;
00111 while (contourOfs!=endLine && *ptr!=0) {
00112 ptr++;
00113 contourOfs++;
00114 }
00115 if (*ptr == 0) contourOfs--;
00116
00117
00118 int sizeContour, sizeBuffer;
00119 float *contour = ipMITKSegmentationGetContour8N( seg, contourOfs, sizeContour, sizeBuffer );
00120
00121 queryPt = annAllocPt( 2 );
00122 ANNpointArray dataPts = annAllocPts( sizeContour, 2 );
00123 nnIdx = new ANNidx[10];
00124 dists = new ANNdist[10];
00125 for (int i=0; i<sizeContour; i++) {
00126 (dataPts[i])[0] = contour[2*i];
00127 (dataPts[i])[1] = contour[2*i+1];
00128 }
00129 annTree = new ANNkd_tree( dataPts, sizeContour, 2 );
00130
00131
00132 int line = history->n[0];
00133
00134 int maxOfs = line * history->n[1];
00135 QUERY_DIST(ofs)
00136 float maxDist = dists[0];
00137 float minDist = 10000;
00138 float oldDist = 0;
00139 int candOfs = ofs;
00140 int nextOfs = -1;
00141 int oldOfs, testOfs, gradCand=-1;
00142 float grad, minGrad;
00143 bool skelettonReached = false;
00144 mitkIpUInt2_t histVal;
00145 mitkIpUInt1_t segVal;
00146 mitkIpUInt2_t maxHist = 10000;
00147 if (maxHist==0 && debug) printf( "maxHist = 0!\n" );
00148 do {
00149 oldOfs = nextOfs;
00150 nextOfs = candOfs;
00151
00152 if (res.numPoints < resContourSize) {
00153 res.traceline[2*res.numPoints] = (float)(nextOfs % line) + 0.5;
00154 res.traceline[2*res.numPoints+1] = (float)(nextOfs / line) + 0.5;
00155 if (nextOfs==gradCand) res.onGradient[res.numPoints] = true;
00156 else res.onGradient[res.numPoints] = false;
00157
00158 if (debug)
00159 {
00160 printf( "(%.f,%.f): H=%i, G=%i\n", res.traceline[2*res.numPoints],
00161 res.traceline[2*res.numPoints+1],
00162 *((mitkIpUInt2_t*)history->data+nextOfs),
00163 res.onGradient[res.numPoints] );
00164 }
00165 res.numPoints++;
00166
00167 if (res.numPoints == resContourSize)
00168 {
00169 resContourSize *= 2;
00170 res.traceline = (float*)realloc( res.traceline, resContourSize*sizeof(float)*2 );
00171 res.onGradient = (bool*)realloc( res.onGradient, resContourSize*sizeof(bool) );
00172 if ((res.traceline == NULL) || (res.onGradient == NULL))
00173 {
00174 res.numPoints = 0;
00175 res.cutIt = false;
00176 return res;
00177 }
00178 }
00179 }
00180
00181 maxHist = *((mitkIpUInt2_t*)history->data + nextOfs);
00182 maxDist = 0;
00183 minGrad = 1.0;
00184
00185 int traceSinceMin = res.numPoints - 1 - res.absMin;
00186 float weight = 20.0 / (20.0+traceSinceMin);
00187 if (weight < 0.5) weight = 0.5;
00188 QUERY_DIST(nextOfs)
00189 if (!skelettonReached && dists[0] < oldDist) {
00190 skelettonReached = true;
00191 if (debug) printf( "skeletton reached at %i, oldDist=%.1f, currentDist=%.1f\n",
00192 res.numPoints - 1, oldDist, dists[0] );
00193 }
00194 oldDist = dists[0];
00195 if (skelettonReached && weight*dists[0] < minDist) {
00196 minDist = dists[0];
00197 res.absMin = res.numPoints - 1;
00198 }
00199
00200
00201 testOfs = nextOfs+1;
00202 if (testOfs%line!=0) {
00203
00204 PROCESS_PIXEL
00205 testOfs = nextOfs-line;
00206 if (testOfs > 0) {
00207 testOfs++;
00208 PROCESS_PIXEL
00209 }
00210
00211 testOfs = nextOfs+line;
00212 if (testOfs < maxOfs) {
00213 testOfs++;
00214 PROCESS_PIXEL
00215 }
00216 }
00217
00218 testOfs = nextOfs-line;
00219 if (testOfs > 0) {
00220 PROCESS_PIXEL
00221 }
00222
00223 testOfs = nextOfs-1;
00224 if (nextOfs%line!=0) {
00225 PROCESS_PIXEL
00226
00227 testOfs = nextOfs-line;
00228 if (testOfs > 0) {
00229 testOfs--;
00230 PROCESS_PIXEL
00231 }
00232
00233 testOfs = nextOfs+line;
00234 if (testOfs < maxOfs) {
00235 testOfs--;
00236 PROCESS_PIXEL
00237 }
00238 }
00239
00240 testOfs = nextOfs+line;
00241 if (testOfs < maxOfs) {
00242 PROCESS_PIXEL
00243 }
00244
00245 if (minGrad < 0.5) {
00246 candOfs = gradCand;
00247 if (debug) printf( "." );
00248 }
00249 else if (debug) printf( "x" );
00250 } while (candOfs != nextOfs && maxHist > 0);
00251
00252 if (res.absMin < (res.numPoints-10)) {
00253 res.absMin += (int)(sqrt(minDist)/2.0);
00254
00255
00256
00257
00258
00259
00260 res.cutIt = true;
00261 float cutXf = (float)res.traceline[2*res.absMin];
00262 float cutYf = (float)res.traceline[2*res.absMin+1];
00263 queryPt[0] = cutXf;
00264 queryPt[1] = cutYf;
00265 annTree->annkSearch( queryPt, 1, nnIdx, dists );
00266 int cutIdx1 = nnIdx[0];
00267 res.cutCoords[0] = contour[2*cutIdx1];
00268 res.cutCoords[1] = contour[2*cutIdx1+1];
00269 int cutIdx2 = cutIdx1;
00270 float minDist = 100000000;
00271 int testCnt = 0;
00272 for (int i=0; i<sizeContour; i++) {
00273 int idxDif = abs(cutIdx1-i);
00274
00275 if (idxDif > (sizeContour/2)) idxDif = sizeContour - idxDif;
00276 if ( idxDif > 50 ) {
00277 float dist = (cutXf-contour[2*i])*(cutXf-contour[2*i]) + (cutYf-contour[2*i+1])*(cutYf-contour[2*i+1]);
00278 if (dist < minDist) {
00279 minDist = dist;
00280 cutIdx2 = i;
00281 }
00282 }
00283 else testCnt++;
00284 }
00285 res.cutCoords[2] = contour[2*cutIdx2];
00286 res.cutCoords[3] = contour[2*cutIdx2+1];
00287 if (debug) printf( "idx1=%i, idx2=%i, %i pts not evaluated.\n", cutIdx1, cutIdx2, testCnt );
00288
00289 if ((res.cutCoords[0] == res.cutCoords[2]) &&
00290 (res.cutCoords[1] == res.cutCoords[3]))
00291 {
00292 free( contour );
00293
00294 annDeallocPt( queryPt );
00295 annDeallocPts( dataPts );
00296 delete[] nnIdx;
00297 delete[] dists;
00298 delete annTree;
00299
00300 res.cutIt = false;
00301
00302 return res;
00303 }
00304 float *curve1 = (float*)malloc( 2*sizeof(float)*sizeContour );
00305 float *curve2 = (float*)malloc( 2*sizeof(float)*sizeContour );
00306 int sizeCurve1, sizeCurve2;
00307 ipMITKSegmentationSplitContour( contour, sizeContour, res.cutCoords, curve1, sizeCurve1, curve2, sizeCurve2 );
00308 float clickX = (float)(ofs % line) + 0.5;
00309 float clickY = (float)(ofs / line) + 0.5;
00310 if (ipMITKSegmentationIsInsideContour( curve1, sizeCurve1, clickX, clickY )) {
00311 res.deleteCurve = curve1;
00312 res.deleteSize = sizeCurve1;
00313 free( curve2 );
00314 }
00315 else {
00316 res.deleteCurve = curve2;
00317 res.deleteSize = sizeCurve2;
00318 free( curve1 );
00319 }
00320 }
00321
00322
00323 free( contour );
00324
00325 annDeallocPt( queryPt );
00326 annDeallocPts( dataPts );
00327 delete[] nnIdx;
00328 delete[] dists;
00329 delete annTree;
00330
00331 return res;
00332 }