使用 opencv 在 Python 中实现光流的问题

Posted

技术标签:

【中文标题】使用 opencv 在 Python 中实现光流的问题【英文标题】:Issues with optical flow implementation in Python using opencv 【发布时间】:2019-09-17 05:52:26 【问题描述】:

我有以下简单的光流代码。这会从 gif 序列中读取前两帧,然后计算它们之间的流。

import cv2
import numpy as np
import tkinter as tk
from tkinter import filedialog
from matplotlib import pyplot as plt

root = tk.Tk()
root.withdraw()

path = filedialog.askopenfilename()
video = cv2.VideoCapture(path)

_,im1 = video.read()
im1 = cv2.cvtColor(im1, cv2.COLOR_BGR2GRAY)
success = True

while(success):
    success,im2 = video.read()
    if success == True:
    im2 = cv2.cvtColor(im2, cv2.COLOR_BGR2GRAY)
success = False

hsv = np.zeros_like(im1)
hsv[...,1] = 255
flow = cv2.calcOpticalFlowFarneback(im1,im2, None, 0.5, 3, 15, 3, 5, 1.2, 0)

mag, ang = cv2.cartToPolar(flow[...,0], flow[...,1])
hsv[...,0] = ang*180/np.pi/2 # Error in this line
hsv[...,2] = cv2.normalize(mag,None,0,255,cv.NORM_MINMAX)
bgr = cv2.cvtColor(hsv,cv.COLOR_HSV2BGR)
cv2.imshow('frame2',bgr)

上述实现是用于计算颜色编码光流的标准 openCV 版本。但是,我在评论的行中遇到错误。这是因为如错误所示,将 (m X n) 向量分配给 (m,) 向量。

ValueError: could not broadcast input array from shape (512,512) into shape (512)

hsv[...,0].shape 给出 512 而 ang.shape 是 512 X 512

>> print(hsv[...,0].shape)
>> 512
>> print(ang.shape)
>> (512,512)

但是来自 openCV 网站的用于计算颜色编码光流的相同代码会产生一个输出,其中会弹出一个带有一些颜色流的窗口并消失,然后出现以下错误:

OpenCV Error: Assertion failed (scn == 3 || scn == 4) in cvtColor,file /build/opencv-L2vuMj/opencv-3.2.0+dfsg/modules/imgproc/src/color.cpp, line 9748
Traceback (most recent call last):
File "OF_Farneback.py", line 12, in <module>
next = cv.cvtColor(frame2,cv.COLOR_BGR2GRAY)
cv2.error: /build/opencv-L2vuMj/opencv-3.2.0+dfsg/modules/imgproc/src/color.cpp:9748: error: (-215) scn == 3 || scn == 4 in function cvtColor

我所指的代码如下:

import numpy as np
import cv2 as cv

cap = cv.VideoCapture("sampleSeq.gif")
ret, frame1 = cap.read()
prvs = cv.cvtColor(frame1,cv.COLOR_BGR2GRAY)
hsv = np.zeros_like(frame1)
hsv[...,1] = 255

while(1):
    ret, frame2 = cap.read()
    next = cv.cvtColor(frame2,cv.COLOR_BGR2GRAY)
    flow = cv.calcOpticalFlowFarneback(prvs,next, None, 0.5, 3, 15, 3, 5, 1.2, 0)
    mag, ang = cv.cartToPolar(flow[...,0], flow[...,1])
    hsv[...,0] = ang*180/np.pi/2
    hsv[...,2] = cv.normalize(mag,None,0,255,cv.NORM_MINMAX)
    bgr = cv.cvtColor(hsv,cv.COLOR_HSV2BGR)
    cv.imshow('frame2',bgr)
    k = cv.waitKey(30) & 0xff
    if k == 27:
        break
    elif k == ord('s'):
        prvs = next

我的问题是:

    为什么在第二种情况下没有出现原始错误,其中颜色编码的流显示在循环内? 如何修复第一个代码中的赋值错误? 如何修复第二个代码中的错误,我猜这主要是因为它已达到 EOF ?

任何指针,建议都会有所帮助。谢谢你。

【问题讨论】:

【参考方案1】:

在您的代码中,hsv 是从im1 创建的,此时后一个矩阵是灰度矩阵,即它只有一个通道。在OpenCV 示例代码中,hsv 是从frame1 创建的,frame1 是一个颜色矩阵,即有3 个颜色通道。因此,hsv 的大小在两个代码 sn-ps 之间有所不同,我认为这是第 1 点和第 2 点的原因。

关于第 3 点,解决此问题的最简单方法是

while(1):
  ret, frame2 = cap.read()
  if(!ret): # ie there is no next frame
    break
  else:
    #code as before

【讨论】:

以上是关于使用 opencv 在 Python 中实现光流的问题的主要内容,如果未能解决你的问题,请参考以下文章

带有opencv的Android光流

使用opencv在android中抓取连续帧

光流直方图是如何工作的? [关闭]

使用 python 的 OpenCV 光流

python中的openCV光流

如何在openCV python中将背景减法与密集光流跟踪相结合