Find Regions Of Similar Color In Image
Solution 1:
You could convert from RGB
to HSL
to make it easier to calculate the distance between the colors. I'm setting the color difference tolerance in the line:
if (color_distance(original_pixels[i], group_headers[j]) < 0.3) {...}
If you change 0.3
, you can get different results.
Please, let me know if it helps.
functionhsl_to_rgb(h, s, l) {
// from http://stackoverflow.com/questions/2353211/hsl-to-rgb-color-conversionvar r, g, b;
if (s == 0) {
r = g = b = l; // achromatic
} else {
var hue2rgb = functionhue2rgb(p, q, t) {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
}
var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
var p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255)];
}
functionrgb_to_hsl(r, g, b) {
// from http://stackoverflow.com/questions/2353211/hsl-to-rgb-color-conversion
r /= 255, g /= 255, b /= 255;
var max = Math.max(r, g, b),
min = Math.min(r, g, b);
var h, s, l = (max + min) / 2;
if (max == min) {
h = s = 0; // achromatic
} else {
var d = max - min;
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
caser:
h = (g - b) / d + (g < b ? 6 : 0);
break;
caseg:
h = (b - r) / d + 2;
break;
caseb:
h = (r - g) / d + 4;
break;
}
h /= 6;
}
return [h, s, l];
}
functioncolor_distance(v1, v2) {
// from http://stackoverflow.com/a/13587077/1204332var i,
d = 0;
for (i = 0; i < v1.length; i++) {
d += (v1[i] - v2[i]) * (v1[i] - v2[i]);
}
returnMath.sqrt(d);
};
functionround_to_groups(group_nr, x) {
var divisor = 255 / group_nr;
returnMath.ceil(x / divisor) * divisor;
};
functionpixel_data_to_key(pixel_data) {
return pixel_data[0].toString() + '-' + pixel_data[1].toString() + '-' + pixel_data[2].toString();
}
functionposterize(context, image_data, palette) {
for (var i = 0; i < image_data.data.length; i += 4) {
rgb = image_data.data.slice(i, i + 3);
hsl = rgb_to_hsl(rgb[0], rgb[1], rgb[2]);
key = pixel_data_to_key(hsl);
if (key in palette) {
new_hsl = palette[key];
new_rgb = hsl_to_rgb(new_hsl[0], new_hsl[1], new_hsl[2]);
rgb = hsl_to_rgb(hsl);
image_data.data[i] = new_rgb[0];
image_data.data[i + 1] = new_rgb[1];
image_data.data[i + 2] = new_rgb[2];
}
}
context.putImageData(image_data, 0, 0);
}
functiondraw(img) {
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
context.drawImage(img, 0, 0, canvas.width, canvas.height);
img.style.display = 'none';
var image_data = context.getImageData(0, 0, canvas.width, canvas.height);
var data = image_data.data;
context.drawImage(target_image, 0, 0, canvas.width, canvas.height);
data = context.getImageData(0, 0, canvas.width, canvas.height).data;
original_pixels = [];
for (i = 0; i < data.length; i += 4) {
rgb = data.slice(i, i + 3);
hsl = rgb_to_hsl(rgb[0], rgb[1], rgb[2]);
original_pixels.push(hsl);
}
group_headers = [];
groups = {};
for (i = 0; i < original_pixels.length; i += 1) {
if (group_headers.length == 0) {
group_headers.push(original_pixels[i]);
}
group_found = false;
for (j = 0; j < group_headers.length; j += 1) {
// if a similar color was already observedif (color_distance(original_pixels[i], group_headers[j]) < 0.3) {
group_found = true;
if (!(pixel_data_to_key(original_pixels[i]) in groups)) {
groups[pixel_data_to_key(original_pixels[i])] = group_headers[j];
}
}
if (group_found) {
break;
}
}
if (!group_found) {
if (group_headers.indexOf(original_pixels[i]) == -1) {
group_headers.push(original_pixels[i]);
}
if (!(pixel_data_to_key(original_pixels[i]) in groups)) {
groups[pixel_data_to_key(original_pixels[i])] = original_pixels[i];
}
}
}
posterize(context, image_data, groups)
}
var target_image = newImage();
target_image.crossOrigin = "";
target_image.onload = function() {
draw(target_image)
};
target_image.src = "http://i.imgur.com/zRzdADA.jpg";
canvas {
width: 300px;
height: 200px;
}
<canvasid="canvas"></canvas>
Solution 2:
You can use "Mean Shift Filtering" algorithm to do the same.
You will have to determine function parameters heuristically.
And here's the wrapper for the same in node.js
npm Wrapper for meanshift algorithm
Hope this helps!
Solution 3:
The process you are trying to complete is called Image Segmentation and it's a wellstudiedarea in computer vision, with hundreds of different algorithms and implementations.
The algorithm you mentioned should work for simple images, however for real world images such as the one you linked to, you will probably need a more sophisticated algorithm, maybe even one that is domain specific (are all of your images contains a view?).
I have little experience in Node.js, however from Googling a bit I found the GraphicsMagic library, which as a segment function that might do the job (haven't verified).
In any case, I would try looking for "Image segmentation" libraries, and if possible, not limit myself only to Node.js implementations, as this language is not the common practice for writing vision applications, as opposed to C++ / Java / Python.
Solution 4:
I would try a different aproach. Check out this description of how a flood fill algorithm could work:
- Create an array to hold information about already colored coordinates.
- Create a work list array to hold coordinates that must be looked at. Put the start position in it.
- When the work list is empty, we are done.
- Remove one pair of coordinates from the work list.
- If those coordinates are already in our array of colored pixels, go back to step 3.
- Color the pixel at the current coordinates and add the coordinates to the array of colored pixels.
- Add the coordinates of each adjacent pixel whose color is the same as the starting pixel’s original color to the work list.
- Return to step 3.
The "search approach" is superior because it does not only search from left to right, but in all directions.
Solution 5:
You might look at k-means clustering. http://docs.opencv.org/3.0-beta/modules/core/doc/clustering.html
Post a Comment for "Find Regions Of Similar Color In Image"