Object detection and tracking in javascript - javascript

Im Recently new here, we have made for our school project a cell detection. That functions under the microscope and detect the cells from PNG images that come out of our software.
On these images there will be a color detection done from tracking.js and then it returns te X and Y position of the image dimensions of the center of the cell.
Our concerning is that the cells we have under our microscope evolve so we take every minute automatically an image of this. So we have a set of 10 images with cells and also dissapearing and new cells. What would be the best way to identify them as new cells, and the cells still exist in the timeframe to identify them by an ID, and the dissapearing cells remove as object.
A lot of text, lets see what we've got right now.
Now as the detection works fine thats great. For each cell we make a new object with the following code:
var cells = [];
celltrack = function (x, y) {
xoutput = (img.offsetLeft + x);
youtput = (img.offsetTop + y);
cells = new cell('cell');
cells.id = count++;
cells.x = xoutput;
cells.y = youtput;
}
cell = function (type) {
this.type = type;
this.id = 0;
this.x = "x";
this.y = "y";
}
A couple of main questions on this moment:
Is this the correct way to create the objects containing the cell info ?
What is the best way to identify a cell before create of delete a object ?
If a cell has moved, how can we link the cell to the same object with 2 different locations.
Thats it for now, if we have got further improvements in our project we keep you informed.

I assume the problem is:
Every minute you will get an image of cells, then properties of cells will be analyzed, the output is a series (an array) of positions for the cells in the image
You would like to track how cells create/disappear/move between time periods
With those assumptions, I think:
Yes, you can use the cell constructor function defined in your snippet, though normally we will capitalize constructor functions (to indicate they should be used with new keyword, as in Cell). The properties that goes into the newly created object are up to you, now they are type, id, x and y.
I think that depends on the rules of identifying cells, based on the input we have (just positions), I am not sure we have a good solution here. Are there other properties of cells we can consider and extract in each image?
It relates to the last question, but once you can identify cells, you can update the cell objects between time periods, the history of locations for a cell can be kept in the Cell object itself, maybe a property called locations of type Array.

Related

How to create a chart with multiple ranges in google apps script for google spreadsheets

I have a google apps script which deploys a variable number of sheets in the spreadsheet it is attached to, with the intent to gather data from an API, which is working just fine.
However, I want to visualize this data in graphs, and since it's meant to be self-deplorable, and because there are a variable number of these sheets of data, I want to create a number of charts representing various parts of the data, and in these charts have a range (series, or y axis), for every sheet of data, so it's variable depending on the initialization or setup.
Long story short and to make it less confusing, I simply want to know how to create a chart and add ranges for every chart. I could iterate through a list for example, but the problem is that I'm getting errors such as:
"TypeError: Cannot find function modify in object EmbeddedChartBuilder. (line 97, file "Code")
Dismiss"
Also, note I'm trying to pull data from other sheets, so I'm using the sheetName!range notation.
Here's the particular function I'm working on, note I'm using placeholder values just to get something working for now.
// TODO
function createCharts(){
var sheet = getSheet('Graphs');
var winrateChart = sheet.newChart().setChartType(Charts.ChartType.LINE).setPosition(2, 1, 0, 0);
// for every user, add appropriate range to chart
winrateChart = winrateChart.modify().addRange('username1!A1:B2');
winrateChart = winrateChart.modify().addRange('username2!A1:B2');
sheet.updateChart(winrateChart);
winrateChart = winrateChart.build()
sheet.insertChart(winrateChart);
}
I've figured out what the problems were, mostly through experimentation, I still am of the opinion the documentation is lacking clarity and good examples.
But here is my my understanding.
First of, there are three classes to deal with for this problem, Sheet, EmbeddedChart and EmbeddedChartBuilder.
EmbeddedChartBuilder is what is returned by Sheet.newChart(), by using the .build() method you get an EmbeddedChart class, which can be used as a parameter to Sheet.insertChart().
Furthermore through experimentation it seems like you must insert a chart by Sheet.insertChart(EmbeddedChart) before you can use EmbeddedChart.modify(), which in turn returns an EmbeddedChartBuilder, which you can use to chain any number of methods such as add range. And of course you still have to use .build() to return an EmbeddedChart from an EmbeddedChartBuilder, then Sheet.updateChart(EmbeddedChart) afterwards.
The last problem was a mistake I've made, I was calling .addRange() using a string as parameter, however addRange requires a Range object.
Anyway, here is some code demonstrating an example use, you can chain as many modify() as you want, for example in a loop that iterates through sheets.
Note: getSheet is a custom function, does what you'd expect.
function createCharts(){
var sheet = getSheet('Graphs');
var chart = sheet.newChart().setChartType(Charts.ChartType.LINE).setPosition(2,1,0,0).build(); // build returns an EmbeddedChart object
Logger.log(chart);
sheet.insertChart(chart);
chart = chart.modify().addRange(getSheet('someSheetName').getRange('B1:B999')).build();
Logger.log(chart);
sheet.updateChart(chart);
}
EDIT: here's the entire, working function, not useful outside this particular code, however, you can see the logic behind it, I'm gonna try to make it universally useful by iterating through sheets or something.
function createChart(range, x, y, title, width, height){
// range: string; x: int; y: int; title: string; width: int; height; int
// Creates a chart with data from all usernames for a given range at x row, y column, with a title, a width and height
var sheet = getSheet('Graphs');
// chart setup
var chart = sheet.newChart()
.setChartType(Charts.ChartType.LINE)
.setPosition(x,y,0,0)
.setNumHeaders(1)
.setOption('title', title)
.setOption('width', width)
.setOption('height', height)
.build();
sheet.insertChart(chart);
// for every username, add corresponding data into chart
for(var i = 0; i < fortniteUsernames.length; i++){
var username = fortniteUsernames[i];
chart = chart.modify().addRange(getSheet(username).getRange(range)).build();
sheet.updateChart(chart);
}
}

