Copy link to clipboard
Copied
As I am sure you know, the Object Selection Tool lets you identify the subject of an image by drawing a rough selection around it. And you can "draw" this "rough selection" with a rectangle or a lasso.
I saw this post on Stack Overflow that lets you script the "drawing" of the rectangle for the Object Selection Tool, if you know the coordinates of a bounding box around the subject. And I am wondering if there is a way to also script the "drawing" with a lasso to feed into the Object Selection Tool?
To explain a little more, I have two images -- an image with an object in it and a black and white pixel-wise mask of the object. I want to isolate the object in the image. I can "Select Subject" on the mask to get a selection of the object, but the problem is that the mask has really ragged edges and isn't completely accurate. Can I somehow feed the selection of the object from the mask into the Object Selection Tool to improve the selection? I feel like this would be more accurate than simply using a rectangular bounding box around the object. I don't know if this is the right approach -- but I was thinking I could turn the initial object selection from the mask into a path, retrieve all of the points in the path, and then use those points in the Object Selection Tool's lasso. I am unsure if this would work and if it would, how I could accomplish this. Please advise. Thank you!
I think that if the Layer Mask has more than one distinct contiguous visible area the Object Selection Tool would need to be used for each individually.
With just one contiguous area (and therefore only one subPathItem) this seems to work.
// use layer mask as basis for object selection tool;
// if the path has more than one subpathitem only the first one will be used;
// 2023, use it at your own risk;
if (app.documents.length > 0) {
if (hasLayerMask () == true) {
loadSelec
...
Copy link to clipboard
Copied
A quick test showed that one can indeed use "polygon" instead of "rectangle", but the Work Path-work-around seems risky because reducing »strong« curves to the two points might be too inexact.
Copy link to clipboard
Copied
Hello guys, pardon the intrusion, can you tell me please were can I find more info about scripting for Photoshop, I know about batching very little, thanx and have a nice day. Hope to be more helpful on this mater in a neer future when I will have more experience on scripting.
Copy link to clipboard
Copied
Copy link to clipboard
Copied
I think that if the Layer Mask has more than one distinct contiguous visible area the Object Selection Tool would need to be used for each individually.
With just one contiguous area (and therefore only one subPathItem) this seems to work.
// use layer mask as basis for object selection tool;
// if the path has more than one subpathitem only the first one will be used;
// 2023, use it at your own risk;
if (app.documents.length > 0) {
if (hasLayerMask () == true) {
loadSelectionOfLayerMask();
makeWorkPath (1);
var thePath = collectPathInfoFromDesc2012(activeDocument, activeDocument.pathItems[activeDocument.pathItems.length-1]);
objectSelectionToolFromPolygon (thePath)
};
};
////// based on code by phantomhive //////
function objectSelectionToolFromPolygon (theArray) {
var idset = stringIDToTypeID( "set" );
var desc4 = new ActionDescriptor();
var idnull = stringIDToTypeID( "null" );
var ref3 = new ActionReference();
var idchannel = stringIDToTypeID( "channel" );
var idselection = stringIDToTypeID( "selection" );
ref3.putProperty( idchannel, idselection );
desc4.putReference( idnull, ref3 );
var idto = stringIDToTypeID( "to" );
var desc14 = new ActionDescriptor();
var idpoints = stringIDToTypeID( "points" );
var list1 = new ActionList();
// the points;
for (var x = 0; x < theArray[0].length-2; x++) {
var desc15 = new ActionDescriptor();
var idpixelsUnit = stringIDToTypeID( "pointsUnit" );
desc15.putUnitDouble( stringIDToTypeID( "horizontal" ), idpixelsUnit, theArray[0][x][0][0] );
desc15.putUnitDouble( stringIDToTypeID( "vertical" ), idpixelsUnit, theArray[0][x][0][1] );
var idpaint = stringIDToTypeID( "paint" );
list1.putObject( idpaint, desc15 );
};
desc14.putList( idpoints, list1 );
var idrectangle = stringIDToTypeID( "polygon" );
desc4.putObject( idto, idrectangle, desc14 );
var iddeepSelect = stringIDToTypeID( "deepSelect" );
desc4.putBoolean( iddeepSelect, true );
var idobjectSelectionMode = stringIDToTypeID( "objectSelectionMode" );
desc4.putInteger( idobjectSelectionMode, 0 );
var idmagicLassoAutoEnhance = stringIDToTypeID( "magicLassoAutoEnhance" );
desc4.putBoolean( idmagicLassoAutoEnhance, true );
var idsmartSubtract = stringIDToTypeID( "smartSubtract" );
desc4.putBoolean( idsmartSubtract, true );
executeAction( idset, desc4, DialogModes.NO );
};
////// has layer mask //////
function hasLayerMask () {
var m_Dsc01, m_Ref01;
m_Ref01 = new ActionReference();
m_Ref01.putEnumerated(stringIDToTypeID("layer"), charIDToTypeID("Ordn"), charIDToTypeID("Trgt"));
m_Dsc01 = executeActionGet(m_Ref01);
return m_Dsc01.hasKey(charIDToTypeID("Usrs"));
};
////// load layer mask //////
function loadSelectionOfLayerMask() {
try {
var idchannel = stringIDToTypeID( "channel" );
var desc70 = new ActionDescriptor();
var ref9 = new ActionReference();
ref9.putProperty( idchannel, stringIDToTypeID( "selection" ) );
desc70.putReference( stringIDToTypeID( "null" ), ref9 );
var ref10 = new ActionReference();
ref10.putEnumerated( idchannel, idchannel, stringIDToTypeID( "mask" ) );
desc70.putReference( stringIDToTypeID( "to" ), ref10 );
executeAction( stringIDToTypeID( "set" ), desc70, DialogModes.NO );
} catch (_error) {alert (_error)}
};
////// make work path from selection //////
function makeWorkPath (theTolerance) {
// =======================================================
var idMk = charIDToTypeID( "Mk " );
var desc5 = new ActionDescriptor();
var idnull = charIDToTypeID( "null" );
var ref3 = new ActionReference();
var idPath = charIDToTypeID( "Path" );
ref3.putClass( idPath );
desc5.putReference( idnull, ref3 );
var idFrom = charIDToTypeID( "From" );
var ref4 = new ActionReference();
var idcsel = charIDToTypeID( "csel" );
var idfsel = charIDToTypeID( "fsel" );
ref4.putProperty( idcsel, idfsel );
desc5.putReference( idFrom, ref4 );
var idTlrn = charIDToTypeID( "Tlrn" );
var idPxl = charIDToTypeID( "#Pxl" );
desc5.putUnitDouble( idTlrn, idPxl, theTolerance );
executeAction( idMk, desc5, DialogModes.NO );
};
////// collect path info from actiondescriptor, smooth added //////
function collectPathInfoFromDesc2012 (myDocument, thePath) {
var originalRulerUnits = app.preferences.rulerUnits;
app.preferences.rulerUnits = Units.POINTS;
// based of functions from xbytor’s stdlib;
var idPath = charIDToTypeID( "Path" );
var ref = new ActionReference();
for (var l = 0; l < myDocument.pathItems.length; l++) {
var thisPath = myDocument.pathItems[l];
if (thisPath == thePath && thisPath.kind == PathKind.WORKPATH) {
ref.putProperty(idPath, cTID("WrPt"));
};
if (thisPath == thePath && thisPath.kind != PathKind.WORKPATH && thisPath.kind != PathKind.VECTORMASK) {
ref.putIndex(idPath, l + 1);
};
if (thisPath == thePath && thisPath.kind == PathKind.VECTORMASK) {
var idvectorMask = stringIDToTypeID( "vectorMask" );
ref.putEnumerated( idPath, idPath, idvectorMask );
};
};
var desc = app.executeActionGet(ref);
var pname = desc.getString(cTID('PthN'));
// create new array;
var theArray = new Array;
var pathComponents = desc.getObjectValue(cTID("PthC")).getList(sTID('pathComponents'));
// for subpathitems;
for (var m = 0; m < pathComponents.count; m++) {
var listKey = pathComponents.getObjectValue(m).getList(sTID("subpathListKey"));
var operation1 = pathComponents.getObjectValue(m).getEnumerationValue(sTID("shapeOperation"));
switch (operation1) {
case 1097098272:
var operation = 1097098272 //cTID('Add ');
break;
case 1398961266:
var operation = 1398961266 //cTID('Sbtr');
break;
case 1231975538:
var operation = 1231975538 //cTID('Intr');
break;
default:
// case 1102:
var operation = sTID('xor') //ShapeOperation.SHAPEXOR;
break;
};
// for subpathitem’s count;
for (var n = 0; n < listKey.count; n++) {
theArray.push(new Array);
var points = listKey.getObjectValue(n).getList(sTID('points'));
try {var closed = listKey.getObjectValue(n).getBoolean(sTID("closedSubpath"))}
catch (e) {var closed = false};
// for subpathitem’s segment’s number of points;
for (var o = 0; o < points.count; o++) {
var anchorObj = points.getObjectValue(o).getObjectValue(sTID("anchor"));
var anchor = [anchorObj.getUnitDoubleValue(sTID('horizontal')), anchorObj.getUnitDoubleValue(sTID('vertical'))];
var thisPoint = [anchor];
try {
var left = points.getObjectValue(o).getObjectValue(cTID("Fwd "));
var leftDirection = [left.getUnitDoubleValue(sTID('horizontal')), left.getUnitDoubleValue(sTID('vertical'))];
thisPoint.push(leftDirection)
}
catch (e) {
thisPoint.push(anchor)
};
try {
var right = points.getObjectValue(o).getObjectValue(cTID("Bwd "));
var rightDirection = [right.getUnitDoubleValue(sTID('horizontal')), right.getUnitDoubleValue(sTID('vertical'))];
thisPoint.push(rightDirection)
}
catch (e) {
thisPoint.push(anchor)
};
try {
var smoothOr = points.getObjectValue(o).getBoolean(cTID("Smoo"));
thisPoint.push(smoothOr)
}
catch (e) {thisPoint.push(false)};
theArray[theArray.length - 1].push(thisPoint);
};
theArray[theArray.length - 1].push(closed);
theArray[theArray.length - 1].push(operation);
};
};
// by xbytor, thanks to him;
function cTID (s) { return cTID[s] || cTID[s] = app.charIDToTypeID(s); };
function sTID (s) { return sTID[s] || sTID[s] = app.stringIDToTypeID(s); };
// reset;
app.preferences.rulerUnits = originalRulerUnits;
return theArray;
};
Copy link to clipboard
Copied
This is great! Thank you.
Find more inspiration, events, and resources on the new Adobe Community
Explore Now