TPCCLIB
Loading...
Searching...
No Matches
imgcomp.c File Reference

Routines for checking if two IMG data are similar. More...

#include "libtpcimgio.h"

Go to the source code of this file.

Functions

int imgMatch (IMG *img1, IMG *img2, float accuracy)
int imgMatchMatrix (IMG *img1, IMG *img2, double accuracy)
int imgMatchTransform (IMG *img1, IMG *img2)
int imgMatchHeader (IMG *img1, IMG *img2)
int imgMatchFrames (IMG *img1, IMG *img2)
int imgMatchPlanes (IMG *img1, IMG *img2)
int imgMaxDifference (IMG *img1, IMG *img2, VOXEL_4D *absdiff, float *abs_max, VOXEL_4D *reldiff, float *rel_max)
int imgSS (IMG *img1, IMG *img2, double *ss)
int imgMatchMatrixSize (IMG *d1, IMG *d2)

Detailed Description

Routines for checking if two IMG data are similar.

Author
Vesa Oikonen

Definition in file imgcomp.c.

Function Documentation

◆ imgMatch()

int imgMatch ( IMG * img1,
IMG * img2,
float accuracy )

Checks if two IMG data contents are similar (header information, frame times, data dimensions, matrix contents inside specified accuracy).

Returns
Returns 0 if match was found, and >0 if not.
See also
imgMatchMatrix, imgMatchHeader, imgMaxDifference, imgConvertUnit
Parameters
img1Pointer to the first IMG data.
img2Pointer to the second IMG data to be compared against the first one.
accuracyPixel values must satisfy condition abs(x1-x2)/abs(mean(x1,x2)) <= accuracy (for example 0.01). If you want exact match, set accuracy=0.0.

Definition at line 15 of file imgcomp.c.

24 {
25 int ret=0;
26
27 if(img1==NULL || img2==NULL) return(1);
28 ret=imgMatchHeader(img1, img2); if(ret!=0) return(100+ret);
29 ret=imgMatchFrames(img1, img2); if(ret!=0) return(200+ret);
30 ret=imgMatchPlanes(img1, img2); if(ret!=0) return(300+ret);
31 ret=imgMatchMatrix(img1, img2, (double)accuracy); if(ret!=0) return(400+ret);
32 ret=imgMatchTransform(img1, img2); if(ret!=0) return(500+ret);
33 return(0);
34}
int imgMatchPlanes(IMG *img1, IMG *img2)
Definition imgcomp.c:307
int imgMatchMatrix(IMG *img1, IMG *img2, double accuracy)
Definition imgcomp.c:47
int imgMatchHeader(IMG *img1, IMG *img2)
Definition imgcomp.c:128
int imgMatchTransform(IMG *img1, IMG *img2)
Definition imgcomp.c:85
int imgMatchFrames(IMG *img1, IMG *img2)
Definition imgcomp.c:286

◆ imgMatchFrames()

int imgMatchFrames ( IMG * img1,
IMG * img2 )

Checks if the frame times of two IMG data do match:

Returns
Returns 0 if match was found, and >0 if they do not match.
See also
imgMatchPlanes
Parameters
img1Pointer to the first IMG structure.
img2Pointer to the second IMG structure.

Definition at line 286 of file imgcomp.c.

291 {
292 if(img1->dimt!=img2->dimt) return(1);
293 for(int fi=0; fi<img1->dimt; fi++) {
294 if(fabs(img1->start[fi]-img2->start[fi])>0.001) return(11);
295 if(fabs(img1->end[fi]-img2->end[fi])>0.001) return(12);
296 if(fabs(img1->mid[fi]-img2->mid[fi])>0.001) return(13);
297 }
298 return(0);
299}
unsigned short int dimt
float * start
float * end
float * mid

Referenced by imgMatch().

◆ imgMatchHeader()

int imgMatchHeader ( IMG * img1,
IMG * img2 )

Checks if two image headers match.

Returns
Returns 0 if headers match, 1 if headers do not match.
See also
imgMatchPlanes, imgMatchFrames, imgMatchTransform
Parameters
img1Pointer to the first IMG structure.
img2Pointer to the second IMG structure.

Definition at line 128 of file imgcomp.c.

