大家好,欢迎来到IT知识分享网。
在做色彩相关的算法分析时候,经常需要使用规则的颜色表来进行辅助。常用的有以下一些内容:
- 512*512的渐变色表,以稀疏采样的方式对rgb做了全覆盖采样,也常作为 3d LUT的基础。
- color checker classic 24 色卡表,24色卡代表自然界最常出现的颜色,也是色彩校准常用的比对标准。
- 其他一些纯色快,如rgb,cmy等
- 色彩渐变条带
- rgb加色表
- cmy减色表
- 色相(hue)
# -*- coding: utf-8 -*- import cv2 import numpy as np COLOR_CHECKER = np.uint8(np.array( [ [[115, 82, 68], [194, 150, 130], [98, 122, 157], [87, 108, 67], [133, 128, 177], [103, 189, 170]], [[214, 126, 44], [80, 91, 166], [193, 90, 99], [94, 60, 108], [157, 188, 64], [224, 163, 46]], [[56, 61, 150], [70, 148, 73], [175, 54, 60], [231, 199, 31], [187, 86, 149], [8, 133, 161]], [[243, 243, 242], [200, 200, 200], [160, 160, 160], [122, 122, 121], [85, 85, 85], [52, 52, 52]], ] )) def expand_pixel_to_grid(matrix, grid_width, grid_height): """ Expand a pixel to a grid. Inside the grid, every pixel have the same value as the source pixel. Parameters ---------- matrix: 2D numpy array grid_width: width of grid grid_height: height of grid """ height, width = matrix.shape[:2] new_heigt = height * grid_height new_width = width * grid_width repeat_num = grid_width * grid_height matrix = np.expand_dims(matrix, axis=2).repeat(repeat_num, axis=2) matrix = np.reshape(matrix, (height, width, grid_height, grid_width)) # put `height` and `grid_height` axes together; # put `width` and `grid_width` axes together. matrix = np.transpose(matrix, (0, 2, 1, 3)) matrix = np.reshape(matrix, (new_heigt, new_width, 1)) return matrix def generate_single_color_band(left_color, right_color, grade=256, height=None): color_band = np.linspace(left_color, right_color, grade) if height is not None: color_band = np.expand_dims(color_band, axis=0) color_band = np.repeat(color_band, repeats=height, axis=0) color_band = np.clip(np.round(color_band), 0, 255).astype(np.uint8) return color_band def generate_color_bands(color_pairs, grade=256, height=32): """ Generate color bands by uniformly changing from left colors to right colors. Note that there might be multiple bands. Parameters ---------- color_pairs: two dimension list/tuple. The outer dimension denotes the number of color bands. The inner dimension denotes one color pair, which contains two elements, the first denotes the starting color of a color band, while the second denotes the ending color. grade: how many colors are contained in one color band. height: height of one color band. """ # check and process color parameters, which should be 2D list # after processing if not isinstance(color_pairs, (tuple, list)): raise ValueError("color_pairs must be a two dimension list/tuple") if not isinstance(color_pairs[0], (tuple, list)): raise ValueError("color_pairs must be a two dimension list/tuple") # initialize channel, and all other colors should have the same channel if not isinstance(color_pairs[0][0], (tuple, list)): channel = 1 else: channel = len(color_pairs[0][0]) # band_num = len(color_pairs) result = [] for color_pair in color_pairs: left_color = color_pair[0] right_color = color_pair[1] if channel != 1 and \ (len(left_color) != channel or len(right_color) != channel): raise ValueError("All colors should have same channel number") color_band = generate_single_color_band(left_color, right_color, grade, height) result.append(color_band) result = np.concatenate(result, axis=0) result = np.squeeze(result) return result def generate_circle_centers(image_height, image_width, radius): rx = radius / 2. ry = np.sqrt(3.) / 2. * radius x1 = image_width / 2. y1 = (image_height - ry) / 2. x2 = x1 - rx y2 = y1 + ry x3 = x1 + rx y3 = y2 xx = [x1, x2, x3] yy = [y1, y2, y3] return xx, yy def generate_additive_circles(image_height, image_width, radius, bg_color=(0, 0, 0), colors=('red', 'green', 'blue')): xx, yy = generate_circle_centers(image_height, image_width, radius) # generate color index color_index = {
'red': 0, 'green': 1, 'blue': 2 } # build meshgrid and initialize output xmesh, ymesh = np.meshgrid(np.arange(0, image_width), np.arange(0, image_height)) res = np.zeros((image_height, image_width, 3), dtype=np.uint8) bg_idx = np.ones((image_height, image_width), dtype=np.bool_) for i in range(3): r = np.sqrt((xmesh - xx[i]) 2 + (ymesh - yy[i]) 2) space_idx = r < radius color_idx = color_index[colors[i]] res[space_idx, color_idx] = 255 bg_idx = bg_idx & (~space_idx) res = res[..., ::-1] res[bg_idx] = bg_color return res def generate_subtractive_circles(image_height, image_width, radius, bg_color=(255, 255, 255), colors=('cyan', 'magenta', 'yellow')): xx, yy = generate_circle_centers(image_height, image_width, radius) # generate color index color_index = {
'cyan': 0, 'magenta': 1, 'yellow': 2 } # build meshgrid and initialize output xmesh, ymesh = np.meshgrid(np.arange(0, image_width), np.arange(0, image_height)) res = np.ones((image_height, image_width, 3), dtype=np.uint8) * 255 bg_idx = np.ones((image_height, image_width), dtype=np.bool_) for i in range(3): r = np.sqrt((xmesh - xx[i]) 2 + (ymesh - yy[i]) 2) space_idx = r < radius color_idx = color_index[colors[i]] res[space_idx, color_idx] = 0 bg_idx = bg_idx & (~space_idx) res = res[..., ::-1] res[bg_idx] = bg_color return res def generate_color_chart(grid_sample_x, grid_sample_y, grid_num_x, grid_num_y): """ Generate color chart by uniformly distributed color indexes, only support 8 bit (uint8). For a commonly seen 512*512 color chart: grid_sample_x = grid_sample_y = 64 grid_num_x = grid_num_y = 8 Parameters ---------- grid_sample_x: Width of color grid. grid_sample_y: Height of color grid. grid_num_x: Number of grids in x direction. grid_num_y: Number of grids in y direction. """ grid_sample_x = round(grid_sample_x) grid_sample_y = round(grid_sample_y) grid_num_x = round(grid_num_x) grid_num_y = round(grid_num_y) grid_num = grid_num_x * grid_num_y red_index = np.uint8(np.round(np.linspace(0, 255, grid_sample_x))) green_index = np.uint8(np.round(np.linspace(0, 255, grid_sample_y))) blue_index = np.uint8(np.round(np.linspace(0, 255, grid_num))) # compute sizes width = grid_sample_x * grid_num_x height = grid_sample_y * grid_num_y result = np.zeros((height, width, 3), dtype=np.uint8) # compute red-green block, (blue will be combined afterward) red_block, green_block = np.meshgrid(red_index, green_index) red_block = red_block[..., np.newaxis] green_block = green_block[..., np.newaxis] rg_block = np.concatenate([red_block, green_block], axis=2) # combine blue channel for col in range(grid_num_x): for row in range(grid_num_y): blue = blue_index[row * grid_num_x + col] blue = np.ones_like(rg_block[..., 0], dtype=np.uint8) * blue color_block = np.concatenate([rg_block, blue[..., np.newaxis]], axis=2) xmin = col * grid_sample_x xmax = xmin + grid_sample_x ymin = row * grid_sample_y ymax = ymin + grid_sample_y result[ymin:ymax, xmin:xmax, :] = color_block result = result[..., ::-1] # convert from rgb to bgr return result def comprehensive_color_chart(): height = 1024 width = 1024 black = [0, 0, 0] white = [255, 255, 255] red = [0, 0, 255] green = [0, 255, 0] blue = [255, 0, 0] yellow = [0, 255, 255] magenta = [255, 0, 255] cyan = [255, 255, 0] res = np.zeros((height, width, 3), dtype=np.uint8) # top left: color chart64 res[:512, :512] = generate_color_chart(64, 64, 8, 8) # top right: color blocks res[:64, 512:576] = np.uint8(255 * 0.8) res[:64, 576:640] = yellow res[:64, 640:704] = cyan res[:64, 704:768] = green res[:64, 768:832] = magenta res[:64, 832:896] = red res[:64, 896:960] = blue res[:64, 960:] = np.uint8(255 * 0.4) # top right: color bands res[64:448, 512:768] = generate_color_bands( [[black, red], [black, green], [black, blue], [black, cyan], [black, magenta], [black, yellow]], height=64) res[64:448, 768:] = generate_color_bands( [[white, red], [white, green], [white, blue], [white, cyan], [white, magenta], [white, yellow]], height=64) res[448:512, 512:768] = generate_color_bands([[black, white]], height=64) temp = generate_color_bands([[0, 255]], grade=16, height=64) temp = expand_pixel_to_grid(temp, 16, 1).repeat(3, axis=2) res[448:512, 768:] = temp # middle: HSL color band hls = np.uint8(np.linspace(0, 180, 64)).reshape([1, -1]) hls = expand_pixel_to_grid(hls, 16, 64).repeat(3, axis=2) hls[..., 1] = 128 hls[..., 2] = 255 hls2rgb = cv2.cvtColor(hls, cv2.COLOR_HLS2BGR) res[512:576, :] = hls2rgb # bottom left: color checker 24 cc = COLOR_CHECKER[..., ::-1] size = 96 margin = 16 rows = np.int32(np.arange(584, 1024, size + margin)) cols = np.int32(np.arange(16, 600, size + margin)) for i in range(4): for j in range(6): res[rows[i]:rows[i] + size, cols[j]:cols[j] + size] = cc[i, j] # bottom right: additive and subtractive colors res[584:792, 688:1008] = generate_additive_circles(208, 320, 64) res[808:1016, 688:1008] = generate_subtractive_circles(208, 320, 64) return res if __name__ == '__main__': color_chart_64 = generate_color_chart(64, 64, 8, 8) color_chart = comprehensive_color_chart() cv2.imwrite(r'color_chart_64.png', color_chart_64) cv2.imwrite(r'color_chart.png', color_chart)
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/111892.html