简体   繁体   English

如何使用 OpenCV 覆盖图像和文本/形状?

[英]How to use OpenCV to overlay an image AND text/shapes?

I ran into a problem regarding OpenCV's transparent overlays.我遇到了一个关于 OpenCV 透明覆盖的问题。 This is my code so far:到目前为止,这是我的代码:

import cv2

cap = cv2.VideoCapture('Sample_Vid.mp4')
stat_overlay = cv2.imread('overlay.png')
fps = 21

if cap.isOpened():
    while cap.isOpened():
        ret, frame = cap.read()
        overlay = frame.copy()
        output = frame.copy()

        cv2.rectangle(overlay, (0, 0), (730, 50), (0, 0, 0), -1)
        cv2.putText(overlay, fps, (1230, 20), cv2.FONT_HERSHEY_DUPLEX, 0.5, (255, 255, 255), 1)
        cv2.addWeighted(overlay, 1.0, output, 0, 0, output)

        cv2.imshow('frame', output)

So I have my frame with a rectangle and the FPS displayed on it.所以我的框架有一个矩形,上面显示了 FPS。 Now I want to overlay my stat_overlay image FIRST and THEN the text and shape, because they are meant to be dynamic.现在我想首先覆盖我的 stat_overlay 图像,然后覆盖文本和形状,因为它们是动态的。 In every explanation I read it was told doing it with cv2.addWeighted(stat_overlay, 1.0, output, 0, 0, output) , but I already have one command like that used by the dynamic overlays and if I insert a second one above it, it does not work.在我读过的每一个解释中,都被告知使用cv2.addWeighted(stat_overlay, 1.0, output, 0, 0, output) ,但我已经有一个类似动态叠加层使用的命令,如果我在它上面插入第二个命令, 这是行不通的。 Any ideas how to solve this?任何想法如何解决这个问题?

Thanks for the answers in advance!感谢您提前回答!

The command you are using: cv2.addWeighted(overlay, 1.0, output, 0, 0, output) , uses alpha = 1.0 , and beta = 0 , so there is no transparency.您正在使用的命令: cv2.addWeighted(overlay, 1.0, output, 0, 0, output) ,使用alpha = 1.0beta = 0 ,因此没有透明度。
You are basically copying overlay image into output image.您基本上是overlay图像复制output图像中。

AddWeighted documentation: AddWeighted文档:

cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]]) cv2.addWeighted(src1, alpha, src2, beta, gamma[, dst[, dtype]])
src1 – first input array. src1 – 第一个输入数组。
alpha – weight of the first array elements. alpha - 第一个数组元素的权重。
src2 – second input array of the same size and channel number as src1. src2 – 与 src1 具有相同大小和通道编号的第二个输入数组。
beta – weight of the second array elements. beta – 第二个数组元素的权重。
dst – output array that has the same size and number of channels as the input arrays. dst – 与输入数组具有相同大小和通道数的输出数组。

You can also use the following code for overlaying the text:您还可以使用以下代码来覆盖文本:

output = frame.copy()
cv2.rectangle(output, (0, 0), (730, 50), (0, 0, 0), -1)
cv2.putText(output, fps, (1230, 20), cv2.FONT_HERSHEY_DUPLEX, 0.5, (255, 255, 255), 1)

For overlaying stat_overlay you can use a solution like Alpha blending code sample.对于覆盖stat_overlay您可以使用诸如Alpha 混合代码示例之类的解决方案。

I don't know if 'overlay.png' is in RGB or RGBA format.我不知道'overlay.png'是 RGB 还是 RGBA 格式。
In case image has an alpha channel, you can use it as transparency plane.如果图像具有 Alpha 通道,您可以将其用作透明平面。
If the image is RGB, you may create your desired alpha plane.如果图像是 RGB,您可以创建所需的 alpha 平面。

In case 'overlay.png' is a small image (like a logo), you probably don't need any of this, you can "place" the small image on the output image.如果'overlay.png'是小图像(如徽标),您可能不需要任何这些,您可以将小图像“放置”在output图像上。


I created a self contained code sample, that based on the alpha blending sample.我创建了一个自包含的代码示例,它基于alpha 混合示例。
In order to make the code self contained, the code uses:为了使代码自包含,代码使用:

  • ffmpeg-python for generating synthetic video (for testing). ffmpeg-python用于生成合成视频(用于测试)。
  • The code, draws a red circle that replaces 'overlay.png'代码绘制了一个红色圆圈来代替'overlay.png'

Here is the code:这是代码:

import ffmpeg
import cv2
import numpy as np

in_filename = 'Sample_Vid.mp4' # Input file for testing (".264" or ".h264" is a convention for elementary h264 video stream file)

## Build synthetic video, for testing:
################################################
# ffmpeg -y -r 10 -f lavfi -i testsrc=size=192x108:rate=1 -c:v libx264 -crf 23 -t 50 test_vid.264

width, height = 640, 480

(
    ffmpeg
    .input('testsrc=size={}x{}:rate=1'.format(width, height), f='lavfi')
    .output(in_filename, vcodec='libx264', crf=23, t=5)
    .overwrite_output()
    .run()
)
################################################


cap = cv2.VideoCapture('Sample_Vid.mp4')
#stat_overlay = cv2.imread('overlay.png')

# Create image with green circle, instead of reaing a file
# The image is created as RGBA (the 4'th plane is the transparency).
stat_overlay = np.zeros((height, width, 4), np.uint8)
cv2.circle(stat_overlay, (320, 240), 80, (0, 0, 255, 255), thickness=20) # Draw red circle (with alpha = 255) 

# https://www.learnopencv.com/alpha-blending-using-opencv-cpp-python/
stat_alpha = stat_overlay[:, :, 3] # Take 4'th plane as alpha channel
stat_alpha = cv2.cvtColor(stat_alpha, cv2.COLOR_GRAY2BGR) # Duplicate alpha channel 3 times (to match output dimensions)

# https://www.learnopencv.com/alpha-blending-using-opencv-cpp-python/
# Normalize the alpha mask to keep intensity between 0 and 1
stat_alpha = stat_alpha.astype(float) / 255

stat_overlay = stat_overlay[:, :, 0:3] # Get RGB channels

fps = 21


if cap.isOpened():
    while cap.isOpened():
        ret, frame = cap.read()
        if ret:            
            output = frame.copy()

            # https://www.learnopencv.com/alpha-blending-using-opencv-cpp-python/
            # Alpha blending:
            foreground = stat_overlay.astype(float)
            background = output.astype(float)

            # Multiply the foreground with the alpha matte
            foreground = cv2.multiply(stat_alpha, foreground)

            # Multiply the background with ( 1 - alpha )
            background = cv2.multiply(1.0 - stat_alpha, background)

            # Add the masked foreground and background.
            output = cv2.add(foreground, background).astype(np.uint8)

            cv2.rectangle(output, (0, 0), (230, 50), (0, 0, 0), -1)
            cv2.putText(output, str(fps), (123, 20), cv2.FONT_HERSHEY_DUPLEX, 0.5, (255, 255, 255), 1)

            cv2.imshow('frame', output)
            cv2.waitKey(1000)

        else:
            break

cv2.destroyAllWindows()

Result (last frame):结果(最后一帧):
在此处输入图片说明

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM