Copy link to clipboard
Copied
Hi,
I have a night timelapse consisting of single images where the foreground is very noisy. What I want to do is open three images, create a smartobject and then use the stackmode median to reduce noise. Then photoshop should move foreward one image and yet again open three images. Is there a way to automate this using actions and the batch editing? I didn't find a way to open more than one image automatically...
Thanks for your help!
Jakob
Try this script. It will pull the files from a folder on your desktop called "source," but you can change the folder by editing the path in the code. It will save to a subfolder, called done, in the same folder. It will append the files with "median" so files don't get over written. It will also save the files as jpgs, and only open jpgs. You can change the file type by changing the extension in the line:
var mask = '*.jpg'
#target photoshop
var srcFolder = new Folder('~/desktop/source/');
va
...
As suggested by Chuck, here is the modified script for mean blending:
/*
https://community.adobe.com/t5/photoshop/batch-median-noise-reduction/m-p/10758011?page=1#M285346
Batch Median Noise Reduction
*/
#target photoshop
var srcFolder = new Folder('~/desktop/source/');
var doneFolder = new Folder(srcFolder + '/done/');
if (!doneFolder.exists) {
doneFolder.create()
};
var jpgOptions = new JPEGSaveOptions();
jpgOptions.quality = 8
var mask = '*.jpg'
var fList = srcFolder.getFiles(mask);
...
Copy link to clipboard
Copied
Did you shoot three shots for each frame, or are you wanting to combing the two frames before and after the selected frame?
Copy link to clipboard
Copied
Yes, I want to combine them with the one before and after the selected frame
Copy link to clipboard
Copied
"I didn't find a way to open more than one image automatically..."
File > Scripts > Load Files into Stack command can open multiple files and position them one above another in the Layers panel if I understand what you want to ask.
Copy link to clipboard
Copied
Yes, that's what I want, but automated. So Photoshop should open file 1, 2 and 3 then create a Smartobject with these three layers, use stack mode median and save the image. Then I want to open files 2, 3 and 4 and do the same, then 3, 4 and 5 and so on... I have about 350 frames so it would take ages if I had to do it manually... I'm sorry if my explanation is a bit hard to understand, but English isn't my first language.
Copy link to clipboard
Copied
Try this script. It will pull the files from a folder on your desktop called "source," but you can change the folder by editing the path in the code. It will save to a subfolder, called done, in the same folder. It will append the files with "median" so files don't get over written. It will also save the files as jpgs, and only open jpgs. You can change the file type by changing the extension in the line:
var mask = '*.jpg'
#target photoshop
var srcFolder = new Folder('~/desktop/source/');
var doneFolder = new Folder(srcFolder + '/done/');
if(!doneFolder.exists){doneFolder.create()};
var jpgOptions = new JPEGSaveOptions();
jpgOptions.quality = 8
var mask = '*.jpg'
var fList = srcFolder.getFiles (mask);
for(var i=0;i<fList.length;i++){
try{
open(fList[i])
}
catch(e){};
try{
open(fList[i -1])
}
catch(e){};
try{
open(fList[i +1])
}
catch(e){};
var base = activeDocument = app.documents[0];
base.flatten();
base.layers[0].isBackgroundLayer = false;
var docNum = app.documents.length;
for(var j=1;j<docNum;j++){
var nextDoc = activeDocument = app.documents[1];
nextDoc.flatten();
nextDoc.activeLayer.duplicate (base.layers[0], ElementPlacement.PLACEBEFORE);
nextDoc.close(SaveOptions.DONOTSAVECHANGES);
}
base.layers[base.layers.length -1].isBackgroundLayer = false;
selectAllLayers ();
makeSO ();
makeMedian ();
base.flatten();
var fName = base.name.split('.')[0];
base.saveAs (new File(doneFolder + '/Median-' + fName + '.jpg'), jpgOptions);
base.close(SaveOptions.DONOTSAVECHANGES);
};//end loop
function selectAllLayers(){
var idselectAllLayers = stringIDToTypeID( "selectAllLayers" );
var desc3 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref1 = new ActionReference();
var idLyr = charIDToTypeID( "Lyr " );
var idOrdn = charIDToTypeID( "Ordn" );
var idTrgt = charIDToTypeID( "Trgt" );
ref1.putEnumerated( idLyr, idOrdn, idTrgt );
desc3.putReference( idnull, ref1 );
executeAction( idselectAllLayers, desc3, DialogModes.NO );
}
function makeSO(){
var idnewPlacedLayer = stringIDToTypeID( "newPlacedLayer" );
executeAction( idnewPlacedLayer, undefined, DialogModes.NO );
}
function makeMedian(){
var idapplyImageStackPluginRenderer = stringIDToTypeID( "applyImageStackPluginRenderer" );
var desc6 = new ActionDescriptor();
var idimageStackPlugin = stringIDToTypeID( "imageStackPlugin" );
var idmedn = charIDToTypeID( "medn" );
desc6.putClass( idimageStackPlugin, idmedn );
var idNm = charIDToTypeID( "Nm " );
desc6.putString( idNm, """Median""" );
executeAction( idapplyImageStackPluginRenderer, desc6, DialogModes.NO );
}
Copy link to clipboard
Copied
Wow, thank you so much! It works perfectly.
Copy link to clipboard
Copied
So, I'm curious how the end video looked by combining the layers in this way? No odd artifacts from ghosting images?
Copy link to clipboard
Copied
Sorry for the late reply... So I didn't apply this technique to the shot I intended to, but I used it for the shot at 0:14 https://youtu.be/Nqcr3E8KZHE
Most of the planes are gone, just one looking a bit odd and I added a satellite back in with After Effects. I did however change your script to work with tif files and I stacked 5 images. I think it looks awesome and I would use this technique again.
Copy link to clipboard
Copied
Very nice!
Copy link to clipboard
Copied
Thanks again, you definitely saved that shot with your script, it was so noisy before that I wouldn't have included it in the final video.
Copy link to clipboard
Copied
Hi Chuck,
I'd like to change the script to use stackmode mean instead of median, what do I have to change? I tried changing a few of the settings but I only got errors in photoshop...
Thanks!
Copy link to clipboard
Copied
It would be best to use scriptListener and record stacking the images using mean, then replace the code for median, in the last function in the above script.
Copy link to clipboard
Copied
As suggested by Chuck, here is the modified script for mean blending:
/*
https://community.adobe.com/t5/photoshop/batch-median-noise-reduction/m-p/10758011?page=1#M285346
Batch Median Noise Reduction
*/
#target photoshop
var srcFolder = new Folder('~/desktop/source/');
var doneFolder = new Folder(srcFolder + '/done/');
if (!doneFolder.exists) {
doneFolder.create()
};
var jpgOptions = new JPEGSaveOptions();
jpgOptions.quality = 8
var mask = '*.jpg'
var fList = srcFolder.getFiles(mask);
for (var i = 0; i < fList.length; i++) {
try {
open(fList[i])
} catch (e) { };
try {
open(fList[i - 1])
} catch (e) { };
try {
open(fList[i + 1])
} catch (e) { };
var base = activeDocument = app.documents[0];
base.flatten();
base.layers[0].isBackgroundLayer = false;
var docNum = app.documents.length;
for (var j = 1; j < docNum; j++) {
var nextDoc = activeDocument = app.documents[1];
nextDoc.flatten();
nextDoc.activeLayer.duplicate(base.layers[0], ElementPlacement.PLACEBEFORE);
nextDoc.close(SaveOptions.DONOTSAVECHANGES);
}
base.layers[base.layers.length - 1].isBackgroundLayer = false;
selectAllLayers();
makeSO();
makeMean();
base.flatten();
var fName = base.name.split('.')[0];
base.saveAs(new File(doneFolder + '/Median-' + fName + '.jpg'), jpgOptions);
base.close(SaveOptions.DONOTSAVECHANGES);
}; //end loop
function selectAllLayers() {
var idselectAllLayers = stringIDToTypeID("selectAllLayers");
var desc3 = new ActionDescriptor();
var idnull = charIDToTypeID("null");
var ref1 = new ActionReference();
var idLyr = charIDToTypeID("Lyr ");
var idOrdn = charIDToTypeID("Ordn");
var idTrgt = charIDToTypeID("Trgt");
ref1.putEnumerated(idLyr, idOrdn, idTrgt);
desc3.putReference(idnull, ref1);
executeAction(idselectAllLayers, desc3, DialogModes.NO);
}
function makeSO() {
var idnewPlacedLayer = stringIDToTypeID("newPlacedLayer");
executeAction(idnewPlacedLayer, undefined, DialogModes.NO);
}
function makeMean() {
var idapplyImageStackPluginRenderer = stringIDToTypeID("applyImageStackPluginRenderer");
var desc252 = new ActionDescriptor();
var idimageStackPlugin = stringIDToTypeID("imageStackPlugin");
var idavrg = charIDToTypeID("avrg");
desc252.putClass(idimageStackPlugin, idavrg);
var idNm = charIDToTypeID("Nm ");
desc252.putString(idNm, """Mean""");
executeAction(idapplyImageStackPluginRenderer, desc252, DialogModes.NO);
}
Copy link to clipboard
Copied
Thanks guys! I tried "mean" as the charID, but that didn't work, "avrg" it is 😄
Copy link to clipboard
Copied
Hi,
I am new here. I was looking for a simmilar script in google and found this.
I would like to open 4 16 bit TIFF files at the time, do median and save as 16 bit TIFF (no layers); then move to the next 4 files until done.
Can someone please edit this script to do so?
Thanks in advance
Copy link to clipboard
Copied
Are the input files flattened Background images, or do they only contain a single layer?
EDIT: Don't worry, I have made sure that both will produce the same result.
Copy link to clipboard
Copied
Try the following code and let me know how it goes. It will combine files into sets of 4 and merge into a smart object stack with median blend mode. A new directory will be created within the input folder where the files are saved. File names are based off either the 4th, 8th etc file name in each set of 4 – or it is easily modified to use the 1st, 5th name etc.
Filenames are expected to be in correct alpha/numeric sorting order.
/*
Stack Sets of 4 Images with Median Blend.jsx
Stephen Marsh - 17th April 2021
This script is based around alpha/numeric sorting files
Batch Median Noise Reduction
https://community.adobe.com/t5/photoshop/batch-median-noise-reduction/m-p/11960956#M529922
*/
#target photoshop
if (app.documents.length === 0) {
try {
// Save and disable dialogs
var restoreDialogMode = app.displayDialogs;
app.displayDialogs = DialogModes.NO;
batchSetProcessing();
function batchSetProcessing() {
// Select the input folder
inputFolder = Folder.selectDialog('Please select the folder with files to process');
if (inputFolder === null) return;
// Create the output sub-directory
var outputFolder = Folder(decodeURI(inputFolder + '/Output Sets Folder'));
if (!outputFolder.exists) outputFolder.create();
// Limit the file format input
var fileList = inputFolder.getFiles(/\.(tif|tiff)$/i);
// Force alpha-numeric list sort
// Use .reverse() for the first filename in the merged file
// Remove .reverse() for the last filename in the merged file
fileList.sort().reverse();
// Images per set
var setQty = 4;
// Validate the input count vs. output count
var inputCount = fileList.length;
// Thanks to Kukurykus for the advice to test using % modulus
var cancelScript = !(inputCount % setQty);
alert(inputCount + ' input files stacked into sets of ' + setQty + ' will produce ' + inputCount / setQty + ' file sets.');
// Test if false, then terminate the script
if (cancelScript === false) {
alert('Script cancelled as the quantity of input files are not evenly divisible by the set quantity.');
return;
}
// Loop through and open the file sets
while (fileList.length) {
// Sets of N files
for (var a = 0; a < setQty; a++) {
try {
app.open(fileList.pop());
} catch (e) { }
}
processOpenImages();
}
// End of script notification
var outputList = outputFolder.getFiles(/\.(tif|tiff)$/i);
alert('Script completed!' + '\n' + outputList.length + ' combined files saved to:' + '\n' + outputFolder.fsName);
// Restore saved dialogs
app.displayDialogs = restoreDialogMode;
function processOpenImages() {
try {
app.activeDocument = documents[0];
docNameToLayerName();
// Combine open docs to base doc
while (app.documents.length) {
app.activeDocument = documents[1];
docNameToLayerName();
app.activeDocument.activeLayer.duplicate(documents[0]);
app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
}
app.activeDocument.flatten();
function docNameToLayerName() {
var layerName = app.activeDocument.name.replace(/\.[^\.]+$/, '');
app.activeDocument.activeLayer.name = layerName;
}
} catch (e) { }
// Select all layers
app.runMenuItem(stringIDToTypeID("selectAllLayers"));
// Create a smart object from all selected layers
makeSO();
// Smart object median stack blend mode
makeMedian();
// Save name+suffix & save path
var Name = app.activeDocument.name.replace(/\.[^\.]+$/, '');
var saveFile = File(outputFolder + '/' + Name + '_MedianBlend' + '.tif');
// Call the save function
saveTIFF(saveFile);
// Close all open files without saving
while (app.documents.length) {
app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
}
// Functions
function makeSO() {
var idnewPlacedLayer = stringIDToTypeID("newPlacedLayer");
executeAction(idnewPlacedLayer, undefined, DialogModes.NO);
}
function makeMedian() {
var idapplyImageStackPluginRenderer = stringIDToTypeID("applyImageStackPluginRenderer");
var desc6 = new ActionDescriptor();
var idimageStackPlugin = stringIDToTypeID("imageStackPlugin");
var idmedn = charIDToTypeID("medn");
desc6.putClass(idimageStackPlugin, idmedn);
var idNm = charIDToTypeID("Nm ");
desc6.putString(idNm, """Median""");
executeAction(idapplyImageStackPluginRenderer, desc6, DialogModes.NO);
}
function saveTIFF(saveFile) {
tiffSaveOptions = new TiffSaveOptions();
tiffSaveOptions.embedColorProfile = true;
tiffSaveOptions.byteOrder = ByteOrder.IBM;
tiffSaveOptions.transparency = true;
// Change .layers to true to preserve layers
tiffSaveOptions.layers = false;
tiffSaveOptions.layerCompression = LayerCompression.ZIP;
tiffSaveOptions.interleaveChannels = true;
tiffSaveOptions.alphaChannels = true;
tiffSaveOptions.annotations = true;
tiffSaveOptions.spotColors = true;
tiffSaveOptions.saveImagePyramid = false;
// Image compression = NONE | JPEG | TIFFLZW | TIFFZIP
tiffSaveOptions.imageCompression = TIFFEncoding.TIFFLZW;
// Save as
app.activeDocument.saveAs(saveFile, tiffSaveOptions, true, Extension.LOWERCASE);
}
}
}
} catch (e) {
// Restore saved dialogs
app.displayDialogs = restoreDialogMode;
}
} else {
alert('Please close all open documents before running this script!');
}
Copy link to clipboard
Copied
Thank you so much!! I will try it tomorrow and let you know
I want to use it macro shots with focus stacking, hopping to get lower noise/better DR as noise is treated by stacking software as detail. Kind of pseudo high resolution mode some modern cameras have.
Copy link to clipboard
Copied
I may sound dumb but how I convert this text to a script file photoshop recognizes? I have not used this feature before..
Copy link to clipboard
Copied
That's pretty easy, just save the file as a .js or .jsx file. I hope it works!
Jakob
Copy link to clipboard
Copied
Copy link to clipboard
Copied
Hi,
Thanks for the extra tips, it was easy and it runs and saves the files.
Unfortunately it does not work well, is not doing the median thing (maybe there is some error on the script?). When the TIFF is saving I can see top layer blending mode is set to "Normal".
Also, do the layers aling before blending? in case there is some movent between layers, just a couple of pixels would be enough to give the output TIFF an unsharp look
Copy link to clipboard
Copied
Hi,
I double checked and even on top of a microscope the shutter shake can cause camera to move a few microns (pixels), so I would need layers to aling before median blending
Copy link to clipboard
Copied
One more thing, for the stacking software to work all images need to be same size, when aligning image size changes by few pixels. I would need to add change canvas size (not image size) to 6000x4000 pixels before saving
I am woorking at magnifications up to 100:1, this is why shutter shock can move the camera a bit