Image registration (aligning one image to match another) - javascript

Currently I have an image that needs to be manipulated so it matches the same scale, position, and rotation as a template.
The grey rectangle with a circle in the middle is the template.
The orange rectangle and circle represents the user's input. It needs to be rotated, scaled and aligned to it matches the grey one. I'm currently stumped on how to proceed. I've no code other than the following.
function align_image()
{
// clever transform alignment code here
}
Bad dog, no biscuit!
The process at of aligning the images would normally be done manual input and judged by eye. I'm hoping to automate this step and align the image to its respective size and position but leaving the comfort and safety of Photoshop DOM I'm not sure how to proceed or even if this is a trivial matter or one left best alone. The project is web based currently using javascript and three.js
So if anyone can give me some pointers I'd appreciated it.

I don't code javascript so I can only talk about the algorithm. Generally best tool for registration is to use feature matching methods (using sift, surf,...) but your image is not the kind that have strong features. Now if you're always dealing with rectangles and circles in your images, find the "edges" of the rectangle with Hough Transform, compute the angle of those edges (lines) then rotate the image with that angle in the opposite direction.
Then with the help of Hough Circle Detector, find the center of the circles in the middle of the images, calculate the distance between them, and move the target rectangle to the source's circle position. After the movement by comparing the radius of the circles, you can resize the target image to make it like the source rectangle.
All of these are conveniently doable with Opencv.

Related

FabricJS object coordinates relative to an image instead of whole canvas

I'm trying to create a small website using the FabricJS library, which adds additional features to the web canvas element.
My issue that I, however, have is that i want to resize the canvas (in red) so that it fills the whole webpage.
On this canvas, there is a background image (in green) where I'll create some drawings on (in orange, this could be lines, squares,...).
Now, I would like to export all drawings in a coordinate system relative to the image and not to the whole canvas, because it should be possible to freely move around and zoom in/out the image for an enhanced drawing experience.
My idea, on how to solve this, would be to calculate the image position relative to the canvas and subtract them from the drawings - but that includes a lot of calculation.. Maybe there is a more genius approach with FabricJS?
Moreover, how can i guarantee that my drawings move around and zoom in/out with the image, so that my drawings are always true to the image?
I've thought about this for days and came to the realization that i need input from the professionals.
I think toLocalPoint() might help. Given an object imageObj and absolute coordinates left and top of your drawing, you can find the relative coordinates like this:
const abs = new fabric.Point(left, top)
const rel = imageObj.toLocalPoint(point, 'left', 'top')
console.log(rel.x, rel.y)
As for your second question: there is no easy way to "tie" two objects together, other than grouping them - and I assume you don't want to group them. Therefore, you would need to listen to all the appropriate events emitted by one object and make the adjustments to the other object in their handlers. To find out what events make sense to listen to in your case, see the events demo.

Detemine all elements at a given point js

