Python - 解析图像上的对象

标签 python opencv image-processing

我需要从简单的游戏 Chrome Dyno 检测图像上的对象。我正在使用 Python 和 Selenium 启动游戏,并加载 Canvas Image。主要任务,它检测此图像上的对象并找到 Dyno 和 Dyno Barriers。

enter image description here

我正在使用此代码,使用 OpenCV 解析图片上的所有对象,cv2图书馆。
在此代码下方(两个主要功能),识别所有对象需要大约 80 - 200 毫秒(基于障碍大小)。

`

# Finding only dino object based on Template.
# This might be optimized later with searching by contours

def find_dino__(self, cv2_image):
    result = cv2.matchTemplate(cv2_image.astype(np.uint8), self.dino_image, cv2.TM_CCOEFF)
    _, _, _, dino_top_left = cv2.minMaxLoc(result)
    dino_bottom_right = (dino_top_left[0] + self.dino_width, dino_top_left[1] + self.dino_height)
    return GenericGameObject(dino_top_left, dino_bottom_right)

# Find other Barrier Objects, based on position, and except
# that, which behind Dino location. Use Dino position.
def find_dino_barriers__(self, cv2_image, dino_object):
    img_fil = cv2.medianBlur(cv2.cvtColor(cv2_image, cv2.COLOR_BGR2GRAY), 13)
    img_th = cv2.adaptiveThreshold(img_fil, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
    im2, contours, hierarchy = cv2.findContours(img_th, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

    objects = []
    for i in range(len(contours)):
        x, y, w, h = cv2.boundingRect(contours[i])
        if y < Settings.DINO_WORKING_Y_AREA[0] \
                or y > Settings.DINO_WORKING_Y_AREA[1]:
            continue
        if x <= dino_object.top_right_point[0]\
                and y <= dino_object.top_right_point[1]:
            continue
        objects.append(GenericGameObject((x, y), (x + w, y + h)))

    return objects

`

我的目标是减少这个时间 ,尽可能使游戏可用于其他脚本。顺便说一句,我启发了 IAMDinosaur 项目,其中使用 JS 和 Robot JS 完成了这项任务。

最佳答案

有助于提高速度的三大建议都归结为同一件事:将图像的不同部分拆分为处理管道的不同部分。通过寻找不同的对象可以获得额外的加速。这两个目标是找到恐龙位置,以及找到图像中新物体的位置。

加速1

删除霸王龙和物体不在的图像部分。我的意思是框架的上半部分(ish)。对象不在此处,这大大减少了搜索空间。

加速2

我在您帖子的评论中提到了这一点。不要在整个框架中寻找霸王龙。您知道霸王龙会在画面中的某些水平边界内停留,并且只能垂直移动。模板匹配绝对是一个缓慢的过程,因此您将通过减少搜索区域获得很大的加速。您可以通过使用更小的模板和更小的搜索区域来进一步细化。同样,您知道霸王龙将在某个部分,这意味着您知道霸王龙的头部或尾部将位于某个较小的区域——因此在该区域搜索头部或尾部或任何其他内容。您可以通过将搜索区域缩小到它在最后一帧中的位置来进一步细化。我是这样做的 tracking Mario例如;您可以看到白色的搜索区域框,它会在最后一帧中马里奥的头部所在的位置移动。

加速3

请注意,您只需要找到新对象...您知道滚动的速度,因此您知道一旦检测到对象移动的速度以及它们在下一帧中的位置。对象不是整个框架的宽度,它们一次只占框架的一部分。因此,实际上您只需要搜索从屏幕右侧进入的新对象。然后你可以标记它们(它们的宽度、高度、位置)并在此之后计算它们的位置,而不是每帧再次找到它们。现在,您的轮廓搜索仅发生在较小的帧子集中(更快),并且您循环遍历的轮廓更少(更快)。

加速4

请注意,您可以简单地通过“地面”线下方的仙人掌底部来检测仙人掌。看起来相似高度的仙人掌具有相似的宽度,所以如果你检测到一个块,比如 4 像素宽,你就会知道仙人掌实际上在两侧延伸了 8 像素,高 30 像素,或者不管实际值是什么。这会将您的问题变成检测仙人掌的基部而不是完整的仙人掌,并极大地减少了仙人掌的搜索区域。此外,您甚至不需要使用这种方法找到轮廓!您可以简单地查找图像底部的块,并在它们相距小于某个预定义距离时将它们组合在一起。这应该更快。如果你这样做,你可能不需要担心只检测右边界的对象,然后计算它们在新帧中的新位置......如果你只为它们查看 4px 宽的 strip ,那就是可能不会比每帧找到它们快多少。

其他建议

我真的不明白模糊和自适应阈值的意义。图像实际上已经是二进制的;黑色或非黑色像素。也许这是一种将多个单独的对象(如单个仙人掌)组合成一个组的方法?无论哪种方式,都可能有更好(更快)的方法来做到这一点;例如,如果您腐 eclipse 了图像(这会扩大暗像素),那么仙人掌会合并。我认为这会更快,但您需要进行测试。如果你这样做了,你的轮廓就会比它们的实际宽度大一点,但是你可以通过使边界框缩小多少像素来进行补偿。当然,如果您实现加速 4,这并不重要,但这是需要考虑的。

关于Python - 解析图像上的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46061089/

相关文章:

opencv - 光流适用于放大和缩小

python - 如何使用 pandas 将 JSON 或 DICT 传递到数据框中?

python - 来自 socket() 的 UDP 数据包 header 与预期不符

c++ - 在 openCV 中循环遍历带有蒙版的图像

python - Ubuntu从14.10更新到16.04后,为什么python找不到libavcodec.so.54?

c++ - 如何计算OpenCV中颜色段中的像素

python - 如何将数据集加载到 Jupyter Notebook 中

Python 设置要捕获的参数数量

android - 使用 Android OpenCV 在图像中检测到图案时拍照

Matlab人脸对齐代码