opencv 查找视频中红色和蓝色颜色值的平均值和标准差

svgewumm  于 2023-08-06  发布在  其他
关注(0)|答案(2)|浏览(99)

我有视频文件,我可以转换成RGB空间与cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)为每帧。
然后,我想计算红色和蓝色值的平均值和标准差,在100秒内取平均值和标准差。我的视频是> 100秒长,所以会想重复这每100秒,并分配值的向量。因此,对于每第n个100秒剪辑,我有值R(ave),R(sd),B(ave),B(sd)。
我是相当新的简历和视频处理,所以会感谢帮助,在任何部分。

qyzbxkaa

qyzbxkaa1#

我终于写出来了。这整个程序将运行足够长的视频超过1分钟长。如果你有一个弱的电脑,那么我不羡慕你。但总的来说它工作得很好。这是:

import cv2

def calc_sd(arr: list, mean_val: float):
    prev_dis = 0
    for k in arr:
        prev_dis += (k - mean_val) ** 2
    dis = prev_dis / len(arr)
    return dis ** (1 / 2)

def calc_mean(arr: list):
    return sum(arr) / len(arr)

# list of your videos here
lst_of_videos = ['vid_test.mkv', 'signs.mkv', 'signs_ml.mkv']
lst_of_all_videos_data = []

for i in lst_of_videos:
    cap = cv2.VideoCapture(i)

    # list for data every 100 sec
    # data there will be like:
    # [['mean_red', 'mean_green', 'mean_blue', 'sd_red', 'sd_green', 'sd_blue'], 'and every 100 sec like this']
    lst_of_data = []

    lst_of_red = []
    lst_of_green = []
    lst_of_blue = []

    # getting video fps
    fps = cap.get(cv2.CAP_PROP_FPS)
    abstract_seconds = 0  # for counting frames

    print('video: ', i)

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

        if abstract_seconds >= 100 or not ret:
            print(' video: ', i, ', 100 secs, ret: ', ret)
            mean_red = calc_mean(lst_of_red)
            mean_green = calc_mean(lst_of_green)
            mean_blue = calc_mean(lst_of_blue)
            print('  mean counted')

            sd_red = calc_sd(lst_of_red, mean_red)
            sd_green = calc_sd(lst_of_green, mean_green)
            sd_blue = calc_sd(lst_of_blue, mean_blue)
            print('  sd counted')

            lst_of_data.append([mean_red, mean_green, mean_blue, sd_red, sd_green, sd_blue])
            lst_of_red.clear()
            lst_of_green.clear()
            lst_of_blue.clear()
            print('  arrays cleared')

            if not ret:
                break

        b, g, r = cv2.split(frame)
        lst_of_red.append(r.sum(axis=0).sum(axis=0) / r.size)
        lst_of_green.append(g.sum(axis=0).sum(axis=0) / g.size)
        lst_of_blue.append(b.sum(axis=0).sum(axis=0) / b.size)

        abstract_seconds += 1 / fps

    print(lst_of_data)
    lst_of_all_videos_data.append(lst_of_data)
    lst_of_data.clear()

字符串

eivgtgni

eivgtgni2#

我将使用类似下面的代码来计算1小时视频的全局统计数据。
我直接在stackoverflow框中修改了它,以满足您的“时间窗口”要求,所以它可能会有一些小错误。我放弃了最后一段,因为你说你想要100秒的窗口,但你可以很容易地适应它,如果你真的需要它。
我保留了BGR格式,因为它和其他格式一样好。
我喜欢这个选项比另一个答案,因为你不是保持了很多列表和平均值和标准计算是为3个通道一次完成。
另一个要点是开放视频的发布。

from docopt import docopt
from contextlib import contextmanager
import cv2
import numpy as np
import sys

@contextmanager
def VideoCapture(input_video):

    # findFileOrKeep allows more searching paths
    capture = cv2.VideoCapture(cv2.samples.findFileOrKeep(input_video))
    if not capture.isOpened():
        print('Unable to open: ' + input_video, file=sys.stderr)
        exit(0)

    try:
        yield capture
    finally:
        # Release the video capture object at the end
        capture.release()

DOCTEXT = f"""
Usage:
  name_of_the_script.py <video_path>... [--windows=<w>]

Options:
  --windows=<w>    Windows seconds [default: 100]
"""

if __name__ == '__main__':

    args = docopt(DOCTEXT, argv=sys.argv[1:], help=True, version=None, options_first=False)
    video_pathes = args['<video_path>']
    windows = float(args['--windows'])
    

    output = []
    for i_video, video_path in enumerate(video_pathes):
        with VideoCapture(video_path) as cap:
    
            fps = cap.get(cv2.CAP_PROP_FPS)
            i = 0

            psum    = np.array([0.0, 0.0, 0.0]) # BGR
            psum_sq = np.array([0.0, 0.0, 0.0]) # BGR
            num_px  = windows * fps * int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) * cap.get(cv2.CAP_PROP_FRAME_HEIGHT)

            while True:
                ret, frame = cap.read()
                if not ret: # frame is None
                    break
    
                fr += 1
                if fr % int(windows * fps) == 0:
                    print(f'Processed {fr / fps}s\tVideo {i_video} / len(video_pathes)\t{video_path}')
                    
                    total_mean = psum / num_px
                    total_var  = (psum_sq / num_px) - (total_mean ** 2)
                    total_std  = np.sqrt(total_var)

                    output.append([total_mean, total_std])

                    psum    = np.array([0.0, 0.0, 0.0]) # BGR
                    psum_sq = np.array([0.0, 0.0, 0.0]) # BGR

                psum = frame.sum(axis=(0, 1))
                psum_sq = (frame ** 2).sum(axis=(0, 1))

    print(f'[mean (BGR), std (BGR)]:\n{output}') # NOTE: or use it as you want. You should make it as a function if you need it to do another thing.

字符串

相关问题