Create a grid on top of an image - node.js

I hope you are all well and safe.
In NodeJS, I wanted to create a grid on top of an image. Like this:
Image without grid
Image with grid
Can someone tell me, please, how can I achieve this (some library or something)?
After creating the grid, I would like to go square by square and check the information for each square. Does anyone have any ideas?
Thank you very much for your time!

The first answer has a native Cairo dependency... Below I used pureimage instead, which has Pure JS implementations of jpeg and png encoding.
static drawParallel = (canvas, step, isYAxis) => {
const c2d = canvas.getContext('2d')
const numberOfSteps = (canvas.width / step) | 0
const end = isYAxis ? canvas.height : canvas.width
console.log(`Steps: ${numberOfSteps}\n`)
c2d.lineWidth = 1.1 // PureImage hides thin lines
c2d.strokeStyle = 'rgba(255,192,203,0.69)'
for (let i = 1; i < numberOfSteps; i++) {
const from = i * step
const to = i * step
const mx = isYAxis ? [from, 0, to, end] : [0, from, end, to]
console.log(`Stroking ${mx[0]}, ${mx[1]} to ${mx[2]}, ${mx[3]}`)
c2d.beginPath()
c2d.moveTo(mx[0], mx[1])
c2d.lineTo(mx[2], mx[3])
c2d.stroke()
}
}
source: https://stackblitz.com/edit/feathersjs-7kqlyt

I would use Canvas. You can use it for all sorts of image jobs and editing. For example, you could get a transparent PNG image of the grid and lay it on:
const Canvas = require("canvas");
const canvas = Canvas.createCanvas(619, 319);
const ctx = canvas.getContext("2d");
let img = await Canvas.loadImage("./path/to/image.png");
ctx.drawImage(img, 0, 0, img.width, img.height);
let grid = await Canvas.loadImage("./path/to/grid.png");
ctx.drawImage(grid, 0, 0, canvas.width, canvas.height);
console.log(canvas.toDataURL());
I myself managed to get something like this.

Related

NodeJS image processing: how to merge two images with a polygon mask?

I am trying to do something the same as this Merge images by mask, but in NodeJS Sharp library instead of Python.
I have two images and a polygon, I want the result to be the merged image where all the pixels inside polygon from image1 otherwise image2, more specifically, how to apply the 'mergeImageWithPolygonMask' function below:
const sharp = require('sharp')
let image1 = sharp('image1.jpg')
let image2 = sharp('image2.jpg')
let polygon = [[0,0], [0, 100], [100, 100], [100, 0]]
let newImage = mergeImagesWithPolygonMask(image1, image2, polygon) // how to do this?
newImage.toFile('out.jpg')
After playing with Sharp library for a while, I come up with a solution, which I think will help other people also as this is a quite common use case.
async function mergeImagesWithPolygonMask(image1, image2, polygonMask, config) {
// merge two images with the polygon mask, where within the polygon we have pixel from image1, outside the polygon with pixels from image2
const { height, width } = config;
// console.log("height", height, "width", width);
const mask = Buffer.from(
`<svg height="${height}" width="${width}"><path d="M${polygonMask.join(
"L"
)}Z" fill-opacity="1"/></svg>`
);
const maskImage = await sharp(mask, { density: 72 }).png().toBuffer();
const frontImage = await image2.toBuffer();
const upperLayer = await sharp(frontImage)
.composite([{ input: maskImage, blend: "dest-in", gravity: "northwest" }])
// Set the output format and write to a file
.png()
.toBuffer();
return image1.composite([{ input: upperLayer, gravity: "northwest" }]);
}
This function will first create an svg image and use sharp composite method to create the polygon mask on the front image. And then composite this masked front image to the background image. The size passed in in config specify the size of the svg image.
to use this function:
const sharp = require('sharp')
const image1 = sharp('image1')
const image2 = sharp('image2')
polygon = [[682, 457], [743, 437], [748, 471], [689, 477]]
mergeImagesWithPolygonMask(image1, image2, polygon, {height: 720, width:1280})

PIXI.js how to stop PIXI.Graphics being blurry?

