gpt4 book ai didi

javascript - 用选定的颜色转换主色

转载 作者:行者123 更新时间:2023-11-30 15:48:12 31 4
gpt4 key购买 nike

在使用画布工作/学习了几个小时之后,我设法获得了图像的克隆,现在是像素,我已使用户从颜色规范中选择一种颜色,并且在我的函数中使用该颜色的十六进制:

move: function (color) {

// 'color' is the value user selected

var img_id = jQuery(".selected_bg_img").attr("id");

alert(img_id);

var x = 0;
var y = 0;
var width = 409;
var height = 409;


var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var img=document.getElementById(img_id);
ctx.drawImage(img,x,y,width,height);

var imageData = ctx.getImageData(0,0,width,height);

var data = imageData.data;

alert(data);

}


现在有两项任务正在进行,
 1.我们如何从数据中提取最大颜色?
 2.如何将最大颜色转换为函数中使用的颜色?
对于现场工作示例,我在最后给出了链接
注意:从产品图像的左侧选择图像(最后3张),选择颜色后,会将图像克隆到下面的画布中。
在这里,我尝试用用户选择的颜色替换最大颜色来克隆图像。
注意:我指的是最大颜色(图像中的主要颜色),例如 http://lokeshdhakar.com/projects/color-thief/这个项目正在获得图像的主要颜色,但是它在节点上,我正尝试获取主要颜色并在克隆之前更改该颜色。

for (var i=0;i<imgData.data.length;i+=4)
{
imgData.data[i]=255-imgData.data[i];
imgData.data[i+1]=255-imgData.data[i+1];
imgData.data[i+2]=255-imgData.data[i+2];
imgData.data[i+3]=255;
}


*****编辑*****
我的问题不是很复杂,我想我有这个形象
enter image description here

因此,我们可以清楚地看到主要颜色是灰色,无论如何,我只是想用功能 move中的新颜色替换该颜色,然后用新颜色绘制该图像。我从那里拍摄的图像并显示了另一个示例:
http://www.art.com/products/p14499522-sa-i3061806/pela-silverman-colorful-season-i.htm?sOrig=CAT&sOrigID=0&dimVals=729271&ui=573414C032AA44A693A641C8164EB595
在图像的左侧,当我们选择相似的图像时,它们在图像的底部中央具有选项“更改颜色”。这正是我要尝试做的。

所以现在我尝试读取图像 1x1,这就是我登录时在控制台中得到的内容(特别是我显示的图像):

[166, 158, 152, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0…]


因此,它可能是从左上角开始的第一个起点,我想需要在整个图像上进行迭代,这就是我在整个图像上进行迭代时得到的结果:

[110, 118, 124, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255…]


我用于迭代的循环是:

var imageData = ctx.getImageData(0,0,width,height);

var data = imageData.data;

for (var i=0;i<data.length;i+=4)
{
data[i]=255-data[i];
data[i+1]=255-data[i+1];
data[i+2]=255-data[i+2];
data[i+3]=255;
}
console.log(data);


这个迭代对吗?如果是的话,现在似乎是替换主色的问题,我在这里空白,我们如何替换它并用替换后的颜色写回图像,或者还有其他内容?
*************编辑***********
我现在在rgb中有用户值,需要寻找应该放置该值的地方

最佳答案

这个答案可能是您想要的,因为还不清楚。

查找图像中的主色

我使用两种方法。还有许多其他方法可以做到这一点,最好的方法取决于所需的需求和质量。我将集中精力使用直方图过滤掉无关像素以得到结果。

简单的方法。

创建一个1 x 1像素的画布。确保启用画布平滑。

ctx.imageSmoothingEnabled = true;    
ctx.mozImageSmoothingEnabled = true;


在1 x 1画布上绘制图像

ctx.drawImage(image,0,0,1,1);


获取像素数据

var data = ctx.getImageData(0,0,1,1);


而rgb值正是您所追求的。

r = data.data[0];
g = data.data[0];
b = data.data[0];


结果应用于下图。

enter image description here

很长的路要走

这种方法很长且存在问题。您需要忽略直方图中rgb的低值和高值(忽略黑白值),而对于HSL则忽略0%或100%的饱和度和值(亮度),否则对于对比度良好的图像,红色总是占主导地位。

在图像处理中,直方图是图像内图像属性(例如,红色,绿色,蓝色)的分布图。由于数字图像具有离散值,因此直方图(条形图)将沿x轴绘制该值,并在y轴上绘制具有该值的像素数。

直方图的示例。请注意,由于存在跨原点限制,因此该代码不会在此处运行。 (对不起,我的浏览器已禁用该功能)。



/** CopyImage.js begin **/
// copies an image adding the 2d context
function copyImage(img){
var image = document.createElement("canvas");
image.width = img.width;
image.height = img.height;
image.ctx = image.getContext("2d");
image.ctx.drawImage(img, 0, 0);
return image;
}
function copyImageScale(img,scale){
var image = document.createElement("canvas");
image.width = Math.floor(img.width * scale);
image.height = Math.floor(img.height * scale);
image.ctx = image.getContext("2d");
image.ctx.drawImage(img, 0, 0,image.width,image.height);
return image;
}
/** CopyImage.js end **/
function getHistogram(img){ // create a histogram of rgb and Black and White
var R,G,B,BW;
R = [];
G = [];
B = [];
BW = []; // Black and white is just a mean of RGB
for(var i=0; i < 256; i++){
R[i] = 0;
G[i] = 0;
B[i] = 0;
BW[i] = 0;
}
var max = 0; // to normalise the values need max
var maxBW = 0; // Black and White will have much higher values so normalise seperatly
var data = img.ctx.getImageData(0,0,img.width,img.height);
var d = data.data;
var r,g,b;
i = 0;
while(i < d.length){
r = d[i++]; // get pixel rgb values
g = d[i++];
b = d[i++];
i++; // skip alpha
R[r] += 1; // count each value
G[g] += 1;
B[b] += 1;
BW[Math.floor((r+g+b)/3)] += 1;
}
// get max
for(i = 0; i < 256; i++){
max = Math.max(R[i],G[i],B[i],max);
maxBW = Math.max(BW[i],maxBW);
}
// return the data
return {
red : R,
green : G,
blue : B,
gray : BW,
rgbMax : max,
grayMax : maxBW,
};
}

