在 pygame 中从 opencv 生成的椭圆中删除边框

问题描述 投票:0回答:2

我已经设置了这个窗口,我在屏幕上

blit
一个椭圆。我想让椭圆全白,边框平滑。它看起来可以接受,但是当我将椭圆添加到白色背景时,椭圆的边框出现了。

import pygame
import cv2
import numpy as np

pygame.init()

# Set up the Pygame window
screen_width = 640
screen_height = 480
screen = pygame.display.set_mode((screen_width, screen_height))

def drawAACircle(surf, color, center, radius, width, angle):
    circle_image = np.zeros((radius*2, radius*2, 4), dtype = np.uint8)
    circle_image = cv2.ellipse(circle_image, (radius, radius), (radius-width, radius-width), (angle*-.5)-90 , 0, angle, (*color, 255), width, lineType=cv2.LINE_AA)  
    #draw it on the surface
    surf.blit(pygame.image.frombuffer(circle_image.tobytes(), circle_image.shape[1::-1], "RGBA").convert_alpha(), (center[0]-radius, center[1]-radius))

# Wait for the user to close the window
while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            quit()
    
    screen.fill((255,255,255))

    drawAACircle(screen, (255,255,255), (screen_width/2,screen_height/2), 200, 20, 360)

    # Update the display
    pygame.display.flip()

当我将背景更改为全白时,我注意到了边框:

我目前正在开发一种贴花工具,我可以在其中将多个椭圆堆叠在一起。我用这样的

copy()
刷新背景屏幕:

def takeSnapshot():
    global snapshot
    snapshot = screen.copy()

def clearSnapshot():
    global snapshot
    snapshot = None

----
# Run the main loop
running = True
while running:
    events = pygame.event.get()
    for event in events:
        if event.type == pygame.QUIT:
            running = False      

    
    # Clear the screen
    if snapshot is None:
        screen.fill((0,0,0))
         
    else:
        screen.blit(snapshot, (0,0))

我已经尝试使用填充多边形的 gfx.aapolygon icm。但我就是不能让它像 opencv 椭圆一样干净利落。

如果有人知道替代方案,我会很高兴听到,否则我可能会忽略一些我可以让 opencv 椭圆完全变白的东西。

编辑:为了清楚起见,我选择了 opencv 椭圆作为厚度选项,能够制作弧形,并且看起来很光滑。

python opencv pygame border ellipse
2个回答
0
投票

你确实有一个 alpha 通道......但是,OpenCV 是愚蠢的,不知道什么是“alpha”。它只是将每个通道的命令值与已经存在的值(黑色!)混合在一起,你得到的是有效的premultiplied alpha.

你需要把这件事告诉pygame,希望它知道如何处理。

如果那不可能,您将不得不取消预乘,即 divide,您的 RGB 通道除以 A 通道。然后那些边界像素实际上是白色的,而不是已经与黑色混合,并且混合将正常工作,假设您可以与“straight alpha”语义混合。


0
投票

问题是抗锯齿不仅应用于alpha通道,还应用于颜色通道(RGB通道)。基本上,这意味着颜色通道已经乘以 alpha 通道。你必须使用模式“BLEND_PREMULTIPLIED”来正确混合这个纹理(见

blit
):

def drawAACircle(surf, color, center, radius, width, angle):
    circle_image = np.zeros((radius*2, radius*2, 4), dtype = np.uint8)
    circle_image = cv2.ellipse(circle_image, (radius, radius), (radius-width, radius-width), (angle*-.5)-90 , 0, angle, (*color, 255), width, lineType=cv2.LINE_AA)  
    circle_surf = pygame.image.frombuffer(circle_image.tobytes(), circle_image.shape[1::-1], "RGBA")
    pos = (center[0]-radius, center[1]-radius)
    
    surf.blit(circle_surf, pos, special_flags=pygame.BLEND_PREMULTIPLIED)

(我没有在这里显示结果,因为它全是白色的。)

© www.soinside.com 2019 - 2024. All rights reserved.