Python视频相对亮度检测

```python

import cv2

import numpy as np

import time

def calculate_frame_luminance(frame):

"""

计算帧的相对亮度(感知亮度)

使用加权公式: Y = 0.299*R + 0.587*G + 0.114*B

"""

转换为灰度图(标准亮度公式)

gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

或者使用RGB加权计算

luminance = 0.299 * frame:,:,2 + 0.587 * frame:,:,1 + 0.114 * frame:,:,0

返回平均亮度和最大亮度

avg_luminance = np.mean(gray)

max_luminance = np.max(gray)

min_luminance = np.min(gray)

return {

'average': avg_luminance,

'max': max_luminance,

'min': min_luminance,

'std': np.std(gray)

}

def calculate_relative_brightness(frame, reference_frame=None):

"""

计算相对亮度

如果提供参考帧,返回相对于参考帧的亮度比

"""

current = calculate_frame_luminance(frame)

if reference_frame is not None:

ref = calculate_frame_luminance(reference_frame)

relative = {

'average_ratio': current'average' / ref'average' if ref'average' > 0 else 0,

'max_ratio': current'max' / ref'max' if ref'max' > 0 else 0,

'min_ratio': current'min' / ref'min' if ref'min' > 0 else 0,

'current': current,

'reference': ref

}

return relative

else:

归一化亮度(0-255映射到0-1)

normalized = {

'average': current'average' / 255.0,

'max': current'max' / 255.0,

'min': current'min' / 255.0,

'std': current'std' / 255.0,

'raw': current

}

return normalized

def detect_video_luminance(video_path, sample_interval=30, reference_frame_index=0):

"""

检测视频的相对亮度变化

"""

cap = cv2.VideoCapture(video_path)

if not cap.isOpened():

print("Error: Could not open video.")

return None

total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))

fps = cap.get(cv2.CAP_PROP_FPS)

print(f"视频信息: {total_frames} 帧, {fps:.2f} FPS")

获取参考帧(第一帧或指定帧)

cap.set(cv2.CAP_PROP_POS_FRAMES, reference_frame_index)

ret, reference_frame = cap.read()

if not ret:

print("Error: Could not read reference frame.")

cap.release()

return None

重置到开始

cap.set(cv2.CAP_PROP_POS_FRAMES, 0)

luminance_data = \[\]

frame_count = 0

print("开始处理...")

start_time = time.time()

while True:

ret, frame = cap.read()

if not ret:

break

按间隔采样

if frame_count % sample_interval == 0:

计算相对亮度

relative = calculate_relative_brightness(frame, reference_frame)

data_point = {

'frame': frame_count,

'timestamp': frame_count / fps,

'relative_avg': relative'average_ratio' if isinstance(relative, dict) else relative'average',

'absolute_avg': relative'current''average' if isinstance(relative, dict) else relative'raw''average' * 255,

'brightness_level': 'bright' if relative'average_ratio' > 1.2 else 'normal' if relative'average_ratio' > 0.8 else 'dark'

}

luminance_data.append(data_point)

进度显示

if len(luminance_data) % 10 == 0:

progress = (frame_count / total_frames) * 100

print(f"进度: {progress:.1f}%")

frame_count += 1

cap.release()

elapsed_time = time.time() - start_time

print(f"处理完成! 耗时: {elapsed_time:.2f}秒")

return {

'data': luminance_data,

'total_frames': total_frames,

'fps': fps,

'sample_interval': sample_interval

}

def analyze_luminance_stats(luminance_result):

"""

分析亮度统计数据

"""

data = luminance_result'data'

if not data:

print("无数据")

return None

relative_values = d\['relative_avg' for d in data]

stats = {

'mean_relative': np.mean(relative_values),

'max_relative': np.max(relative_values),

'min_relative': np.min(relative_values),

'std_relative': np.std(relative_values),

'total_samples': len(data),

'bright_segments': sum(1 for d in data if d'brightness_level' == 'bright'),

'normal_segments': sum(1 for d in data if d'brightness_level' == 'normal'),

'dark_segments': sum(1 for d in data if d'brightness_level' == 'dark')

}

return stats

def visualize_luminance(luminance_result, output_path='luminance_plot.png'):

"""

可视化亮度变化

"""

import matplotlib.pyplot as plt

data = luminance_result'data'

times = d\['timestamp' for d in data]

relative_values = d\['relative_avg' for d in data]

absolute_values = d\['absolute_avg' for d in data]

fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 8))

相对亮度图

ax1.plot(times, relative_values, 'b-', linewidth=1.5)

ax1.axhline(y=1.0, color='r', linestyle='--', alpha=0.5, label='参考亮度')

ax1.axhline(y=1.2, color='g', linestyle=':', alpha=0.5, label='亮阈值')

ax1.axhline(y=0.8, color='orange', linestyle=':', alpha=0.5, label='暗阈值')

ax1.set_xlabel('时间 (秒)')

ax1.set_ylabel('相对亮度 (参考帧=1.0)')

ax1.set_title('视频相对亮度变化')

ax1.grid(True, alpha=0.3)

ax1.legend()

绝对亮度图

ax2.plot(times, absolute_values, 'g-', linewidth=1.5)

ax2.set_xlabel('时间 (秒)')

ax2.set_ylabel('绝对亮度 (0-255)')

ax2.set_title('视频绝对亮度变化')

ax2.grid(True, alpha=0.3)

plt.tight_layout()

plt.savefig(output_path, dpi=150)

plt.show()

print(f"可视化图表已保存到: {output_path}")

def get_luminance_summary(luminance_result, stats):

"""

生成亮度检测摘要

"""

summary = f"""

========== 视频亮度检测摘要 ==========

总帧数: {luminance_result'total_frames'}

FPS: {luminance_result'fps':.2f}

采样间隔: {luminance_result'sample_interval'} 帧

亮度统计:

  • 平均相对亮度: {stats'mean_relative':.3f}

  • 最大相对亮度: {stats'max_relative':.3f}

  • 最小相对亮度: {stats'min_relative':.3f}

  • 标准差: {stats'std_relative':.3f}

亮度分布:

  • 亮段 (>1.2): {stats'bright_segments'} 个样本

  • 正常段 (0.8-1.2): {stats'normal_segments'} 个样本

  • 暗段 (<0.8): {stats'dark_segments'} 个样本

总体评价:

  • 平均亮度 {'偏亮' if stats'mean_relative' > 1.1 else '正常' if stats'mean_relative' > 0.9 else '偏暗'}

  • 亮度变化 {'较大' if stats'std_relative' > 0.2 else '平稳'}

=====================================

"""

return summary

========== 使用示例 ==========

if name == "main":

示例1: 检测视频文件

video_path = "your_video.mp4" # 替换为你的视频路径

try:

进行亮度检测

result = detect_video_luminance(video_path, sample_interval=15, reference_frame_index=0)

if result:

分析统计数据

stats = analyze_luminance_stats(result)

打印摘要

summary = get_luminance_summary(result, stats)

print(summary)

可视化

visualize_luminance(result)

except FileNotFoundError:

print("视频文件未找到,请检查路径")

except Exception as e:

print(f"处理过程中出错: {e}")

```

