diff --git a/MRIcroGL.lps b/MRIcroGL.lps index 8184dd9..455e468 100755 --- a/MRIcroGL.lps +++ b/MRIcroGL.lps @@ -19,8 +19,8 @@ - - + + @@ -151,7 +151,7 @@ - + @@ -159,23 +159,23 @@ - + - - - - + + + + - - + + @@ -204,9 +204,8 @@ - - - + + @@ -214,7 +213,7 @@ - + @@ -418,7 +417,7 @@ - + @@ -428,123 +427,123 @@ - + - + - + - + - + - - + + - - + + - - + + - - + + - + - + - - + + - - + + - - + + - + - + - + - + - + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - + diff --git a/MRIcroGL_llvm.lpi b/MRIcroGL_llvm.lpi index 927c95b..d112630 100755 --- a/MRIcroGL_llvm.lpi +++ b/MRIcroGL_llvm.lpi @@ -139,7 +139,7 @@ diff --git a/mainunit.pas b/mainunit.pas index 5dc7677..f63e161 100755 --- a/mainunit.pas +++ b/mainunit.pas @@ -5602,7 +5602,8 @@ procedure TGLForm1.SaveNIfTIMenuClick(Sender: TObject); niftiVol: TNIfTI; fnm : string; begin - if not vols.Layer(0,niftiVol) then exit; + //if not vols.Layer(0,niftiVol) then exit; //save background layer + if not vols.Layer(LayerList.ItemIndex,niftiVol) then exit; //save selected layer fnm := NiftiSaveDialogFilename(false, niftiVol.Filename); if fnm = '' then exit; niftiVol.SaveFormatBasedOnExt(fnm); @@ -8754,6 +8755,8 @@ function versionStr: string; {$ENDIF} {$IFDEF CPULLVM} w := w + ' LLVM'; + {$ELSE} + w := w + ' FPC'; {$ENDIF} w := w + chr(13)+chr(10); w := w + 'Author: Chris Rorden' +kEOLN; diff --git a/nifti.pas b/nifti.pas index be64c42..5feeecd 100755 --- a/nifti.pas +++ b/nifti.pas @@ -803,13 +803,18 @@ function correlR(var x, y: TFloat32s): single; {$ENDIF} //FASTCORREL2 function TNIfTI.EdgeMap(isSmooth: boolean): TUInt8s; //https://afni.nimh.nih.gov/pub/dist/doc/htmldoc/programs/3dedge3_sphx.html +// 2dedge3 uses R. Deriche formula https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.476.5736&rep=rep1&type=pdf //https://en.wikipedia.org/wiki/Sobel_operator#Extension_to_other_dimensions +//optional compile: +// Asjad and M. Deriche: https://www.researchgate.net/publication/283280465_A_new_approach_for_salt_dome_detection_using_a_3D_multidirectional_edge_detector +//{$DEFINE ASJAD} var x, y, z, vx, nXYZ, nXY, nX, nY, nZ: int64; llh, mlh, hlh, lmh, mmh, hmh, lhh, mhh, hhh, //voxel neighbors: slice above (high) llm, mlm, hlm, lmm, hmm, lhm, mhm, hhm, //voxel neighbors: same slice (middle) lll, mll, hll, lml, mml, hml, lhl, mhl, hhl, //voxel neighbors: slice below (low) gx, gy, gz, mn, mx, scale255: single; + {$IFDEF ASJAD}g45, g135: single; {$ENDIF} vol8: TUInt8s; vol32: TFloat32s; begin @@ -866,7 +871,47 @@ function TNIfTI.EdgeMap(isSmooth: boolean): TUInt8s; gx := (hlh + hmh + hhh + hlm + hmm + hhm + hll + hml + hhl) - (llh + lmh + lhh + llm + lmm + lhm + lll + lml + lhl); gy := (lhh + mhh + hhh + lhm + mhm + hhm + lhl + mhl + hhl) - (llh + mlh + hlh + llm + mlm + hlm + lll + mll + hll); gz := (llh + mlh + hlh + lmh + mmh + hmh + lhh + mhh + hhh) - (lll + mll + hll + lml + mml + hml + lhl + mhl + hhl); + {$IFDEF ASJAD} + //slice above (high) + llh := vol8[vx - 1 - nX + nXY] * 2; + mlh := vol8[vx - 0 - nX + nXY]; + hlh := vol8[vx + 1 - nX + nXY] * 2; + lmh := vol8[vx - 1 - 0 + nXY]; + //mmh := vol8[vx - 0 - 0 + nXY] * 0; + hmh := vol8[vx + 1 - 0 + nXY]; + lhh := vol8[vx - 1 + nX + nXY] * 2; + mhh := vol8[vx - 0 + nX + nXY]; + hhh := vol8[vx + 1 + nX + nXY] * 2; + //same slice (middle) + llm := vol8[vx - 1 - nX + 0] * 4; + mlm := vol8[vx - 0 - nX + 0] * 2; + hlm := vol8[vx + 1 - nX + 0] * 4; + lmm := vol8[vx - 1 - 0 + 0] * 2; + //mmm := vol8[vx - 0 - 0 + 0]; + hmm := vol8[vx + 1 - 0 + 0] * 2; + lhm := vol8[vx - 1 + nX + 0] * 4; + mhm := vol8[vx - 0 + nX + 0] * 2; + hhm := vol8[vx + 1 + nX + 0] * 4; + //slice below (low) + lll := vol8[vx - 1 - nX - nXY] * 2; + mll := vol8[vx - 0 - nX - nXY]; + hll := vol8[vx + 1 - nX - nXY] * 2; + lml := vol8[vx - 1 - 0 - nXY]; + //mml := vol8[vx - 0 - 0 - nXY] * 0; + hml := vol8[vx + 1 - 0 - nXY]; + lhl := vol8[vx - 1 + nX - nXY] * 2; + mhl := vol8[vx - 0 + nX - nXY]; + hhl := vol8[vx + 1 + nX - nXY] * 2; + + g45 := (hmh + mlh + hlh + hmm + mlm + hlm + hml + mll + hll) - (lhh + mhh + lmh + lhm + mhm + lmm + lhl + mhl + lml); + g135 := (lmh + llh + mlh + lmm + llm + mlm + lml + lll +mll) - (mhh + hhh + hmh + mhm + hhm + hmm + mhl + hhl + hml); + + + vol32[vx] += sqrt( sqr(gx) + sqr(gy) + sqr(gz) + sqr(g45) + sqr(g135)); + {$ELSE} vol32[vx] += sqrt( sqr(gx) + sqr(gy) + sqr(gz)); + {$ENDIF} + end; //scale 0..1 mn := infinity; diff --git a/niftis.pas b/niftis.pas index 4001e95..141129b 100644 --- a/niftis.pas +++ b/niftis.pas @@ -393,6 +393,7 @@ function TNIfTIs.AddEdgeLayer(Idx: integer; backColor: TRGBA): boolean; if length(img8) < 1 then exit; hdr := niis[Idx].Header; hdr.intent_code := kNIFTI_INTENT_NONE; + hdr.descrip := 'Sobel MRIcroGL'+kVers; prefix := 'edge_'; niis[fNumLayers] := TNIfTI.Create(prefix+niis[Idx].shortname, backColor, niis[Idx].Mat, niis[Idx].Dim, fInterpolateOverlays, hdr, TFloat32s(img8), true); fNumLayers := fNumLayers + 1;