我正在处理一个涉及视频帧操作的项目,其中一项要求就是在帧上添加平滑圆角。我研究过如何使用PIL或其他图像处理库给图片添加圆角,但它们产生的效果都是较为粗糙的,看起来不够专业。
这是我尝试过的代码:
def add_corners(im, rad):
circle = Image.new('L', (rad * 2, rad * 2), 0)
draw = ImageDraw.Draw(circle)
draw.ellipse((0, 0, rad * 2 - 1, rad * 2 - 1), fill=255)
alpha = Image.new('L', im.size, 255)
w, h = im.size
alpha.paste(circle.crop((0, 0, rad, rad)), (0, 0))
alpha.paste(circle.crop((0, rad, rad, rad * 2)), (0, h - rad))
alpha.paste(circle.crop((rad, 0, rad * 2, rad)), (w - rad, 0))
alpha.paste(circle.crop((rad, rad, rad * 2, rad * 2)), (w - rad, h - rad))
im.putalpha(alpha)
return im
im = Image.open('sand.png')
im = add_corners(im, 50)
im.save('sand_corner.png')
如上面的截图所示,这种方法得到的结果中,圆角显得很粗糙且存在明显的像素化现象,不像在Figma中使用iOS风格的圆角那样平滑:
我也参考了Stack Overflow上的一个问题,该问题也提出了同样的需求,但是没有展示具体的实现代码:链接
我希望在添加圆角时确保帧的质量不受损失,圆角应当平滑,并且最好能达到Figma中那种平滑度。
编辑更新:
out = cv2.VideoWriter('assets/pathToSave.mp4', fourcc, fps, (1920, 1080))
def generate_frame():
while cap.isOpened():
code, frame = cap.read()
if code:
yield frame
else:
print("完成")
break
for i, frame in enumerate(generate_frame()):
# 将OpenCV帧转换为PIL图像
img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
im_pil = Image.fromarray(img)
ss = 4
alpha = Image.new('L', (im.width*ss, im.height*ss))
# 绘制圆角矩形并进行下采样
d = ImageDraw.Draw(alpha)
d.rounded_rectangle([0,0,im.width*ss-1,im.height*ss-1],radius=120,fill='white')
alpha = alpha.resize((alpha.width//ss, alpha.height//ss), resample=Image.Resampling.LANCZOS)
alpha.save('DEBUG-alpha.png')
# 将新透明通道应用到原始图像并保存
im_pil.putalpha(alpha)
im_np = np.array(im_pil.convert('RGB'))
open_cv_image = im_np[:, :, ::-1].copy()
outputVideo.write(open_cv_image)
为了从传入的视频帧中添加圆角,我尝试了上述代码,但仍然得到了粗糙的圆角:
请看白色边框部分,透明的圆角实际上是背景的一部分,在视频渲染在其上时显现出来的。