560 lines
15 KiB
Python
560 lines
15 KiB
Python
|
|
import math
|
|||
|
|
import numpy as np
|
|||
|
|
from shapely.geometry import Polygon
|
|||
|
|
|
|||
|
|
|
|||
|
|
# ==================
|
|||
|
|
# 色域覆盖率计算公式
|
|||
|
|
# ==================
|
|||
|
|
|
|||
|
|
|
|||
|
|
def calculate_gamut_coverage(points1, points2):
|
|||
|
|
"""
|
|||
|
|
计算色域覆盖率(使用 shapely 库)
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
points1: 测量三角形 [[x1, y1], [x2, y2], [x3, y3]]
|
|||
|
|
points2: 参考三角形 [[x1, y1], [x2, y2], [x3, y3]]
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
area: 交集面积
|
|||
|
|
coverage: 覆盖率(%)≤ 100%
|
|||
|
|
"""
|
|||
|
|
try:
|
|||
|
|
# 创建多边形对象
|
|||
|
|
poly1 = Polygon(points1)
|
|||
|
|
poly2 = Polygon(points2)
|
|||
|
|
|
|||
|
|
# 计算交集
|
|||
|
|
intersection = poly1.intersection(poly2)
|
|||
|
|
|
|||
|
|
# 计算面积
|
|||
|
|
intersection_area = intersection.area
|
|||
|
|
reference_area = poly2.area
|
|||
|
|
|
|||
|
|
# 计算覆盖率
|
|||
|
|
coverage = (
|
|||
|
|
(intersection_area / reference_area) * 100 if reference_area > 0 else 0.0
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
return intersection_area, coverage
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
print(f"❌ 计算色域覆盖率失败: {e}")
|
|||
|
|
return 0.0, 0.0
|
|||
|
|
|
|||
|
|
|
|||
|
|
def calculate_gamut_coverage_DCIP3(points):
|
|||
|
|
"""
|
|||
|
|
计算 CIE 1931 xy 色度空间下的 DCI-P3 覆盖率
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
points: [[x1, y1], [x2, y2], [x3, y3]] 测量的 xy 坐标
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
area: 交集面积
|
|||
|
|
coverage: 覆盖率(%)
|
|||
|
|
"""
|
|||
|
|
# DCI-P3 标准色域坐标(CIE 1931 xy)
|
|||
|
|
dcip3_xy = [
|
|||
|
|
[0.680, 0.320], # Red
|
|||
|
|
[0.265, 0.690], # Green
|
|||
|
|
[0.150, 0.060], # Blue
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
area, coverage = calculate_gamut_coverage(points, dcip3_xy)
|
|||
|
|
return area, coverage
|
|||
|
|
|
|||
|
|
|
|||
|
|
def calculate_gamut_coverage_BT709(results):
|
|||
|
|
"""
|
|||
|
|
计算相对于 BT.709 的色域覆盖率
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
results: 测量结果列表
|
|||
|
|
[[x1, y1, lv1, X1, Y1, Z1], ...]
|
|||
|
|
或 [[x1, y1], [x2, y2], [x3, y3]]
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
tuple: (intersection_area, coverage_percentage)
|
|||
|
|
"""
|
|||
|
|
# BT.709 标准色域三角形(CIE 1931 xy)
|
|||
|
|
bt709_triangle = [
|
|||
|
|
[0.6400, 0.3300], # Red
|
|||
|
|
[0.3000, 0.6000], # Green
|
|||
|
|
[0.1500, 0.0600], # Blue
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
# 提取测量的 RGB 三个点的 xy 坐标
|
|||
|
|
if len(results[0]) > 2:
|
|||
|
|
measured_points = [[r[0], r[1]] for r in results[:3]]
|
|||
|
|
else:
|
|||
|
|
measured_points = results[:3]
|
|||
|
|
|
|||
|
|
area, coverage = calculate_gamut_coverage(measured_points, bt709_triangle)
|
|||
|
|
return area, coverage
|
|||
|
|
|
|||
|
|
|
|||
|
|
def calculate_gamut_coverage_BT601(results):
|
|||
|
|
"""
|
|||
|
|
计算相对于 BT.601 的色域覆盖率
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
results: 测量结果列表
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
tuple: (intersection_area, coverage_percentage)
|
|||
|
|
"""
|
|||
|
|
# BT.601 标准色域三角形(NTSC 版本)
|
|||
|
|
bt601_triangle = [
|
|||
|
|
[0.6300, 0.3400], # Red
|
|||
|
|
[0.3100, 0.5950], # Green
|
|||
|
|
[0.1550, 0.0700], # Blue
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
# 提取测量点
|
|||
|
|
if len(results[0]) > 2:
|
|||
|
|
measured_points = [[r[0], r[1]] for r in results[:3]]
|
|||
|
|
else:
|
|||
|
|
measured_points = results[:3]
|
|||
|
|
|
|||
|
|
area, coverage = calculate_gamut_coverage(measured_points, bt601_triangle)
|
|||
|
|
return area, coverage
|
|||
|
|
|
|||
|
|
|
|||
|
|
def calculate_gamut_coverage_BT2020(results):
|
|||
|
|
"""
|
|||
|
|
计算相对于 BT.2020 的色域覆盖率
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
results: 测量结果列表
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
tuple: (intersection_area, coverage_percentage)
|
|||
|
|
"""
|
|||
|
|
# BT.2020 标准色域三角形
|
|||
|
|
bt2020_triangle = [
|
|||
|
|
[0.7080, 0.2920], # Red
|
|||
|
|
[0.1700, 0.7970], # Green
|
|||
|
|
[0.1310, 0.0460], # Blue
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
# 提取测量点
|
|||
|
|
if len(results[0]) > 2:
|
|||
|
|
measured_points = [[r[0], r[1]] for r in results[:3]]
|
|||
|
|
else:
|
|||
|
|
measured_points = results[:3]
|
|||
|
|
|
|||
|
|
area, coverage = calculate_gamut_coverage(measured_points, bt2020_triangle)
|
|||
|
|
return area, coverage
|
|||
|
|
|
|||
|
|
|
|||
|
|
def xy_to_uv_1976(x, y):
|
|||
|
|
"""
|
|||
|
|
CIE 1931 xy → CIE 1976 u'v' 转换(现代标准)
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
x: CIE 1931 x 坐标
|
|||
|
|
y: CIE 1931 y 坐标
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
(u', v'): CIE 1976 色度坐标
|
|||
|
|
"""
|
|||
|
|
denom = -2 * x + 12 * y + 3
|
|||
|
|
if abs(denom) < 1e-10:
|
|||
|
|
return (0, 0)
|
|||
|
|
|
|||
|
|
u_prime = (4 * x) / denom
|
|||
|
|
v_prime = (9 * y) / denom
|
|||
|
|
|
|||
|
|
return (u_prime, v_prime)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def calculate_uv_gamut_coverage(uv_coords, reference="DCI-P3"):
|
|||
|
|
"""
|
|||
|
|
计算 CIE 1976 u'v' 色度空间下的色域覆盖率
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
uv_coords: [[u1, v1], [u2, v2], [u3, v3]] 测量的 u'v' 坐标
|
|||
|
|
reference: 参考标准 ("DCI-P3", "BT.709", "BT.2020", "BT.601")
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
float: 覆盖率百分比
|
|||
|
|
"""
|
|||
|
|
try:
|
|||
|
|
# ========== 根据参考标准选择 xy 坐标 ==========
|
|||
|
|
if reference == "BT.2020":
|
|||
|
|
ref_xy = [
|
|||
|
|
(0.7080, 0.2920), # Red
|
|||
|
|
(0.1700, 0.7970), # Green
|
|||
|
|
(0.1310, 0.0460), # Blue
|
|||
|
|
]
|
|||
|
|
elif reference == "BT.709":
|
|||
|
|
ref_xy = [
|
|||
|
|
(0.6400, 0.3300), # Red
|
|||
|
|
(0.3000, 0.6000), # Green
|
|||
|
|
(0.1500, 0.0600), # Blue
|
|||
|
|
]
|
|||
|
|
elif reference == "DCI-P3":
|
|||
|
|
ref_xy = [
|
|||
|
|
(0.680, 0.320), # Red
|
|||
|
|
(0.265, 0.690), # Green
|
|||
|
|
(0.150, 0.060), # Blue
|
|||
|
|
]
|
|||
|
|
elif reference == "BT.601":
|
|||
|
|
ref_xy = [
|
|||
|
|
(0.6300, 0.3400), # Red
|
|||
|
|
(0.3100, 0.5950), # Green
|
|||
|
|
(0.1550, 0.0700), # Blue
|
|||
|
|
]
|
|||
|
|
else:
|
|||
|
|
# 默认使用 DCI-P3
|
|||
|
|
ref_xy = [
|
|||
|
|
(0.680, 0.320),
|
|||
|
|
(0.265, 0.690),
|
|||
|
|
(0.150, 0.060),
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
# 转换参考标准为 u'v'
|
|||
|
|
ref_uv = [list(xy_to_uv_1976(x, y)) for x, y in ref_xy]
|
|||
|
|
|
|||
|
|
# 确保测量坐标格式正确
|
|||
|
|
measured_uv = [[float(u), float(v)] for u, v in uv_coords]
|
|||
|
|
|
|||
|
|
# 计算覆盖率
|
|||
|
|
area, coverage = calculate_gamut_coverage(measured_uv, ref_uv)
|
|||
|
|
|
|||
|
|
return coverage
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
print(f"❌ 计算 u'v' 色域覆盖率失败: {str(e)}")
|
|||
|
|
import traceback
|
|||
|
|
|
|||
|
|
traceback.print_exc()
|
|||
|
|
return 0.0
|
|||
|
|
|
|||
|
|
|
|||
|
|
def calculate_gamut_coverage_DCIP3_uv(uv_points):
|
|||
|
|
"""
|
|||
|
|
计算 CIE 1976 u'v' 色度空间下的 DCI-P3 覆盖率
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
uv_points: [[u1, v1], [u2, v2], [u3, v3]] 测量的 u'v' 坐标
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
area: 交集面积
|
|||
|
|
coverage: 覆盖率(%)
|
|||
|
|
"""
|
|||
|
|
dcip3_xy = [
|
|||
|
|
(0.680, 0.320), # Red
|
|||
|
|
(0.265, 0.690), # Green
|
|||
|
|
(0.150, 0.060), # Blue
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
dcip3_uv = [list(xy_to_uv_1976(x, y)) for x, y in dcip3_xy]
|
|||
|
|
area, coverage = calculate_gamut_coverage(uv_points, dcip3_uv)
|
|||
|
|
return area, coverage
|
|||
|
|
|
|||
|
|
|
|||
|
|
def calculate_gamut_coverage_BT709_uv(uv_points):
|
|||
|
|
"""
|
|||
|
|
计算 CIE 1976 u'v' 色度空间下的 BT.709 覆盖率
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
uv_points: [[u1, v1], [u2, v2], [u3, v3]] 测量的 u'v' 坐标
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
area: 交集面积
|
|||
|
|
coverage: 覆盖率(%)
|
|||
|
|
"""
|
|||
|
|
bt709_xy = [
|
|||
|
|
(0.6400, 0.3300), # Red
|
|||
|
|
(0.3000, 0.6000), # Green
|
|||
|
|
(0.1500, 0.0600), # Blue
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
bt709_uv = [list(xy_to_uv_1976(x, y)) for x, y in bt709_xy]
|
|||
|
|
area, coverage = calculate_gamut_coverage(uv_points, bt709_uv)
|
|||
|
|
return area, coverage
|
|||
|
|
|
|||
|
|
|
|||
|
|
def calculate_gamut_coverage_BT2020_uv(uv_points):
|
|||
|
|
"""
|
|||
|
|
计算 CIE 1976 u'v' 色度空间下的 BT.2020 覆盖率
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
uv_points: [[u1, v1], [u2, v2], [u3, v3]] 测量的 u'v' 坐标
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
area: 交集面积
|
|||
|
|
coverage: 覆盖率(%)
|
|||
|
|
"""
|
|||
|
|
bt2020_xy = [
|
|||
|
|
(0.7080, 0.2920), # Red
|
|||
|
|
(0.1700, 0.7970), # Green
|
|||
|
|
(0.1310, 0.0460), # Blue
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
bt2020_uv = [list(xy_to_uv_1976(x, y)) for x, y in bt2020_xy]
|
|||
|
|
area, coverage = calculate_gamut_coverage(uv_points, bt2020_uv)
|
|||
|
|
return area, coverage
|
|||
|
|
|
|||
|
|
|
|||
|
|
def calculate_gamut_coverage_BT601_uv(uv_points):
|
|||
|
|
"""
|
|||
|
|
计算 CIE 1976 u'v' 色度空间下的 BT.601 覆盖率
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
uv_points: [[u1, v1], [u2, v2], [u3, v3]] 测量的 u'v' 坐标
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
area: 交集面积
|
|||
|
|
coverage: 覆盖率(%)
|
|||
|
|
"""
|
|||
|
|
bt601_xy = [
|
|||
|
|
(0.6300, 0.3400), # Red
|
|||
|
|
(0.3100, 0.5950), # Green
|
|||
|
|
(0.1550, 0.0700), # Blue
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
bt601_uv = [list(xy_to_uv_1976(x, y)) for x, y in bt601_xy]
|
|||
|
|
area, coverage = calculate_gamut_coverage(uv_points, bt601_uv)
|
|||
|
|
return area, coverage
|
|||
|
|
|
|||
|
|
|
|||
|
|
# ===============
|
|||
|
|
# Gamma 计算公式
|
|||
|
|
# ===============
|
|||
|
|
|
|||
|
|
|
|||
|
|
def calculate_gamma(results, max_index_fix, pattern_params=None):
|
|||
|
|
"""
|
|||
|
|
计算 Gamma 值
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
results: [[x, y, lv, X, Y, Z], ...] 测量结果
|
|||
|
|
max_index_fix: 最大灰阶索引
|
|||
|
|
pattern_params: [[R, G, B], ...] 8bit pattern参数,用于计算input_level
|
|||
|
|
如果提供,则使用 pattern_value/255 作为底数
|
|||
|
|
如果不提供,则使用传统的 灰阶百分比 作为底数
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
results_with_gamma: [[x, y, lv, gamma], ...]
|
|||
|
|
"""
|
|||
|
|
if not results:
|
|||
|
|
raise ValueError("测量结果为空")
|
|||
|
|
|
|||
|
|
# 提取亮度值
|
|||
|
|
luminance_values = [result[2] for result in results]
|
|||
|
|
|
|||
|
|
if len(luminance_values) < 2:
|
|||
|
|
raise ValueError(f"数据点数量不足: {len(luminance_values)}")
|
|||
|
|
|
|||
|
|
# 使用实际的最大亮度值
|
|||
|
|
max_luminance = max(luminance_values)
|
|||
|
|
min_luminance = min(luminance_values)
|
|||
|
|
|
|||
|
|
if max_luminance <= 0:
|
|||
|
|
raise ValueError(f"最大亮度无效: {max_luminance}")
|
|||
|
|
|
|||
|
|
# 判断数据排列顺序
|
|||
|
|
is_descending = luminance_values[0] > luminance_values[-1]
|
|||
|
|
|
|||
|
|
results_with_gamma = []
|
|||
|
|
valid_gamma_sum = 0.0
|
|||
|
|
valid_gamma_count = 0
|
|||
|
|
|
|||
|
|
for i, result in enumerate(results):
|
|||
|
|
x, y, lv = result[0], result[1], result[2]
|
|||
|
|
|
|||
|
|
# 归一化亮度
|
|||
|
|
L_bar = lv / max_luminance
|
|||
|
|
|
|||
|
|
# 计算输入灰阶值 input_level
|
|||
|
|
if pattern_params is not None and i < len(pattern_params):
|
|||
|
|
# 使用 8bit pattern 数据 / 255 作为底数(22293 Gamma 数据对齐)
|
|||
|
|
# 取 R 通道值(灰阶图案 R=G=B)
|
|||
|
|
pattern_value = pattern_params[i][0]
|
|||
|
|
input_level = pattern_value / 255.0
|
|||
|
|
else:
|
|||
|
|
# 传统计算方式:根据数据顺序计算输入灰阶值
|
|||
|
|
if is_descending:
|
|||
|
|
# 从亮到暗: i=0 (100%) → i=max (0%)
|
|||
|
|
input_level = 1.0 - (i / max_index_fix) if max_index_fix > 0 else 0
|
|||
|
|
else:
|
|||
|
|
# 从暗到亮: i=0 (0%) → i=max (100%)
|
|||
|
|
input_level = (i / max_index_fix) if max_index_fix > 0 else 0
|
|||
|
|
|
|||
|
|
# 计算 Gamma
|
|||
|
|
gamma = 0.0
|
|||
|
|
|
|||
|
|
# 跳过极端值(接近 0% 和 100%)
|
|||
|
|
if input_level <= 0.01 or input_level >= 0.99 or L_bar <= 0.001:
|
|||
|
|
gamma = 0.0
|
|||
|
|
else:
|
|||
|
|
try:
|
|||
|
|
log_L = math.log(L_bar)
|
|||
|
|
log_I = math.log(input_level)
|
|||
|
|
gamma = log_L / log_I
|
|||
|
|
|
|||
|
|
# 合理性检查
|
|||
|
|
if 0.5 <= gamma <= 5.0:
|
|||
|
|
valid_gamma_sum += gamma
|
|||
|
|
valid_gamma_count += 1
|
|||
|
|
else:
|
|||
|
|
gamma = 0.0
|
|||
|
|
|
|||
|
|
except (ValueError, ZeroDivisionError):
|
|||
|
|
gamma = 0.0
|
|||
|
|
|
|||
|
|
results_with_gamma.append(
|
|||
|
|
[round(x, 7), round(y, 7), round(lv, 7), round(gamma, 4)]
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
return results_with_gamma
|
|||
|
|
|
|||
|
|
|
|||
|
|
def calculate_L_bar(results):
|
|||
|
|
"""
|
|||
|
|
计算归一化亮度列表(用于绘制 Gamma 曲线)
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
results: 测量结果列表 [[x, y, lv, X, Y, Z], ...]
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
L_bar: 归一化亮度列表 [0.0, 0.1, 0.2, ..., 1.0]
|
|||
|
|
"""
|
|||
|
|
if not results:
|
|||
|
|
return []
|
|||
|
|
|
|||
|
|
# 提取亮度值
|
|||
|
|
luminance_values = [result[2] for result in results]
|
|||
|
|
|
|||
|
|
# 使用实际的最大亮度值
|
|||
|
|
max_luminance = max(luminance_values)
|
|||
|
|
|
|||
|
|
if max_luminance <= 0:
|
|||
|
|
return [0.0] * len(luminance_values)
|
|||
|
|
|
|||
|
|
# 归一化
|
|||
|
|
L_bar = [lv / max_luminance for lv in luminance_values]
|
|||
|
|
|
|||
|
|
return L_bar
|
|||
|
|
|
|||
|
|
|
|||
|
|
# ============
|
|||
|
|
# 色度坐标提取
|
|||
|
|
# ============
|
|||
|
|
|
|||
|
|
|
|||
|
|
def calculate_cct_from_results(results):
|
|||
|
|
"""
|
|||
|
|
从测量结果提取色度坐标(xy 坐标)
|
|||
|
|
|
|||
|
|
⚠️ 注意:方法名保持不变(历史原因),实际功能是提取色度坐标
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
results: [[x, y, lv, ...], ...] 测量结果列表
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
dict: {
|
|||
|
|
'x': [x1, x2, x3, ...],
|
|||
|
|
'y': [y1, y2, y3, ...],
|
|||
|
|
'lv': [lv1, lv2, lv3, ...]
|
|||
|
|
}
|
|||
|
|
"""
|
|||
|
|
x_values = []
|
|||
|
|
y_values = []
|
|||
|
|
lv_values = []
|
|||
|
|
|
|||
|
|
for result in results:
|
|||
|
|
try:
|
|||
|
|
if isinstance(result, (list, tuple)) and len(result) >= 2:
|
|||
|
|
x = float(result[0])
|
|||
|
|
y = float(result[1])
|
|||
|
|
x_values.append(x)
|
|||
|
|
y_values.append(y)
|
|||
|
|
|
|||
|
|
# 如果有亮度值也保存(可选)
|
|||
|
|
if len(result) >= 3:
|
|||
|
|
lv = float(result[2])
|
|||
|
|
lv_values.append(lv)
|
|||
|
|
else:
|
|||
|
|
# 数据格式错误时的默认值(D65 白点)
|
|||
|
|
x_values.append(0.3127)
|
|||
|
|
y_values.append(0.3290)
|
|||
|
|
lv_values.append(0.0)
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
print(f"⚠️ 提取色度坐标失败: {str(e)}")
|
|||
|
|
x_values.append(0.3127)
|
|||
|
|
y_values.append(0.3290)
|
|||
|
|
lv_values.append(0.0)
|
|||
|
|
|
|||
|
|
return {"x": x_values, "y": y_values, "lv": lv_values if lv_values else None}
|
|||
|
|
|
|||
|
|
|
|||
|
|
# ========
|
|||
|
|
# 测试代码
|
|||
|
|
# ========
|
|||
|
|
if __name__ == "__main__":
|
|||
|
|
print("=" * 60)
|
|||
|
|
print("PQ 算法库测试(使用 shapely 库)")
|
|||
|
|
print("=" * 60)
|
|||
|
|
|
|||
|
|
# 测试 1: DCI-P3 覆盖率
|
|||
|
|
print("\n1. 测试 DCI-P3 覆盖率计算")
|
|||
|
|
test_points = [[0.680, 0.320], [0.265, 0.690], [0.150, 0.060]]
|
|||
|
|
area, coverage = calculate_gamut_coverage_DCIP3(test_points)
|
|||
|
|
print(f" DCI-P3 覆盖率: {coverage:.2f}% (期望: 100.00%)")
|
|||
|
|
|
|||
|
|
# 测试 2: BT.709 覆盖率
|
|||
|
|
print("\n2. 测试 BT.709 覆盖率计算(测量色域超出标准)")
|
|||
|
|
test_results_bt709 = [
|
|||
|
|
[0.6637, 0.3236, 41.90],
|
|||
|
|
[0.3087, 0.6250, 160.29],
|
|||
|
|
[0.1435, 0.0447, 12.69],
|
|||
|
|
]
|
|||
|
|
area, coverage = calculate_gamut_coverage_BT709(test_results_bt709)
|
|||
|
|
print(f" BT.709 覆盖率: {coverage:.2f}% (期望: ~98%)")
|
|||
|
|
|
|||
|
|
# 测试 3: BT.2020 覆盖率
|
|||
|
|
print("\n3. 测试 BT.2020 覆盖率计算(测量色域小于标准)")
|
|||
|
|
test_results_bt2020 = [
|
|||
|
|
[0.6662, 0.3216, 39.75],
|
|||
|
|
[0.3096, 0.6282, 155.24],
|
|||
|
|
[0.1440, 0.0452, 11.96],
|
|||
|
|
]
|
|||
|
|
area, coverage = calculate_gamut_coverage_BT2020(test_results_bt2020)
|
|||
|
|
print(f" BT.2020 覆盖率: {coverage:.2f}% (期望: ~60%)")
|
|||
|
|
|
|||
|
|
# 测试 4: 色度坐标提取
|
|||
|
|
print("\n4. 测试色度坐标提取")
|
|||
|
|
test_results = [
|
|||
|
|
[0.3127, 0.3290, 190.5],
|
|||
|
|
[0.3125, 0.3288, 150.2],
|
|||
|
|
[0.3129, 0.3292, 100.8],
|
|||
|
|
]
|
|||
|
|
chromaticity_data = calculate_cct_from_results(test_results)
|
|||
|
|
print(f" x 坐标: {chromaticity_data['x']}")
|
|||
|
|
print(f" y 坐标: {chromaticity_data['y']}")
|
|||
|
|
print(f" 亮度值: {chromaticity_data['lv']}")
|
|||
|
|
|
|||
|
|
# 测试 5: Gamma 计算
|
|||
|
|
print("\n5. 测试 Gamma 计算")
|
|||
|
|
test_gamma_results = [
|
|||
|
|
[0.31, 0.33, 450.0, 0, 0, 0],
|
|||
|
|
[0.31, 0.33, 350.0, 0, 0, 0],
|
|||
|
|
[0.31, 0.33, 250.0, 0, 0, 0],
|
|||
|
|
[0.31, 0.33, 150.0, 0, 0, 0],
|
|||
|
|
[0.31, 0.33, 50.0, 0, 0, 0],
|
|||
|
|
[0.31, 0.33, 0.1, 0, 0, 0],
|
|||
|
|
]
|
|||
|
|
gamma_results = calculate_gamma(test_gamma_results, 5)
|
|||
|
|
for i, result in enumerate(gamma_results):
|
|||
|
|
print(f" 点{i+1}: Gamma={result[3]:.3f}")
|
|||
|
|
|
|||
|
|
print("\n" + "=" * 60)
|
|||
|
|
print("✅ 测试完成!")
|
|||
|
|
print("=" * 60)
|