javascript - 如何确定像素的颜色或色调对应于某种颜色的度数范围?

标签 javascript colors rgb hsl

是否有一些约定将 HSL 色环划分为度数范围以定义基本颜色?
例如,80-150 度将被视为绿色,210-280 度将被视为蓝色,依此类推。
我想自动检测属于某个“颜色组”的像素颜色,发现 HSL 可以很好地确定色调。就我的目的而言,定义红色、橙色、黄色、绿色、青色、蓝色、洋红色、粉色的边界就足够了。
这种划分是否已经有解决方案?
编辑
在悬赏之前,我会添加更多推理和示例...
我的最终想法是通过主色来索引我们图像的库存,因此我可以将颜色作为一个查询参数。
我已经定义了一些边界如何划分 HSL 色轮:

  1-15 red
  16-50 orange
  51-72 yellow
  73-155 green
  156-185 cyan
  186-268 blue
  269-310 magenta
  311-344 pink
  345-359 red
我有一个函数来确定像素的颜色:
function getPixelTone(pixel) {
  let [ hue, sat, light ] = rgbToHsl( ...pixel );
  sat   = parseInt(sat);
  light = parseInt(light);

  if ( light < 3 || sat < 50  && light < 5 ) {
    return 'black';
  }

  if ( light > 96 ) {
    return 'white';
  }

  if ( hue === 0 || isPixelGray(pixel) ) {
    return 'gray';
  }

  if ( (hue > 0 && hue < 16 ) || (hue > 344 && hue < 360 ) ) {
    if ( light > 55 ) {
      return 'pink';
    }

    if ( light < 34 || ( sat < 30 && light < 80 ) ) {
      return 'brown';
    }  

    return 'red';
  }

  if ( hue > 15 && hue < 51 ) {
    if ( light < 34 ) {
      return 'brown';
    }  
    return 'orange';
  }
  if ( hue > 50 && hue < 73 ) {
    return 'yellow';
  }
  if ( hue > 72 && hue < 156 ) {
    return 'green';
  }
  if ( hue > 155 && hue < 186 ) {
    return 'cyan';
  }
  if ( hue > 185 && hue < 269 ) {
    return 'blue';
  }
  if ( hue > 268 && hue < 311 ) {
    return 'magenta';
  }
  if ( hue > 310 && hue < 345 ) {
    return 'pink';
  }

  return 'color';

}
功能 rgbToHsl来自模块 rgb-to-hsl , 功能 isPixelGray定义如下:
function isPixelGray(pixel) {
  if ( Math.max(pixel) - Math.min(pixel) < 3 ) {
    return true;
  }
  return false;
}
所以我的问题的所有目的是将像素量化为最简单的感知颜色之一。我认为这些颜色是:红色、橙色、黄色、绿色、青色、蓝色、品红色、粉色、棕色、黑色 , 和 白色 , 它还可以包括 米色 如果它可以很容易地确定。
确定属于这些颜色之一的像素的最佳方法是什么?
PS 我选择 HSL 颜色空间作为基础,因为从我的 Angular 来看,它在 RGB 之前具有优势。但它不应该是这样的。

最佳答案

在这里,您有一个色轮,当您将其悬停时,它会从像素中确定最简单的颜色,它由纯 组成。 JS .在函数 getColorFromWheel()你会得到 rba值,然后将其转换为 hsl .当它转换为 hsl函数getColorNameFromHsl()决定什么颜色 它是,然后它只显示 <div> 中的值.如果您想要更精确的颜色,您可以找到更精确的 rba 列表。或 hsl颜色来命名数组并使其发挥作用。
这是一个可以转换 rba 的库颜色到名称:Name that color
希望这个解决方案对您有所帮助。

function newEl(tag){return document.createElement(tag)}

window.addEventListener('load', onDocLoaded, false);
function onDocLoaded(evt)
{
    var wheel = makeColorWheel(256);
    wheel.addEventListener('mousemove', getColorFromWheel);
    document.body.appendChild( wheel );
}

var convertToHsl = function convertToHsl(rgbArr) {
  var r1 = Number(rgbArr[0]) / 255, g1 = Number(rgbArr[1]) / 255, b1 = Number(rgbArr[2]) / 255;
  var maxColor = Math.max(r1,g1,b1), minColor = Math.min(r1,g1,b1);
  var L = (maxColor + minColor) / 2 , S = 0, H = 0;
  if(maxColor != minColor){
    if(L < 0.5){
      S = (maxColor - minColor) / (maxColor + minColor);
    }else{
      S = (maxColor - minColor) / (2.0 - maxColor - minColor);
    }
    if(r1 == maxColor){
      H = (g1-b1) / (maxColor - minColor);
    }else if(g1 == maxColor){
      H = 2.0 + (b1 - r1) / (maxColor - minColor);
    }else{
      H = 4.0 + (r1 - g1) / (maxColor - minColor);
    }
  }
  L = L * 100;
  S = S * 100;
  H = H * 60;
  if(H<0){
    H += 360;
  }
  return {h:H, s:S, l:L};
}

