【问题标题】:Opencv-Overlay a Video on WebcamOpencv-在网络摄像头上叠加视频
【发布时间】:2021-02-07 03:15:41
【问题描述】:

伙计们,我在将视频叠加到网络摄像头时遇到问题。我可以打开网络摄像头而没有任何问题或错误,但我的视频没有显示。我正在尝试以特定的 x-y 坐标播放我的视频。我从另一个 stackoverflow 问题中获取了我的大部分代码,但我找不到它知道,所以我不能在这里提及它。

那么有人可以帮我解决这个问题吗?为什么我的视频没有在我的网络摄像头中播放? 我有以下代码:

from os.path import sep
import cv2 as cv2

# load the overlay image. size should be smaller than video frame size
img = cv2.VideoCapture('photos' + sep + 'Baslksz-3.mp4')


# Get Image dimensions
width  = img.set(cv2.CAP_PROP_FRAME_WIDTH, 150)   # float `width`
height = img.set(cv2.CAP_PROP_FRAME_HEIGHT, 150)

# Start Capture
cap = cv2.VideoCapture(0)
cap = cv2.VideoCapture(0 + cv2.CAP_DSHOW)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
cap.set(cv2.CAP_PROP_FPS, 30)

frame_vid = img.read()

# Decide X,Y location of overlay image inside video frame. 
# following should be valid:
#   * image dimensions must be smaller than frame dimensions
#   * x+img_width <= frame_width
#   * y+img_height <= frame_height
# otherwise you can resize image as part of your code if required

x = 50
y = 50

while(True):
    # Capture frame-by-frame
    ret, frame = cap.read()
    # add image to frame
    frame[ y:y+width , x:x+height ] = img
    
    '''
    tr = 0.3 # transparency between 0-1, show camera if 0
    frame = ((1-tr) * frame.astype(np.float) + tr * frame_vid.astype(np.float)).astype(np.uint8)
    '''
    # Display the resulting frame
    cv2.imshow('frame',frame)

    # Exit if ESC key is pressed
    if cv2.waitKey(20) & 0xFF == 27:
        break

cap.release()
cv2.destroyAllWindows()

【问题讨论】:

  • 变量名选择不当。 frame[ y:y+width , x:x+height ] = img ...img 不是图像,而是 cv&gt;VideoCapture 的一个实例,因此该声明没有任何意义。
  • 另外,cv.VideoCapture.set 返回一个布尔值,所以widthheight 也不是他们所说的那样,使得上述声明更加荒谬。此外,在VideoCapture读取文件时设置宽度和高度属性完全没有效果,它只对改变相机的分辨率有用。
  • 感谢回复,我知道了。感谢您的帮助
  • *你能看看这个问题吗:stackoverflow.com/questions/66088152/…我需要你的帮助

标签: python opencv opencv-python


【解决方案1】:

让我开始逐步分析代码。

  • 步骤#1
img = cv2.VideoCapture('photos' + sep + 'Baslksz-3.mp4')

上面的代码看起来不错,但是如果你给出一个字符串名称会更好

video_name = 'photos' + sep + 'Baslksz-3.mp4'
img = cv2.VideoCapture(video_name)
  • 步骤 #2
# Get Image dimensions
width = img.set(cv2.CAP_PROP_FRAME_WIDTH, 150)  # float `width`
height = img.set(cv2.CAP_PROP_FRAME_HEIGHT, 150)

现在什么是widthheight 变量?

# Get Image dimensions
width = img.set(cv2.CAP_PROP_FRAME_WIDTH, 150)  # float `width`
height = img.set(cv2.CAP_PROP_FRAME_HEIGHT, 150)
print(width)
print(height)

结果是:

False
False

您似乎想将widthheight 设置为维度(150, 150)。单独初始化会更好

# Get Image dimensions
img.set(cv2.CAP_PROP_FRAME_WIDTH, 150)  # float `width`
img.set(cv2.CAP_PROP_FRAME_HEIGHT, 150)
width = 150
height = 150
  • 步骤#3
# Start Capture
cap = cv2.VideoCapture(0)
cap = cv2.VideoCapture(0 + cv2.CAP_DSHOW)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
cap.set(cv2.CAP_PROP_FPS, 30)

为什么要初始化cap变量两次?

  • 步骤#4
frame_vid = img.read()

为什么你初始化frame_vid你没有在代码的任何地方使用?

  • 步骤#5
while (True):
    # Capture frame-by-frame
    ret, frame = cap.read()
    frame[y:y + width, x:x + height] = img

上面的代码没有任何意义,只要你的网络摄像头打开,你就想显示你的视频。您也没有检查当前的网络摄像头帧是否返回。您还将VideoCapture 变量设置为数组?