133 {
134
135 if(img1->unit!=img2->unit){
136 fprintf(stderr, "In the header: Mismatching unit.\n");
137 return 1;
138 }
139
140 // Not always preserved in read&write, therefore tested if present in both
141 if(img1->calibrationFactor>0.0 && img2->calibrationFactor>0.0 &&
143 {
144 fprintf(stderr, "In the header: Mismatching calibration factor.\n");
145 return 1;
146 }
147
148 if(img1->zoom!=img2->zoom){
149 fprintf(stderr, "In the header: Mismatching zoom.\n");
150 return 1;
151 }
152 if(strcasecmp(img1->radiopharmaceutical,img2->radiopharmaceutical)){
153 fprintf(stderr, "In the header: Mismatching radiopharmaceutical.\n");
154 return 1;
155 }
156 if(img1->isotopeHalflife!=img2->isotopeHalflife){
157 fprintf(stderr, "In the header: Mismatching isotope halflife.\n");
158 return 1;
159 }
160 if(img1->decayCorrection!=img2->decayCorrection){
161 fprintf(stderr, "In the header: One of the images is not corrected for decay.\n");
162 return 1;
163 }
164 if(img1->branchingFraction!=img2->branchingFraction){
165 fprintf(stderr, "In the header: Mismatching branching ratio.\n");
166 return 1;
167 }
168 if(img1->scanStart!=img2->scanStart){
169 fprintf(stderr, "In the header: Mismatching scan start times.\n");
170 fprintf(stderr, "difftime := %g s\n", difftime(img1->scanStart, img2->scanStart));
171 return 1;
172 }
173 if(img1->orientation!=img2->orientation){
174 fprintf(stderr, "In the header: Mismatching orientation.\n");
175 return 1;
176 }
177 if(img1->axialFOV!=img2->axialFOV){
178 fprintf(stderr, "In the header: Mismatching axial FOV.\n");
179 return 1;
180 }
181 if(img1->transaxialFOV!=img2->transaxialFOV){
182 fprintf(stderr, "In the header: Mismatching transaxial FOV.\n");
183 return 1;
184 }
185 if(img1->sampleDistance!=img2->sampleDistance){
186 fprintf(stderr, "In the header: Mismatching sample distance.\n");
187 return 1;
188 }
189
190 if(strcasecmp(img1->studyNr,img2->studyNr)){
191 fprintf(stderr, "In the header: Mismatching study number.\n");
192 return 1;
193 }
194 if(strcmp(img1->userProcessCode,img2->userProcessCode)){
195 fprintf(stderr, "In the header: Mismatching user process code.\n");
196 return 1;
197 }
198 if(strcmp(img1->studyDescription,img2->studyDescription)){
199 fprintf(stderr, "In the header: Mismatching study description.\n");
200 return 1;
201 }
202 if(strcasecmp(img1->patientName,img2->patientName)){
203 fprintf(stderr, "In the header: Mismatching patient name.\n");
204 return 1;
205 }
206 if(strcasecmp(img1->patientID,img2->patientID)){
207 fprintf(stderr, "In the header: Mismatching patient ID.\n");
208 return 1;
209 }
210
211 if(img1->type!=IMG_TYPE_UNKNOWN && img2->type!=IMG_TYPE_UNKNOWN &&
212 img1->type!=img2->type)
213 {
214 fprintf(stderr, "In the header: Mismatching image type.\n");
215 return 1;
216 }
217
218 if(img1->sizex!=img2->sizex){
219 fprintf(stderr, "In the header: Mismatching size (x-axis).\n");
220 return 1;
221 }
222 if(img1->sizey!=img2->sizey){
223 fprintf(stderr, "In the header: Mismatching size (y-axis).\n");
224 return 1;
225 }
226 if(img1->sizez!=img2->sizez){
227 fprintf(stderr, "In the header: Mismatching size (z-axis).\n");
228 return 1;
229 }
230 if(img1->gapx!=img2->gapx){
231 fprintf(stderr, "In the header: Mismatching x gap.\n");
232 return 1;
233 }
234 if(img1->gapy!=img2->gapy){
235 fprintf(stderr, "In the header: Mismatching y gap.\n");
236 return 1;
237 }
238 if(img1->gapz!=img2->gapz){
239 fprintf(stderr, "In the header: Mismatching z gap.\n");
240 return 1;
241 }
242
243 if(img1->resolutionx!=img2->resolutionx){
244 fprintf(stderr, "In the header: Mismatching resolution (x-axis).\n");
245 return 1;
246 }
247 if(img1->resolutiony!=img2->resolutiony){
248 fprintf(stderr, "In the header: Mismatching resolution (y-axis).\n");
249 return 1;
250 }
251 if(img1->resolutionz!=img2->resolutionz){
252 fprintf(stderr, "In the header: Mismatching resolution (z-axis).\n");
253 return 1;
254 }
255
256 if(img1->scanner!=img2->scanner){
257 fprintf(stderr, "In the header: Mismatching scanner.\n");
258 return 1;
259 }
260 if(img1->modality!=img2->modality){
261 fprintf(stderr, "In the header: Mismatching modality.\n");
262 return 1;
263 }
264 if(img1->_dataType!=img2->_dataType){
265 fprintf(stderr, "In the header: Mismatching data type.\n");
266 return 1;
267 }
268 if(img1->_fileFormat!=img2->_fileFormat){
269 fprintf(stderr, "In the header: Mismatching file format.\n");
270 return 1;
271 }
272 if(img1->isWeight!=img2->isWeight){
273 fprintf(stderr, "In the header: Mismatching in weights.\n");
274 return 1;
275 }
276
277 return 0;
278}
#define IMG_TYPE_UNKNOWN
float sizex
float branchingFraction
char type
float resolutionx
char patientName[32]
float resolutiony
char studyDescription[32]
float sampleDistance
float gapx
char decayCorrection
float transaxialFOV
char unit
time_t scanStart
int _fileFormat
char userProcessCode[11]
int _dataType
char patientID[16]
int scanner
float sizey
int modality
int orientation
float calibrationFactor
float zoom
char radiopharmaceutical[32]
float isotopeHalflife
char studyNr[MAX_STUDYNR_LEN+1]
float gapy
float gapz
float axialFOV
char isWeight
float sizez
float resolutionz

Referenced by imgMatch().

◆ imgMatchMatrix()

int imgMatchMatrix ( IMG * img1,
IMG * img2,
double accuracy )

Checks if two image matrices match in the accuracy of argument "accuracy".

For example, set accuracy=0.99 and you will get match if all matrix values satisfy abs(x1-x2)/abs(mean(x1,x2))<=0.01). If you want exact match, set accuracy=0.0.