var getColorNameFromHsl = function (hsl) {
        var l = Math.floor(hsl.l), s = Math.floor(hsl.s), h = Math.floor(hsl.h);
        if (s <= 10 && l >= 90) {
            return ("White")
        } else if ((s <= 10 && l <= 70) || s === 0) {
            return ("Gray")
        } else if (l <= 15) {
            return ("Black")
        } else if ((h >= 0 && h <= 15) || h >= 346) {
            return ("Red");
        } else if (h >= 16 && h <= 35) {
            if (s < 90) {
                return ("Brown");
            } else {
                return ("Orange");
            }
        } else if (h >= 36 && h <= 54) {
            if (s < 90) {
                return ("Brown");
            } else {
                return ("Yellow");
            }
        } else if (h >= 55 && h <= 165) {
            return ("Green");
        } else if (h >= 166 && h <= 260) {
            return ("Blue")
        } else if (h >= 261 && h <= 290) {
            return ("Purple")
        } else if (h >= 291 && h <= 345) {
            return ("Pink")
        }
    }

var hsv2rgb = function(hsv) {
  var h = hsv.hue, s = hsv.sat, v = hsv.val;
  var rgb, i, data = [];
  if (s === 0) {
    rgb = [v,v,v];
  } else {
    h = h / 60;
    i = Math.floor(h);
    data = [v*(1-s), v*(1-s*(h-i)), v*(1-s*(1-(h-i)))];
    switch(i) {
      case 0:
        rgb = [v, data[2], data[0]];
        break;
      case 1:
        rgb = [data[1], v, data[0]];
        break;
      case 2:
        rgb = [data[0], v, data[2]];
        break;
      case 3:
        rgb = [data[0], data[1], v];
        break;
      case 4:
        rgb = [data[2], data[0], v];
        break;
      default:
        rgb = [v, data[0], data[1]];
        break;
    }
  }
  return rgb;
};

function clamp(min, max, val)
{
    if (val < min) return min;
    if (val > max) return max;
    return val;
}

function makeColorWheel(diameter)
{
    var can = newEl('canvas');
    var ctx = can.getContext('2d');
    can.width = diameter;
    can.height = diameter;
    var imgData = ctx.getImageData(0,0,diameter,diameter);
    var maxRange = diameter / 2;
    
    for (var y=0; y<diameter; y++)
    {
        for (var x=0; x<diameter; x++)
        {
            var xPos = x - (diameter/2);
            var yPos = (diameter-y) - (diameter/2);
            
            
            var polar = pos2polar( {x:xPos, y:yPos} );
            var sat = clamp(0,1,polar.len / ((maxRange/2)));
            var val = clamp(0,1, (maxRange-polar.len) / (maxRange/2) );
            
            var rgb = hsv2rgb( {hue:polar.ang, sat:sat, val:val} );
            
            var index = 4 * (x + y*diameter);
            imgData.data[index + 0] = rgb[0]*255;
            imgData.data[index + 1] = rgb[1]*255;
            imgData.data[index + 2] = rgb[2]*255;
            imgData.data[index + 3] = 255;
        }
    }
    ctx.putImageData(imgData, 0,0);
    return can;
}

function deg2rad(deg)
{
    return (deg / 360) * ( 2 * Math.PI );
}
function rad2deg(rad)
{
    return (rad / (Math.PI * 2)) * 360;
}

function pos2polar(inPos)
{
    var vecLen = Math.sqrt( inPos.x*inPos.x + inPos.y*inPos.y );
    var something = Math.atan2(inPos.y,inPos.x);
    while (something < 0)
        something += 2*Math.PI;
        
    return { ang: rad2deg(something), len: vecLen };
}



function getColorFromWheel(event) 
{
    var can = this;
    var ctx = can.getContext('2d');
    var color = document.getElementById('color');
    
  var x = event.layerX;
  var y = event.layerY;
  var pixel = ctx.getImageData(x, y, 1, 1);
  var data = pixel.data;
  var rgba = 'rgba(' + data[0] + ',' + data[1] +
             ',' + data[2] + ',' + (data[3] / 255) + ')';
  colorName.style.background =  rgba;
 var rgbArray = [data[0], data[1], data[2]];
 var color = getColorNameFromHsl(convertToHsl(rgbArray));
   colorName.textContent = color;
}
div {
width: 200px; 
height: 100px;
float: right;
border-radius: 25px;
text-align: center;
vertical-align: middle;
line-height: 100px; 
}
<div id="colorName" ></div>

关于javascript - 如何确定像素的颜色或色调对应于某种颜色的度数范围?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66762405/

相关文章:

javascript - Algolia Geo Search 看不到排名信息

javascript - 是否可以将第 3 方 js 脚本注入(inject)到文档中已有的注释中?

Javascript:函数中的 forEach 方法?

powershell - 以编程方式更改 PowerShell 的 16 种默认控制台颜色

macos - 如何在 Swift OS X 应用程序中更改 NSWindow 的标题颜色?

matlab - 根据一个颜色 channel 的强度将 RGB 图像转换为灰度图像

java - Java 中的 RGB 到 CMYK 转换器,无需导入

javascript - 在 Javascript 中导入 Typescript 文件

javascript - RGB转十六进制和十六进制转RGB

python - 将图像中的每个像素乘以一个因子