diff --git a/js/brainchop/connectedComponents3DAll.js b/js/brainchop/connectedComponents3DAll.js index 44d7eb6..66539bf 100644 --- a/js/brainchop/connectedComponents3DAll.js +++ b/js/brainchop/connectedComponents3DAll.js @@ -4,8 +4,8 @@ ========================================================= * Discription: Pure Javascript code for 3D and 2D connected components -* -* +* +* * * Authors: Mohamed Masoud and Sergey Plis - 2022 ========================================================= @@ -14,7 +14,7 @@ ========================================================= 3D/2D Connected Components -=========================================================*/ +=========================================================*/ /** * Get binary mask of slice data @@ -27,20 +27,20 @@ * getBinaryMaskData1D([0,100,100, 0,255,255, .. ]) * // => [0,1,1, 0,1,1, .. ] * - */ + */ getBinaryMaskData1D = (sliceData) => { // greyImage is one channel 2D image with values 0-255 - + let maskBinaryData1D = []; for (let idx = 0; idx < sliceData.length; idx++) { if(sliceData[idx] > 0) { - maskBinaryData1D[idx] = 1; + maskBinaryData1D[idx] = 1; } else { - maskBinaryData1D[idx] = 0; + maskBinaryData1D[idx] = 0; } } - + return maskBinaryData1D; } @@ -62,15 +62,17 @@ * [0,0,1], * ] * - */ + */ - convertBinaryDataTo2D = (binaryData1D, imgHeight, imgWidth) => { - return tf.tensor(binaryData1D, [imgHeight, imgWidth]).arraySync(); + function convertBinaryDataTo2D(binaryData1D, imgHeight, imgWidth) { + let arr2D = []; + for (let i = 0; i < binaryData1D.length; i += imgWidth) { + let row = binaryData1D.slice(i, i + imgWidth); + arr2D.push(row); + } + return arr2D; } - - - /** * Add zero padding to 2D array e.g label2D * pad([[1,1],[1,1]]) means: 1 row of zeros befor, 1 row of zeros after, @@ -91,12 +93,25 @@ * [0,0,0,0,0], * ] * - */ + */ - addZeroPaddingTo2dArray = (arr2d) => { - const tensor2d = tf.tensor2d(arr2d); - return tensor2d.pad([[1,1],[1,1]]).arraySync(); - } + function addZeroPaddingTo2dArray(arr2d) { + let paddedArray = []; + let width = arr2d[0].length; + + // Add a row of zeros at the top + paddedArray.push(new Array(width + 2).fill(0)); + + // Add a column of zeros at the start and end of each row + for (let row of arr2d) { + paddedArray.push([0, ...row, 0]); + } + + // Add a row of zeros at the bottom + paddedArray.push(new Array(width + 2).fill(0)); + + return paddedArray; + } /** @@ -119,21 +134,22 @@ * [0,0,1], * ] * - */ + */ - removeZeroPaddingFrom2dArray = (arr2d) => { - const tensor2d = tf.tensor2d(arr2d); - [h, w] = tensor2d.shape; - return tensor2d.slice([1,1],[h-2,w-2]).arraySync(); + function removeZeroPaddingFrom2dArray(arr2d) { + // Slice the array to remove the first and last rows and columns + let unPaddedArray = arr2d.slice(1, arr2d.length - 1).map(row => { + return row.slice(1, row.length - 1); + }); + return unPaddedArray; } - ////////////////////////////////////////////////////////////////////////////////////////////////// ///////////// 2D Connected Components ///////////////// ////////////////////////////////////////////////////////////////////////////////////////////////// // class ConnectCompFor2D extends basicImageProcessing { - class ConnectCompFor2D { + class ConnectCompFor2D { constructor () { this._equivalenceTabel = []; this._equivalenceTabel[0] = 0; @@ -152,19 +168,19 @@ /** * Adjust equivalence table for connected components finding. Recursive call -- (refine) - * adjust Equivalence table labels such that if eqvTabel[3] = 2 && eqvTabel[2] = 1 then eqvTabel[3] = 1 + * adjust Equivalence table labels such that if eqvTabel[3] = 2 && eqvTabel[2] = 1 then eqvTabel[3] = 1 * * @since 1.0.0 - * @param {number} labelIdx + * @param {number} labelIdx * - */ + */ _adjustEquivalenceTable = (labelIdx) => { if(this._equivalenceTabel[labelIdx] != labelIdx) { this._equivalenceTabel[labelIdx] = this._adjustEquivalenceTable(this._equivalenceTabel[labelIdx]); - } - + } + return this._equivalenceTabel[labelIdx]; } @@ -181,12 +197,12 @@ * @example * * _checkNeighbors2D( [ [0,0,0,0], - * [0,0,4,0], + * [0,0,4,0], * [0,5,0,0], * [0,0,0,0] ], 2, 2, 5) * // => 4 * - */ + */ _checkNeighbors2D = (label, row, col, maxLabel) => { @@ -199,18 +215,18 @@ let smallerLabel = ( label[row][col - 1] < label[row - 1][col] ) ? label[row][col - 1] : label[row - 1][col]; let largerLabel = ( label[row][col - 1] > label[row - 1][col] ) ? label[row][col - 1] : label[row - 1][col]; - this._updateEquivalenceTable(largerLabel, smallerLabel); + this._updateEquivalenceTable(largerLabel, smallerLabel); return smallerLabel; } } else if ( label[row ][col - 1] ) { return label[row ][col - 1] ; } else if ( label[row - 1][col] ) { - return label[row - 1][col]; + return label[row - 1][col]; } else { - this._updateEquivalenceTable(maxLabel+1, maxLabel+1); + this._updateEquivalenceTable(maxLabel+1, maxLabel+1); return maxLabel+1 ; - } + } } @@ -220,7 +236,7 @@ * Get connected components For 2D slice -- (refine) * * @since 1.0.0 - * @param {Array} binaryMaskData2D- The array represents slice binary mask values in 2D, zero padding is needed. + * @param {Array} binaryMaskData2D- The array represents slice binary mask values in 2D, zero padding is needed. * @param {number} imgHeight- Slice Height * @param {number} imgWidth - Slice Width * @returns {Array} Returns Connected Components labels in 2D @@ -233,29 +249,29 @@ * [0,0,0,0,0] * ] * - */ + */ - getConComponentsFor2D = (binaryMaskData2D, imgHeight, imgWidth) => { + getConComponentsFor2D = (binaryMaskData2D, imgHeight, imgWidth) => { // initiat label let label1D = []; - this._resetEquivalenceTable(); + this._resetEquivalenceTable(); for(let idx = 0; idx < imgHeight * imgWidth; idx++) { label1D[idx] = 0; - } - - let label2D = convertBinaryDataTo2D(label1D, imgHeight, imgWidth); + } - let label2DwithPad = addZeroPaddingTo2dArray(label2D); - let binaryMaskData2DwithPad = addZeroPaddingTo2dArray(binaryMaskData2D); + let label2D = convertBinaryDataTo2D(label1D, imgHeight, imgWidth); + + let label2DwithPad = addZeroPaddingTo2dArray(label2D); + let binaryMaskData2DwithPad = addZeroPaddingTo2dArray(binaryMaskData2D); // maxLabel initiation to zero, starting label for 2d and 3d labeling - this._maxLabel = 0; + this._maxLabel = 0; // 1st pass for(let row = 1; row <= imgHeight; row++) { - for(let col = 1; col <= imgWidth; col++) { - + for(let col = 1; col <= imgWidth; col++) { + if( binaryMaskData2DwithPad[row][col] != 0) { label2DwithPad[row][col] = this._checkNeighbors2D(label2DwithPad, row, col, this._maxLabel) if(this._maxLabel < label2DwithPad[row][col]) { @@ -265,24 +281,24 @@ } } } - + label2D = removeZeroPaddingFrom2dArray(label2DwithPad); - // adjust Equivalence table labels such that eqvTabel[3] = 2 && eqvTabel[2] = 1 => eqvTabel[3] = 1 - for(let labelIdx = this._equivalenceTabel.length - 1; labelIdx > 0; labelIdx = labelIdx-1 ) { + // adjust Equivalence table labels such that eqvTabel[3] = 2 && eqvTabel[2] = 1 => eqvTabel[3] = 1 + for(let labelIdx = this._equivalenceTabel.length - 1; labelIdx > 0; labelIdx = labelIdx-1 ) { this._adjustEquivalenceTable (labelIdx); - } + } - // 2nd pass : relabeling the slice after eqvTable adjustment + // 2nd pass : relabeling the slice after eqvTable adjustment for(let row = 0; row < imgHeight; row++) { - for(let col = 0; col < imgWidth; col++) { - + for(let col = 0; col < imgWidth; col++) { + if( label2D[row][col] != 0) { label2D[row][col] = this._equivalenceTabel[label2D[row][col]]; } } - } + } return label2D; } @@ -308,28 +324,28 @@ class ConnectCompFor3D extends ConnectCompFor2D { * @param {number} sliceHeight- Slice Height * @param {number} sliceWidth - Slice Width * @param {number} numSlices - Total Number of slices (a.k.a z-dim) - * @returns {number} Returns Maximum label found + * @returns {number} Returns Maximum label found * @example * * getMaxLabelFor3D( [ [[0,0,0],[0,1,0]],[[0,2,0],[0,0,3]] ], 2, 3, 2) * // => 3 * - */ + */ - getMaxLabelFor3D = (label3D, sliceHeight, sliceWidth, numSlices) => { + getMaxLabelFor3D = (label3D, sliceHeight, sliceWidth, numSlices) => { - let maxLabelFor3D = 0; + let maxLabelFor3D = 0; for(let sliceIdx = 0; sliceIdx < numSlices; sliceIdx++ ) { for(let row = 0; row < sliceHeight; row++) { - for(let col = 0; col < sliceWidth; col++) { - + for(let col = 0; col < sliceWidth; col++) { + if( label3D[sliceIdx][row][col] > maxLabelFor3D) { maxLabelFor3D = label3D[sliceIdx][row][col]; } } } - } + } return maxLabelFor3D; } @@ -349,36 +365,36 @@ class ConnectCompFor3D extends ConnectCompFor2D { * getMostFreqVolumeLabel3D( [ [[0,1,0],[0,1,0]],[[0,2,0],[0,0,3]] ], 2, 3, 2) * // => 1 * - */ - + */ + getMostFreqVolumeLabel3D = (label3D, sliceHeight, sliceWidth, numSlices) => { - // Initiat connected component volumes to zeros + // Initiat connected component volumes to zeros let ccVolume = []; let maxCCLabel3D = this.getMaxLabelFor3D(label3D, sliceHeight, sliceWidth, numSlices) - for( let idx = 0; idx < maxCCLabel3D; idx ++) { + for( let idx = 0; idx < maxCCLabel3D; idx ++) { ccVolume[idx] = 0; - } - - for(let sliceIdx = 0; sliceIdx < numSlices; sliceIdx++ ) { + } + + for(let sliceIdx = 0; sliceIdx < numSlices; sliceIdx++ ) { for(let row = 0; row < sliceHeight; row++) { - for(let col = 0; col < sliceWidth; col++) { + for(let col = 0; col < sliceWidth; col++) { ccVolume[label3D[sliceIdx][row][col]] = ccVolume[label3D[sliceIdx][row][col]] +1; - } + } } } - + let maxCcVolume = 0; let maxCcVolumeLabel = -1; - for( let idx = 1; idx < maxCCLabel3D; idx ++) { + for( let idx = 1; idx < maxCCLabel3D; idx ++) { if( maxCcVolume < ccVolume[idx] ) { maxCcVolume = ccVolume[idx]; maxCcVolumeLabel = idx; - } - } + } + } return maxCcVolumeLabel; } @@ -398,12 +414,12 @@ class ConnectCompFor3D extends ConnectCompFor2D { * @example * * _checkNeighbors3D( [ [0,0, 0,0], - * [0,0,17,0], + * [0,0,17,0], * [0,18,0,0], * [0,0 ,0,0] ], 16 , 2, 2, 18) * // => 16 * - */ + */ _checkNeighbors3D = (label, z_1PixelLabel, row, col, maxLabel) => { //z_1PixelLabel same x,y pixel label of z-1 prev slice @@ -415,10 +431,10 @@ class ConnectCompFor3D extends ConnectCompFor2D { } else { let smallLabel = ( label[row][col - 1] < label[row - 1][col] ) ? label[row][col - 1] : label[row - 1][col]; - let smallestLabel = ( z_1PixelLabel < smallLabel ) ? z_1PixelLabel : smallLabel; + let smallestLabel = ( z_1PixelLabel < smallLabel ) ? z_1PixelLabel : smallLabel; let largerLabel = ( label[row][col - 1] > label[row - 1][col] ) ? label[row][col - 1] : label[row - 1][col]; - this._updateEquivalenceTable(largerLabel, smallestLabel); - this._updateEquivalenceTable(smallLabel, smallestLabel); + this._updateEquivalenceTable(largerLabel, smallestLabel); + this._updateEquivalenceTable(smallLabel, smallestLabel); return smallestLabel; } @@ -431,10 +447,10 @@ class ConnectCompFor3D extends ConnectCompFor2D { let smallerLabel = ( label[row][col - 1] < label[row - 1][col] ) ? label[row][col - 1] : label[row - 1][col]; let largerLabel = ( label[row][col - 1] > label[row - 1][col] ) ? label[row][col - 1] : label[row - 1][col]; - this._updateEquivalenceTable(largerLabel, smallerLabel); + this._updateEquivalenceTable(largerLabel, smallerLabel); return smallerLabel; } - + } else if ( label[row - 1][col] && z_1PixelLabel ) { @@ -445,12 +461,12 @@ class ConnectCompFor3D extends ConnectCompFor2D { let smallerLabel = ( z_1PixelLabel < label[row - 1][col] ) ? z_1PixelLabel : label[row - 1][col]; let largerLabel = ( z_1PixelLabel > label[row - 1][col] ) ? z_1PixelLabel : label[row - 1][col]; - this._updateEquivalenceTable(largerLabel, smallerLabel); + this._updateEquivalenceTable(largerLabel, smallerLabel); return smallerLabel; - } + } } else if ( label[row][col - 1] && z_1PixelLabel ) { - + if( label[row][col - 1] == z_1PixelLabel ) { return z_1PixelLabel; @@ -458,22 +474,22 @@ class ConnectCompFor3D extends ConnectCompFor2D { let smallerLabel = ( label[row][col - 1] < z_1PixelLabel ) ? label[row][col - 1] : z_1PixelLabel; let largerLabel = ( label[row][col - 1] > z_1PixelLabel ) ? label[row][col - 1] : z_1PixelLabel; - this._updateEquivalenceTable(largerLabel, smallerLabel); + this._updateEquivalenceTable(largerLabel, smallerLabel); return smallerLabel; } - + } else if ( label[row ][col - 1] ) { return label[row ][col - 1] ; } else if ( label[row - 1][col] ) { - return label[row - 1][col]; + return label[row - 1][col]; } else if ( z_1PixelLabel) { - return z_1PixelLabel; + return z_1PixelLabel; } else { - this._updateEquivalenceTable(maxLabel+1, maxLabel+1); + this._updateEquivalenceTable(maxLabel+1, maxLabel+1); return maxLabel+1 ; - } + } } - + /** * Get connected components For 3D Volume --(refine) @@ -499,19 +515,19 @@ class ConnectCompFor3D extends ConnectCompFor2D { * * [ [0,0,0,0], * [0,0,1,1], - * [0,2,0,0]], + * [0,2,0,0]], * ] * - */ + */ getConComponentsFor3DVolume = (volumeSlices, sliceHeight, sliceWidth) => { let binaryMaskData1D = []; - let binaryMaskData2D = []; - let label3D = []; + let binaryMaskData2D = []; + let label3D = []; for(let sliceIdx = 0; sliceIdx < volumeSlices.length; sliceIdx++) { - - binaryMaskData1D[sliceIdx] = getBinaryMaskData1D(volumeSlices[sliceIdx]); // binaryMaskData1D has values 0 or 1 + + binaryMaskData1D[sliceIdx] = getBinaryMaskData1D(volumeSlices[sliceIdx]); // binaryMaskData1D has values 0 or 1 binaryMaskData2D[sliceIdx] = convertBinaryDataTo2D(binaryMaskData1D[sliceIdx], sliceHeight, sliceWidth); @@ -530,36 +546,36 @@ class ConnectCompFor3D extends ConnectCompFor2D { let row, col; for(row = 0; row < sliceHeight; row++) { for(col = 0; col < sliceWidth; col++) { - + if( label3D[sliceIdx][row][col] != 0) { label3D[sliceIdx][row][col] = this._equivalenceTabel[label3D[sliceIdx][row][col]]; } } - } - } + } + } - return label3D; + return label3D; } // For future use - + getConComponentsFor3DVolumeWithTimer = async(volumeSlices, sliceHeight, sliceWidth) => { const self = this; - + return new Promise((resolve, reject) => { document.getElementById("progressBarChild").parentElement.style.visibility = "visible"; document.getElementById("progressBarChild").style.width = 0; let binaryMaskData1D = []; - let binaryMaskData2D = []; + let binaryMaskData2D = []; let label3D = []; - let sliceIdx = 0; + let sliceIdx = 0; let ccTimer = window.setInterval(function() { - binaryMaskData1D[sliceIdx] = getBinaryMaskData1D(volumeSlices[sliceIdx]); // binaryMaskData1D has values 0 or 1 + binaryMaskData1D[sliceIdx] = getBinaryMaskData1D(volumeSlices[sliceIdx]); // binaryMaskData1D has values 0 or 1 binaryMaskData2D[sliceIdx] = convertBinaryDataTo2D(binaryMaskData1D[sliceIdx], sliceHeight, sliceWidth); if(sliceIdx == 0) { @@ -580,13 +596,13 @@ class ConnectCompFor3D extends ConnectCompFor2D { let row, col; for(row = 0; row < sliceHeight; row++) { for(col = 0; col < sliceWidth; col++) { - + if( label3D[sliceIdx][row][col] != 0) { label3D[sliceIdx][row][col] = self._equivalenceTabel[label3D[sliceIdx][row][col]]; } } - } - } + } + } resolve(label3D); } @@ -595,8 +611,8 @@ class ConnectCompFor3D extends ConnectCompFor2D { document.getElementById("progressBarChild").style.width = (sliceIdx + 1)*100/volumeSlices.length + "%"; }, 10); // timer delay - - }) + + }) } @@ -619,34 +635,34 @@ class ConnectCompFor3D extends ConnectCompFor2D { * [0,0,0,0,0]] , [[0,0,0,0,0], * [0,0,0,1,0], * [0,0,0,0,0]] , 3, 5); - * + * * // => [ [0,0,0,0,0], * [0,2,0,1,0], * [0,0,0,0,0] * ] * - */ + */ + - - _getConComponentsFor2Slices = (binaryMaskData2D, preSliceLabels, imgHeight, imgWidth) => { + _getConComponentsFor2Slices = (binaryMaskData2D, preSliceLabels, imgHeight, imgWidth) => { let label1D = []; - // resetEquivalenceTable(); + // resetEquivalenceTable(); for(let idx = 0; idx < imgHeight * imgWidth; idx++) { label1D[idx] = 0; - } - + } + let label2D = convertBinaryDataTo2D(label1D, imgHeight, imgWidth); - // Add zero padding for cases where image has pixel value > 0 on borders + // Add zero padding for cases where image has pixel value > 0 on borders // e.g. MRI is touching borders or there is noisy pixel with value > 0 at row 0 or column 0 - let label2DwithPad = addZeroPaddingTo2dArray(label2D); - let binaryMaskData2DwithPad = addZeroPaddingTo2dArray(binaryMaskData2D); - let preSliceLabelsWithPad = addZeroPaddingTo2dArray(preSliceLabels); + let label2DwithPad = addZeroPaddingTo2dArray(label2D); + let binaryMaskData2DwithPad = addZeroPaddingTo2dArray(binaryMaskData2D); + let preSliceLabelsWithPad = addZeroPaddingTo2dArray(preSliceLabels); for(let row = 1; row <= imgHeight; row++) { - for(let col = 1; col <= imgWidth; col++) { - + for(let col = 1; col <= imgWidth; col++) { + if( binaryMaskData2DwithPad[row][col] != 0) { label2DwithPad[row][col] = this._checkNeighbors3D(label2DwithPad, preSliceLabelsWithPad[row][col], row, col, this._maxLabel) if(this._maxLabel < label2DwithPad[row][col]) { @@ -656,22 +672,22 @@ class ConnectCompFor3D extends ConnectCompFor2D { } } } - + label2D = removeZeroPaddingFrom2dArray(label2DwithPad); // console.log("First pass label2D :", label2D); - for(let labelIdx = this._equivalenceTabel.length - 1; labelIdx > 0; labelIdx = labelIdx-1 ) { + for(let labelIdx = this._equivalenceTabel.length - 1; labelIdx > 0; labelIdx = labelIdx-1 ) { this._adjustEquivalenceTable (labelIdx); - } + } for(let row = 0; row < imgHeight; row++) { - for(let col = 0; col < imgWidth; col++) { - + for(let col = 0; col < imgWidth; col++) { + if( label2D[row][col] != 0) { label2D[row][col] = this._equivalenceTabel[label2D[row][col]]; } } - } + } return label2D; } @@ -694,55 +710,51 @@ class ConnectCompFor3D extends ConnectCompFor2D { * * // => [ [0,0,0,0, 0,1,1,0, 0,0,0,0], * [0,0,0,0, 0,0,1,1, 0,0,0,0], - * [0,0,0,0, 0,0,0,1, 0,0,0,0] + * [0,0,0,0, 0,0,0,1, 0,0,0,0] * ] * - */ + */ findLargest3dRegion = (volumeSlices, sliceHeight, sliceWidth) => { - let label3D = []; - + let label3D = []; + label3D = this.getConComponentsFor3DVolume(volumeSlices, sliceHeight, sliceWidth); //-- label3D = await this.getConComponentsFor3DVolumeWithTimer(volumeSlices, sliceHeight, sliceWidth); - - // Filter only largest volumetric 3d region with the most voxels of same label and remove noisy smaller 3d regions - let maxVolumeLabel = this.getMostFreqVolumeLabel3D(label3D, sliceHeight, sliceWidth, volumeSlices.length); + + // Filter only largest volumetric 3d region with the most voxels of same label and remove noisy smaller 3d regions + let maxVolumeLabel = this.getMostFreqVolumeLabel3D(label3D, sliceHeight, sliceWidth, volumeSlices.length); for(let sliceIdx = 0; sliceIdx < volumeSlices.length; sliceIdx++) { - //Get max volume mask + //Get max volume mask let row, col; for(row = 0; row < sliceHeight; row++) { - for(col = 0; col < sliceWidth; col++) { + for(col = 0; col < sliceWidth; col++) { // remove nosiy smaller regions if(label3D[sliceIdx][row][col] != maxVolumeLabel) { label3D[sliceIdx][row][col] = 0; } else { - //mask largest 3d volumatic region + //mask largest 3d volumatic region label3D[sliceIdx][row][col] = 255; } - } - } + } + } let pixelIdx; for(row = 0, pixelIdx = 0; row < sliceHeight; row++) { - for(col = 0; col < sliceWidth; col++, pixelIdx++) { - //Filter smaller regions original MRI data + for(col = 0; col < sliceWidth; col++, pixelIdx++) { + //Filter smaller regions original MRI data if(label3D[sliceIdx][row][col] == 0) { volumeSlices[sliceIdx][pixelIdx] = 0; } - } - } + } + } } - //-- Postprocess volumeSlices after remove noisy regions or smaller regions + //-- Postprocess volumeSlices after remove noisy regions or smaller regions return volumeSlices; - } + } } - - - - diff --git a/js/brainchop/mainMeshNetFunctions.js b/js/brainchop/mainMeshNetFunctions.js index d9b8fc2..84efc02 100644 --- a/js/brainchop/mainMeshNetFunctions.js +++ b/js/brainchop/mainMeshNetFunctions.js @@ -7160,7 +7160,6 @@ resetMainParameters = () => { console.log(tf.getBackend()); //-- set this flag so that textures are deleted when tensors are disposed. tf.env().set("WEBGL_DELETE_TEXTURE_THRESHOLD", 0); - // tf.env().set('WEBGL_FORCE_F16_TEXTURES', true); console.log("tf env() features :", tf.env().features); console.log("tf env total features: ", Object.keys(tf.env().features).length); diff --git a/js/brainchop/mainParameters.js b/js/brainchop/mainParameters.js index df60410..5fa1890 100644 --- a/js/brainchop/mainParameters.js +++ b/js/brainchop/mainParameters.js @@ -113,9 +113,9 @@ isBatchOverlapEnable: false, //create extra overlap batches for inference numOverlapBatches: 0, //Number of extra overlap batches for inference enableTranspose : true, // Keras and tfjs input orientation may need a tranposing step to be matched - enableCrop: true, // For speed-up inference, crop brain from background before feeding to inference model to lower memory use. - cropPadding: 2, // Padding size add to cropped brain - autoThreshold: 0.1, // Threshold between 0 and 1, given no preModel and tensor is normalized either min-max or by quantiles. Will remove noisy voxels around brain + enableCrop: false, // For speed-up inference, crop brain from background before feeding to inference model to lower memory use. + cropPadding: 0, // Padding size add to cropped brain + autoThreshold: 0, // Threshold between 0 and 1, given no preModel and tensor is normalized either min-max or by quantiles. Will remove noisy voxels around brain enableQuantileNorm: false, // Some models needs Quantile Normaliztion. filterOutWithPreMask: false, // Can be used to multiply final output with premodel output mask to crean noisy areas enableSeqConv: false, // For low memory system and low configuration, enable sequential convolution instead of last layer @@ -182,14 +182,14 @@ modelName:"\u{1FA93} Subcortical + GWM (High Mem, Fast)", labelsPath: "./models/model18cls/labels.json", colorsPath: "./models/model18cls/colorLUT.json", - preModelId: 1,// Model run first e.g. crop the brain { null, 1, 2, .. } + preModelId: null,// Model run first e.g. crop the brain { null, 1, 2, .. } preModelPostProcess: false, // If true, perform postprocessing to remove noisy regions after preModel inference generate output. isBatchOverlapEnable: false, //create extra overlap batches for inference numOverlapBatches: 200, //Number of extra overlap batches for inference enableTranspose : true, // Keras and tfjs input orientation may need a tranposing step to be matched enableCrop: true, // For speed-up inference, crop brain from background before feeding to inference model to lower memory use. cropPadding: 0, // Padding size add to cropped brain - autoThreshold: 0, // Threshold between 0 and 1, given no preModel and tensor is normalized either min-max or by quantiles. Will remove noisy voxels around brain + autoThreshold: 0.2, // Threshold between 0 and 1, given no preModel and tensor is normalized either min-max or by quantiles. Will remove noisy voxels around brain enableQuantileNorm: false, // Some models needs Quantile Normaliztion. filterOutWithPreMask: false, // Can be used to multiply final output with premodel output mask to crean noisy areas enableSeqConv: false, // For low memory system and low configuration, enable sequential convolution instead of last layer @@ -206,14 +206,14 @@ modelName:"\u{1FA93} Subcortical + GWM (Low Mem, Slow)", labelsPath: "./models/model18cls/labels.json", colorsPath: "./models/model18cls/colorLUT.json", - preModelId: 1,// Model run first e.g. crop the brain { null, 1, 2, .. } + preModelId: null,// Model run first e.g. crop the brain { null, 1, 2, .. } preModelPostProcess: false, // If true, perform postprocessing to remove noisy regions after preModel inference generate output. isBatchOverlapEnable: false, //create extra overlap batches for inference numOverlapBatches: 200, //Number of extra overlap batches for inference enableTranspose : true, // Keras and tfjs input orientation may need a tranposing step to be matched enableCrop: true, // For speed-up inference, crop brain from background before feeding to inference model to lower memory use. cropPadding: 0, // Padding size add to cropped brain - autoThreshold: 0, // Threshold between 0 and 1, given no preModel and tensor is normalized either min-max or by quantiles. Will remove noisy voxels around brain + autoThreshold: 0.2, // Threshold between 0 and 1, given no preModel and tensor is normalized either min-max or by quantiles. Will remove noisy voxels around brain enableQuantileNorm: false, // Some models needs Quantile Normaliztion. filterOutWithPreMask: false, // Can be used to multiply final output with premodel output mask to crean noisy areas enableSeqConv: true, // For low memory system and low configuration, enable sequential convolution instead of last layer @@ -230,14 +230,14 @@ modelName:"\u{1FA93} Subcortical + GWM (Low Mem, Faster)", labelsPath: "./models/model30chan18cls/labels.json", colorsPath: "./models/model30chan18cls/colorLUT.json", - preModelId: 1, // model run first e.g. Brain_Extraction { null, 1, 2, .. } + preModelId: null, // model run first e.g. Brain_Extraction { null, 1, 2, .. } preModelPostProcess: false, // If true, perform postprocessing to remove noisy regions after preModel inference generate output. isBatchOverlapEnable: false, //create extra overlap batches for inference numOverlapBatches: 200, //Number of extra overlap batches for inference enableTranspose : true, // Keras and tfjs input orientation may need a tranposing step to be matched enableCrop: true, // For speed-up inference, crop brain from background before feeding to inference model to lower memory use. cropPadding: 0, // Padding size add to cropped brain - autoThreshold: 0, // Threshold between 0 and 1, given no preModel and tensor is normalized either min-max or by quantiles. Will remove noisy voxels around brain + autoThreshold: 0.2, // Threshold between 0 and 1, given no preModel and tensor is normalized either min-max or by quantiles. Will remove noisy voxels around brain enableQuantileNorm: false, // Some models needs Quantile Normaliztion. filterOutWithPreMask: false, // Can be used to multiply final output with premodel output mask to crean noisy areas enableSeqConv: true, // For low memory system and low configuration, enable sequential convolution instead of last layer diff --git a/paper/paper.pdf b/paper/paper.pdf index 4e0fbce..ff823f1 100644 Binary files a/paper/paper.pdf and b/paper/paper.pdf differ