Find mean and sd of red and blue colour values in video
Question:
I have video files that I can convert into RGB space withcv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
for each frame.
I then want to calculate the mean value and standard deviation of red and blue colour values, averaged and sd’ed over a 100sec period. My videos are >100sec long, so would want to repeat this for every 100 seconds and assign the values to a vector.
So for every n’th 100 second clip, I have values R(ave), R(sd), B(ave), B(sd).
I am fairly new to CV and video processing, so would appreciate help in any part of this.
Answers:
I finally wrote it. This whole program will run long enough on videos that are over 1 minute long. And if you have a weak computer, then I do not envy you. But generally it works well enough. Here it is:
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()
I have video files that I can convert into RGB space withcv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
for each frame.
I then want to calculate the mean value and standard deviation of red and blue colour values, averaged and sd’ed over a 100sec period. My videos are >100sec long, so would want to repeat this for every 100 seconds and assign the values to a vector.
So for every n’th 100 second clip, I have values R(ave), R(sd), B(ave), B(sd).
I am fairly new to CV and video processing, so would appreciate help in any part of this.
I finally wrote it. This whole program will run long enough on videos that are over 1 minute long. And if you have a weak computer, then I do not envy you. But generally it works well enough. Here it is:
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()