14

我有一个应用程序可以索引视频中出现的前 16 种颜色。

我正在尝试编写另一个允许用户选择颜色的应用程序,然后该应用程序会找到该颜色出现的所有视频。

问题是因为我只为每个视频索引 16 种颜色,所以用户选择了 RGB 颜色。这种颜色被索引的可能性非常低,所以我的应用程序几乎总是不返回任何结果。

我想了一种方法来完成这项工作——我可以索引视频中出现的颜色并将它们转换为最接近的 8 位颜色。

然后,当用户选择 RGB 颜色时,我可以将用户选择转换为相同的 8 位最接近颜色。

这样我总是有比赛的。

我现在唯一的主要问题是如何将 RGB 颜色转换为最接近的 8 位颜色?

4

7 回答 7

11

要转换为 web 安全调色板,您需要将每个 r、g、b 组件的范围从 0-255 转换为 0-5 并将它们组合起来:

color = (r*6/256)*36 + (g*6/256)*6 + (b*6/256)
于 2012-10-09T21:48:30.683 回答
6

您需要做的是将 RGB 转换为 HSB(色相饱和度亮度)值。HSB 是 3 个字节,就像 RGB 一样,不同之处在于 HSB 值比 RGB 更容易比较。

您的下一步是确定“重要性”权重。例如,如果您只关心“颜色/色调”,而不是饱和度或亮度,那么您可以丢弃 S 和 B 字节而只使用颜色字节。

如果是我并且我被限制为 8 位,我将使用 4 位颜色信息(16 种不同颜色)、3 位饱和度(8 种不同值)和 1 位亮度信息(亮或暗)。

本文介绍了如何在 Java 中进行 HSB:

http://java.sys-con.com/node/43559

本文的源代码有一个 Java 中的 RGB 到 HSB 转换器。

于 2012-10-09T21:43:53.257 回答
3

一种可能性是简单地将 24 位颜色缩小为 8 位颜色空间。正如 cHao 所提到的,您可以将 RRRGGGBB 用于您的 8 位数字。然后可以通过简单的缩放算法计算每个颜色分量,例如:

byte red = (originalColor.red * 8) / 256;
byte green = (originalColor.green * 8) / 256;
byte blue = (originalColor.blue * 4) / 256;

8、4 和 254 是每个颜色分量中可能值的数量。在你原来的 24 位颜色中,红色、绿色和蓝色都可以有 256 个可能的值,所以这是缩放方程的除数。在示例 8 位颜色中,红色和绿色各为 3 位(8 个可能值),蓝色为 2 位(4 个可能值)。

获得这三个组件后,您可以将它们与一些简单的位移算法结合起来:

byte eightBitColor = (red << 5) | (green << 2) | blue;

然后您可以简单地比较这些 8 位颜色。它们大幅降低的分辨率可能会对您有所帮助。

或者,您可以执行 Tyler 建议的操作,先转换为 HSB 或 HSV,然后仅比较色调(取决于您是否需要亮度和饱和度信息)。根据您的目标,这实际上可能是一个更理想的解决方案。

编辑:修改缩放算法以解决 Mark Ransom 指出的缺点。

于 2013-05-28T20:00:24.400 回答
1

tmux 具有将 24 位 RGB 转换为 256 色的逻辑。它使用最接近的 6x6x6 或最接近的灰色。 https://github.com/tmux/tmux/blob/dae2868d1227b95fd076fb4a5efa6256c7245943/colour.c#L57

于 2020-07-10T03:13:00.857 回答
1

这是几年前我发现的一个非常有用的 Python 脚本。所有功劳归于 Micah Elliott

