【问题标题】:Find an image inside of a video using python使用python在视频中查找图像
【发布时间】:2017-05-11 05:50:12
【问题描述】:

我想知道我是否以正确的方式进行此操作,或者是否有更有效的方式。

我正在尝试在视频中查找图像,例如在视频的每一帧中,该图像可能包含在其中的某个位置(它不是全尺寸的帧,只是一个小帧)。

目前正在将视频拉成这样的图片:

import cv2
vidcap = cv2.VideoCapture('My_Video.mp4')
success,image = vidcap.read()
count = 0
success = True
while success:
  success,image = vidcap.read()
  print ('Read a new frame: ', success)
  cv2.imwrite("frame%d.jpg" % count, image)     # save frame as JPEG file
  count += 1

然后循环遍历它们:

import cv2
import numpy as np
from matplotlib import pyplot as plt

img_rgb = cv2.imread('frame1.png')
img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)
template = cv2.imread('small_icon_I_am_looking_for.png',0)
w, h = template.shape[::-1]

res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
threshold = 0.8
loc = np.where( res >= threshold)
for pt in zip(*loc[::-1]):
    cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)

cv2.imwrite('res.png',img_rgb)

有没有办法跳过图片的保存?我在数千小时的视频中执行此操作,并且保存和删除我觉得会使用大量可能不需要的时间的每一帧。有什么想法可以在不需要每次都保存图片的情况下进行搜索吗?这是我的意思的一个例子,比如说有一个超级马里奥正在播放的视频,它会寻找这个硬币:

并这样检测它:

这目前有效,但只是在寻找更好的方法。

【问题讨论】:

  • 您在阅读图像时不能处理它们吗?还是您的意思是避免在第二部分中保存迷你帧?
  • 我的意思是在第一部分,只是不知道该怎么做。你知道吗,我没有经常使用这种代码,这是我能做的最好的。
  • 答案已添加,但我可能误解了你。在 cmets 中告诉我。
  • 这也将保存可能会杀死您计算机内存的每一帧。也许您可以添加一个条件以仅在找到该值时才保存帧?取决于你想做什么。

标签: python python-3.x image-recognition cv2


【解决方案1】:

如果我没有误解你,下面的应该可以工作。总体而言,您的代码编写得很好,只需进行最少的更改即可完成您的要求。由于 while 循环的结构,您丢弃第一帧也存在问题。避免这种情况的一个好方法是循环和一个 half/while True 构造:

import cv2
import numpy as np
from matplotlib import pyplot as plt

def process_img(img_rgb, template, count):
    img_gray = cv2.cvtColor(img_rgb, cv2.COLOR_BGR2GRAY)

    w, h = template.shape[::-1]

    res = cv2.matchTemplate(img_gray,template,cv2.TM_CCOEFF_NORMED)
    threshold = 0.8
    loc = np.where( res >= threshold)
    for pt in zip(*loc[::-1]):
        cv2.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0,0,255), 2)

    # This will write different res.png for each frame. Change this as you require
    cv2.imwrite('res{0}.png'.format(count),img_rgb)   


def main():
    vidcap = cv2.VideoCapture('My_Video.mp4')
    template = cv2.imread('small_icon_I_am_looking_for.png',0)  # open template only once
    count = 0
    while True:
      success,image = vidcap.read()
      if not success: break         # loop and a half construct is useful
      print ('Read a new frame: ', success)
      process_image(image, template, count)
      count += 1

【讨论】:

  • 尚未测试,但这看起来正是我想要的。希望这运行得更快。很棒的工作:)
  • @Lain 看起来很酷的程序!如果这不起作用或仍然很慢,请告诉我;我们可以尝试进一步优化它。
  • 我当然需要更多地修改它。理想情况下,它只需要检查每 100 帧(因为我在加载屏幕上检测到一个图标)。找到图标后,它也可以跳过 20 分钟的视频。我会尽力修改而不打扰您。
  • 有没有办法跳过 main 中的帧读取?目前它每 100 帧调用一次进程映像,但 vidcap.read() 只是读取下一帧,我可以告诉它从现在开始读取... 100 帧吗?对于我需要的东西,它仍然很慢。
  • @Lain 问题是一些视频编码使用来自当前帧的信息解码下一帧,因此很难将它们离散化。根据this 的回答,您显然可以使用vidcap.grab() 跳过帧,但我对此不太确定。试一试!你有包含这些文件的 github 存储库吗?我可以尝试查看代码运行缓慢的地方。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-15
  • 2013-09-28
  • 2013-03-15
  • 2017-08-20
  • 1970-01-01
  • 2021-06-02
相关资源
最近更新 更多