I am working on an API that use shapes (and irregular) shapes to build websites. My problem is where I can provide a div that can carry as a background to irregular shapes so .
However to do this I would need to know the max area the object is taking up by having the max height and width.
I am aware that element.getBoundingClientRect does this but my roadblock is that is does not consider any psuedo elements, which is how most of these shapes are made.
I know when working with the CSS transform property, especially using scale, the browser knows to resize the whole shape including the pseudo element that makes up the shape.
It also uses the border-box coordinate system.
However the browser does not provide this information as it comes from the user agent
My main question is how do I access the dimensions the user agent computes for any given element, or how do I find the proper dimensions of a 'getBoundingClientRect' that considers an elements psuedo classes
My shapes can be found in the attached links.
httpsmichaelodumosu57.github.iosigma-xi-mu
https://css-tricks.com/examples/ShapesOfCSS/
I can't afford to use any other method to create my shapes because I have limited time on the project, but I do know that the browser can provide me with the information I am looking for.
Yes I have answered my own question. What you want to do is to scale the image to a very small since (since transform scale() works perfectly) and place it in a grid box (this could be a div of small size as well. You would run document.elementsFromPoint(x, y)
(notice the pluralization) on every point in the div containing you shrunked irregular shape and from there you can find the height and width of its bounding box by the difference of the highest range of their respective coordinate values. To center you must place your irregular shape in the bounding box of the background drop with the re-scaled dimensions (remember your skrunked your irregular shape to find them) and have the margin of the inner shape set to zero. This works only if your real (not pseudo element) is to the left most of the screen. Question is how do you position your background when your irregular shape is not properrly centering inside of it?
You can use document.elementFromPoint(x, y) for getting the element that exists in specific point, but I have not tested it for any kind of shapes.

Can I sharpen edges with fabric.js?

With fabric.js, is it possible to sharpen (drastically) the edges of objects added to the canvas?
Here's a zoomed-in picture of some small (5x5 pixels) squares I'm using, and they come out like the square on the right, but I need them to be the square on the left.
because I'm trying to take the produced image and turn the white background transparent and apply the resulting image on top of another image, and with those fuzzed borders, it comes out looking like absolute garbage once overlayed. There isn't really a good solution involving changing the transparency threshold, because it ends up no longer being a perfect square if I drop it to get rid of the gray.
After ensuring top/left are exact integers
After ctx.translate(0.50, 0.50)

Wraparound for HTML5 Canvas: How to Get (Static) Shapes to Continue around Edges of Canvas

I'm trying to draw a tiled background using Javascript on an HTML5 canvas, but it's not working because shapes that intersect the edges of the canvas don't wrap around to the other side. (Just to be clear: these are static shapes--no motion in time is involved.) How can I get objects interrupted by one side of the canvas to wrap around to the other side?
Basically I'm looking for the "wraparound" effect that many video games use--most famously Asteroids; I just want that effect for a static purpose here. This page seems to be an example that shows it is possible. Note how an asteroid, say, on the right edge of the screen (whether moving or not) continues over to the left edge. Or for that matter, an object in the corner is split between all four corners. Again, no motion is necessarily involved.
Anyone have any clues how I might be able to draw, say, a square or a line that wraps around the edges? Is there perhaps some sort of option for canvas or Javascript? My google searches using obvious keywords have come up empty.
Edit
To give a little more context, I'm basing my work off the example here: Canvas as Background Image. (Also linked from here: Use <canvas> as a CSS background.) Repeating the image is no problem. The problem is getting the truncated parts of shapes to wrap around to the other side.
I'm not sure how you have the tiles set-up, however, if they are all part of a single 'wrapper' slide which has it's own x,x at say 0,0, then you could actually just draw it twice, or generate a new slide as needed. Hopefully this code will better illustrate the concept.
// Here, the 'tilegroup' is the same size of the canvas
function renderbg() {
tiles.draw(tiles.posx, tiles.posy);
if(tiles.posx < 0)
tiles.draw(canvas.width + tiles.posx, tiles.posy);
if(tiles.posx > 0)
tiles.draw(-canvas.width + tiles.posx, tiles.posy);
}
So basically, the idea here is to draw the groupings of tiles twice. Once in it's actual position, and again to fill in the gap. You still need to calculate when the entire group leaves the canvas completely, and then reset it, but hopefully this leads you in the correct direction!
You could always create your tillable image in canvas, generate a toDataUrl(), and then assign that data url as a background to something and let CSS do the tiling.. just a thought.
Edit: If you're having trouble drawing a tillable image, you could create a 3*widthx3*width canvas, draw on it as regular (assuming you grab data from the center square of data as the final result), and then see if you can't draw from subsets of the canvas to itself. Looks like you'd have to use:
var myImageData = context.getImageData(left, top, width, height);
context.putImageData(myImageData, dx, dy);
(with appropriate measurements)
https://developer.mozilla.org/En/HTML/Canvas/Pixel_manipulation_with_canvas/
Edit II: The idea was that you'd have a canvas big enough that has a center area of interest, and buffer areas around it big enough to account for any of the shapes you may draw, like so:
XXX
XCX
XXX
You could draw the shapes once to this big canvas and then just blindly draw each of the areas X around that center area to the center area (and then clear those areas out for the next drawing). So, if K is the number of shapes instead of 4*K draws, you have K + 8 draws (and then 8 clears). Obviously the practical applicability of this depends on the number of shapes and overlapping concerns, although I bet it could be tweaked. Depending upon the complexity of your shapes it may make sense to draw a shape 4 times as you originally thought, or to draw to some buffer or buffer area and then draw it's pixel data 4 times or something. I'll admit, this is some idea that just popped into my head so I might be missing something.
Edit III: And really, you could be smart about it. If you know how a set of objects are going to overlap, you should only have to draw from the buffer once. Say you got a bunch of shapes in a row that only draw to the north overlapping region. All you should need to do is draw those shapes, and then draw the north overlapping region to the south side. The hairy regions would be the corners, but I don't think they really get hairy unless the shapes are large.... sigh.. at this point I probably need to quiet down and see if there's any existing implementations of what I speak out there because I'm not sure my writing off-the-cuff is helping anybody.

Transparency Face-Jumping?

I've been working on a WebGL project that runs on top of the Three.js library. I am rendering several semi-transparent meshes, and I notice that depending on the angle you tilt the camera, a different object is on top.
To illustrate the problem, I made a quick demo using three semi-transparent cubes. When you rotate the image past perpendicular to the screen, the second half of the smallest cube "jumps" and is no longer visible. However, shouldn't it still be visible? I tried adjusting some of the blending equations, but that didn't seem to make a difference.
What I'm wondering is whether or not this is a bug in WebGL/Three, or something I can fix. Any insight would be much appreciated :)
Well, that's something they weren't able to solve when they invented all this hardware accelerated graphics business and sounds like we'll have to deal with this for a long while.
The issue here is that graphic cards do not sort the polygons, nor objects. The graphics card is "dumb", you tell it to draw an object and it will draw the pixels that represent it and also, in another non-visible "image" called zbuffer (or depthbuffer), will draw the pixels that represent the object but instead of color it will draw the distance to the camera for each pixels. Any other objects that you draw afterwards, the graphics card will check if the distance to the camera for each pixel, and if it's farther, it won't draw it (unless you disable the check, that is).
This speeds up things a lot and gives you nice intersections between solid objects. But it doesn't play well with transparency. Say that you have 2 transparent objects and you want A to be drawn behind B. You'll need to tell the graphics card to draw A first and then B. This works fine as long as they're not intersecting. In order to draw 2 transparent objects intersecting then the graphics would have to sort all the polygons, and as the graphics card doesn't do that, then you'll have to do it.
It's one of these things that you need to understand and specifically tweak for your case.
In three.js, if you set material.transparent = true we'll sort that object so it's drawn before (earlier) other objects that are in front. But we can't really help you if you want to intersect them.

Categories