// Time-Lapse Video Macros // // Based onto the Time-lapse_Capture macro, written by Wayne Rasband and available at the // http://rsb.info.nih.gov/ij/macros/Time-lapse_Capture.txt // Author: Gilles Carpentier, Faculte des Sciences et Technologie, Universite Paris 12 Val de Marne // Uses the QuickTime Capture plugin to capture a sequence. Requires a version of the plugin at // <http://rsb.info.nih.gov/ij/plugins/qt-capture.html> // dated 2007/05/22 or later. // Notice: // Using another macro during time-lapse capture may cause // an error unless you are running ImageJ 1.39q or later. // // This toolset proposes some functionalities around the video quicktime resources of ImageJ. // The image source is the Live ImageJ window (invisible in batch mode) and available // from the File->Import->Video menu. // It is advised to first start the live video, using the "Live Preview [l]" macro, before to use the // other macros of this macroset. // Press space bar to stop the image preview and live histogram. // Live histogram can be temporarely supended by using the "Stop Live Histogram [s]" macro menu // (use this function before handling acquired images or stacks). // Capture (as blind capture) can be aborted using the "Abort Timelapse Capturing [a]" macro menu // (the acquired stack becomesTimeLapseVideoMacros.txt visible in its states). // - Live grey levels or color histogram can be visualised by "Live Histogram macro" (shortcut h) // and "Live RGB Histogram [r]" menus. It is possible to switch from one to the other, // keeping the live histogram viewing. // - The Y scale of the histogram can be adjusted by the "Increase Live Histogram Atenuation" // and the "Decrease Live Histogram Atenuation" macro menus (respectively shorcuts "i" and "d"), // to dinamicaly optimize the live histogram visualisation. // - The interval between two calculated histograms, can be set by the // "Increase Live Histogram Interval" and the "Decrease Live Histogram Interval" macro menus // (respectively shorcuts "m" and "q"). This function can be used during live hitogram visualisation. // Some statistical infomations are given into the status area of the ImageJ toolbar (min and max level, // highest value of the histogram, and the correponding level, visualisation parameters) // - Time Lapse image acquisition can be performed with a live preview by the // "Timelapse Capture using "Live" ImageJ window" macro menu, or in batch with the // "Blind Timelapse Capture using "Live" ImageJ window" macro menu. // The live histogram viewing, if activated, will be interrupted during the image acquisitions. // Use macro menus to animate the acquired time lapse image stacks. // Change the default time lapse settings with the "Timelapse Capture Settings" macro menu. var histo=0, yHistoAtenuation=40,HistoInterval = 0.1; var TimeLapseFrames = 20, TimeLapseInterval = 0.5, abortTimeLapse=0; // seconds var delais=1000,stopHisto=0,restartHisto=0,acqui=0,RGBhistoSet=0; var greyHisto=newArray(256); var redHisto=newArray(256); var greenHisto=newArray(256); var blueHisto=newArray(256); macro "Live Preview [l]" { if (! isOpen("Live (press space bar to stop)")) doCommand("Video"); } macro "-" {} macro "Timelapse Capture using \"Live\" ImageJ window [c]" { TimeLapseConditions (); TimeLapseCapture (0,TimeLapseInterval,TimeLapseFrames); } macro "Blind Timelapse Capture using \"Live\" ImageJ window [b]" { TimeLapseConditions (); TimeLapseCapture (1,TimeLapseInterval,TimeLapseFrames); } macro "Timelapse Capture Settings [t]" { TimeLapseConditions (); Dialog.create("Timelapse Capture Settings"); Dialog.addMessage("Choose the number of frames \nand frame interval \(sec\)"); Dialog.addNumber("Nb frames", TimeLapseFrames, 0, 3, " "); Dialog.addNumber("Nb frames", TimeLapseInterval, 2, 4, "sec"); Dialog.show(); TimeLapseFrames=Dialog.getNumber(); TimeLapseInterval=Dialog.getNumber(); } macro "Abort Timelapse Capturing [a]" { if (call("ij.macro.Interpreter.isBatchMode")=="true") { beep(); if (acqui==1) abortTimeLapse=1; } } macro "-" {} macro "Animate" { if (call("ij.macro.Interpreter.isBatchMode")=="true") {beep();exit;} doCommand("Start Animation [\\]"); } macro "Animate Settings" { run("Animation Options..."); } macro "-" {} macro "Get a Single Image using \"Live\" ImageJ window [g]" { TimeLapseConditions (); if (! isOpen("Live (press space bar to stop)")) {doCommand("Video"); wait(2*delais); } acqui=1;abortTimeLapse=0; setBatchMode(true); selectWindow ("Live (press space bar to stop)"); newImage("Grab Image","RGB",getWidth,getHeight,1); grabima = getImageID; selectWindow ("Live (press space bar to stop)"); run("Copy"); selectImage(grabima); run("Paste"); run("Select None"); setBatchMode(false); acqui=0; if (histo==1 && restartHisto== 1) LiveRGBHisto (RGBhistoSet);restartHisto=0; } macro "-" {} macro "Live Grey Level Histogram [h]" { if (call("ij.macro.Interpreter.isBatchMode")=="true") { beep(); if (acqui==1) exit; RGBhistoSet=0;exit; } LiveRGBHisto (0); } macro "Live RGB Histogram [r]" { if (call("ij.macro.Interpreter.isBatchMode")=="true") { beep(); if (acqui==1) exit; RGBhistoSet=1;exit; } LiveRGBHisto (1); } macro "Stop Live Histogram [s]" { if (call("ij.macro.Interpreter.isBatchMode")=="true") { beep(); if (acqui==1) exit; stopHisto=1; wait (delais);stopHisto=0; } } macro "-" {} macro "Increase Live Histogram Atenuation [i]" { yHistoAtenuation= yHistoAtenuation+5; } macro "Decrease Live Histogram Atenuation [d]" { yHistoAtenuation= yHistoAtenuation-5; if (yHistoAtenuation < 0) yHistoAtenuation=0; } macro "Increase Live Histogram Interval [m]" { HistoInterval = HistoInterval+0.05; } macro "Decrease Live Histogram Interval [q]" { HistoInterval =HistoInterval-0.05; if (HistoInterval < 0.05) HistoInterval = 0.05; } // functions // function TimeLapseConditions () { if (call("ij.macro.Interpreter.isBatchMode")=="true") { beep(); if (acqui==1) exit; if (histo==1) stopHisto=1; restartHisto=1;wait (delais); } } // Timelapse function function TimeLapseCapture (blind,interval,frames) { setBatchMode(true); acqui=1; abortTimeLapse=0; setPasteMode("Copy"); if (blind == 0) {if (! isOpen("Live (press space bar to stop)")) {doCommand("Video"); wait(2*delais); }} // check for the video window status if (blind == 1) { if (isOpen("Live (press space bar to stop)")) { selectWindow ("Live (press space bar to stop)"); close (); wait(delais); } doCommand("Video"); wait(2*delais); } start = getTime; // acquisition for (i=1; i<=frames; i++) { showProgress(i, frames); selectWindow ("Live (press space bar to stop)"); run("Copy"); if (i==1) { newImage("Video","RGB",getWidth,getHeight,frames); stack = getImageID; } selectImage(stack); setSlice(i); run("Paste"); setMetadata(d2s((getTime-start)/1000,2)); while (getTime-start<interval*i*1000) wait(1); if (abortTimeLapse==1) {abortTimeLapse=0;acqui=0;histo=0;stopHisto=0;setBatchMode("exit and display");exit;} } run("Select None"); setBatchMode(false); acqui=0; if (histo==1 && restartHisto==1) LiveRGBHisto (RGBhistoSet);restartHisto=0; } // live histogram printing function function LiveRGBHisto (RGBhisto) { histo=1;stopHisto=0;RGBhistoSet=RGBhisto; xhisto=256; yhisto=240; HistoInterval = 0.05; // seconds if (! isOpen("Live (press space bar to stop)")) {doCommand("Video"); wait(2*delais); } if (! isOpen("Live Histogram")) { newImage("Live Histogram", "RGB White", xhisto, yhisto, 1); setLocation(0, (screenHeight-yhisto-40)); name=getTitle(); } if (RGBhistoSet==1 && bitDepth() != 24) {RGBhistoSet=0; showMessage ("Video is 8-bit encoded, RGB histogram will not be printed.");} while (isOpen("Live (press space bar to stop)") && stopHisto != 1) { start = getTime; setBatchMode(true); selectWindow ("Live (press space bar to stop)"); getStatistics(area, mean, min, max, std, histogram); greyHisto=histogram; if (RGBhistoSet == 1) { run("Duplicate...", "title=H"); run("RGB Stack");pile=getTitle();//wait (10); if (isOpen(pile)) {setSlice(1); getStatistics(area, mean, min, max, std, histogram);redHisto=histogram;} if (isOpen(pile)) {setSlice(2); getStatistics(area, mean, min, max, std, histogram);greenHisto=histogram;} if (isOpen(pile)) {setSlice(3); getStatistics(area, mean, min, max, std, histogram);blueHisto=histogram;} close (); } scale= (area/yhisto)/yHistoAtenuation; if (isOpen("Live Histogram")) { selectImage ("Live Histogram"); for (i=0; i<=255; i++) { setColor(0,0,0); drawLine(i, yhisto , i, 0); setColor(128,128,128); drawLine(i, (yhisto-1), i, (yhisto-1- (greyHisto[i])/scale)); // rgb as line if (RGBhistoSet == 1) { if (i<255) {setColor(255,0,0); drawLine(i, (yhisto-1- (redHisto[i+1])/scale), i, (yhisto-1- (redHisto[i])/scale));} if (i<255) {setColor(0,255,0); drawLine(i, (yhisto-1- (greenHisto[i+1])/scale), i, (yhisto-1- (greenHisto[i])/scale));} if (i<255) {setColor(0,0,255); drawLine(i, (yhisto-1- (blueHisto[i+1])/scale), i, (yhisto-1- (blueHisto[i])/scale));} } } } else { histo=0; exit ("\"Live Histogram\" window can\'t be found");} while (getTime-start<HistoInterval*1000) wait(1); maxFreqLevel=FindMinAndMaxFreq (greyHisto); histoStatus= " "+d2s(HistoInterval,2) + "s Ate:"+yHistoAtenuation+" Min="+min+ " max="+max + " highest="+histogram [lengthOf(greyHisto)-1] + " \(level "+maxFreqLevel+"\)" ; if (RGBhistoSet ==0) showStatus(histoStatus); setBatchMode(false); } if (stopHisto==0) histo=0; if (stopHisto==1 && restartHisto ==1) histo=1; if (histo==0) { selectImage ("Live Histogram"); rename("Histogram"); } } // Histogram analysis function. Derived the SortDemo macro from Wayne Rasband available at the // "/ij/macros/SortDemo.txt" function FindMinAndMaxFreq (a) { b=newArray (lengthOf(a)); for (i=0; i<lengthOf(a); i++) {b[i]=i;} quickSort(a,b, 0, (lengthOf(a)-1)); return b[lengthOf(b)-1]; } function quickSort(a,b, from, to) { i = from; j = to; center = a[(from+to)/2]; do { while (i<to && center>a[i]) i++; while (j>from && center<a[j]) j--; if (i<j) { temp=a[i]; a[i]=a[j]; a[j]=temp; temp=b[i];b[i]=b[j]; b[j]=temp; } if (i<=j) {i++; j--;} } while(i<=j); if (from<j) quickSort(a,b,from, j); if (i<to) quickSort(a,b, i, to); }