I have a PIXI.Graphics object where I add 9 times a 16x16 texture, then I upscale, but the result is very blurry.
Code :
const graphics: PIXI.Graphics = new PIXI.Graphics();
const slotTexture: PIXI.Texture = game.textureManager.getTexture('hotBarSlot');
graphics.beginTextureFill({
texture: slotTexture,
});
graphics.drawRect(0, 0, width * 16, height * 16);
graphics.endFill();
graphics.scale.set(6, 6);
There is the result I get :
This is my texture (it's really small) :
How can I fix this problem ?
Okay, I figure it out!
I have to add this line :
slotTexture.texture.baseTexture.scaleMode = PIXI.SCALE_MODES.NEAREST;

Tweening Colors on Spark AR via Script

what would be the equivalent of a transition Patch in Reactive script? I would like to tween a color from say 0,0,0,1 to 1,1,1,1 in RGBA. I know ho to animate a single value as alpha, like this:
const timeDriver = Animation.timeDriver(timeDriverParameters);
const alphaSampler = Animation.samplers.linear(1, 0);
const alphaAnimation = Animation.animate(timeDriver, alphaSampler);
mymaterial.opacity = alphaAnimation;
Using visual patches you can use a Transform Patch to link a Vector3 to an animation progress. I cannot find something like this anywhere in the docs for reactive script. anyone can tell me?
Thank you!
you need to look at ShaderModule. Find the material by name, and then you can use setTexture.
const R = require('Reactive');
const A = require('Animation');
const S = require('Shaders');
const Materials = require('Materials');
const material = Materials.get('matName');
const driver = A.timeDriver({ durationMilliseconds : 1000});
const sampler = A.samplers.linear(
[1, 1, 1, 1],
[0, 0, 0, 1]
);
const colorAnimation = A.animate(
driver,
sampler
);
material.setTexture(
R.pack4(
colorAnimation.get(0),
colorAnimation.get(1),
colorAnimation.get(2),
colorAnimation.get(3)
),
{textureSlotName: S.DefaultMaterialTextures.DIFFUSE}
);
Here i've used ArrayOfScalarSamplers, but it's not crucial.

What to use as inputs in OpenCV calibrateCamera cameraMatrix and distCoeffs parameters?

I'm trying to get calibrateCamera working on my Node.js backend. The library is working fine, but I'm having trouble with the OpenCV functions not giving any error messages if I have faulty inputs. I'm kind of flying in the dark.
But that's beside the point. I've taken 17 images of the chessboard calibration pattern, and got the code to detect the pattern in all of the images. Everything works just fine until I call cv.calibrateCamera(), probably due to me not knowing what I should use as the required inputs for cameraMatrix and distCoeff (4th and 5th input parameters). However, I can't be 100% this is the issue because of not receiving any error messages from errors in the cv... functions.
I tried to follow the example at https://docs.opencv.org/3.1.0/dc/dbb/tutorial_py_calibration.html , but on python in the tutorial you can use None as inputs to cameraMatrix and distCoeff. I tried to use null, but that didn't work either.
Any help would be appreciated.
const size = new cv.Size(9,6);
let mat = null;
let objpt = [];
for(let i=0;i<9;i++) {
for(let j=0;j<6;j++) {
objpt.push(cv.Point(2.5*i,2.5*j,0))
}
}
let objectPoints = [];
let imagePoints =[];
for (let i=0; i < 17;i++) {
mat = cv.imread('./calib/calib'+(i+1)+'.jpg');
let smallmat = mat.resize(756,1008);
const corners = smallmat.findChessboardCorners(size);
if (corners.returnValue) {
objectPoints = objectPoints.concat(objpt);
imagePoints = imagePoints.concat(corners.corners);
}
}
// THIS IS WHERE EXECUTION JUST STOPS WITH NO ERROR MESSAGE
cv.calibrateCamera(
objectPoints,
imagePoints,
new cv.Size(756,1008),
new cv.Mat(3, 3, cv.CV_32FC1,0),
[0,0,0,0,0]
);
According to the test parameters should be passed like this:
[_objectPoints, _objectPoints],
[imagePoints, imagePoints],
imageSize,
_cameraMatrix,
distCoefficients
where
const _cameraMatrix = new cv.Mat([
[800, 0, 100],
[0, 800, 100],
[0, 0, 1]
], cv.CV_64F);
and
const distCoefficients = [0, 0.5, 1.0, 1.0];

How and when to use PIXI.RenderTexture

I am building a tool which visualises bicycle wheels. It uses approximately 100 PIXI.Graphics to build the entire wheel, which is all placed in a PIXI.Container and then rendered. It seems like quite a lot to render every frame, so I was looking into the PIXI.RenderTexture class and thought it might make sense to use it in this case. So question 1, is this a good use case? and question 2, how can I use it because I am having trouble working it out.
const options = {
transparent: true,
antialias: true,
backgroundColor: 0xffffff,
resolution: window.devicePixelRatio,
view: canvasEle,
};
const app = new PIXI.Application(width, height, options);
const wrapper = new PIXI.Container(); // Wrapper is used for zooming and panning the wheel
app.stage.addChild(wrapper);
const wheel = new Wheel(wheelOpts); // Returns PIXI.Container full of PIXI.Graphics
wrapper.addChild(wheel);
And my attempt to use the renderTexture is as follows. But I can't seem to work it out
const options = {
transparent: true,
antialias: true,
backgroundColor: 0xffffff,
resolution: window.devicePixelRatio,
view: canvasEle,
};
const app = new PIXI.Application(width, height, options);
const wrapper = new PIXI.Container(); // Wrapper is used for zooming and panning the wheel
app.stage.addChild(wrapper);
const wheelRenderTexture = new PIXI.RenderTexture.create(width, height);
const wheelSprite = new PIXI.Sprite(wheelRenderTexture)
wrapper.addChild(wheelSprite)
const wheel = new Wheel(wheelOpts); // Returns PIXI.Container full of PIXI.Graphics
app.ticker.add(() =>
{
app.renderer.render(wheel, wheelRenderTexture);
})
Thanks for any help
I worked out how to use it and made a small jsfiddle https://jsfiddle.net/hp98ygz5/1/
const width = 600
const height = 600
var app = new PIXI.Application(width, height, {backgroundColor : 0xffffff});
document.body.appendChild(app.view);
const wheelRenderTexture = PIXI.RenderTexture.create(width, height);
const wheelRenderSprite = new PIXI.Sprite(wheelRenderTexture);
app.stage.addChild(wheelRenderSprite)
const wheelContainer = new PIXI.Container()
//app.stage.addChild(wheelContainer)
wheelContainer.addChild(drawCircle(100,100,50,0xfec3dc,2,0Xfe68a4))
wheelContainer.addChild(drawCircle(100,100,20,0xFFCC66,2,0X55ff77))
app.renderer.render(wheelContainer,wheelRenderTexture)
I am not sure what was wrong with the above example but it works now

Resources