获取忽略透明像素的 Surface 的平均颜色
Get the average Color of a Surface ignoring transparent pixels
我的图片有白色背景,使用 image.set_colorkey
设置为不可见。
我正在尝试获取非透明像素的平均颜色(在这种情况下它只有一种颜色)。
pygame.transform.average_color
对我不起作用,因为它还采用不可见的白色像素,这导致返回颜色的阴影非常浅(返回颜色的 alpha 为 0,我不明白)。
这是图片(白色背景,主色 = (38, 43, 68))
这是我能想到的最小的代码示例:
image = pygame.image.load('enemy.png')
image.set_colorkey((255, 255, 255))
color = pygame.transform.average_color(self.image, self.image.get_rect())
# color = (171, 172, 182, 0)
您需要根据表面像素数 (width * height) 与不透明像素的数量。像素数可以用 pygame.mask.Mask.count
:
得到
def get_averqge_color(surf):
color = pygame.transform.average_color(surf, surf.get_rect())
pxiel_count = pygame.mask.from_surface(surf).count()
scale = surf.get_width() * surf.get_height() / pxiel_count
return (round(color[0]*scale), round(color[1]*scale), round(color[2]*scale))
由于颜色通道是整数值,因此仍然存在一些准确性问题,但结果接近。看例子:
import pygame
def get_averqge_color(surf):
color = pygame.transform.average_color(surf, surf.get_rect())
pxiel_count = pygame.mask.from_surface(surf).count()
scale = surf.get_width() * surf.get_height() / pxiel_count
print(color, scale, pxiel_count)
return (round(color[0]*scale), round(color[1]*scale), round(color[2]*scale))
pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 70)
test_surface = pygame.Surface((300, 300))
test_surface.set_colorkey((0, 0, 0))
pygame.draw.rect(test_surface, (255, 0, 0), (50, 50, 100, 100))
pygame.draw.rect(test_surface, (0, 255, 0), (150, 50, 100, 100))
pygame.draw.rect(test_surface, (255, 255, 0), (50, 150, 100, 100))
pygame.draw.rect(test_surface, (0, 0, 255), (150, 150, 100, 100))
avg_color = get_averqge_color(test_surface)
color_text = font.render(f"{avg_color[0]} {avg_color[1]} {avg_color[2]}", True, "black")
background = pygame.Surface(window.get_size())
ts, w, h, c1, c2 = 80, *window.get_size(), (160, 160, 160), (96, 96, 96)
tiles = [((x*ts, y*ts, ts, ts), c1 if (x+y) % 2 == 0 else c2) for x in range((w+ts-1)//ts) for y in range((h+ts-1)//ts)]
[pygame.draw.rect(background, color, rect) for rect, color in tiles]
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.blit(background, (0, 0))
rect = test_surface.get_rect(center = window.get_rect().center)
window.blit(test_surface, rect)
pygame.draw.rect(window, "black", rect, 5, 5)
window.blit(color_text, color_text.get_rect(center = rect.center))
pygame.display.flip()
clock.tick(60)
pygame.quit()
exit()
我的图片有白色背景,使用 image.set_colorkey
设置为不可见。
我正在尝试获取非透明像素的平均颜色(在这种情况下它只有一种颜色)。
pygame.transform.average_color
对我不起作用,因为它还采用不可见的白色像素,这导致返回颜色的阴影非常浅(返回颜色的 alpha 为 0,我不明白)。
这是图片(白色背景,主色 = (38, 43, 68))
这是我能想到的最小的代码示例:
image = pygame.image.load('enemy.png')
image.set_colorkey((255, 255, 255))
color = pygame.transform.average_color(self.image, self.image.get_rect())
# color = (171, 172, 182, 0)
您需要根据表面像素数 (width * height) 与不透明像素的数量。像素数可以用 pygame.mask.Mask.count
:
def get_averqge_color(surf):
color = pygame.transform.average_color(surf, surf.get_rect())
pxiel_count = pygame.mask.from_surface(surf).count()
scale = surf.get_width() * surf.get_height() / pxiel_count
return (round(color[0]*scale), round(color[1]*scale), round(color[2]*scale))
由于颜色通道是整数值,因此仍然存在一些准确性问题,但结果接近。看例子:
import pygame
def get_averqge_color(surf):
color = pygame.transform.average_color(surf, surf.get_rect())
pxiel_count = pygame.mask.from_surface(surf).count()
scale = surf.get_width() * surf.get_height() / pxiel_count
print(color, scale, pxiel_count)
return (round(color[0]*scale), round(color[1]*scale), round(color[2]*scale))
pygame.init()
window = pygame.display.set_mode((400, 400))
clock = pygame.time.Clock()
font = pygame.font.SysFont(None, 70)
test_surface = pygame.Surface((300, 300))
test_surface.set_colorkey((0, 0, 0))
pygame.draw.rect(test_surface, (255, 0, 0), (50, 50, 100, 100))
pygame.draw.rect(test_surface, (0, 255, 0), (150, 50, 100, 100))
pygame.draw.rect(test_surface, (255, 255, 0), (50, 150, 100, 100))
pygame.draw.rect(test_surface, (0, 0, 255), (150, 150, 100, 100))
avg_color = get_averqge_color(test_surface)
color_text = font.render(f"{avg_color[0]} {avg_color[1]} {avg_color[2]}", True, "black")
background = pygame.Surface(window.get_size())
ts, w, h, c1, c2 = 80, *window.get_size(), (160, 160, 160), (96, 96, 96)
tiles = [((x*ts, y*ts, ts, ts), c1 if (x+y) % 2 == 0 else c2) for x in range((w+ts-1)//ts) for y in range((h+ts-1)//ts)]
[pygame.draw.rect(background, color, rect) for rect, color in tiles]
run = True
while run:
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
window.blit(background, (0, 0))
rect = test_surface.get_rect(center = window.get_rect().center)
window.blit(test_surface, rect)
pygame.draw.rect(window, "black", rect, 5, 5)
window.blit(color_text, color_text.get_rect(center = rect.center))
pygame.display.flip()
clock.tick(60)
pygame.quit()
exit()