Returns
Returns 0 if matrices match, 1 if matrices do not match.
See also
imgMatch, imgMatchHeader, imgMaxDifference, imgSS
Parameters
img1Pointer to the first IMG structure.
img2Pointer to the second IMG structure.
accuracyRequired accuracy

Definition at line 47 of file imgcomp.c.

54 {
55
56 int xi, yi, pi, fi;
57 double s;
58
59 for(pi=0; pi<img1->dimz; pi++) for(yi=0; yi<img1->dimy; yi++)
60 for(xi=0; xi<img1->dimx; xi++) for(fi=0; fi<img1->dimt; fi++) {
61 s=fabs(img1->m[pi][yi][xi][fi]+img2->m[pi][yi][xi][fi])/2.0;
62 if(accuracy==0.0 || s==0.0) {
63 if(img1->m[pi][yi][xi][fi]!=img2->m[pi][yi][xi][fi]){
64 fprintf(stderr, "Mismatch in image matrix.\n");
65 return(1);
66 }
67 } else {
68 if(fabs(img1->m[pi][yi][xi][fi]-img2->m[pi][yi][xi][fi])/s > (1.0-accuracy)) {
69 fprintf(stderr, "Mismatch in image matrix.\n");
70 printf("img[%d][%d][%d][%d]: %g vs %g\n", pi, yi, xi, fi,
71 img1->m[pi][yi][xi][fi], img2->m[pi][yi][xi][fi]);
72 return(1);
73 }
74 }
75 }
76 return 0;
77}
unsigned short int dimx
float **** m
unsigned short int dimz
unsigned short int dimy

Referenced by imgMatch().

◆ imgMatchMatrixSize()

