Finding most common color of an image - javascript

I have a bunch of products on a page that have 200x200 images. My first run at this was to get the data for each pixel (nested for loop, one for x, one for y), then convert rgb to hex, and store them in an array and then get the most frequent one. This script needs to run on 96 items per page at a time.
Currently, it creates a canvas and puts the product image in that canvas and then performs the above operations.
Is there some kind of averaging algorithm that would make this faster?

Yes!
Lokesh Dhakar has created a script called "color thief" that calculates the dominant color of an image. It uses the modified median cut quantization algorithm (MCCQ) to quickly cluster colors and determine the dominant color (or even the whole color palette).
There is a demo here: http://lokeshdhakar.com/projects/color-thief/ and the script is available on github here: https://github.com/lokesh/color-thief

I know it sounds easy to use library and all, but i found a much simpler solution that pretty much serves the purpose.
When you apply a blur filter what it does is takes the average of pixel intensities. So if you apply a blur to the image with pretty high pixel value like
filter:blur(30px);
or
filter:blur(50px);
or anything that suits, it average outs the entire image and provides you with a solid background color which is most of time the prominent color from the image.
Its much simpler to do, and should work almost always. Just try tinkering with the blur amount.
Also remember to set overflow-y to be hidden because high blur causes white padding outside the image. hiding the overflow will fix that.
Hope that helps :)

Related

How to improve OpenCV background drop from two images

I am using OpenCV with NodeJS (opencv4nodejs) and am attempting to replace background from webcam pics (one with and one without head in the frame).
My code works but the quality of the mask is useless presumably because I need to apply better filters but I am not sure what.
Here's my simple code
const bgSubtractor = new cv.BackgroundSubtractorMOG2()
const back = cv.imread('/app/src/services/back.jpg').bgrToGray()
const face = cv.imread('/app/src/services/face.jpg').bgrToGray()
bgSubtractor.apply(back)
return bgSubtractor.apply(face)
I've gray scaled them but that's about it. I'm not attaching particular images as I want to see if I can make a generic model but the intention is to replace the background from someone taking a headshot with their cam then asked to drop out for the background (which could vary) shot. I am not sure it's possible to obtain a decent quality with just two images though.
Perhaps a different would be better? I assume that if I could properly align the images to account for minor shifts between stills and subtract but perhaps that's what the cv.BackgroundSubtractorMOG2 does? I've worked from a few examples that use movies but the results didn't pan out well.
As #rayryeng pointed out, MOG2 Bg Subtractor needs to be trained with several background samples in order to be able to understand what a background actually is.
Try in this way:
take several background images (pretty obvious :) )
feed with them the MOG object with a
learning rate > 0
apply trained MOG to your frame with learning rate
= 0 to retrieve foreground objects
Very useful link that explains everything

Is there a way to change tint of selected pixels in a Sprite?

Hello dear StackOverflow's community!
This is my very first question on the site, so I hope I'll be clear enough. Also, I am a French guy and I apologize in advance for the language mistakes!
Let me explain my situation (I like to be precise so it will be a bit long) :
I am currently doing an internship in my University. Here's the topic : my teacher made a 2D serious game based on image processing, where each player (4 maximum) must replace the right colors on each part of an animal. She used the XNA framework of Visual Studio to do it.
My task is to develop a new version of this game using Javascript technologies, particularly Pixi.js.
The game works like this : the main Container of the application is separated in 4 areas, one per player ; each of these areas sets its background using a Sprite that I create from the grey-scaled image of the animal the player chosed. At the center of the screen is a color palette represented by an array of Sprites. From this I can drag n' drop a color to the animal Sprite, and the region that represents a part of its body detects the drop. Everything works fine until here, but this is the point where I encounter difficulties.
I would like to change the tint of only the pixels corresponding to this region. The positions of these pixels are registered in an array I create from a text file, that's how I can detect which region receives the color.
I already tried to use a Graphics object from Pixi to redraw the color above the Sprite, but it is extremely slow. I also tried to use Filter, but since I want to color only some pixels and not the entire Sprite, I need to pass (using uniforms) the array of positions to my WebGL shader to make it verify for each pixel if it is part of the ones I want to change. But the shader needs me to declare this array indicating its size. I cannot do that because every region has a different number of pixels.
I am blocked now, and I don't know how to perform what I want...
Is there any solution that does not imply separating my image in several Sprites? I think it would work but if there can be another way, allowing me to avoid this, I would be very thankful!
Thanks in advance, and sorry that this message is so long!

