Sorry if this question was already asked. I found undefined errors but not for array so heres my question:
I get an 'undefined is not an object' error when im trying to declare selRef41 with the given Array.
(btw Im using ESTK and i am writing this script for Photoshop)
var docRef = app.activeDocument;
var layRef = docRef.activeLayer;
function createSelection(layRef) {
// Declare function variables
const oneT = 1/3;
const twoT = (1/3)*2;
docRef = app.activeDocument;
layRef = app.activeLayer;
if (detailFactor == "2x2") {
var selRef41 = Array(Array(0, 0),
Array(layRef.width.value / 2, 0),
Array(layRef.width.value / 2, layRef.height.value / 2),
Array(0, layRef.height.value / 2));
}
The corresponding main is just a one-liner to call the function:
function main() {
createSelection(layRef);
}
Where did you find this layRef.width.value? Layers don't have width or height property (only documents have), this is the thing that causes error in your code. You can calculate width and height using their bounds:
var layRef = docRef.activeLayer;
refWidth = layRef.bounds[2] - layRef.bounds[0];
refheight = layRef.bounds[3] - layRef.bounds[1];
alert([refWidth,refheight]);
You can check Photoshop Scripting Reference pdf to check properties and methods of DOM objects.
Also, as cybernetic.nomad noted, this won't work: layRef = app.activeLayer;, and plus you have if (detailFactor == "2x2") but detailFactor wan't assigned.
Related
I'm attempting to use opencv.js to align images to a baseline image. I'm following some basic python guidance that i've seen work (example: https://alexanderpacha.com/2018/01/29/aligning-images-an-engineers-solution/)
but i'm getting tripped up with an error that I don't quite understand. The error is "opencv.js:30 Uncaught TypeError: Cannot use 'in' operator to search for 'type' in 1e-10" and it seems to be caused by the "criteria" variable passed to "cv.findTransformECC();" see here.
any guidance as to what I'm doing wrong here?
function Align_img(){
let image_baseline = cv.imread(imgElement_Baseline);
let image = cv.imread('imageChangeup');
let im1_gray = new cv.Mat();
let im2_gray = new cv.Mat();
let im2_aligned = new cv.Mat();
//get size of baseline image
width1 = image_baseline.cols;
height1 = image_baseline.rows;
//resize image to baseline image
let dim1 = new cv.Size(width1, height1);
cv.resize(image, image, dim1, cv.INTER_AREA);
// Convert images to grayscale
cv.cvtColor(image_baseline, im1_gray, cv.COLOR_BGR2GRAY);
cv.cvtColor(image, im2_gray, cv.COLOR_BGR2GRAY);
// Find size of image1
let dsize = new cv.Size(image_baseline.rows, image_baseline.cols);
// Define the motion model
warp_mode = cv.MOTION_HOMOGRAPHY;
// Define 3x3 matrix and initialize the matrix to identity
let warp_matrix = cv.Mat.eye(3, 3, cv.CV_8U);
// Specify the number of iterations.
number_of_iterations = 5000;
// Specify the threshold of the increment in the correlation coefficient between two iterations
termination_eps = 0.0000000001; //1e-10;
// Define termination criteria
criteria = (cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, number_of_iterations, termination_eps);
//Run the ECC algorithm. The results are stored in warp_matrix.
cv.findTransformECC(im1_gray, im2_gray, warp_matrix, warp_mode, criteria, null, 5);
// Use warpPerspective for Homography
cv.warpPerspective (image, im2_aligned, warp_matrix, dsize, cv.INTER_LINEAR + cv.WARP_INVERSE_MAP);
cv.imshow('imageChangeup', im2_aligned);
im1_gray.delete();
im2_gray.delete();
im2_aligned.delete();
};
UPDATE: 2 things. 1. Found easy fix to error (code below) and 2. looks like a bug in the findTransformECC opencv.js API causing this method not to work. Here is current code.
The API has 2 optional parameters (inputMask and gaussFiltSize) but if you don't include them you get an error ("function findTransformECC called with 5 arguments, expected 7 args!").
The issue is what to use for inputMask - "null" does not work, there doesn't seem to be support for 'cv.noArray()' and I can't find a mask that doesn't lead to a 'uncaught exception' error.
I'll update again once I find a workaround. Let me know if anyone sees a work around.
function Align_img(){
let image_baseline = cv.imread(imgElement_Baseline);
let image = cv.imread('imageChangeup');
let im1_gray = new cv.Mat();
let im2_gray = new cv.Mat();
let im2_aligned = new cv.Mat();
//get size of baseline image
var width1 = image_baseline.cols;
var height1 = image_baseline.rows;
//resize image to baseline image
let dim1 = new cv.Size(width1, height1);
cv.resize(image, image, dim1, cv.INTER_AREA);
// Convert images to grayscale
cv.cvtColor(image_baseline, im1_gray, cv.COLOR_BGR2GRAY);
cv.cvtColor(image, im2_gray, cv.COLOR_BGR2GRAY);
// Find size of image1
let dsize = new cv.Size(image_baseline.rows, image_baseline.cols);
// Define the motion model
const warp_mode = cv.MOTION_HOMOGRAPHY;
// Define 3x3 matrix and initialize the matrix to identity
let warp_matrix = cv.Mat.eye(3, 3, cv.CV_8U);
// Specify the number of iterations.
const number_of_iterations = 5000;
// Specify the threshold of the increment in the correlation coefficient between two iterations
const termination_eps = 0.0000000001; //1e-10;
// Define termination criteria
//const criteria = (cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, number_of_iterations, termination_eps);
let criteria = new cv.TermCriteria(cv.TERM_CRITERIA_EPS | cv.TERM_CRITERIA_COUNT, number_of_iterations, termination_eps);
//Run the ECC algorithm. The results are stored in warp_matrix.
//let inputMask = new cv.Mat.ones(im1_gray.size(), cv.CV_8U); //uint8
cv.findTransformECC(im1_gray, im2_gray, warp_matrix, warp_mode, criteria, null, 5);
// Use warpPerspective for Homography
cv.warpPerspective (image, im2_aligned, warp_matrix, dsize, cv.INTER_LINEAR + cv.WARP_INVERSE_MAP);
getMatStats(im2_aligned, 1); //0 = baseline (srcMat), 1 = image (srcMat_compare)
cv.imshow('imageChangeup', im2_aligned);
im1_gray.delete();
im2_gray.delete();
im2_aligned.delete();
};
UPDATE 2 I verified code works fine in Python. code below. The issue at hand now is simply, how do you this in Javascript: "inputMask=None"
Python:
# Read the images to be aligned
im1 = cv2.imread(r"C:\temp\tcoin\69.jpg");
im2 = cv2.imread(r"C:\temp\tcoin\pic96_crop.jpg");
#resize image to compare
width1 = int(im1.shape[1])
height1 = int(im1.shape[0])
dim1 = (width1, height1)
im2 = cv2.resize(im2, dim1, interpolation = cv2.INTER_AREA)
# Convert images to grayscale
im1_gray = cv2.cvtColor(im1,cv2.COLOR_BGR2GRAY)
im2_gray = cv2.cvtColor(im2,cv2.COLOR_BGR2GRAY)
# Find size of image1
sz = im1.shape
# Define the motion model
warp_mode = cv2.MOTION_HOMOGRAPHY
# Define 2x3 or 3x3 matrices and initialize the matrix to identity
warp_matrix = np.eye(3, 3, dtype=np.float32)
# Specify the number of iterations.
number_of_iterations = 5000;
# Specify the threshold of the increment
# in the correlation coefficient between two iterations
termination_eps = 1e-10;
# Define termination criteria
criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, number_of_iterations, termination_eps)
# Run the ECC algorithm. The results are stored in warp_matrix.
(cc, warp_matrix) = cv2.findTransformECC (im1_gray,im2_gray,warp_matrix, warp_mode, criteria, inputMask=None, gaussFiltSize=1)
# Use warpPerspective for Homography
im2_aligned = cv2.warpPerspective (im2, warp_matrix, (sz[1],sz[0]), flags=cv2.INTER_LINEAR + cv2.WARP_INVERSE_MAP)
# Show final results
cv2.imshow("Aligned Image 2", im2_aligned)
cv2.imwrite(r"c:\temp\tcoin\output\pic96_cropB.jpg", im2_aligned)
cv2.waitKey(0)
I'm using my own custom connector implementation and i want to be able to consider other connectors to the same elements in order to calculate the source and target points better.
joint.connectors.custom = function (sourcePoint, targetPoint, vertices) {
// I want to calculate the "middle" point while considering other links that might interrupt
var sourceMiddleX = this.sourceBBox.x + this.sourceBBox.width / 2;
var d = ['M', sourcePoint.x, sourcePoint.y, targetPoint.x, targetPoint.y];
return d.join(' ');
};
So far i couldn't find anything helpful under the function context nor under the VElement..
Unless anyone has a better idea, i'll pass the total links per element in each model which doesn't feels right.
Thanks in advance!
Connector functions in JointJS are called with a value of this equal to a joint.dia.LinkView instance. Each linkView has access to the paper it's rendered in.
var paper = this.paper; // an instance of `joint.dia.Paper`
var graph = this.paper.model; // an instance of `joint.dia.Graph`
var link = this.model; // an instance of `joint.dia.Link`
// an instance of `joint.dia.Element` or `null`
var sourceElement = link.getSourceElement();
var sourceElementLinks = sourceElement
// an array of `joint.dia.Link` including the link
// these are connecting the same source element as the link
? graph.getConnectedLinks(sourceElement, { outbound: true })
// the link is not connected to a source element
: [];
// an instance of `joint.dia.Element` or `null`
var targetElement = link.getTargetElement();
var targetElementLinks = targetElement
// an array of `joint.dia.Link` including the link
// these are connecting the same target element as the link
? graph.getConnectedLinks(targetElement, { inbound: true })
// the link is not connected to a target element
: [];
You can also check the jumpOver connector, that implements a similar logic.
I've been reading this article: http://blogs.adobe.com/cantrell/archives/2011/03/native-cursors-in-air-2-6.html on how to create a native cursor in AIR without having to hack it by moving a sprite in place of a hidden cursor to fake it.
However I'm using HTML/JavaScript instead of ActionScript.
So far I have:
function nativeCursor(){
// load in a bitmap
var loader = new air.Loader();
loader.load(new air.URLRequest('./assets/cursor.png'));
var bitmaps = new air.Vector["<String>"]();
var bmd = new air.BitmapData(32, 32, true, 0x00000000);
var p = new window.runtime.flash.geom.Point(0, 0);
var r = new window.runtime.flash.geom.Rectangle(32 , 0, 32, 32);
var image = new window.runtime.flash.display.Bitmap(loader.content);
bmd.copyPixels([image.bitmapData], r, p);
bitmaps.push(bmd);
var mcd = new window.runtime.flash.ui.MouseCursorData();
mcd.data = bitmaps;
mcd.hotSpot = new Point(0, 0);
mcd.frameRate = 24;
window.runtime.flash.ui.Mouse.registerCursor("defaultCursor", mcd);
window.runtime.flash.ui.Mouse.cursor = "defaultCursor";
}
But I get an error TypeError: Error #1034: Type Coercion failed: cannot convert []#2b9d1f1 to flash.display.BitmapData. for this line: bmd.copyPixels([image.bitmapData], r, p);
If I remove the brackets for that line so it's just: bmd.copyPixels(image.bitmapData, r, p); the error becomes TypeError: Error #2007: Parameter sourceBitmapData must be non-null.
So I'm assuming that the error is because the bitmap data is null... but why? The image is being loaded in fine so is the way I'm trying to get the bitmap data incorrect?
BitmapData, not String
The vector is supposed to be of type BitmapData, not String, that is:
air.Vector["<flash.display.BitmapData>"]
See HTML Developer’s Guide for Adobe AIR - Working with Vectors for more information.
Asynchronous loaders
Also the Loader class probably works asynchronously in JavaScript too, it's not documented properly in the HTML API reference and I've never used JS for AIR development, so I can only assume that, and that one can refer to the AS3 reference for the missing docs, however it makes sense judging from the available examples.
http://help.adobe.com/.../html/flash/display/BitmapData.html#includeExamplesSummary
Loader.bitmapData doesn't exist
There is no bitmapData property on the Loader class, only a content property that holds a DisplayObject, which might actually be a Bitmap object which in turn has a bitmapData property.
An example
Here's some untested example code that should get you started:
var mcd = new window.runtime.flash.ui.MouseCursorData();
mcd.hotSpot = new air.Point(0, 0);
mcd.frameRate = 24;
var loader = new air.Loader();
loader.contentLoaderInfo.addEventListener(air.Event.COMPLETE, function(event)
{
var image = air.Bitmap(loader.content);
var bitmaps = new air.Vector["<flash.display.BitmapData>"]();
bitmaps.push(image.bitmapData);
mcd.data = bitmaps;
air.Mouse.registerCursor('defaultCursor', mcd);
air.Mouse.cursor = 'defaultCursor';
});
var request = new air.URLRequest('./assets/cursor.png');
loader.load(request);
In raphael, if I want to render the following shape:
I have to do something like:
var paper = Raphael("notepad", 320, 200);
var rect = paper.rect(...);
var line1 = paper.path(...);
var line2 = paper.path(...);
which create three elements: rect, line1, line2.
BUT, I would like to treat the rendered shape as one object in other js code insteand of three. In Raphael, how can I create this shape which returns me just one object not three?
You want to create a set.
Creates array-like object to keep and operate couple of elements at once. Warning: it doesn't create any elements for itself in the page.
var st = paper.set();
st.push(
paper.circle(10, 10, 5),
paper.circle(30, 10, 5)
);
st.attr({fill: "red"});
Your code would look something like this:
var paper = Raphael("notepad", 320, 200),
st = paper.set();
st.push(
paper.rect(...),
paper.path(...),
paper.path(...)
);
// use st elsewhere
Edit
How can I access individual element in the set then?
You can grab references to the objects before you add them to the set:
var paper = Raphael("notepad", 320, 200),
st = paper.set(),
rect1 = paper.rect(...),
path1 = paper.path(...),
path2 = paper.path(...);
st.push(rect1, path1, path2);
I'm not 100% sure, but since the docs say that a set is "array-like," then you should also be able to access elements in the set using array index notation:
var i, elt;
for (i=0; i<st.length; i++)
{
elt = st[i];
// do stuff with elt
}
I'm using the YUI 2.7 library to handle a dual-slider (range slider) control in a webpage.
It works great-- however, I wanted to allow users to switch the range values by Ajax-- effectively changing the price range from "0-50,000" to a subset (eg. "50-250") without reloading the page.
The problem is that it appears the values from the existing slider do not get reset, even when I explicitly set them back to NULL inside the function to "rebuild" the slider.
The slider handles appear out of position after the ajax request, (way off the scale to the right) and the values of the slider apparently randomly fluctuate.
Is there a way to explicitly destroy the YUI slider object, beyond setting its reference to null? Or do I just need to redeclare the scale and min/max values somehow?
Thanks for any help (I'll try to post a link to an example asap)
here's the code:
function slider(bg,minthumb,maxthumb,minvalue,maxvalue,startmin,startmax,aSliderName,soptions) {
var scaleFactor = null;
var tickSize = null;
var range = null;
var dual_slider = null;
var initVals = null;
var Dom = null;
range = options.sliderLength;
if ((startmax - startmin) < soptions.sliderLength) {
tickSize = (soptions.sliderLength / (startmax - startmin));
}else{
tickSize = 1;
}
initVals = [ 0,soptions.sliderLength ], // Values assigned during instantiation
//Event = YAHOO.util.Event,
dual_slider,
scaleFactor = ((startmax - startmin) / soptions.sliderLength);
dual_slider = YAHOO.widget.Slider.getHorizDualSlider(
bg,minthumb,maxthumb,range, tickSize, initVals);
dual_slider.subscribe("change", function(instance) {
priceMin = (dual_slider.minVal * scaleFactor) + startmin;
priceMax = (dual_slider.maxVal * scaleFactor) + startmin;
});
dual_slider.subscribe("slideEnd", function(){ alert(priceMin + ' ' + priceMax); });
return dual_slider;
}
Store the startmin, startmax, and scaleFactor on the dual_slider object, then in your ajax callback, update those properties with new values. Change your change event subscriber to reference this.startmin, this.startmax, and this.scaleFactor.
Slider and DualSlider only really understand the pixel offsets of the thumbs, and report the values as such. As you've done (and per most Slider examples), you need to apply a conversion factor to translate a pixel offset to a "value". This common idiom has been rolled into the core logic of the YUI 3 Slider (though there isn't yet a DualSlider in the library).
Here's an example that illustrates dynamically updating value ranges:
http://yuiblog.com/sandbox/yui/v282/examples/slider/slider_factor_change.html