int imgMatchMatrixSize ( IMG * d1,
IMG * d2 )

Check whether two IMG data have the same matrix (x,y,z) size.

Returns
0 in case of match, 1 otherwise.
See also
imgMatch, imgMatchFrames
Author
Vesa Oikonen
Parameters
d1Pointer to IMG structure.
d2Pointer to IMG structure.

Definition at line 447 of file imgcomp.c.

452 {
453 if(d1==NULL || d2==NULL) return(1);
454 if(d1->dimz!=d2->dimz) return(1);
455 if(d1->dimy!=d2->dimy) return(1);
456 if(d1->dimx!=d2->dimx) return(1);
457 return(0);
458}

◆ imgMatchPlanes()

int imgMatchPlanes ( IMG * img1,
IMG * img2 )

Checks if the planes of two IMG data do match: number of planes and plane numbers.

Returns
Returns 0 if match was found, and >0 if no match.
See also
imgMatchFrames
Parameters
img1Pointer to the first IMG structure.
img2Pointer to the second IMG structure.

Definition at line 307 of file imgcomp.c.

312 {
313 if(img1->dimz!=img2->dimz) return(1);
314 for(int zi=0; zi<img1->dimz; zi++) {
315 if(img1->planeNumber[zi]!=img2->planeNumber[zi]) return(11);
316 }
317 return(0);
318}
int * planeNumber

Referenced by imgMatch().

◆ imgMatchTransform()

int imgMatchTransform ( IMG * img1,
IMG * img2 )

Checks if the transform parameters of two image headers match.

Returns
Returns 0 if headers match, 1 if headers do not match.
See also
imgMatchHeader
Parameters
img1Pointer to the first IMG structure.
img2Pointer to the second IMG structure.

Definition at line 85 of file imgcomp.c.

90 {
91 int i;
92 float f;
93
94 if(img1->xform[0]!=img2->xform[0]) {
95 fprintf(stderr, "In the header: Mismatching qform.\n");
96 return 1;
97 }
98 if(img1->xform[1]!=img2->xform[1]) {
99 fprintf(stderr, "In the header: Mismatching sform.\n");
100 return 1;
101 }
102
103 for(i=0; i<18; i++) {
104 f=img1->quatern[i]-img2->quatern[i];
105 if(fabs(f)>1.0E-05) {
106 fprintf(stderr, "In the header: Mismatching transformation parameter.\n");
107 return 1;
108 }
109 }
110
111 for(i=0; i<12; i++) {
112 f=img1->mt[i]-img2->mt[i];
113 if(fabs(f)>1.0E-05) {
114 fprintf(stderr, "In the header: Mismatching matrix transformation.\n");
115 return 1;
116 }
117 }
118
119 return 0;
120}
short int xform[2]
float mt[12]
float quatern[18]

Referenced by imgMatch().

◆ imgMaxDifference()

int imgMaxDifference ( IMG * img1,
IMG * img2,
VOXEL_4D * absdiff,
float * abs_max,
VOXEL_4D * reldiff,
float * rel_max )

Calculates the maximal pixel value differences (absolute and relational) between two image matrices.

Returns
Returns 0 if successful, and some difference was found, -1 if no difference at all was found, and >0 in case of an error.
See also
imgSS, imgMatch, imgMatchMatrix, imgMatchHeader, imgMRT
Parameters
img1Pointer to the first IMG structure.
img2Pointer to the second IMG, with the same dimensions as img1.
absdiffVoxel where absolute difference was found largest; enter NULL if not needed; returns [0,0,0,0] if no difference was found.
abs_maxPointer where max absolute difference is written; NULL if not needed.
reldiffVoxel where relational difference was found largest; enter NULL if not needed; returns [0,0,0,0] if no difference was found.
rel_maxPointer where max relational difference is written; NULL if not needed.

Definition at line 328 of file imgcomp.c.

