【问题标题】:Change Single Color in a Video with OpenCV Python使用 OpenCV Python 更改视频中的单色
【发布时间】:2019-02-21 23:07:17
【问题描述】:

我有一个破砖游戏的视频。有些砖是红色的。我必须把红色变成黑色。我试图在 numpy 数组中找到红色像素的位置并在这些像素上分配黑色。我在下面提供的代码将红色变为黑色。但是这个过程太慢了,12s 的视频花了 5 多分钟。有没有更快的方法来做到这一点?

import numpy as np
import cv2


vid = "input.mp4"
cap = cv2.VideoCapture(vid)

while(True):
    ret, frame = cap.read()
    if ret: 
        for i in zip(*np.where(frame == [0,0,255])):
            frame[i[0], i[1], 0] = 0
            frame[i[0], i[1], 1] = 0
            frame[i[0], i[1], 2] = 0
        cv2.imshow('frame',frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    else:
        break
cv2.destroyAllWindows()

【问题讨论】:

标签: python opencv


【解决方案1】:

试试这个,阅读代码中的 cmets 了解更多信息。

import cv2
import numpy as np

img = cv2.imread("1.png")

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
# define range of red color in HSV
lower_red = np.array([0,50,50])
upper_red = np.array([10,255,255])
# Threshold the HSV image to get only red colors
mask = cv2.inRange(hsv, lower_red, upper_red)
red_only = cv2.bitwise_and(img,img, mask= mask)

#convert mask to 3-channel image to perform subtract
mask = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR)

res = cv2.subtract(img,mask) #negative values become 0 -> black

cv2.imshow("img",img)
cv2.imshow("mask",mask)
cv2.imshow("red_only",red_only)
cv2.imshow("res",res)
cv2.waitKey()
cv2.destroyAllWindows()

PS。而且这种方法几乎不需要时间,我在我的机器上测试过,1280x720的图像大约需要3ms

【讨论】:

  • Op 问别的东西
  • 最后一帧的负值变为0,红色变为黑色。如果我想把红色变成黄色怎么办?
  • @Sourav 您需要在主要问题中提出问题。此外,您还提出了与您的问题不同的答案。您询问如何更改单一颜色,但您赞成“删除 HSV 中的颜色间隔”的答案。这个答案甚至没有回答你的“如何改变颜色”,而是告诉你“如何去除颜色”。结果,您提出了新问题。本站不是论坛。这个网站是“特殊问题”和“准确答案”
【解决方案2】:

这仅适用于灰色

(您不能用要替换的颜色指定通道)

color_find = [0,0,255]
indexes=np.where(frame == color_find)
frame[indexes]=0 # 0-255 creates [0,0,0] - [255,255,255]

更一般的态度是这样的

这里指定RGB轴,可以替换成任意颜色

red = [0,0,255]
black = [0,0,0]
indexes=np.where(np.all(frame == red,axis = 2))
frame[indexes] = black

【讨论】:

  • 我没有投反对票,但也许您可以在这里解释每个步骤在做什么并链接相关文档(尤其是 np.all 调用与 axis kwarg)。我跟着,但新手可能不会。另外我要补充一点,np.where() 调用是不必要的,您可以将np.all 的结果用作frames 的布尔索引器。
  • 你在做什么?代码有 4 行,其中 3 行是变量赋值,但我应该解释每个步骤并提供文档?
  • 同样,新手可能会感到困惑的部分是np.all(frame == red, axis=2)。是的,最好在适用的地方链接文档。我只是说这个问题已经很容易回答了,所以如果 OP 不知道该怎么做,那么最好链接到相关文档。参见例如how to answer.
  • @Martin 你能解释一下这段代码 np.where(np.all(frame == red,axis = 2)) 在这里轴是什么意思?不是 BGR 图像带有三个 (BGR) 2D np 数组。如果我定义轴 =2 ,将指示绿色通道?
  • @Sourav 如果您已经接受了答案,我为什么要在我的问题中解释代码?这个问题不是结束了吗?
【解决方案3】:

你可以用这个替换你的 for 循环:

    # [b,g,r]
    color_in = [0, 0, 255]  # color you want to filter
    color_out = [0, 0, 0]   # color you want to set
    for i in range(3):
        frame[frame[:, :, i] == color_in[i]] = color_out[i]

您可以将其用于具有 3 个颜色通道的视频帧。此外,您可以使用条件运算符(替换为 >、

像这样使用来过滤颜色范围:

frame[frame[:, :, i] < color_in[i]] = color_out[i]

【讨论】:

  • 这是我的第一篇文章,你能解释一下为什么它被否决了吗?我的答案正是问题所要求的:找到红色像素并用黑色替换,它做得更快,为什么它被否决了?
  • 不仅在代码中,如果你这样做,你还可以过滤颜色范围:frame[frame[:, :, i]
  • 我投了反对票。因为它是多余的。您可以在没有循环的情况下执行此操作。通过检查二维数组中的值来改变颜色也不是很好的方法。对不起,如果这让你不高兴。我只是认为不是干净的解决方案
【解决方案4】:

使用 Ha Bom 的代码和我的部分代码,问题已经解决。但是,这需要一点时间。处理 12 秒的视频大约需要 20-25 秒。主要目的是将红色像素转换为橙色- 代码如下 -

cap = cv2.VideoCapture("input.avi")

while(True):
    ret, frame = cap.read()
    if ret:

        # hsv is better to recognize color, convert the BGR frame to HSV
        hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

        # in hsv red color located in two region. Create the mask for red color
        # mask the red color and get an grayscale output where red is white
        # everything else are black
        mask1 = cv2.inRange(hsv, (0,50,20), (5,255,255))
        mask2 = cv2.inRange(hsv, (175,50,20), (180,255,255))
        mask = cv2.bitwise_or(mask1, mask2)

        # get the index of the white areas and make them orange in the main frame
        for i in zip(*np.where(mask == 255)):
                frame[i[0], i[1], 0] = 0
                frame[i[0], i[1], 1] = 165
                frame[i[0], i[1], 2] = 255

        # play the new video
        cv2.imshow("res",frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    else:
        break
cv2.destroyAllWindows()

【讨论】:

    猜你喜欢
    • 2016-02-16
    • 1970-01-01
    • 1970-01-01
    • 2020-01-07
    • 1970-01-01
    • 2017-08-18
    • 2012-05-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多