如何使用:

  1. 复制整个代码并创建一个.py具有所需名称的文件。
  2. 该程序可以转换 (Hex -> RGB) 和 (RGB -> Hex)
  3. 运行该程序并进行如下论证:python file.py 9CE445获取最接近的 8 位颜色值并python file.py 204获取准确的 Hex 值。

    """ Convert values between RGB hex codes and xterm-256 color codes.
    Nice long listing of all 256 colors and their codes. Useful for
    developing console color themes, or even script output schemes.
    Resources:
    * http://en.wikipedia.org/wiki/8-bit_color
    * http://en.wikipedia.org/wiki/ANSI_escape_code
    * /usr/share/X11/rgb.txt
    I'm not sure where this script was inspired from. I think I must have
    written it from scratch, though it's been several years now.
    """
    
    __author__    = 'Micah Elliott http://MicahElliott.com'
    __version__   = '0.1'
    __copyright__ = 'Copyright (C) 2011 Micah Elliott.  All rights reserved.'
    __license__   = 'WTFPL http://sam.zoy.org/wtfpl/'
    
    #---------------------------------------------------------------------
    
    import sys, re
    
    CLUT = [  # color look-up table
    #    8-bit, RGB hex
    
        # Primary 3-bit (8 colors). Unique representation!
        ('00',  '000000'),
        ('01',  '800000'),
        ('02',  '008000'),
        ('03',  '808000'),
        ('04',  '000080'),
        ('05',  '800080'),
        ('06',  '008080'),
        ('07',  'c0c0c0'),
    
        # Equivalent "bright" versions of original 8 colors.
        ('08',  '808080'),
        ('09',  'ff0000'),
        ('10',  '00ff00'),
        ('11',  'ffff00'),
        ('12',  '0000ff'),
        ('13',  'ff00ff'),
        ('14',  '00ffff'),
        ('15',  'ffffff'),
    
        # Strictly ascending.
        ('16',  '000000'),
        ('17',  '00005f'),
        ('18',  '000087'),
        ('19',  '0000af'),
        ('20',  '0000d7'),
        ('21',  '0000ff'),
        ('22',  '005f00'),
        ('23',  '005f5f'),
        ('24',  '005f87'),
        ('25',  '005faf'),
        ('26',  '005fd7'),
        ('27',  '005fff'),
        ('28',  '008700'),
        ('29',  '00875f'),
        ('30',  '008787'),
        ('31',  '0087af'),
        ('32',  '0087d7'),
        ('33',  '0087ff'),
        ('34',  '00af00'),
        ('35',  '00af5f'),
        ('36',  '00af87'),
        ('37',  '00afaf'),
        ('38',  '00afd7'),
        ('39',  '00afff'),
        ('40',  '00d700'),
        ('41',  '00d75f'),
        ('42',  '00d787'),
        ('43',  '00d7af'),
        ('44',  '00d7d7'),
        ('45',  '00d7ff'),
        ('46',  '00ff00'),
        ('47',  '00ff5f'),
        ('48',  '00ff87'),
        ('49',  '00ffaf'),
        ('50',  '00ffd7'),
        ('51',  '00ffff'),
        ('52',  '5f0000'),
        ('53',  '5f005f'),
        ('54',  '5f0087'),
        ('55',  '5f00af'),
        ('56',  '5f00d7'),
        ('57',  '5f00ff'),
        ('58',  '5f5f00'),
        ('59',  '5f5f5f'),
        ('60',  '5f5f87'),
        ('61',  '5f5faf'),
        ('62',  '5f5fd7'),
        ('63',  '5f5fff'),
        ('64',  '5f8700'),
        ('65',  '5f875f'),
        ('66',  '5f8787'),
        ('67',  '5f87af'),
        ('68',  '5f87d7'),
        ('69',  '5f87ff'),
        ('70',  '5faf00'),
        ('71',  '5faf5f'),
        ('72',  '5faf87'),
        ('73',  '5fafaf'),
        ('74',  '5fafd7'),
        ('75',  '5fafff'),
        ('76',  '5fd700'),
        ('77',  '5fd75f'),
        ('78',  '5fd787'),
        ('79',  '5fd7af'),
        ('80',  '5fd7d7'),
        ('81',  '5fd7ff'),
        ('82',  '5fff00'),
        ('83',  '5fff5f'),
        ('84',  '5fff87'),
        ('85',  '5fffaf'),
        ('86',  '5fffd7'),
        ('87',  '5fffff'),
        ('88',  '870000'),
        ('89',  '87005f'),
        ('90',  '870087'),
        ('91',  '8700af'),
        ('92',  '8700d7'),
        ('93',  '8700ff'),
        ('94',  '875f00'),
        ('95',  '875f5f'),
        ('96',  '875f87'),
        ('97',  '875faf'),
        ('98',  '875fd7'),
        ('99',  '875fff'),
        ('100', '878700'),
        ('101', '87875f'),
        ('102', '878787'),
        ('103', '8787af'),
        ('104', '8787d7'),
        ('105', '8787ff'),
        ('106', '87af00'),
        ('107', '87af5f'),
        ('108', '87af87'),
        ('109', '87afaf'),
        ('110', '87afd7'),
        ('111', '87afff'),
        ('112', '87d700'),
        ('113', '87d75f'),
        ('114', '87d787'),
        ('115', '87d7af'),
        ('116', '87d7d7'),
        ('117', '87d7ff'),
        ('118', '87ff00'),
        ('119', '87ff5f'),
        ('120', '87ff87'),
        ('121', '87ffaf'),
        ('122', '87ffd7'),
        ('123', '87ffff'),
        ('124', 'af0000'),
        ('125', 'af005f'),
        ('126', 'af0087'),
        ('127', 'af00af'),
        ('128', 'af00d7'),
        ('129', 'af00ff'),
        ('130', 'af5f00'),
        ('131', 'af5f5f'),
        ('132', 'af5f87'),
        ('133', 'af5faf'),
        ('134', 'af5fd7'),
        ('135', 'af5fff'),
        ('136', 'af8700'),
        ('137', 'af875f'),
        ('138', 'af8787'),
        ('139', 'af87af'),
        ('140', 'af87d7'),
        ('141', 'af87ff'),
        ('142', 'afaf00'),
        ('143', 'afaf5f'),
        ('144', 'afaf87'),
        ('145', 'afafaf'),
        ('146', 'afafd7'),
        ('147', 'afafff'),
        ('148', 'afd700'),
        ('149', 'afd75f'),
        ('150', 'afd787'),
        ('151', 'afd7af'),
        ('152', 'afd7d7'),
        ('153', 'afd7ff'),
        ('154', 'afff00'),
        ('155', 'afff5f'),
        ('156', 'afff87'),
        ('157', 'afffaf'),
        ('158', 'afffd7'),
        ('159', 'afffff'),
        ('160', 'd70000'),
        ('161', 'd7005f'),
        ('162', 'd70087'),
        ('163', 'd700af'),
        ('164', 'd700d7'),
        ('165', 'd700ff'),
        ('166', 'd75f00'),
        ('167', 'd75f5f'),
        ('168', 'd75f87'),
        ('169', 'd75faf'),
        ('170', 'd75fd7'),
        ('171', 'd75fff'),
        ('172', 'd78700'),
        ('173', 'd7875f'),
        ('174', 'd78787'),
        ('175', 'd787af'),
        ('176', 'd787d7'),
        ('177', 'd787ff'),
        ('178', 'd7af00'),
        ('179', 'd7af5f'),
        ('180', 'd7af87'),
        ('181', 'd7afaf'),
        ('182', 'd7afd7'),
        ('183', 'd7afff'),
        ('184', 'd7d700'),
        ('185', 'd7d75f'),
        ('186', 'd7d787'),
        ('187', 'd7d7af'),
        ('188', 'd7d7d7'),
        ('189', 'd7d7ff'),
        ('190', 'd7ff00'),
        ('191', 'd7ff5f'),
        ('192', 'd7ff87'),
        ('193', 'd7ffaf'),
        ('194', 'd7ffd7'),
        ('195', 'd7ffff'),
        ('196', 'ff0000'),
        ('197', 'ff005f'),
        ('198', 'ff0087'),
        ('199', 'ff00af'),
        ('200', 'ff00d7'),
        ('201', 'ff00ff'),
        ('202', 'ff5f00'),
        ('203', 'ff5f5f'),
        ('204', 'ff5f87'),
        ('205', 'ff5faf'),
        ('206', 'ff5fd7'),
        ('207', 'ff5fff'),
        ('208', 'ff8700'),
        ('209', 'ff875f'),
        ('210', 'ff8787'),
        ('211', 'ff87af'),
        ('212', 'ff87d7'),
        ('213', 'ff87ff'),
        ('214', 'ffaf00'),
        ('215', 'ffaf5f'),
        ('216', 'ffaf87'),
        ('217', 'ffafaf'),
        ('218', 'ffafd7'),
        ('219', 'ffafff'),
        ('220', 'ffd700'),
        ('221', 'ffd75f'),
        ('222', 'ffd787'),
        ('223', 'ffd7af'),
        ('224', 'ffd7d7'),
        ('225', 'ffd7ff'),
        ('226', 'ffff00'),
        ('227', 'ffff5f'),
        ('228', 'ffff87'),
        ('229', 'ffffaf'),
        ('230', 'ffffd7'),
        ('231', 'ffffff'),
    
        # Gray-scale range.
        ('232', '080808'),
        ('233', '121212'),
        ('234', '1c1c1c'),
        ('235', '262626'),
        ('236', '303030'),
        ('237', '3a3a3a'),
        ('238', '444444'),
        ('239', '4e4e4e'),
        ('240', '585858'),
        ('241', '626262'),
        ('242', '6c6c6c'),
        ('243', '767676'),
        ('244', '808080'),
        ('245', '8a8a8a'),
        ('246', '949494'),
        ('247', '9e9e9e'),
        ('248', 'a8a8a8'),
        ('249', 'b2b2b2'),
        ('250', 'bcbcbc'),
        ('251', 'c6c6c6'),
        ('252', 'd0d0d0'),
        ('253', 'dadada'),
        ('254', 'e4e4e4'),
        ('255', 'eeeeee'),
    ]
    
    def _str2hex(hexstr):
        return int(hexstr, 16)
    
    def _strip_hash(rgb):
        # Strip leading `#` if exists.
        if rgb.startswith('#'):
            rgb = rgb.lstrip('#')
        return rgb
    
    def _create_dicts():
        short2rgb_dict = dict(CLUT)
        rgb2short_dict = {}
        for k, v in short2rgb_dict.items():
            rgb2short_dict[v] = k
        return rgb2short_dict, short2rgb_dict
    
    def short2rgb(short):
        return SHORT2RGB_DICT[short]
    
    def print_all():
        """ Print all 256 xterm color codes.
        """
        for short, rgb in CLUT:
            sys.stdout.write('\033[48;5;%sm%s:%s' % (short, short, rgb))
            sys.stdout.write("\033[0m  ")
            sys.stdout.write('\033[38;5;%sm%s:%s' % (short, short, rgb))
            sys.stdout.write("\033[0m\n")
        print ("Printed all codes.")
        print ("You can translate a hex or 0-255 code by providing an argument.")
    
    def rgb2short(rgb):
        """ Find the closest xterm-256 approximation to the given RGB value.
        @param rgb: Hex code representing an RGB value, eg, 'abcdef'
        @returns: String between 0 and 255, compatible with xterm.
        >>> rgb2short('123456')
        ('23', '005f5f')
        >>> rgb2short('ffffff')
        ('231', 'ffffff')
        >>> rgb2short('0DADD6') # vimeo logo
        ('38', '00afd7')
        >>> rgb2short('3D3D3D')
        ('237', '3a3a3a')
        >>> rgb2short('070707')
        ('232', '080808')
        """
        rgb = _strip_hash(rgb)
        # Break 6-char RGB code into 3 integer vals.
        parts = [ int(h, 16) for h in re.split(r'(..)(..)(..)', rgb)[1:4] ]
    
        incs = [0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff]
    
        if parts[0] == parts[1] == parts[2]:
            gs_incs = range(0x08, 0xee, 10)
            incs = sorted(incs + gs_incs + [0xee,])
    
        res = []
        for part in parts:
            i = 0
            while i < len(incs)-1:
                s, b = incs[i], incs[i+1]  # smaller, bigger
                if s <= part <= b:
                    s1 = abs(s - part)
                    b1 = abs(b - part)
                    if s1 < b1: closest = s
                    else: closest = b
                    res.append(closest)
                    break
                i += 1
        #print '***', res
        res = ''.join([ ('%02.x' % i) for i in res ])
        equiv = RGB2SHORT_DICT[ res ]
        #print '***', res, equiv
        return equiv, res
    
    RGB2SHORT_DICT, SHORT2RGB_DICT = _create_dicts()
    
    #---------------------------------------------------------------------
    
    if __name__ == '__main__':
        import doctest
        doctest.testmod()
        if len(sys.argv) == 1:
            print_all()
            raise SystemExit
        arg = sys.argv[1]
        if len(arg) < 4 and int(arg) < 256:
            rgb = short2rgb(arg)
            sys.stdout.write('xterm color \033[38;5;%sm%s\033[0m -> RGB exact \033[38;5;%sm%s\033[0m' % (arg, arg, arg, rgb))
            sys.stdout.write("\033[0m\n")
        else:
            short, rgb = rgb2short(arg)
            sys.stdout.write('RGB %s -> xterm color approx \033[38;5;%sm%s (%s)' % (arg, short, short, rgb))
            sys.stdout.write("\033[0m\n")
    
