我正在进行一个OpenCV项目,需要一些帮助。我从电脑游戏(例如《堡垒之夜》)中获取图像,并希望从中提取不同的元素,例如计时器值、材料数量、生命值和护盾等。
目前,我执行了一系列图像预处理功能,直到得到二值图像,然后定位图像中的轮廓,并将这些轮廓发送到机器学习算法(K-最近邻)。
在很多情况下我都能成功,但有些图像中我无法找到某些轮廓,因此无法获取所有数据。
需要注意的是,我对所有图像使用相同的预处理流程,因为我希望找到尽可能稳健的解决方案。
我想知道我可以做些什么来提高程序的性能。
- KNN是否适合这种任务,或者是否有其他模型可以提供更好的结果?
- 是否有不需要定位轮廓就能识别字符的方法?
- 考虑到所有图像的背景差异很大,如何使我的预处理流程尽可能稳健?
我的目标是尽可能快地处理图像,起始速度至少要达到每秒2张图像。
提前感谢您能提供的任何帮助或建议!
- 这是一张预处理前的示例图像
- 这是预处理后的图像,在这个例子中,我无法找到右侧的数字4的轮廓。
回答:
简单来说,放大图像可能会有所帮助,因为这会增加数字的暗边框。
我拼凑了一些实现这一功能的代码。结果可以进一步改进,但我的重点是展示现在可以检测到数字4的轮廓。为了提高效率,我只选择了特定大小的轮廓。
此外,由于这是HUD的一部分,通常意味着屏幕上的位置总是相同的。如果是这样,您可以通过仅选择有数值的区域(如这里所述)来大幅提高性能 – 我已经手动完成了这一步骤。
最后,由于数字形状一致,您可以尝试使用matchShapes作为kNN的替代方案来识别数字。不过,我不知道它们的性能对比如何,所以您需要自己尝试一下。
代码:
import numpy as np import cv2# load imageimg = cv2.imread("fn2.JPG")# enlarge imageimg = cv2.resize(img,None,fx=4, fy=4, interpolation = cv2.INTER_CUBIC)# convert to grayscalegray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)# create mask using thresholdret,mask = cv2.threshold(gray,200,255,cv2.THRESH_BINARY)# find contours in maskim, contours, hierarchy = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)# draw contour on imagefor cnt in contours: if cv2.contourArea(cnt) < 3000 and cv2.contourArea(cnt) > 200: cv2.drawContours(img, [cnt], 0, (255,0,0), 2)#show imagescv2.imshow("Mask", mask)cv2.imshow("Image", img)cv2.waitKey(0)cv2.destroyAllWindows()