Reb*_*cca 0 python text pygame glow python-3.x
我想复制 Watson-scott 测试中显示的效果,其中文本似乎会发光。示例链接:https://www.youtube.com/watch?v =2ySNm4gltkE
跳到 11:17,文字似乎在发光;我如何用 pygame 复制这种效果?我尝试在文本背景中添加一个灰色矩形,但它看起来很糟糕。我也尝试像这个例子一样对文本进行阴影处理,但没有任何效果。
我也在使用Python 3.7.4。感谢您的帮助,我真的需要它!
Thy*_*men 12
有时我们可以说这是不可能的,但很多时候这并不是该软件包的主要目标。尽管如此,让我们看看能否解决这个问题。
我冒昧地假设除此之外pygame
还允许使用其他包,但最终结果应该在pygame
. 为了创建绽放/发光效果,我使用了包opencv-python
(cv2)和numpy
(np)。
该解决方案的第一部分将讨论创建发光边框和一些发光文本。第二部分将讨论如何在表面上渲染它pygame
。
TL;博士; 跳到下面的摘要部分并将代码复制到各自的文件中。
为了获得一些漂亮的发光边框和文本,我们可以使用opencv的模糊功能,也称为平滑。由于我们想要创建不同强度的发光,因此我们首先应用GaussianBlur
, 在图像周围创建一些随机模糊度,然后使用法线 扩展该模糊度blur
。
def apply_blooming(image: np.ndarray) -> np.ndarray:
# Provide some blurring to image, to create some bloom.
cv2.GaussianBlur(image, ksize=(9, 9), sigmaX=10, sigmaY=10, dst=image)
cv2.blur(image, ksize=(5, 5), dst=image)
return image
Run Code Online (Sandbox Code Playgroud)
ksize
注意:内核大小 ( ) 和西格玛 (sigmaX
和)的值是sigmaY
根据经验选择的,您可以稍微调整一下这些值,直到得到您想要的值。
一个小插曲,因为我们需要提供一些非常漂亮的可怕的颜色,所以下面的类包含一些(可怕的)颜色。
class Colors:
WHITE_ISH = (246, 246, 246)
YELLOW_ISH = (214, 198, 136)
RED_ISH = (156, 60, 60)
Run Code Online (Sandbox Code Playgroud)
为了获得发光边框,创建了一个辅助函数,它将绘制一个具有一些预定义属性的矩形。所选属性为:
def create_border(image: np.ndarray, margin: int, thickness: int, color: Colors) -> np.ndarray:
"""
Create a normal border around an image, with specified colors.
Args:
image: The image, that requires a border.
margin: The border distance from the sides of the image.
thickness: The thickness of the border.
color: The border color, by default a slightly yellow color.
Modifies:
The input image, will be modified with a border.
Returns:
The same image, with a border inserted.
"""
# Numpy uses the convention `rows, columns`, instead of `x, y`.
# Therefore height, has to be before width.
height, width = image.shape[:2]
cv2.rectangle(image, (margin, margin), (width - margin, height - margin), color, thickness=thickness)
return image
Run Code Online (Sandbox Code Playgroud)
apply_blooming
然后可以使用和函数绘制最终边框create_border
。
def glowing_border(image: np.ndarray, margin=20, thickness=10, color: Colors = Colors.WHITE_ISH):
"""
Create a glowing border around an image.
Args:
image: The image, that requires a border.
margin: The border distance from the sides of the image.
thickness: The thickness of the border.
color: The border color, by default a slightly yellow color.
Modifies:
The input image, will be modified with a blooming border.
Returns:
The same image, with a blooming border inserted.
"""
# Generate yellowish colored box
image = create_border(image, margin, thickness, color)
# Apply the blooming.
image = apply_blooming(image)
# Reassert the original border, to get a clear outline.
# Similar to the Watson-Scott test, two borders were added here.
image = create_border(image, margin - 1, 1, color)
image = create_border(image, margin + 1, 1, color)
return image
Run Code Online (Sandbox Code Playgroud)
为了测试发光边框,我们可以使用cv2.imshow
, 来显示图像。由于我们稍后将使用此功能,因此创建了一个小函数。该函数将图像和显示时间(代码继续执行之前的等待时间)作为输入。
def show(image, delay=0):
"""
Display an image using cv2.
Notes:
By default cv2 uses the BGR coloring, instead RGB.
Hence image shown by cv2, which are meant to be RGB,
has to be transformed using `cvtColor`.
Args:
image: Input image to be displayed
delay: Time delay before continuing running.
When 0, The program will wait until a key stroke or window is closed.
When 1, The program will continue as quickly as possible.
Returns:
Nothing, it displays the image.
"""
cv2.imshow('Test', cv2.cvtColor(image, cv2.COLOR_RGB2BGR))
cv2.waitKey(delay)
Run Code Online (Sandbox Code Playgroud)
实际测试代码:
image = np.zeros((480, 640, 3), dtype=np.uint8)
border = glowing_border(image.copy(), color=Colors.YELLOW_ISH)
show(border, delay=0)
Run Code Online (Sandbox Code Playgroud)
类似的方法可以用于发光文本,通过使用cv2.putText
.
def glowing_text(image: np.ndarray, text: str, org: Tuple[int, int], color: Colors) -> np.ndarray:
"""
Args:
image: The image, that requires a border.
text: The text to be placed on the image.
org: The starting location of the text.
color: The color of the text.
Modifies:
The input image, will be modified with a blooming text.
Returns:
The same image, with a blooming text inserted.
"""
image = cv2.putText(image, text, org, cv2.FONT_HERSHEY_COMPLEX_SMALL, fontScale=.7, color=color, thickness=1)
image = apply_blooming(image)
image = cv2.putText(image, text, org, cv2.FONT_HERSHEY_COMPLEX_SMALL, fontScale=.7, color=color, thickness=1)
return image
Run Code Online (Sandbox Code Playgroud)
有测试代码
image = np.zeros((480, 640, 3), dtype=np.uint8)
text = glowing_text(image.copy(), text="Welcome to this game", org=(50, 70), color=Colors.YELLOW_ISH)
show(text, delay=0)
Run Code Online (Sandbox Code Playgroud)
在我继续展示如何在 中显示它之前pygame
,我将添加一个额外的内容并展示文本如何显示在屏幕上,就好像一个人正在慢慢地输入它一样。以下代码之所以有效,是因为我们分别绘制边框和文本,然后使用np.bitwise_or
.
image = np.zeros((480, 640, 3), dtype=np.uint8)
# Create the glowing border, and a copy of the image, for the text, that will be placed on it later.
border = glowing_border(image.copy(), color=Colors.YELLOW_ISH)
text = image.copy()
# This message will be incrementally written
message = "Welcome to this game. Don't be scared :)."
for idx in range(len(message) + 1):
text = glowing_text(image.copy(), text=message[:idx], org=(50, 70), color=Colors.YELLOW_ISH)
# We use a random time delay between keystrokes, to simulate a human.
show(np.bitwise_or(border, text), delay=np.random.randint(1, 250))
# Pause the screen after the full message.
show(np.bitwise_or(border, text), delay=0)
Run Code Online (Sandbox Code Playgroud)
注意:或者,我们可以首先在同一图像上生成边框和文本,然后应用绽放滤镜。请记住,我们必须再次重新绘制边框和文本,为它们提供坚实的基础。
现在我们可以生成具有正确的绽放边框和文本的画布,必须将其插入到pygame
. 让我们将所有以前的函数放入一个名为 的文件中blooming.py
,并在新文件中引用它game.py
。
以下代码是如何将 numpy 数组放入 pygame 的最小工作示例。
import contextlib
from typing import Tuple
# This suppresses the `Hello from pygame` message.
with contextlib.redirect_stdout(None):
import pygame
import numpy as np
import blooming
def image_generator(size: Tuple[int, int], color: blooming.Colors):
image = np.zeros((*size[::-1], 3), dtype=np.uint8)
# Create the glowing border, and a copy of the image, for the text, that will be placed on it later.
border = blooming.glowing_border(image.copy(), color=color)
text = image.copy()
# This message will be incrementally written
message = "Welcome to this game. Don't be scared :)."
for idx in range(len(message) + 1):
text = blooming.glowing_text(image.copy(), text=message[:idx], org=(50, 70), color=color)
yield np.bitwise_or(border, text)
return np.bitwise_or(border, text)
if __name__ == '__main__':
pygame.init()
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
running = True
while running:
for image in image_generator(screen.get_size(), color=blooming.Colors.YELLOW_ISH):
screen.fill((0, 0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
# This is where we insert the numpy array.
# Because pygame and numpy use different coordinate systems,
# the numpy image has to be flipped and rotated, before being blit.
img = pygame.surfarray.make_surface(np.fliplr(np.rot90(image, k=-1)))
screen.blit(img, (0, 0))
pygame.display.flip()
clock.tick(np.random.randint(10, 30))
pygame.quit()
Run Code Online (Sandbox Code Playgroud)
blooming.py
from typing import Tuple
import cv2
import numpy as np
class Colors:
WHITE_ISH = (246, 246, 246)
YELLOW_ISH = (214, 198, 136)
RED_ISH = (156, 60, 60)
def create_border(image: np.ndarray, margin: int, thickness: int, color: Colors) -> np.ndarray:
"""
Create a normal border around an image, with specified colors.
Args:
image: The image, that requires a border.
margin: The border distance from the sides of the image.
thickness: The thickness of the border.
color: The border color, by default a slightly yellow color.
Modifies:
The input image, will be modified with a border.
Returns:
The same image, with a border inserted.
"""
# Numpy uses the convention `rows, columns`, instead of `x, y`.
# Therefore height, has to be before width.
height, width = image.shape[:2]
cv2.rectangle(image, (margin, margin), (width - margin, height - margin), color, thickness=thickness)
return image
def apply_blooming(image: np.ndarray) -> np.ndarray:
# Provide some blurring to image, to create some bloom.
cv2.GaussianBlur(image, ksize=(9, 9), sigmaX=10, sigmaY=10, dst=image)
cv2.blur(image, ksize=(5, 5), dst=image)
return image
def glowing_border(image: np.ndarray, margin=20, thickness=10, color: Colors = Colors.WHITE_ISH):
"""
Create a glowing border around an image.
Args:
image: The image, that requires a border.
margin: The border distance from the sides of the image.
thickness: The thickness of the border.
color: The border color, by default a slightly yellow color.
Modifies:
The input image, will be modified with a blooming border.
Returns:
The same image, with a blooming border inserted.
"""
# Generate yellowish colored box
image = create_border(image, margin, thickness, color)
# Apply the blooming.
image = apply_blooming(image)
# Reassert the original border, to get a clear outline.
# Similar to the Watson-Scott test, two borders were added here.
image = create_border(image, margin - 1, 1, color)
image = create_border(image, margin + 1, 1, color)
return image
def glowing_text(image: np.ndarray, text: str, org: Tuple[int, int], color: Colors) -> np.ndarray:
"""
Args:
image: The image, that requires a border.
text: The text to be placed on the image.
org: The starting location of the text.
color: The color of the text.
Modifies:
The input image, will be modified with a blooming text.
Returns:
The same image, with a blooming text inserted.
"""
image = cv2.putText(image, text, org, cv2.FONT_HERSHEY_COMPLEX_SMALL, fontScale=.7, color=color, thickness=1)
image = apply_blooming(image)
image = cv2.putText(image, text, org, cv2.FONT_HERSHEY_COMPLEX_SMALL, fontScale=.7, color=color, thickness=1)
return image
def show(image, delay=0):
"""
Display an image using cv2.
Notes:
By default cv2 uses the BGR coloring, instead RGB.
Hence image shown by cv2, which are meant to be RGB,
has to be transformed using `cvtColor`.
Args:
image: Input image to be displayed
delay: Time delay before continuing running.
When 0, The program will wait until a key stroke or window is closed.
When 1, The program will continue as quickly as possible.
Returns:
Nothing, it displays the image.
"""
cv2.imshow('Test', cv2.cvtColor(image, cv2.COLOR_RGB2BGR))
cv2.waitKey(delay)
if __name__ == '__main__':
image = np.zeros((480, 640, 3), dtype=np.uint8)
# Create the glowing border, and a copy of the image, for the text, that will be placed on it later.
border = glowing_border(image.copy(), color=Colors.YELLOW_ISH)
text = image.copy()
# This message will be incrementally written
message = "Welcome to this game. Don't be scared :)." + " " * 10
for idx in range(len(message) + 1):
text = glowing_text(image.copy(), text=message[:idx], org=(50, 70), color=Colors.YELLOW_ISH)
# We use a random time delay between keystrokes, to simulate a human.
show(np.bitwise_or(border, text), delay=np.random.randint(1, 250))
# Pause the screen after the full message.
show(np.bitwise_or(border, text), delay=0)
Run Code Online (Sandbox Code Playgroud)
game.py
import contextlib
from typing import Tuple
# This suppresses the `Hello from pygame` message.
with contextlib.redirect_stdout(None):
import pygame
import numpy as np
import blooming
def image_generator(size: Tuple[int, int], color: blooming.Colors):
image = np.zeros((*size[::-1], 3), dtype=np.uint8)
# Create the glowing border, and a copy of the image, for the text, that will be placed on it later.
border = blooming.glowing_border(image.copy(), color=color)
text = image.copy()
# This message will be incrementally written
message = "Welcome to this game. Don't be scared :)." + " " * 10
for idx in range(len(message) + 1):
text = blooming.glowing_text(image.copy(), text=message[:idx], org=(50, 70), color=color)
yield np.bitwise_or(border, text)
return np.bitwise_or(border, text)
if __name__ == '__main__':
pygame.init()
screen = pygame.display.set_mode((640, 480))
clock = pygame.time.Clock()
running = True
while running:
for image in image_generator(screen.get_size(), color=blooming.Colors.YELLOW_ISH):
screen.fill((0, 0, 0))
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
running = False
# This is where we insert the numpy array.
# Because pygame and numpy use different coordinate systems,
# the numpy image has to be flipped and rotated, before being blit.
img = pygame.surfarray.make_surface(np.fliplr(np.rot90(image, k=-1)))
screen.blit(img, (0, 0))
pygame.display.flip()
clock.tick(np.random.randint(10, 30))
pygame.quit()
Run Code Online (Sandbox Code Playgroud)
请注意,真实的东西看起来比这张图片清晰得多。另外,调整文本的粗细和模糊滤镜的大小也会对结果产生很大的影响。对于此图像, 的ksize
已GaussianBlur
增加至(17, 17)
,并且sigmaX
和sigmaY
均已设为 100。
归档时间: |
|
查看次数: |
3967 次 |
最近记录: |