前言
昨天在我的博客中已经做了一个用python-OpenCV实现魔方墙找茬 的程序,具体可查看https://blog.csdn.net/FujLiny/article/details/109494251
现在在第1版的基础上,加上分值计算、倒计时、记录存储三部分功能。这篇文章主要讲解一下倒计时的效果该如何做出来。
先展示一下最终的效果:
为了达到更有趣味性,设置了游戏规则:
初始时间为36秒,找到一个小方块时间加2.3秒,
根据设置的小方块尺寸和数量不同,单次分数计算规则:方块数量 * (1080/单个方块宽度)
程序实现过程
这里主要分析一下如何把时间和分值实时地显示在图像上,其他的内容可自行阅读代码进行修改、分析。
OpenCV有一个putText()函数,可以在图像上添加文本内容,利用此函数就可以把倒计时和分数写在图像上进行显示。
程序实现过程如下:
- 创建一个黑色背景并覆盖在图像中间的黑色区域
- 把文本内容–倒计时和分数 添加到图像上
- 等待20毫秒 waitKey(20)
- 回到第1步执行
1.创建一个黑色画布并覆盖在图像中间的黑色区域
# self.height 画布的高度
# self.interval 左右画布中间黑色区域的间距
self.imgInterval = np.zeros((self.height, self.interval,3), 'uint8')
self.img[0:self.height, self.height:self.height + self.interval] = self.imgInterval
就是在上图橙色箭头的那一个黑色区域,创建的黑色画布的尺寸也必须刚好就是那一块区域的大小,否则会遮盖掉旁边的颜色块。
有些人可能会疑问,为什要创建这个黑色画布去覆盖原来的黑色背景?不是多此一举吗?
这一步当然是重要的步骤,如果不这样做的话,那么接下来的步骤中,每次在图像上写入的文本就会重叠在上一个文本上面。
2.把文本内容–倒计时和分数 添加到图像上
这里对先 putText() 函数的参数进行解释一下:
# 关于 putText() 函数的定义
def putText(img, text, org, fontFace, fontScale, color, thickness=None, lineType=None, bottomLeftOrigin=None)
img:要显示的GUI窗口
text:要写入图像的文本内容
org:写入的位置 (x, y)
fontFace:字体样式 (OpenCV自带有几种字体样式,例如 cv.FONT_HERSHEY_SIMPLEX)
fontScale:字体大小
color:颜色 (r,g,b)
thickness:线条的宽度
lineType:线条类型(lineType = cv.LINE_AA可以有抗锯齿的效果)
bottomLeftOrigin:如果为True,文字从右往左写,如果为False,文字从左往右写。
在执行 putText() 函数之前,先定义字体样式和字体大小:
self.font = cv.FONT_HERSHEY_SIMPLEX
self.fontsize = self.interval / 120
self.fontsize = 0.5 if len(str(self.score)) > 5 else self.fontsize
self.fontsize = 0.45 if len(str(self.score)) > 6 else self.fontsize
# 字体大小 fontsize为什么要这么定义,读者朋友可以不用太在意。
# len(str(self.score))是对要分数这个文本内容进行长度判断,
# 如果长度超过5位数或6位数的话,就要缩小一点字体的大小,否则可能会超出中间的黑色区域
执行 putText() 函数,在图像上写入文本:
# self.score 分数 timeRemain 倒计时
cv.putText(self.img, str(self.score), self.org, self.font, self.fontsize, (255, 255, 255), 1, cv.LINE_AA,False)
cv.putText(self.img, str(timeRemain), self.org_2, self.font, self.fontsize, (255, 255, 255), 1, cv.LINE_AA,False)
现在就成功地在图像上写入文本内容了
3. 等待20毫秒 waitKey(20)
等待20毫秒后,回到第一步重新用黑色画布覆盖在中间的黑色区域,继续往图像上添加文本,就可以实现倒计时的效果了。
while True:
self.img[0:self.height, self.height:self.height + self.interval] = self.imgInterval
self.fontsize = 0.5 if len(str(self.score)) > 5 else self.fontsize
self.fontsize = 0.45 if len(str(self.score)) > 6 else self.fontsize
cv.putText(self.img, str(self.score), self.org, self.font, self.fontsize, (255, 255, 255), 1, cv.LINE_AA)
cv.putText(self.img, str(timeRemain), self.org_2, self.font, self.fontsize, (255, 255, 255), 1, cv.LINE_AA,False)
cv.imshow('img', self.img)
if cv.waitKey(20) == 13 or timeRemain <= 0:
break
数据存储
这个2.0版本还增加了对每次的数据进行存储,每次获得的分数记录都会被存储下来,这里采用json文件进行存储,具体存储过程就不展开讲述了,可以自行查看源代码,这里简单对json文件的结构说明一下。
当倒计时结束后就会对分数进行存储,根据时间、方块数量、方块尺寸、单次的分值等进行存储,也会对最高分、排名前二十、每一次刷新的最高分进行存储。
总结
这个版本主要是完善了在图像上显示倒计时的功能,如果大家要用OpenCV制作一段文本变换的视频不妨可以参考这个方式。
下载代码
程序源代码已经上传,点击下载:https://download.csdn.net/download/FujLiny/13090460