gpt4 book ai didi

javascript - 在图像中查找相似颜色的区域

转载 作者:IT老高 更新时间:2023-10-28 23:11:08 26 4
gpt4 key购买 nike

我研究这个问题已经有一段时间了,但几乎没有什么可喜的结果。我正在尝试将图像拆分为相似颜色的连接区域。 (基本上将所有像素的列表分成多个组(每个组包含属于它的像素的坐标并共享相似的颜色)。

例如: http://unsplash.com/photos/SoC1ex6sI4w/

在这张图片中,顶部的乌云可能会归为一组。一些山上的灰色岩石在另一个,一些橙色的草在另一个。雪将是另一种 - 背包的红色 - 等等。

我正在尝试设计一种既准确又高效的算法(它需要在中端笔记本电脑级硬件上以毫秒为单位运行)


以下是我尝试过的:

使用基于连接组件的算法从左上角遍历每个像素,从左到右扫描每一行像素(并将当前像素与顶部像素和左侧像素进行比较)。使用 CIEDE2000 色差公式,如果顶部或左侧的像素在一定范围内,则将其视为“相似”且属于该组。

这种工作 - 但问题是它依赖于具有锐利边缘的颜色区域 - 如果任何颜色组通过软渐变连接,它将沿着该渐变移动并继续“连接”像素作为被比较的单个像素足够小,可以被认为是“相似的”。

为了解决这个问题,我选择将每个访问像素的颜色设置为最“相似”的相邻像素(顶部或左侧)的颜色。如果没有相似的像素,则保留其原始颜色。这在一定程度上解决了边界更模糊或边缘更柔和的问题,因为随着算法的进展,新组的第一种颜色将被“携带”,最终该颜色与当前比较颜色之间的差异将超过“相似性”阈值,并且不再是该组的一部分。

希望这是有道理的。问题是这些选项都没有真正起作用。在上图中,返回的不是干净的组,而是嘈杂的碎片组,这不是我想要的。

我不是专门寻找代码 - 而是更多关于如何构建算法以成功解决此问题的想法。有人对此有想法吗?

谢谢!

最佳答案

您可以将 RGB 转换为 HSL,以便更轻松地计算颜色之间的距离。我在行中设置色差容差:

if (color_distance(original_pixels[i], group_headers[j]) < 0.3) {...}

如果你改变0.3,你会得到不同的结果。

See it working .

如果有帮助,请告诉我。

function hsl_to_rgb(h, s, l) {
// from http://stackoverflow.com/questions/2353211/hsl-to-rgb-color-conversion
var r, g, b;

if (s == 0) {
r = g = b = l; // achromatic
} else {
var hue2rgb = function hue2rgb(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)];
}

function rgb_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) {
case r:
h = (g - b) / d + (g < b ? 6 : 0);
break;
case g:
h = (b - r) / d + 2;
break;
case b:
h = (r - g) / d + 4;
break;
}
h /= 6;
}

return [h, s, l];
}

function color_distance(v1, v2) {
// from http://stackoverflow.com/a/13587077/1204332
var i,
d = 0;

for (i = 0; i < v1.length; i++) {
d += (v1[i] - v2[i]) * (v1[i] - v2[i]);
}
return Math.sqrt(d);
};

function round_to_groups(group_nr, x) {
var divisor = 255 / group_nr;
return Math.ceil(x / divisor) * divisor;
};

function pixel_data_to_key(pixel_data) {
return pixel_data[0].toString() + '-' + pixel_data[1].toString() + '-' + pixel_data[2].toString();

}

function posterize(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);
}


function draw(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 observed
if (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 = new Image();
target_image.crossOrigin = "";
target_image.onload = function() {
draw(target_image)
};
target_image.src = "http://i.imgur.com/zRzdADA.jpg";
canvas {
width: 300px;
height: 200px;
}
<canvas id="canvas"></canvas>

关于javascript - 在图像中查找相似颜色的区域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41072400/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com