Pixel-by-pixel animation with javascript

I'm animating a sprite on a pixel grid. I have a few options, with pros and cons for each. I have a fair amount of javascript experience (six years), but none with this kind of thing. The problem is I don't know how expensive each option will be.
The sprite needs to render quite fast, and be inexpensive enough to have at least five running at the same time while running collision detection.
Ideally, I would like to use a grid of elements inside of a wrapper, rendering colour and alpha channels to each element from a multidimensional array.
The major pro here is that I can run pixel-by-pixel collision detection and click past the transparent parts of the sprite. With any image-based sprite, the onClick event will fire even if I click on a transparent pixel (I'll have to do a lot of work to pass clicks through transparent pixels, and it might be quite expensive).
The next option is to use css sprites. css-tricks.com/css-sprites/
This would be easy peasy, but as mentioned previously, onClicks won't pass through the transparent pixels. I can probably force it, but again, it may be expensive, and take a lot of time to impliment.
Another option is animated gifs, but they are huge, limited in the colour department, and hard to control animation-wise. I'd rather not go there.
And then there's the html5 canvas element, which I don't know very much about and would like to stay away from if at all possible. I don't know how any of my code would even work in relation to the canvas element and I doubt it would do what I want in the long-run.
So which is the best for performance? Would the first (and most preferable) be a viable option? Or have I missed something out?
With today's browsers you will be fine on desktop computers for building a sprite out of positioned pixel sub-elements (as long as they aren't too complicated or large), and just to be safe I'd limit yourself to about 10 active sprites. With Mobile things might get a bit slow and clunky, but considering you seem to be designing a game that requires precision "onclicks" I doubt that this will be a problem.
Your most flexible bet is to use HTML5 Canvas, as you have already worked out, but it will involve quite a bit more JavaScript coding. But this sytem will allow you to apply a number of effects to your sprites and will allow you to use pixel perfect detection by using getImageData (which allows you to read the exact pixel colour at any pixel offset).
getPixel from HTML Canvas?
If you wanted to avoid the techinical problems and challenges of having a full screen canvas system (which can be tricky), you can actually create as many smaller Canvas elements and move them around as your sprites (with the ease of HTML Elements).. Then all you have to do is design the code that draws your animation frames, and also tells if the mouse has hit or not hit the sprite using the aforementioned method (along with a click handler and some code to calculate where the user has clicked relative to your canvas elements position). Obviously, it would be best to do this in a generalised way so your code can be applied to all your sprites :)
To draw your images on the canvas you can use a spritesheet as you were mentioning in your question, and use the rather flexible drawImage() method which supports a slicing mode. This just needs to be tied up to a setInterval or requestAnimationFrame style game loop.
https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Using_images
http://www.playmycode.com/blog/2011/08/building-a-game-mainloop-in-javascript/
UPDATE - for those who wish to be very optimal
If you wish to take a more optimal route - which is a little bit more involved again - you can do the following. This method benefits if you have many sprites that are exactly the same with only a few (20 or 30) frames of animation:
Power your sprites by normal DIVs with a background image sprite sheet that you shift the background position of. This is the most optimal you can be, save having static images as sprites, because the browser does all the work.
for each sprite type draw your spritesheet on a hidden canvas element that is big enough to incorporate your whole spritesheet.
When a user clicks on one of your DIV sprites, take the background position as coordinates, invert them, and you should then know where on your canvas element (looked up by sprite's type) the pixel data resides.
Use the getPixelData method on your hidden canvas to work out if the user has clicked on the sprite or not.
The above means you only have one canvas element in use - per sprite type, the browser handles all the graphics for you and you get pixel perfect collisions with an onclick.
Hope the above makes sense?
How about splitting your image spirit into 30x30 cells and only have elements where the cell is opaque and leave a gap where the cell is transparent so that clicks fall through. You lose a bit of accuracy in where the cells can be clicked though.

Remove background color from image in HTML5 Canvas

I'm trying to strip the background out of a photo image loaded into a HTML5 Canvas. Think of something like a green screen effect.
I'm using HTML/JS/jQuery
The background of the photo will be, for example, a green curtain. The color wont be exact across the curtain because of lighting and such like.
What i'm doing right now is grabbing the RGB value of a pixel that the user clicks on within the Canvas. That's then considered to be the background. I add the R+G+B of that pixel to set what is considered as the background.
I'm then going through the canvas, pixel by pixel, checking if the pixel is close to the RGB value set as the background (say within 50 above or below). If it matches, I change the pixel to be transparent within the canvas.
This works well enough as a proof of concept but not well enough to do anything with.
Does anyone have any better ideas on background subtraction?
Cheers!
Have a look at the GrabCut algorithm or GrowCut algorithm; the former describing 'Foreground Extraction using Iterated Graph Cuts' and the latter, 'Image Segmentation By Cellular Automata'. Both those papers will give you a deeper insight into some of the older algorithms used to remove background image data. If you could somehow implement one of those algorithms in Javascript then I think you're most of the way there.
The OPENcv computer vision library (written in c/c++) has plenty of efficient image manipulation methods to examine. You could try and port one of the OPENcv library's BackgroundSubtractor methods (which I believe is partly based on Chris Stauļ¬€er and W.E.L Grimson's algorithm) to Javascript and then use that to analyse the background and therefore subtract it, but I think they are based on progressive video frames rather than static images.
The js-aruco project on Google code has ported some of the functionality of the OPENcv library already (codebase is here) so you might want to look there first for some inspiration and then, if you're feeling brave, have a look at how you could program the GrabCut or GrowCut algorithms

