jimp-dev / jimp

An image processing library written entirely in JavaScript for Node, with zero external or native dependencies.
http://jimp-dev.github.io/jimp/
MIT License
14k stars 759 forks source link

how can i remove a color use jimp #395

Closed yhc-yhc closed 6 years ago

yhc-yhc commented 6 years ago

I want remove blue color in a image, can jimp do this ?

steffkelsey commented 6 years ago

"Remove blue color from an image" can mean a couple of things. But you can do color manipulations per channel. The example below would mess with just the blue channel.

image.color([
    { apply: 'blue', params: [ <amount> ] }
]);

Where <amount> is a value between 0 and 255.

I am not sure if you will get the desired effect from that. But, you have other actions to mess with using the same image.color call. eg: hue or spin, tint, mix, xor. There's some more details in the README and some examples in test/color.test.js

yhc-yhc commented 6 years ago
blue

@steffkelsey like this picture, how can i conversion the blue pixel to transparent, i test the code image.color([*]) can not work well.

yhc-yhc commented 6 years ago

@theill @aurium @natecavanaugh @katzj can you help me?

czycha commented 6 years ago

I think the best way to accomplish this is to calculate the distance between the color you want to replace and the color of each pixel in the image, and, if that distance is smaller than a threshold, replace the color.

import Jimp from 'jimp';

Jimp.read('./green.png').then(image => {
  const targetColor = {r: 60, g: 171, b: 118, a: 255};  // Color you want to replace
  const replaceColor = {r: 0, g: 0, b: 0, a: 0};  // Color you want to replace with
  const colorDistance = (c1, c2) => Math.sqrt(Math.pow(c1.r - c2.r, 2) + Math.pow(c1.g - c2.g, 2) + Math.pow(c1.b - c2.b, 2) + Math.pow(c1.a - c2.a, 2));  // Distance between two colors
  const threshold = 32;  // Replace colors under this threshold. The smaller the number, the more specific it is.
  image.scan(0, 0, image.bitmap.width, image.bitmap.height, (x, y, idx) => {
    const thisColor = {
      r: image.bitmap.data[idx + 0],
      g: image.bitmap.data[idx + 1],
      b: image.bitmap.data[idx + 2],
      a: image.bitmap.data[idx + 3]
    };
    if(colorDistance(targetColor, thisColor) <= threshold) {
      image.bitmap.data[idx + 0] = replaceColor.r;
      image.bitmap.data[idx + 1] = replaceColor.g;
      image.bitmap.data[idx + 2] = replaceColor.b;
      image.bitmap.data[idx + 3] = replaceColor.a;
    }
  });
  image.write('transparent.png');
});

Image output: transparent

yhc-yhc commented 6 years ago

@czycha thank you, but if i has many of this picture, the value of threshold must be changed to adapt each picture, so is any good ideas?

czycha commented 6 years ago

Unless you do some machine learning (which I haven't seen with Jimp), there's not much you can do about it. You can test manually on a bunch of sample inputs to try and find an optimal threshold.

steffkelsey commented 6 years ago

I didn't realize you were trying to do background removal. It's just a completely different algorithm. You can find some examples if you look up Primatte Chromakey Algorithm. Also you can ness around with other algorithms using OpenCv and look for blue / green screen examples. I think you're not going to be satisfied with anything from Jump.

If you MUST do this in browser, I would recommend checking out WASM wrappers of OpenCV. Then you can run at closer to native speed and have all the algorithms you need abstracted for you. JIT JavaScript is just going to be too slow for this kind of thing right now. You need real threading

yhc-yhc commented 6 years ago

@czycha thank you, @steffkelsey yes , i do it at backend use Jimp with nodejs. I have another way that is use openCV to resolve this problem, but it may be must use machine learning yet, because in openCV the params also need changed to work well, thank you.

hipstersmoothie commented 6 years ago

machine learning is just a bit out of scope for jimp ;) closing, but feel free to add ML to jimp if you ever get that working

turakvlad commented 6 years ago

Guys, I've created a small package for replacing color with another one pixel by pixel. I'll allow myself to share it with you. The package is called replace-color and it implements one of the best color difference algorithm - CIEDE2000.

Image output: output

master-of-null commented 5 years ago

@turakvlad did you build that to only change one hex code color? Or a range of colors?

turakvlad commented 5 years ago

@master-of-null, hey.

It works for one color only right now, but you can run a few iterations to change a range of colors.