TPCCLIB
Loading...
Searching...
No Matches
imgsegm.c
Go to the documentation of this file.
1
5/*****************************************************************************/
6#include "libtpcimgp.h"
7/*****************************************************************************/
8
9/*****************************************************************************/
11typedef struct {
13 int p;
15 int r;
17 int c;
19 int mrl;
21 double dauc;
23 int order;
24} IMGSEGMMASK;
25/*****************************************************************************/
26
27/*****************************************************************************/
41 IMG *img,
43 float minValue,
45 float maxValue,
47 IMG *timg
48) {
49 int frame, plane, i, j, ret;
50
51 if(img->status!=IMG_STATUS_OCCUPIED) return(1);
52 /* Allocate memory for the mask data */
53 ret=imgAllocateWithHeader(timg, img->dimz, img->dimy, img->dimx, 1, img);
54 if(ret) return(ret);
55 timg->start[0]=img->start[0]; timg->end[0]=img->end[img->dimt-1];
56 timg->mid[0]=(timg->start[0]+timg->end[0])/2.0;
57 timg->isWeight=0;
58
59 /* Make the mask data */
60 for(plane=0; plane<img->dimz; plane++)
61 for(j=0; j<img->dimy; j++) for(i=0; i<img->dimx; i++) {
62 frame=0;
63 if(img->m[plane][j][i][frame]<minValue)
64 timg->m[plane][j][i][frame]=1.0;
65 else if(img->m[plane][j][i][frame]>maxValue)
66 timg->m[plane][j][i][frame]=2.0;
67 else
68 timg->m[plane][j][i][frame]=0.0;
69 }
70 return(0);
71}
72/*****************************************************************************/
73
74/*****************************************************************************/
85 IMG *img,
87 IMG *template,
89 float minValue,
91 float maxValue
92) {
93 int frame, plane, i, j;
94
95 if(img->status!=IMG_STATUS_OCCUPIED) return(1);
96 if(template->status!=IMG_STATUS_OCCUPIED) return(2);
97 for(plane=0; plane<img->dimz; plane++)
98 for(j=0; j<img->dimy; j++) for(i=0; i<img->dimx; i++)
99 if(template->m[plane][j][i][0]==1.0) {
100 for(frame=0; frame<img->dimt; frame++)
101 img->m[plane][j][i][frame]=minValue;
102 } else if(template->m[plane][j][i][0]==2.0) {
103 for(frame=0; frame<img->dimt; frame++)
104 img->m[plane][j][i][frame]=maxValue;
105 }
106 return(0);
107}
108/*****************************************************************************/
109
110/*****************************************************************************/
118 IMG *img,
120 float minValue,
122 float maxValue
123) {
124 int frame, plane, i, j;
125
126 if(img->status!=IMG_STATUS_OCCUPIED) return(1);
127 for(plane=0; plane<img->dimz; plane++)
128 for(j=0; j<img->dimy; j++) for(i=0; i<img->dimx; i++)
129 for(frame=0; frame<img->dimt; frame++)
130 if(img->m[plane][j][i][frame]<minValue)
131 img->m[plane][j][i][frame]=0.0;
132 else if(img->m[plane][j][i][frame]>maxValue)
133 img->m[plane][j][i][frame]=maxValue;
134 return(0);
135}
136/*****************************************************************************/
137
138/*****************************************************************************/
144 IMG *img
145) {
146 int plane, i, j;
147
148 if(img->status!=IMG_STATUS_OCCUPIED) return(1);
149 if(img->dimt>1) return(2);
150 for(plane=0; plane<img->dimz; plane++)
151 for(j=0; j<img->dimy; j++) for(i=0; i<img->dimx; i++) {
152 if(img->m[plane][j][i][0]>0.0) img->m[plane][j][i][0]=0.0;
153 else img->m[plane][j][i][0]=-1.0;
154 }
155 return(0);
156}
157/*****************************************************************************/
158
159/*****************************************************************************/
168 IMG *sumimg,
170 IMG *cluster,
172 float *max,
174 int *plane,
176 int *row,
178 int *col
179) {
180 int p, i, j, maxp=0, maxi=0, maxj=0;
181
182 if(sumimg->status!=IMG_STATUS_OCCUPIED) return(1);
183 if(cluster->status!=IMG_STATUS_OCCUPIED) return(2);
184 if(sumimg->dimt>1) return(3);
185 if(cluster->dimt>1) return(4);
186 if(sumimg->dimx!=cluster->dimx || sumimg->dimy!=cluster->dimy) return(5);
187 if(sumimg->dimz!=cluster->dimz) return(6);
188
189 *max=-1.0e8;
190 long long n=0;
191 for(p=0; p<sumimg->dimz; p++) {
192 for(j=0; j<sumimg->dimy; j++) for(i=0; i<sumimg->dimx; i++)
193 if(cluster->m[p][j][i][0]<-0.1) {
194 if(sumimg->m[p][j][i][0]>*max) {
195 *max=sumimg->m[p][j][i][0]; maxp=p; maxj=j; maxi=i;
196 }
197 n++;
198 }
199 }
200 if(n==0) return(-1);
201 *plane=maxp; *row=maxj; *col=maxi;
202 return(0);
203}
204/*****************************************************************************/
205
206/*****************************************************************************/
221 IMG *cimg,
223 IMG *simg,
225 IMG *dimg,
227 int clusterID,
229 int pi,
231 int ri,
233 int ci,
235 int pj,
237 int rj,
239 int cj,
241 float CVlim,
243 float CClim,
245 int verbose
246) {
247 if(verbose>0) {
248 printf("imgsegmClusterExpand(cimg, simg, dimg, %d, %d, %d, %d, %d, %d, %d, %f, %f, %d)\n",
249 clusterID, pi, ri, ci, pj, rj, cj, CVlim, CClim, verbose);
250 fflush(stdout);
251 }
252 if(cimg==NULL || cimg->status!=IMG_STATUS_OCCUPIED) return(2);
253 if(simg==NULL || simg->status!=IMG_STATUS_OCCUPIED) return(3);
254 if(dimg==NULL || dimg->status!=IMG_STATUS_OCCUPIED) return(4);
255
256 /* Check that test pixel resides inside image volume */
257 if(pi<0 || ri<0 || ci<0 || pi>=cimg->dimz || ri>=cimg->dimy || ci>=cimg->dimx) {
258 if(verbose>1) printf("pixels does not reside inside image\n");
259 return(1);
260 }
261
262 /* Check that test pixel is not already part of any cluster */
263 if(cimg->m[pi][ri][ci][0]>=-0.1) {
264 if(verbose>1)
265 printf("pixel already belongs to cluster %g\n", cimg->m[pi][ri][ci][0]);
266 return(1);
267 }
268
269 /* Check that AUCs are matching */
270 {
271 float mean=0.5*(simg->m[pi][ri][ci][0]+simg->m[pj][rj][cj][0]);
272 float a=simg->m[pi][ri][ci][0]-mean;
273 float b=simg->m[pj][rj][cj][0]-mean;
274 float cv;
275 if(fabs(mean)>1.0e-10) cv=(a*a + b*b) / mean; else cv=0.0;
276 if(verbose>2) printf("cv=%g CVlim=%g mean=%g\n", cv, CVlim, mean);
277 if(cv>CVlim) {
278 if(verbose>2) printf("AUCs are not matching, %g>%g\n", cv, CVlim);
279 return(1);
280 }
281 }
282
283 /* Check that TACs are correlating */
284 {
285 float r=imgsegmPearson(dimg->m[pj][rj][cj], dimg->m[pi][ri][ci], dimg->dimt);
286 if(verbose>3) printf(" r=%g CClim=%g\n", r, CClim);
287 if(r<CClim) {
288 if(verbose>2) printf("TACs are not correlating, %g<%g\n", r, CClim);
289 return(1);
290 }
291 }
292
293 /* If we got this far, the test pixel belongs to the cluster */
294 cimg->m[pi][ri][ci][0]=clusterID;
295 if(verbose>1) {
296 printf(" [%d][%d][%d] belongs to cluster %d\n", pi, ri, ci, clusterID);
297 fflush(stdout);
298 }
299
300 /* Check if the neighbouring pixels belong to this cluster */
301 for(int pk=pi-1; pk<=pi+1; pk++) if(pk>=0 && pk<cimg->dimz)
302 for(int rk=ri-1; rk<=ri+1; rk++) if(rk>=0 && rk<cimg->dimy)
303 for(int ck=ci-1; ck<=ci+1; ck++) if(ck>=0 && ck<cimg->dimx)
304 if((pk!=pi || rk!=ri || ck!=ci) && cimg->m[pk][rk][ck][0]<-0.1) {
305 int ret=imgsegmClusterExpand(cimg, simg, dimg, clusterID,
306 pk, rk, ck, pj, rj, cj, CVlim, CClim, verbose);
307 if(ret>1) return(ret);
308 }
309
310 return(0);
311}
312/*****************************************************************************/
313
314/*****************************************************************************/
324 float *x,
326 float *y,
328 long long nr
329) {
330 int i;
331 float sumx=0.0, sumy=0.0, sumsx=0.0, sumsy=0.0, sumxy=0.0, r, q;
332
333 if(nr<1 || x==NULL || y==NULL) return(0.0);
334 if(nr<3) return(1.0);
335 for(i=0; i<nr; i++) {
336 sumx+=x[i]; sumy+=y[i];
337 sumsx+=x[i]*x[i]; sumsy+=y[i]*y[i];
338 sumxy+=x[i]*y[i];
339 }
340 q=(sumsx - sumx*sumx/(float)nr) * (sumsy - sumy*sumy/(float)nr);
341 if(q<=0.0) return(1.0);
342 r=(sumxy-((sumx*sumy)/(float)nr)) / sqrt(q);
343 return(r);
344}
345/*****************************************************************************/
346
347/*****************************************************************************/
359 IMG *dimg,
361 IMG *cimg,
363 int clusterID,
365 float *avg,
367 int verbose
368) {
369 int fi, pi, ri, ci;
370
371 /* Check the arguments */
372 if(dimg==NULL || cimg==NULL || avg==NULL) return(-1);
373 if(cimg->dimx!=dimg->dimx || cimg->dimy!=dimg->dimy || cimg->dimz!=dimg->dimz)
374 return(-2);
375
376 if(verbose>0) printf("calculating avg of cluster %d:", clusterID);
377 for(fi=0; fi<dimg->dimt; fi++) avg[fi]=0.0;
378 long long n=0;
379 for(pi=0; pi<cimg->dimz; pi++)
380 for(ri=0; ri<cimg->dimy; ri++)
381 for(ci=0; ci<cimg->dimx; ci++)
382 if(fabs(cimg->m[pi][ri][ci][0]-(float)clusterID)<0.1) {
383 for(fi=0; fi<dimg->dimt; fi++)
384 avg[fi]+=dimg->m[pi][ri][ci][fi];
385 n++;
386 }
387 if(n>0) for(fi=0; fi<dimg->dimt; fi++) avg[fi]/=(float)n;
388 if(verbose>0) printf(" %lld pixels\n", n);
389 return(n);
390}
391/*****************************************************************************/
392
393/*****************************************************************************/
400 IMG *cimg,
402 int pi,
404 int ri,
406 int ci
407) {
408 int pj, rj, cj;
409
410 for(pj=pi-1; pj<=pi+1; pj++) if(pj>=0 && pj<cimg->dimz)
411 for(rj=ri-1; rj<=ri+1; rj++) if(rj>=0 && rj<cimg->dimy)
412 for(cj=ci-1; cj<=ci+1; cj++) if(cj>=0 && cj<cimg->dimx)
413 if((pi!=pj || ri!=rj || ci!=cj) && cimg->m[pj][rj][cj][0]<-0.1) return(0);
414 return(1);
415}
416/*****************************************************************************/
417
418/*****************************************************************************/
429 IMG *dimg,
431 IMG *cimg,
433 int pi,
435 int ri,
437 int ci
438) {
439 int pj, rj, cj;
440 float cc, best_cc, best_ID;
441
442 best_ID=-1.0; best_cc=-1.0e+20;
443 for(pj=pi-1; pj<=pi+1; pj++) if(pj>=0 && pj<cimg->dimz)
444 for(rj=ri-1; rj<=ri+1; rj++) if(rj>=0 && rj<cimg->dimy)
445 for(cj=ci-1; cj<=ci+1; cj++) if(cj>=0 && cj<cimg->dimx)
446 if((pi!=pj || ri!=rj || ci!=cj)) {
447 cc=imgsegmPearson(dimg->m[pj][rj][cj], dimg->m[pi][ri][ci], dimg->dimt);
448 if(cc>best_cc) {
449 best_cc=cc;
450 best_ID=cimg->m[pj][rj][cj][0];
451 }
452 }
453 if(best_ID<0.0) return(1);
454 cimg->m[pi][ri][ci][0]=best_ID;
455 return(0);
456}
457/*****************************************************************************/
458
459/*****************************************************************************/
461int imgsegmSimilarSort(const void *mask1, const void *mask2)
462{
463 if( ((IMGSEGMMASK*)mask1)->order > ((IMGSEGMMASK*)mask2)->order ) return(-1);
464 else if( ((IMGSEGMMASK*)mask1)->order < ((IMGSEGMMASK*)mask2)->order ) return(+1);
465 else return(0);
466}
468
480 IMG *input,
482 int smoothDim,
484 int smoothNr,
486 IMG *output,
488 int verbose
489) {
490 int ret, pi, ri, ci, pj, rj, cj, mi, mj, fi, maskNr, smod;
491 IMG sum;
492 IMGSEGMMASK mask[125];
493
494
495 if(verbose>0) printf("in filterSimilar(input, %d, %d, output)\n", smoothDim, smoothNr);
496 /* Check the parameters */
497 if(input->status!=IMG_STATUS_OCCUPIED) return(1);
498 if(input->dimt<2) return(2);
499 if(smoothDim==3) smod=1; else smod=2;
500 if(smoothNr<2) smoothNr=9;
501
502 /* Compute AUC image */
503 imgInit(&sum);
504 ret=imgFrameIntegral(input, 0, input->dimt-1, &sum, verbose);
505 if(ret) return(10+ret);
506
507 /* Allocate space for smoothed image */
509 output, input->dimz, input->dimy, input->dimx, input->dimt, input);
510 if(ret) {imgEmpty(&sum); return(20+ret);}
511
512 /* One pixel at a time */
513 for(pi=0; pi<input->dimz; pi++) {
514 if(input->dimz>1) {fprintf(stdout, "."); fflush(stdout);}
515 for(ri=0; ri<input->dimy; ri++) {
516 for(ci=0; ci<input->dimx; ci++) {
517 /* Fill the smoothing mask values */
518 for(mi=0; mi<125; mi++) mask[mi].order=0;
519 mi=0;
520 for(pj=pi-smod; pj<=pi+smod; pj++) if(pj>=0 && pj<input->dimz) {
521 for(rj=ri-smod; rj<=ri+smod; rj++) if(rj>=0 && rj<input->dimy) {
522 for(cj=ci-smod; cj<=ci+smod; cj++) if(cj>=0 && cj<input->dimx) {
523 mask[mi].p=pj; mask[mi].r=rj; mask[mi].c=cj;
524 /* Calculate the AUC difference */
525 mask[mi].dauc=fabs(sum.m[pi][ri][ci][0]-sum.m[pj][rj][cj][0]);
526 /* Calculate the MRL */
527 mask[mi].mrl=imgsegmCalcMRL(input->m[pi][ri][ci], input->m[pj][rj][cj], input->dimt);
528 mi++;
529 }
530 }
531 }
532 maskNr=mi;
533 /* Put mask values in similarity order */
534 for(mi=0; mi<maskNr; mi++) {
535 mask[mi].order=0;
536 for(mj=0; mj<maskNr; mj++) {
537 if(mask[mj].dauc>mask[mi].dauc) mask[mi].order++;
538 if(mask[mj].mrl>mask[mi].mrl) mask[mi].order++;
539 }
540 }
541 qsort(mask, maskNr, sizeof(IMGSEGMMASK), imgsegmSimilarSort);
542 /* Calculate average */
543 mj=smoothNr; if(mj>maskNr/2) mj=maskNr/2;
544 for(fi=0; fi<input->dimt; fi++) {
545 output->m[pi][ri][ci][fi]=0.0;
546 for(mi=0; mi<mj; mi++) {
547 /*printf("order=%d pj=%d rj=%d cj=%d\n", mask[mi].order, mask[mi].p, mask[mi].r, mask[mi].c);*/
548 output->m[pi][ri][ci][fi]+=
549 input->m[mask[mi].p][mask[mi].r][mask[mi].c][fi];
550 }
551 output->m[pi][ri][ci][fi]/=(double)mj;
552 }
553 }
554 }
555 }
556 if(input->dimz>1) {fprintf(stdout, "\n"); fflush(stdout);}
557 imgEmpty(&sum);
558 return(0);
559}
560/*****************************************************************************/
561
562/*****************************************************************************/
569 float y1[],
571 float y2[],
573 long long n
574) {
575 long long i, mrl=0, rl=0;
576 char last_sign=0, sign;
577
578 for(i=0; i<n; i++) {
579 if(y1[i]>y2[i]) sign=1; else if(y1[i]<y2[i]) sign=-1; else sign=0;
580 if(sign!=last_sign) {
581 rl=0; last_sign=sign;
582 } else {
583 if(sign!=0) {rl++; if(rl>mrl) mrl=rl;}
584 }
585 }
586 return(mrl);
587}
588/*****************************************************************************/
589
590/*****************************************************************************/
int imgAllocateWithHeader(IMG *image, int planes, int rows, int columns, int frames, IMG *image_from)
Definition img.c:279
void imgEmpty(IMG *image)
Definition img.c:121
void imgInit(IMG *image)
Definition img.c:60
int imgFrameIntegral(IMG *img, int first, int last, IMG *iimg, int verbose)
Definition imgarithm.c:346
int imgsegmThresholdMask(IMG *img, float minValue, float maxValue, IMG *timg)
Definition imgsegm.c:39
int imgsegmCheckNeighbours(IMG *cimg, int pi, int ri, int ci)
Definition imgsegm.c:398
int imgsegmClusterMean(IMG *dimg, IMG *cimg, int clusterID, float *avg, int verbose)
Definition imgsegm.c:357
int imgsegmMaskToCluster(IMG *img)
Definition imgsegm.c:142
int imgsegmFindBestNeighbour(IMG *dimg, IMG *cimg, int pi, int ri, int ci)
Definition imgsegm.c:427
int imgsegmFindMaxOutsideClusters(IMG *sumimg, IMG *cluster, float *max, int *plane, int *row, int *col)
Definition imgsegm.c:166
float imgsegmPearson(float *x, float *y, long long nr)
Definition imgsegm.c:322
int imgsegmThreshold(IMG *img, float minValue, float maxValue)
Definition imgsegm.c:116
int imgsegmThresholdByMask(IMG *img, IMG *template, float minValue, float maxValue)
Definition imgsegm.c:83
int imgsegmCalcMRL(float y1[], float y2[], long long n)
Definition imgsegm.c:567
int imgsegmSimilar(IMG *input, int smoothDim, int smoothNr, IMG *output, int verbose)
Definition imgsegm.c:478
int imgsegmClusterExpand(IMG *cimg, IMG *simg, IMG *dimg, int clusterID, int pi, int ri, int ci, int pj, int rj, int cj, float CVlim, float CClim, int verbose)
Definition imgsegm.c:219
#define IMG_STATUS_OCCUPIED
Header file for libtpcimgp.
int mean(double *x, double *y, int nr, double *xmean, double *xsd, double *ymean, double *ysd)
Definition pearson.c:341
unsigned short int dimx
float **** m
char status
unsigned short int dimt
float * start
unsigned short int dimz
unsigned short int dimy
float * end
float * mid
char isWeight