343 {
344
345 int xi, yi, zi, ti;
346 float s, v, absmax=0.0, relmax=0.0;
347
348 /* Initiate result voxels */
349 if(absdiff!=NULL) absdiff->x=absdiff->y=absdiff->z=absdiff->t=0;
350 if(abs_max!=NULL) *abs_max=0;
351 if(reldiff!=NULL) reldiff->x=reldiff->y=reldiff->z=reldiff->t=0;
352 if(rel_max!=NULL) *rel_max=0;
353
354 /* Check input */
355 if(img1==NULL || img2==NULL) return 1;
356 if(img1->dimx!=img2->dimx) return 2;
357 if(img1->dimy!=img2->dimy) return 3;
358 if(img1->dimz!=img2->dimz) return 4;
359 if(img1->dimt!=img2->dimt) return 5;
360
361
362 /* Search for max absolute difference */
363 for(zi=0; zi<img1->dimz; zi++) for(yi=0; yi<img1->dimy; yi++)
364 for(xi=0; xi<img1->dimx; xi++) for(ti=0; ti<img1->dimt; ti++) {
365 s=fabs(img1->m[zi][yi][xi][ti]-img2->m[zi][yi][xi][ti]);
366 if(s>absmax) {
367 absmax=s;
368 if(absdiff!=NULL) {absdiff->x=xi+1; absdiff->y=yi+1; absdiff->z=zi+1; absdiff->t=ti+1;}
369 }
370 }
371 //printf("absmax := %g\n", absmax);
372 if(abs_max!=NULL) *abs_max=absmax;
373
374
375 /* Search for max relational difference.
376 If relational difference is Inf (image average is zero), then relmax
377 is set to FLT_MAX, and from those pixels the one where
378 absolute difference is highest is searched */
379 float local_absmax=0.0;
380 for(zi=0; zi<img1->dimz; zi++) for(yi=0; yi<img1->dimy; yi++)
381 for(xi=0; xi<img1->dimx; xi++) for(ti=0; ti<img1->dimt; ti++) {
382 s=fabs(img1->m[zi][yi][xi][ti]-img2->m[zi][yi][xi][ti]);
383 v=0.5*fabs(img1->m[zi][yi][xi][ti]+img2->m[zi][yi][xi][ti]);
384 if(v>0.0) {
385 s/=v;
386 if(s>relmax && local_absmax==0.0) {
387 relmax=s;
388 if(reldiff!=NULL) {reldiff->x=xi+1; reldiff->y=yi+1; reldiff->z=zi+1; reldiff->t=ti+1;}
389 }
390 } else if(s>0.0) { // if relational max is find out the pixel where
391 if(s>local_absmax) {
392 local_absmax=s;
393 if(reldiff!=NULL) {reldiff->x=xi+1; reldiff->y=yi+1; reldiff->z=zi+1; reldiff->t=ti+1;}
394 }
395 }
396 }
397 if(local_absmax>0.0) relmax=FLT_MAX;
398 //printf("relmax := %g\n", relmax);
399 if(rel_max!=NULL) *rel_max=relmax;
400
401 /* Was there any difference? 0=yes, -1=no */
402 if(absmax>0.0 || relmax>0.0) return 0; else return -1;
403}

◆ imgSS()

int imgSS ( IMG * img1,
IMG * img2,
double * ss )

Calculates the sum-of-squares between pixels values of two images.

Precondition
Make sure that image pixel values are in the same units.
Returns
Returns <>0 in case of an error.
See also
imgMatchMatrix, imgMatchHeader, imgMaxDifference, imgConvertUnit
Parameters
img1Pointer to the first IMG data.
img2Pointer to the second IMG data.
ssPointer to the double variable to write the SS into.

Definition at line 412 of file imgcomp.c.

419 {
420 if(ss!=NULL) *ss=0.0;
421 if(img1==NULL || img2==NULL) return(1);
422 if(img1->dimz!=img2->dimz) return(2);
423 if(img1->dimy!=img2->dimy) return(3);
424 if(img1->dimx!=img2->dimx) return(4);
425 if(img1->dimt!=img2->dimt) return(5);
426
427 double sumsqr=0.0;
428 for(int z=0; z<img1->dimz; z++)
429 for(int y=0; y<img1->dimy; y++)
430 for(int x=0; x<img1->dimx; x++)
431 for(int i=0; i<img1->dimt; i++) {
432 double d=img1->m[z][y][x][i]-img2->m[z][y][x][i];
433 sumsqr+=d*d;
434 }
435 if(ss!=NULL) *ss=sumsqr;
436
437 return(0);
438}