Home > OS >  Dark borders in cv2.blur
Dark borders in cv2.blur

Time:11-17

I have this code on python that I use as a Bloom effect on my game, but I've noticed that it has this weird black shadow around the particles

Effect in White Background Effect in Grey  Background

The effect looks like this ^

as you can see, there is some shadows on the particles, on white background it's obvious, while in grey is subtle

I would like to know if there is a way to remove/reduce this weird effect

This is the code for the bloom (where the shadows are coming from):

def Bloom(canvas: pygame.Surface):
    size = canvas.get_size()
    canvas_color = pygame.surfarray.array2d(canvas)
    canvas_rgba = canvas_color.view(dtype=np.uint8).reshape((*canvas_color.shape, 4))

    newCanvas = pygame.Surface(size, pygame.SRCALPHA)


    cv2.blur(canvas_rgba, ksize=(9, 9), dst=canvas_rgba)

    
    pygame.surfarray.blit_array(newCanvas, canvas_color)

    return newCanvas

Any help would be great :3

Edit: Removed the image with black background (no reason to be there)

CodePudding user response:

The problem isn't with the "bloom" algorithm, but with the way you blit the surface to the target.
Not just the alpha channel is blurred, also the color channels are blurred. Therefore you have to
left: Bloom; center: Bloom BLEND_PREMULTIPLIED; right: BloomNoPremultipliedAlpha

import pygame, cv2 
import numpy as np

def Bloom(canvas: pygame.Surface):
    size = canvas.get_size()
    canvas_color = pygame.surfarray.array2d(canvas)
    canvas_rgba = canvas_color.view(dtype=np.uint8).reshape((*canvas_color.shape, 4))
    newCanvas = pygame.Surface(size, pygame.SRCALPHA)
    cv2.blur(canvas_rgba, ksize=(25, 25), dst=canvas_rgba)
    pygame.surfarray.blit_array(newCanvas, canvas_color)
    return newCanvas

def BloomNoPremultipliedAlpha(canvas: pygame.Surface):
    size = canvas.get_size()
    canvas_color = pygame.surfarray.array2d(canvas)
    canvas_rgba = canvas_color.view(dtype=np.uint8).reshape((*canvas_color.shape, 4))
    newCanvas = pygame.Surface(size, pygame.SRCALPHA)
    cv2.blur(canvas_rgba, ksize=(25, 25), dst=canvas_rgba)

    canvas_rgba[:,:,0:3] = canvas_rgba[:,:,0:3] * 255.0 / canvas_rgba[:,:,[3,3,3]]

    pygame.surfarray.blit_array(newCanvas, canvas_color)
    return newCanvas

pygame.init()
window = pygame.display.set_mode((800, 300))
clock = pygame.time.Clock()

background = pygame.Surface(window.get_size())
ts, w, h, c1, c2 = 100, *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]

surface = pygame.Surface((250, 250), pygame.SRCALPHA)
pygame.draw.circle(surface, (255, 255, 255), surface.get_rect().center, 100)
surface1 = Bloom(surface)
surface2 = Bloom(surface)
surface3 = BloomNoPremultipliedAlpha(surface)

run = True
while run:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False 

    window.blit(background, (0, 0))
    window.blit(surface1, surface1.get_rect(center = (150, 150)))
    window.blit(surface2, surface2.get_rect(center = (400, 150)), special_flags = pygame.BLEND_PREMULTIPLIED)
    window.blit(surface3, surface1.get_rect(center = (650, 150)))
    pygame.display.flip()
    clock.tick(60)

pygame.quit()
exit()
  • Related