while cap.isOpened():
    # Capture frame-by-frame
    ret, frame = cap.read()

现在你正在获取框架,只要你的网络摄像头是打开的,那么你需要检查网络摄像头框架是否返回。如果网络摄像头帧返回,那么您需要开始读取视频帧。如果视频帧成功返回,则将视频帧大小调整为(width, height),然后将其设置为frame

while cap.isOpened():
    # Capture frame-by-frame
    ret, frame = cap.read()

    if ret:
        ret_video, frame_video = img.read()

        if ret_video:
            # add image to frame
            frame_video = cv2.resize(frame_video, (width, height))
            frame[y:y + width, x:x + height] = frame_video
  • 步骤#6

确保在执行后关闭img变量。

img.release()
cap.release()
cv2.destroyAllWindows()

请将img 变量更改为有意义的值。就像将 img 变量重命名为 video_capturecap 重命名为 webcam_capture

当视频停止时,网络摄像头会堆叠。但我想继续不定式。和视频应该重新开始。但是视频不是从一开始就开始的。并且网络摄像头冻结了

更新


Playback loop option in OpenCV videos中提到了这个问题

如果您查看答案,则可以通过计算视频帧数来解决问题。当视频帧数等于捕获帧数时 (CAP_PROP_FRAME_COUNT) 设置为 counter,CAP_PROP_FRAME_COUNT 设置为 0。

首先初始化帧计数器。

video_frame_counter = 0

当网络摄像头打开时,获取框架。如果帧返回,则将计数器增加 1。

while cap.isOpened():
    # Capture frame-by-frame
    ret, frame = cap.read()

    if ret:
        ret_video, frame_video = img.read()
        video_frame_counter += 1

如果计数器等于捕获类帧计数,则将两个变量都初始化为 0。

if video_frame_counter == img.get(cv2.CAP_PROP_FRAME_COUNT):
    video_frame_counter = 0
    img.set(cv2.CAP_PROP_POS_FRAMES, 0)

代码:


from os.path import sep
import cv2 as cv2

# load the overlay image. size should be smaller than video frame size
# img = cv2.VideoCapture('photos' + sep + 'Baslksz-3.mp4')
video_name = 'photos' + sep + 'Baslksz-3.mp4'
img = cv2.VideoCapture(video_name)

# Get Image dimensions
img.set(cv2.CAP_PROP_FRAME_WIDTH, 150)  # float `width`
img.set(cv2.CAP_PROP_FRAME_HEIGHT, 150)
width = 150
height = 150

# Start Capture
cap = cv2.VideoCapture(0)
# cap = cv2.VideoCapture(0 + cv2.CAP_DSHOW)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)
cap.set(cv2.CAP_PROP_FPS, 30)

# frame_vid = img.read()

# Decide X,Y location of overlay image inside video frame.
# following should be valid:
#   * image dimensions must be smaller than frame dimensions
#   * x+img_width <= frame_width
#   * y+img_height <= frame_height
# otherwise you can resize image as part of your code if required

x = 50
y = 50

video_frame_counter = 0

while cap.isOpened():
    # Capture frame-by-frame
    ret, frame = cap.read()

    if ret:
        ret_video, frame_video = img.read()
        video_frame_counter += 1

        if video_frame_counter == img.get(cv2.CAP_PROP_FRAME_COUNT):
            video_frame_counter = 0
            img.set(cv2.CAP_PROP_POS_FRAMES, 0)

        if ret_video:
            # add image to frame
            frame_video = cv2.resize(frame_video, (width, height))
            frame[y:y + width, x:x + height] = frame_video

            '''
            tr = 0.3 # transparency between 0-1, show camera if 0
            frame = ((1-tr) * frame.astype(np.float) + tr * frame_vid.astype(np.float)).astype(np.uint8)
            '''
            # Display the resulting frame
            cv2.imshow('frame', frame)

            # Exit if ESC key is pressed
            if cv2.waitKey(1) & 0xFF == 27:
                break

img.release()
cap.release()
cv2.destroyAllWindows()

【讨论】:

  • 感谢您的回复,您的回复让一切都清楚了。真的很感谢你....
  • 好的,但仍要确保您不会在代码中留下任何未使用的变量。如果您打算将来使用,请务必评论它们
  • 我能问点什么吗?我认为我们的代码有问题。当视频停止时,网络摄像头会堆叠。但我想继续不定式。和视频应该重新开始。但是视频不是从一开始就开始的。并且网络摄像头冻结了。
  • 我已经根据问题更新了我的代码。如果您想阅读说明,请参阅更新部分。
  • 是的,谢谢你的回答,我是opencv的新手,正在努力学习。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-05
相关资源
最近更新 更多