/* Run CLAHE on a stack of images v211007: added some progress indicators */ macroL = "CLAHE_Stack_v211007"; getDimensions(width, height, channels, slices, frames); isComposite = channels > 1; imgTs = newArray(nImages); imgIDs = newArray(nImages); activeImageID = getImageID(); for (i=0; i=0) { Dialog.addCheckbox("Remove current selection first?", true); Dialog.addMessage("CLAHE will be restricted to current selection unless removed"); } Dialog.addNumber("blocksize",50,0,4,"pixels \(should be larger than detail to be preserved\)"); Dialog.addNumber("histogram",256,0,4,"should be < total pixels in block"); Dialog.addNumber("maximum gradient",1.3,1,4,"limits contrast stretch, needs to be >1"); if (nImages>1) Dialog.addChoice("Use a mask to select region?",Array.concat(imgTs,"*None*"),"*None*"); Dialog.addRadioButtonGroup("Accurate or fast?",newArray("accurate","fast"),1,2,"accurate"); Dialog.addNumber("Post-process gamma \(1 means none, 0 means Auto\)",1,2,4,"maximum value = 5"); Dialog.show; if (selectionType>0) { if (Dialog.getCheckbox()) run("Select None"); } parameters = "blocksize=" + Dialog.getNumber() + " histogram=" + Dialog.getNumber() + " maximum=" + Dialog.getNumber(); if (nImages>1) mask = Dialog.getChoice(); else mask = "*None*"; parameters += " mask=" + mask; accuracy = Dialog.getRadioButton(); gam = minOf(5,Dialog.getNumber()); if (accuracy != "accurate") parameters += " fast_(less_accurate)"; if (isComposite) parameters += " process_as_composite"; for (f=1; f<=frames; f++ ) { Stack.setFrame( f ); if (frames>1) showStatus("Applying CLAHE to frame " + f); for (s=1; s<=slices; s++ ) { Stack.setSlice( s ); if (slices>1){ showProgress(s-1, slices+1); /* 1 more slice total than necessary so the bar is retained for the final slice */ showStatus("Applying CLAHE to slice " + s); } for (c=1; c<=channels; c++ ) { if (channels>1){ Stack.setChannel(c); showStatus("Applying CLAHE to channel " + c); } run( "Enhance Local Contrast (CLAHE)", parameters ); if (gam!=1){ if (gam==0) gammaTweakF(); else run("Gamma...", "value="+gam); } } } } Stack.setFrame(1); Stack.setSlice(1); showStatus(macroL + " completed"); /* ( 8(|)) ( 8(|)) ( 8(|)) ASC Functions @@@@@:-) @@@@@:-) @@@@@:-) */ function gammaTweakF() { /* v211216 first version based on formula */ getStatistics(null, meanI, minI, maxI); originalBitDepth = bitDepth; if (originalBitDepth==16) fMaxI = pow(2,16); else if (originalBitDepth==32) fMaxI = maxI; fMaxI = 255; gParameters = "value=" + log(0.5)/log(meanI/fMaxI); if (nSlices>1) gParameters += " slice"; run("Gamma...", gParameters); }