Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 图像调色板缩减_Algorithm_Image Processing_Gif - Fatal编程技术网

Algorithm 图像调色板缩减

Algorithm 图像调色板缩减,algorithm,image-processing,gif,Algorithm,Image Processing,Gif,我第一次玩计算机图形编程。我想将RGB(24位)图像转换为索引调色板(8位)图像(如GIF)。我最初的想法是使用k-means(k=256) 如何为给定的图像选择最佳调色板?这对我来说是一次学习经历,所以我更喜欢一个概述类型的答案,而不是源代码 编辑:抖动当前已脱离主题。我只是指“简单”的颜色转换,撇开心理-视觉/知觉模型不谈;颜色空间目前也不是话题,但在颜色空间之间移动首先让我想到了这一点:) 八叉树 中央切口 K-均值 色域细分 编辑: 更新以支持256色调色板 如果您需要最简单的方法,

我第一次玩计算机图形编程。我想将RGB(24位)图像转换为索引调色板(8位)图像(如GIF)。我最初的想法是使用k-means(k=256)

如何为给定的图像选择最佳调色板?这对我来说是一次学习经历,所以我更喜欢一个概述类型的答案,而不是源代码

编辑:抖动当前已脱离主题。我只是指“简单”的颜色转换,撇开心理-视觉/知觉模型不谈;颜色空间目前也不是话题,但在颜色空间之间移动首先让我想到了这一点:)

  • 八叉树
  • 中央切口
  • K-均值
  • 色域细分
编辑: 更新以支持256色调色板

如果您需要最简单的方法,我建议使用基于直方图的方法:

Calculate histograms of R/G/B channels Define 4 intensity ranges For each channel in intensity range Split histogram into 4 equal parts For each histogram part Extract most frequent value of that part 计算R/G/B通道的直方图 定义4个强度范围 对于强度范围内的每个通道 将直方图分成4等份 对于每个直方图部分 提取该部分的最频繁值 现在您将拥有4*4^3=256色调色板。将像素指定给调色板颜色时,只需计算像素的平均强度即可查看必须使用的强度区域。之后,只需将64种颜色中的一种强度区域映射到像素值


祝你好运。

人们提供的参考链接很好,这个问题有几种解决方案,但由于我最近一直在研究这个问题(完全不知道其他人是如何解决的),我用简单的英语提供了我的方法:

首先,认识到(人类感知的)颜色是三维的。这基本上是因为人眼有三种不同的感受器:红色、绿色和蓝色。同样,您的显示器具有红色、绿色和蓝色像素元素。可以使用其他表示,如色调、饱和度、亮度(HSL),但基本上所有表示都是三维的

这意味着RGB颜色空间是一个立方体,具有红色、绿色和蓝色轴。从24位源图像中,此多维数据集在每个轴上有256个离散级别。将图像减少到8位的一种简单方法是简单地减少每个轴的级别。例如,通过获取红色和绿色值的高3位和蓝色值的高2位,可以轻松创建8x8x4立方体调色板,其中红色和绿色为8级,蓝色为4级。这很容易实现,但有几个缺点。在生成的256色调色板中,许多条目将根本不使用。如果图像具有使用非常细微的颜色偏移的细节,这些偏移将随着颜色捕捉到同一调色板条目而消失

自适应调色板方法不仅需要考虑图像中的平均/常见颜色,还需要考虑颜色空间中变化最大的区域。也就是说,具有数千种浅绿色细微色调的图像需要与具有数千个像素的浅绿色完全相同色调的图像不同的调色板,因为后者在理想情况下会为该颜色使用单个调色板条目

为此,我采用了一种方法,该方法产生256个bucket,每个bucket包含完全相同数量的不同值。因此,如果原始图像包含256000种不同的24位颜色,该算法将生成256个存储桶,每个存储桶包含1000个原始值。这是通过使用不同值的中值(而不是平均值)对颜色空间进行二元空间分割来实现的

在英语中,这意味着我们首先将整个颜色立方体划分为小于红色中值的一半像素和大于红色中值的一半像素。然后,将每个结果的一半除以绿色值,然后除以蓝色,依此类推。每个分割都需要一个位来指示像素的下半部分或上半部分。经过8次分割后,方差在颜色空间中有效地分割为256个同等重要的簇

在psuedo代码中:

// count distinct 24-bit colors from the source image
// to minimize resources, an array of arrays is used 
paletteRoot = {colors: [ [color0,count],[color1,count], ...]} // root node has all values 
for (i=0; i<8; i++) {
  colorPlane = i%3 // red,green,blue,red,green,blue,red,green
  nodes = leafNodes(paletteRoot) // on first pass, this is just the root itself
  for (node in nodes) {
    node.colors.sort(colorPlane) // sort by red, green, or blue
    node.lo = { colors: node.colors[0..node.colors.length/2] }
    node.hi = { colors: node.colors[node.colors.length/2..node.colors.length] } 
    delete node.colors // free up space! otherwise will explode memory
    node.splitColor = node.hi.colors[0] // remember the median color used to partition
    node.colorPlane = colorPlane // remember which color this node split on
  }
}
//从源图像中计算不同的24位颜色
//为了最小化资源,使用了一个数组数组
paletteRoot={colors:[[color0,count],[color1,count],…]}//根节点具有所有值

对于(i=0;i来说,回答这个问题可能有点晚,但请尝试以下方法:

  • 为图像中的每种颜色制作一组
  • 根据红色、绿色和蓝色对它们进行排序(如果前面的通道相等),(它们现在进入列表)
  • 如果附近的颜色太相似,则抑制它们,即rgb空间中的距离小于4
  • 如果颜色仍然过多,请抑制使用最少的颜色

  • 每次你压制一种颜色时,你都必须将颜色和它的目的地添加到散列图中。

    这不是一项简单的任务。这种转换有很多方法可以实现(例如抖动和人类的颜色感知)。你只是问了一大口……我敢打赌,整个大学课程都满了:)+1关于一个好问题,请看下面我的答案。您可能希望从24位值和标准“web安全”调色板之间的转换开始。这比确定自己的调色板要简单得多(虽然可能没有那么有趣)。因此,对于每个(RGB)通道,我有4个强度范围桶(0-63、64-127、128-191、192-255)。每个铲斗进一步分为4个子范围铲斗(例如[0-63]范围的0-15、16-31、32-47、48-63);每个通道总共提供16个桶。每个此类(子)桶将以其平均值的形式表示(例如,R[0-15]子桶为12)。我现在一共有16种红色(绿色和蓝色都一样),总共有16*16*16=4096种颜色?!我做错了什么?!这是因为您混合了来自不同强度范围的颜色。算法思想是找出要使用的强度桶-例如计算像素强度Ip=(R+G+B)/3。然后通过该Ip选择强度桶,并对所有三个R/G/B通道使用相同的强度桶。(如果有的话)