使用说明

主要功能

  1. calculate_frame_luminance(): 计算单帧的亮度统计(平均值、最大值、最小值、标准差)

  2. calculate_relative_brightness(): 计算相对于参考帧的亮度比

  3. detect_video_luminance(): 检测整个视频的亮度变化

  4. visualize_luminance(): 生成亮度变化曲线图

快速使用

```python

基本使用

result = detect_video_luminance("your_video.mp4")

分析并可视化

stats = analyze_luminance_stats(result)

visualize_luminance(result)

print(get_luminance_summary(result, stats))

```

说明

· sample_interval: 采样间隔(帧),默认30帧采样一次

· reference_frame_index: 参考帧索引,默认使用第0帧

· 相对亮度 > 1.2 判定为偏亮,< 0.8 判定为偏暗

相关推荐
Csvn1 小时前
Python 开发技巧 · logging 最佳实践 —— 告别 print,搭建工程级日志系统
后端·python
ShallWeL1 小时前
【机器学习】(16)—— 数值数据
人工智能·python·算法·机器学习·数据分析
gr95ZS6E61 小时前
基础入门java安全(一)--CC1基础分析
开发语言·python
极度的坦诚就是无坚不摧1 小时前
数据分析DAY1-Python基础
python·数据分析
snow@li1 小时前
中台:中台即复用 / 理解企业架构中的能力抽象与分层共享 / 中台体系全景梳理 / 共性能力抽象、沉淀并复用
数据库
SelectDB技术团队2 小时前
AB 实验指标计算场景:Apache Doris / SelectDB 的技术能力、选型对比与实践
大数据·数据库·数据分析·apache·用户运营·apache doris·selectdb
hongyucai2 小时前
详解rlinf强化学习四步曲
人工智能·python·算法·架构
c_lb72882 小时前
2026年下半年AI量化工具,阶段不同重点也不同
人工智能·python
snow@li2 小时前
数据库:B+ 树 / 数据库索引的底层支柱
数据库