function plotHistogram(data,ctx,sel){
var w = ctx.canvas.width;
var h = ctx.canvas.height;
ctx.clearRect(0,0,w,h); // clear any existing data
var d = data[sel];
if(sel !== "gray"){
ctx.fillStyle = sel;
}
var rw = 1 / d.length; // normalise bar width
rw *= w; // scale to draw area;
for(var i = 0; i < d.length; i++ ){
var v = 1-(d[i]/data.rgbMax); // normalise and invert for plot
v *= h; // scale to draw area;
var x = i/d.length; // normaise x axis
x *= w; // scale to draw area
if(sel === 'gray'){
ctx.fillStyle = "rgb("+i+","+i+","+i+")";
}
ctx.fillRect(x,v,rw,h-v); // plot the bar
}
}

var canMain = document.createElement("canvas");
canMain.width = 512;
canMain.height = 512;
canMain.ctx = canMain.getContext("2d");
document.body.appendChild(canMain);
var ctx = canMain.ctx;

var can = document.createElement("canvas");
can.width = 512;
can.height = 512;
can.ctx = can.getContext("2d");

// load image and display histogram
var image = new Image();
image.src = "http://i.stack.imgur.com/tjTTJ.jpg";
image.onload = function(){
image = copyImage(this);
var hist = getHistogram(image);
// make background black
ctx.fillStyle = "black"
ctx.fillRect(0,0,ctx.canvas.width,ctx.canvas.height);

// create and show each plot
plotHistogram(hist,can.ctx,"red");
document.body.appendChild(copyImageScale(can,0.5));
ctx.drawImage(can,0,0,canvas.width,canvas.height);
plotHistogram(hist,can.ctx,"green");
document.body.appendChild(copyImageScale(can,0.5));
ctx.globalCompositeOperation = "lighter"
ctx.drawImage(can,0,0,canvas.width,canvas.height);
plotHistogram(hist,can.ctx,"blue");
document.body.appendChild(copyImageScale(can,0.5));
ctx.globalCompositeOperation = "lighter"
ctx.drawImage(can,0,0,canvas.width,canvas.height);
plotHistogram(hist,can.ctx,"gray");
document.body.appendChild(copyImageScale(can,0.5));
ctx.globalCompositeOperation = "source-over"
ctx.globalAlpha = 0.9;
ctx.drawImage(can,0,0,canvas.width,canvas.height);
ctx.globalAlpha = 1;
}





由于上述代码需要托管图像,因此结果如下所示。

图片

enter image description here

以上代码输出的RGB和灰色直方图。

enter image description here

从中您可以看到图像上的主要通道和rgb的分布(请注意,我删除了黑色,因为此图像上有很多黑色像素,从而使其余像素数减少到无关紧要的程度)

要找到主色,您可以对HSL值执行相同的操作。为此,您需要将RGB转换为HSL。 This answer具有执行此操作的功能。然后,只需计算每个HSL值并创建直方图即可。

下一个图像是上述样本图像在HSL中的直方图。

enter image description here

如您所见,有很多红色,然后是黄色,另外一个是绿色。

但这仍然无法满足您的需求。第二个直方图(饱和度)在中心显示一个清晰的峰值。有很多颜色具有很好的饱和度,但这并不能告诉您是什么颜色。

您需要将HSL值过滤到该峰值附近。

我要做的是将HSL值乘以 f(s) = 1-Math.abs(s-50)/50,即饱和度范围0-100。这将放大饱和度最大的色相和值。生成的直方图看起来像

enter image description here

现在,峰值色调(忽略红色)为橙色。色相值为〜42。然后,应用滤镜将所有不接近色相= 42的像素移除(您可能希望产生衰减)。您将此过滤器应用于在最后一步之后获得的HSL值。下图显示了将此滤镜应用于原始图像后的结果图像

enter image description here

然后得到所有剩余像素的R,G,B之和。每个RGB值的平均值是常用颜色。

这种方法的常用颜色。

enter image description here

请注意,结果与上述方法和上面的代码中应用此方法的结果不同。我使用自己的图像处理应用程序获取了说明步骤,并且它使用的真对数光子计数用于RGB值,该值往往比线性插值要暗。最后一步将经过滤波的像素图像扩展为一个过于复杂的示例步骤,此处无法对其进行描述(对开始时对简单方法的修改)。好像

enter image description here

我也将其应用于整个图像,这对于大图像来说可能非常慢,但是如果您首先减小图像的大小(必须启用图像平滑功能(大多数浏览器的默认设置)),它的效果也一样。 128 8 128大小合适,但您可以放低一些。这将取决于图像您可以将其缩小多少,因为它会失败。

关于javascript - 用选定的颜色转换主色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39757535/

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