opencv / opencv

Open Source Computer Vision Library
https://opencv.org
Apache License 2.0
75.95k stars 55.62k forks source link

interpolation blend colors even when fully transparent #25473

Open Edu371 opened 3 weeks ago

Edu371 commented 3 weeks ago

System Information

OpenCV python version: 4.9.0.80 Operating System / Platform: Windows 10 Python version: 3.11.2

Detailed description

when using any type of interpolation the border matches background color, which is expected, the problem is that even when the background alpha is 0, it is still blending the others RGB channels

Steps to reproduce

import numpy as np
import math
from PIL import Image, ImageDraw

height = 100
width = 500

image =  Image.new("RGBA", (width, height), (0, 0, 0, 0))
draw = ImageDraw.Draw(image)
draw.rounded_rectangle((5, 5, width-5, height-5), fill='#0000ff', radius=10)

image = np.array(image.getdata(), dtype=np.uint8).reshape(height, width, 4)

angleInDegrees = 4

h, w = image.shape[:2]
img_c = (w / 2, h / 2)

rot = cv2.getRotationMatrix2D(img_c, angleInDegrees, 1)

rad = math.radians(angleInDegrees)
sin = math.sin(rad)
cos = math.cos(rad)
b_w = math.ceil((h * abs(sin)) + (w * abs(cos)))
b_h = math.ceil((h * abs(cos)) + (w * abs(sin)))

rot[0, 2] += ((b_w / 2) - img_c[0])
rot[1, 2] += ((b_h / 2) - img_c[1])

outImg = cv2.warpAffine(image, rot, (b_w, b_h), flags=cv2.INTER_LINEAR)

out_pil = Image.fromarray(outImg)
bg =  Image.new("RGBA", out_pil.size, (255, 255, 255, 255))
bg.paste(out_pil, (0, 0), out_pil)

black

image =  Image.new("RGBA", (width, height), (255, 0, 0, 0))

red

image =  Image.new("RGBA", (width, height), (0, 255, 0, 0))

green

zoom in the images to see

Issue submission checklist

asmorkalov commented 3 weeks ago

warpAffine applies interpolation to all channels, including alpha. It means, that alpha value on rectangle border is not strictly 0 or 255.

Edu371 commented 3 weeks ago

yes, but the problem is that when the background color is (255, 0, 0, 0) it is interpolating to red even though alpha is 0.

when image background is RGBA (0, 0, 0, 0) black_zoomed

when image background is RGBA (255, 0, 0, 0) red_zoomed

when image background is RGBA (0, 255, 0, 0) green_zoomed

background is fully transparent so it be (0, 0, 0, 0) or (255, 0, 0, 0) or (0, 255, 0, 0) should produce same results, the RGB channels should be ignored when alpha is 0

this wikipedia articles describes this problem https://en.wikipedia.org/wiki/Alpha_compositing#Comparison The most significant advantage of premultiplied alpha is that it allows for correct blending, interpolation, and filtering. Ordinary interpolation without premultiplied alpha leads to RGB information leaking out of fully transparent (A=0) regions, even though this RGB information is ideally invisible. When interpolating or filtering images with abrupt borders between transparent and opaque regions, this can result in borders of colors that were not visible in the original image. Errors also occur in areas of semitransparency because the RGB components are not correctly weighted, giving incorrectly high weighting to the color of the more transparent (lower alpha) pixels.

Edu371 commented 2 weeks ago

@asmorkalov i provided more info about this ussue please reconcider