于 2020-02-25T10:17:10.520 回答
0

您熟悉Floyd-Steinberg 抖动吗?这用于将高阶颜色转换为低阶颜色,例如 24 位 RGB 到 3 位(8 色)RGB 或将 RGB 图像限制为 8 位(256 色)以进行 GIF 转换。

该算法在链接的维基百科页面上进行了描述。

于 2012-10-09T21:42:10.590 回答
0

如果要将 24 bpp 图像转换为 8 bpp 图像,请尝试此算法:

for y = 0 to ImageHeight - 1
   for x = 0 to ImageWidth - 1
      GetPixel(x,y,red,grn,blu)
      {read RGB data from 24bpp file}
      d0 = red^2 + grn^2 + blu^2
      ColorIndex = 0
      for cl = 0 to 255
         GetPaletteData(p_red,p_gre,p_blu)
         {read RGB data from 8bpp palette}
         d = (red - p_red)^2 + (grn - p_grn)^2 + (blu - p_blu)^2
         if d0 >= d then
            ColorIndex = cl
            d0 = d
         end if
      next cl
        {use ColorIndex to create your 8bpp file}
     next x
   next y

在此步骤之前,请从 Wikipedia 或其他来源阅读有关 8bpp 文件的更多信息。

祝你好运!

于 2015-12-14T20:29:36.097 回答