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 判定为偏暗

相关推荐
【心态好不摆烂】3 分钟前
MySQL——复合查询
数据库·mysql
编程阿峰6 分钟前
Python 环境配置(二)安装jupyter、matplotlib、numpy库
开发语言·python·jupyter·numpy·matplotlib
AC赳赳老秦7 分钟前
CSDN 技术社区数据采集:OpenClaw 抓取公开技术热帖,生成领域技术热点周报
java·大数据·前端·数据库·python·php·openclaw
瞬间&永恒~36 分钟前
【MySQL】 InnoDB 锁等待排查与并发压测实验
运维·数据库·mysql
金銀銅鐵38 分钟前
[Python] 一次打开多个常用的网址
python
布鲁飞丝44 分钟前
对 .NET线程 异常退出引发程序崩溃的反思
数据库·c#·.net
zcmodeltech1 小时前
智能矿井沙盘模型多系统协同控制系统设计:基于STM32与Modbus RTU的感知-传输-控制一体化方案
服务器·数据库·分布式·stm32·单片机·嵌入式硬件
明如正午1 小时前
【python】Python + OpenCV 实现视频关键帧提取与智能去重
python·opencv·音视频
aqi001 小时前
15天学会AI应用开发(十八)使用LangGraph实现精确记忆功能
人工智能·python·大模型·ai编程·ai应用