Dynamically pixelate an html image element

I'm to take an image on a webpage, and then use javascript (or whatever would be best suited) to dynamically 'pixelate' it (e.g. into 20px squares). Then, as the user scrolls down the page, I need the image to gradually increase in resolution, till it is no longer pixelated.
Any ideas how I could go about doing this? I realise I could use php to resize an image and several times and just switch out the image, but that would require loading several extra images. Also, I know I could probably do the effect with flash & pixelbender, but I want to achieve it within the limitations of HTML5, CSS & Javascript if possible.
Appreciate any thoughts!
Update: Something like this, but with Javascript instead of Flash? http://www.reflektions.com/miniml/template_permalink.asp?id=390
You could render the picture in a hidden <canvas> element. Then use a derivation of the technique described here http://dev.opera.com/articles/view/html-5-canvas-the-basics/#pixelbasedmanipulation . To create a pixelated version of the image in a second <canvas> element using ever decreasing fillRect's. This way you even buffer the orginal image data.
edit: I would use 2 <canvas> elements so that you only have to fetch and draw the original image once. Perhaps you could buffer/cache this image in the same <canvas> element but by drawing it outside of the view port i am not sure if this is possible though.
I would use a calculation where you get the width in pixels divided by the square width and then the height divided by the square height. This would give you the lower resolution your looking for.
Then you can find a way to change the resolution to the result or grab the color of every pixel at position (height and width)/2 of the square your looking for. Then generate them into div tags or table with the appropriate color and size eventually resulting in the image its self.
I have a probably faster idea where you can have multiple versions of the image and change their z-index or their visibility as you scroll. Basically each image would have the different resolutions. If you have to do that to many images then this solution wont be as efficient as there would be lots of image editing but you can always do a batch edit.
Let me see If I can think of more ideas then I will edit.
Have a look at http://close-pixelate.desandro.com/
Explanation here: https://stackoverflow.com/a/8372981/22470
Not in a portable way.
That might be doable in Flash. Firefox JS extensions allow it to read images as JS arrays, Base64 strings etc. You might experiment with "1 DIV=1 pixel" hack, but it's hard to get any reasonable size of the image at any reasonable speed. If you feel really hyper, you could try creating base64-encoded images on the fly using the data: URI... many ways but none good...

Categories