Adobe Acrobat Pro DC JavaScript field properties not propagating

I have been brought in mid stream on an Adobe Acrobat Pro DC customization project. The goal of this project is to add a warning along the left edge of each page. I have been given a piece of JavaScript that does this with one exception and asked to fix that exception.
The code is:
var inch = 72;
for (var p = 0; p < this.numPages; p++) {
var aRect = this.getPageBox( {nPage: p} );
aRect[0] = 8.25*inch; //how far from the left the box ends
aRect[1] = 0.5*inch; //how high from the bottom the box is
aRect[2] = 7.75*inch; //how far from the left the box starts
aRect[3] = 11.0*inch; //how tall the box is
var f = this.addField("ControlledDoc", "text", p, aRect )
f.rotation = 270;
f.delay = true;
f.textSize = 7.5;
f.textFont = font.HelvB;
f.textColor = color.red;
f.alignment = "center";
f.readonly = true;
f.display = display.visible;
f.delay = false;
}
var myWillSaveScript = 'var f = this.getField("ControlledDoc"); \r'
+ 'f.value = "This is an electronic controlled copy of a paper based document management system. When printed on the copy machine it becomes an uncontrolled paper copy valid until the end of the printing day."; \r';
this.setAction("WillSave", myWillSaveScript);
The problem presents when a document is more than one page in length. The ControlledDoc field is replicated on each page as expected. Each page gets a ControlledDoc#n-1 field, where n is the page number. On the first page, the f.rotation setting is retained and shows up in the UI as the Orientation dropdown in the Properties dialog being set to 270. However, on the second and subsequent pages the Orientation is set to 0. I can manually edit the document and set the Orientation to 270, but that defeats the purpose of automating things with JavaScript.
I am new to controlling Acrobat Pro DC with JavaScript, so I will not be surprised if I am missing something stupid...
What do I need to change to make the rotation setting stick on the second and subsequent pages?
Field properties can be on a field level (the same for all copies of the field, with the same nam), or on a widget level (can be different from copy of the field to copy of the field).
The Acrobat JavaScript documentation has a list of those properties. Unfortunately, those two lists (field level and widget level) do not contain the rotation property. That means, we do not really know whether it is field or widget level. From your description, I get the feeling that it is widget level.
What you may try is to create an individual field for every page. You would do that with the line
var f = this.addField("ControlledDoc." + p, "text", p, aRect) ;
About the delay property: I always use the doc.delay property (instead of the field.delay), and because of that outside of a loop, so that it can provide maximum performance gain. However, if the script exits from within the loop, I would have to set delay to false via the Console. From my experience, this will create all appearances (but in order to find out, we'd have to get onto that page, and then they are created immediately…).
I'm assuming you're on page 1 when you run the script. That's why it looks correct on page one.
The delay property, when false, tells Acrobat to delay updating the appearance of the field until it's set to true. When you add the field to the pages, you're telling Acrobat not to generate appearances until all of the settings are set... that's OK... but then, I suspect, you never visit the subsequent pages so the appearances never get updated for those pages even though the delay property is now set to true. Just pull out the two lines that set the delay property and it should work.

how to get the html file of an edited canvas in html5

I am trying to make a website which helps its users to create a page by dragging and dropping elements on the canvas. The user should be able to save the html file of the edited canvas. I cannot figure how to convert the changes made to the canvas to an html file.
I don't think it's possible to get Markup out of canvas. I've searched it for a month but can't find a valid solution. but may be some experts may know. Best of luck buddy.
Canvas is basically just a bit-map image. Whatever you draw on the canvas is stored as pixels not as elements. So changes to the canvas are just changes in pixel values. To do what you wish you would need to store your 'elements' as 'objects' within your code where each 'object' stores all the required data for your 'element'.
it would then be possible to open a new window and export code into it using document.writeln
The code below may give you an idea of what sort of thing would be needed
newwindow=window.open('','_blank');
newwindow.document.writeln('<!DOCTYPE HTML>');
newwindow.document.writeln('<html>');
newwindow.document.writeln('<head>');
newwindow.document.writeln('<style>');
newwindow.document.writeln('#element0 {');
newwindow.document.writeln('background:'+ obj0.background+';');
newwindow.document.writeln('width:'+ obj0.width+';');
newwindow.document.writeln ('}');
newwindow.document.writeln('</style>');
newwindow.document.writeln('</head>');
newwindow.document.writeln('<body>');
newwindow.document.writeln('<div id="element0"></div>');
newwindow.document.writeln('</body>');
newwindow.document.writeln('</html>');
newwindow.document.writeln('<html>');
newwindow.document.close();
Hope this helps
Canvas won't help you here for anything other than to visualize the objects you have dropped onto it.
You need to record the objects you drop in a "shadow" structure behind the scene sort of. That is to say: build a object list internally which you then can use as source data to render:
Canvas visualization of it
Raw HTML code from it.
You can for example drop an image to the canvas and your code will record a new object (intention with the following code is to show the principle not to provide a full working solution):
var myObjects = [];
/// a drop occurred
var o = new myElement(x, y, width, height, id, type);
myElement is a pre-defined object that you set up in advance to hold the given arguments.
Then push the object to your object stack and render it to canvas:
myObjects.push(o);
for(var i = 0, o; o = myObjects[i]; i++) {
/// draw the look of this object here to canvas
}
When you then need a HTML version of it you do the same:
for(var i = 0, o; o = myObjects[i]; i++) {
var el = '<' + o.type + ' id="' + o.id + ' .... other things here
}
This way you can produce canvas graphics, HTML, send data over a socket etc.
The key in these sort things is to keep raw base data available. In this case it would be the element type you want to drop, its position and dimension. For HTML you also have to consider things as nesting etc. but that would require a bit more code than shown here.

Javascript board game: looking for optimization

I'm working on a html/javascript game for android. It's a board game which does the following.
It has tiles of different colors and user can place one tile (chosen programatically) on the board. If we get 4 or more tiles of the same color/shape we score some points and these tiles will disappear. The tiles above the removed tiles will replace them and new tiles will be added to the empty places. The image below shows how it works (this is just an example, the real board can have different dimensions):
The Tiles are <img> elements with their ids stored in an array which I use to check for matches and replacement.
It all works pretty well but once the new tiles are added to board I need to examine the whole board to check if new matches are avalable. And I want some advice here, because examining the whole board can be really slow. Is there a way I can do this efficiently?
Here's what I thought about doing:
Given the previous example,I thought about examining only the elements in the red area, i.e. only the elements that have been moved or added. It can be effective if the tiles move vertically, as I'll only have to check the moved/added tiles and it'll give me the new matches. But in case where I remove tiles horizontally it can be problematic, because if these tiles are at the bottom i'll have to examine the whole board and i confront the same problem.
Any advice or suggestion will be appreciated.
Note: I didn't add any code because it simply consists of checking the lines and columns for a given tile and look for matches. But if needed I can provide it.
EDIT: Before anyone can object I want to inform that I just added this question to Game Development section as I didn't receive any answers here :).
EDIT: Adding my code
function initializeBoard(){
//items is an array which contains tiles/images names
for(var i=0; i < totalItems; i++)
board[i+1] = Math.floor(Math.random() * (items.length - 1)) + 1;
for(var i=0; i < totalItems; i++)
{
if( !(i % numberShapesXAxis) )
document.write("<BR>");
document.write("<img src=\"images/"+ items[board[i+1]]+ ".gif\" style = \"border:0; height:"+ itemSize+ "px; width:"+ itemSize+ "px;\" name=\"t", i+1,"\" onclick = \"replaceAndCheck(", i+1, ")\"><\/a>");
}
}
//so basically board contains image ids.
How about checking if there is a new match when you move a stone. So when stone x moves down you check if the new position of X creates a match. That way you can create a recursive kind of method.

How do i make a allocation table?

I have build a grid of div's as playground for some visual experiments. In order to use that grid, i need to know the x and y coordinates of each div. That's why i want to create a table with the X and Y position of each div.
X:0 & Y:0 = div:eq(0), X:0 Y:1 = div:eq(1), X:0 Y:2 = div:eq(2), X:0 Y:3 = div:eq(3), X:1 Y:0 = div:eq(4) etc..
What is the best way to do a table like that? Creating a OBJECT like this:
{
00: 0,
01: 1,
02: 2,
etc..
}
or is it better to create a array?
position[0][0] = 0
the thing is i need to use the table in multiple way's.. for example the user clicked the div nb: 13 what are the coordinates of this div or what is the eq of the div x: 12 y: 5.
Thats how i do it right now:
var row = 0
var col = 0
var eq = 0
c.find('div').each(function(i){ // c = $('div#stage')
if (i !=0 && $(this).offset().top != $(this).prev().offset().top){
row++
col = 0
}
$(this).attr({'row': row, 'col': col })
col++
})
I think it would be faster to build a table with the coordinates, instead of adding them as attr or data to the DOM. but i cant figure out how to do this technically.
How would you solve this problem width JS / jQuery?
A few questions:
Will the grid stay the same size or will it grow / shrink?
Will the divs stay in the same position or will they move around?
Will the divs be reused or will they be dynamically added / removed?
If everything is static (fixed grid size, fixed div positions, no dynamic divs), I suggest building two indices to map divs to coordinates and coordinates to divs, something like (give each div an id according to its position, e.g. "x0y0", "x0y1"):
var gridwidth = 20, gridheight = 10,
cells = [], // coordinates -> div
pos = {}, // div -> coordinates
id, i, j; // temp variables
for (i = 0; i < gridwidth; i++) {
cells[i] = [];
for (j = 0; j < gridheight; j++) {
id = 'x' + i + 'y' + j;
cells[i][j] = $('#' + id);
pos[id] = { x: i, y: j };
}
}
Given a set of coordinates (x, y) you can get the corresponding div with:
cells[x][y] // jQuery object of the div at (x, y)
and given a div you can get its coordinates with:
pos[div.attr('id')] // an object with x and y properties
Unless you have very stringent performance requirements, simply using the "row" and "col" attributes will work just fine (although setting them through .data() will be faster). To find the div with the right row/col, just do a c.find("div[row=5][col=12]"). You don't really need the lookup.
Let me elaborate on that a little bit.
If you were to build a lookup table that would allow you to get the row/col for a given div node, you would have to specify that node somehow. Using direct node references is a very bad practice that usually leads to memory leaks, so you'd have to use a node Id or some attribute as a key. That is basically what jQuery.data() does - it uses a custom attribute on the DOM node as a key into its internal lookup table. No sense in copying that code really. If you go the jQuery.data() route, you can use one of the plugins that allows you to use that data as part of the selector query. One example I found is http://plugins.jquery.com/project/dataSelector.
Now that I know what it's for...
It might not seem efficient at first, but I think It would be the best to do something like this:
Generate the divs once (server side), give them ids like this: id="X_Y" (X and Y are obviously numbers), give them positions with CSS and never ever move them. (changing position takes a lot of time compared to eg. background change, and You would have to remake the array I describe below)
on dom ready just create a 2D array and store jquery objests pointing the divs there so that
gridfields[0][12] is a jQuery object like $('#0_12'). You make the array once and never use selectors any more, so it's fast. Moreover - select all those divs in a container and do .each() on them and put them to proper array fields splitting their id attributes.
To move elements You just swap their css attributes (or classes if You can - it's faster) or simply set them if You have data that has the information.
Another superfast thing (had that put to practice in my project some time ago) is that You just bind click event to the main container and check coordinates by spliting $(e.target).attr('id')
If You bind click to a grid 100x100 - a browser will probably die. Been there, did that ;)
It may not be intuitive (not changing the div's position, but swapping contents etc.), but from my experience it's the fastest it can get. (most stuff is done on dom ready)
Hope You use it ;) Good luck.
I'm not 100% sure that I understand what you want, but I'd suggest to avoid using a library such as jQuery if you are concerned about performance. While jQuery has become faster recently, it still does has more overhead than "pure" JS/DOM operations.
Secondly - depending on which browsers you want to support - it may even be better to consider using a canvas or SVG scripting.

Categories

Resources