首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python -解析图像上的对象

Python -解析图像上的对象
EN

Stack Overflow用户
提问于 2017-09-05 18:17:47
回答 1查看 384关注 0票数 3

我需要检测图像上的物体从简单的游戏Chrome。我使用Python和Selenium开始游戏,并加载Canvas。主要目标是检测图像上的物体并找到Dyno和Dyno屏障。

我使用这段代码,使用OpenCV、cv2库解析图片上的所有对象。在这个代码下面(两个主要函数),大约需要80-200毫秒(根据障碍物大小)来识别所有对象。

`

代码语言:javascript
复制
# 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完成了这个任务。

EN

回答 1

Stack Overflow用户

发布于 2017-09-06 06:49:52

帮助加快速度的三大建议归结为同一件事:将图像的不同部分分割为处理管道的不同部分。有一个额外的速度,可以获得通过寻找不同的对象。这两个目标是查找dino位置,并在图像中找到新对象的位置。

加速比1

移除图像中the和对象不存在的部分.我指的是框架的上半部分。对象不在这里,这大大减少了搜索空间。

加速比2

我在你的帖子的评论中提到了这一点。不要在整个画面中寻找the。你知道the会在框架内的一些水平边界内停留,并且只垂直移动。模板匹配肯定是一个缓慢的过程,因此您将得到一个大的加速通过减少搜索区域。您可以通过使用更小的模板和更小的搜索区域来进一步完善这一点。再一次,你知道the会在某个区域,这意味着the的头或尾会在一个较小的区域--所以在这个区域搜索头尾或者任何东西。通过将搜索区域缩小到最后一个帧中的位置,您可以再次细化这一点。例如,我是在追踪马里奥中这样做的;您可以看到白色搜索区域框,它在马里奥的头部位于最后一帧的位置附近移动。

加速比3

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

加速比4

请注意,您可以简单地通过“地面”线下的仙人掌底部来检测仙人掌。看起来类似高度的仙人掌有相似的宽度,所以如果你发现一个块,比如4像素宽,你知道仙人掌实际上比两边高出8个像素,有30像素高,或者不管实际值是多少。这会把你的问题变成探测仙人掌的底部而不是完整的仙人掌,大大减少了你对仙人掌的搜索范围。此外,您甚至不需要用这种方法找到等高线!您可以简单地在图像的底部查找块,并在它们小于预定义的距离时将它们组合在一起。这应该更快些。如果你这样做的话,你可能不需要担心仅仅检测到正确的边界上的物体,然后在新的frames...if中计算它们的新位置--你只需要为它们寻找一个4px宽的条带,它可能不会比找到每个帧快得多。

其他建议

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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46061089

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档