python opencv 计算 色坐标(CIE 1931 )

目录

1.前言

2.计算过程

3.判断与显示

4.完整代码


1.前言

CIE 色坐标 是国际照明委员会(Commission Internationale de l'Éclairage,简称 CIE)制定的用于定量描述颜色 的标准化坐标系统,最常用的是 CIE 1931 xy 色度坐标

效果如下:

CIE屏幕录制 2026-04-22 102714

其中, CIE 1931 马蹄形色度图背景图片 (文件名 cie.png)如下:

2.计算过程

(1)先获取RGB三个通道的均值,可用cv2.mean

复制代码
x, y, w, h = roi
cropped_img = img[y:y + h, x:x + w]
height, width, channels = img.shape
if( channels==3):
    #获取均值
    mean_val = cv2.mean(cropped_img)
    blue=mean_val[0]
    green = mean_val[1]
    red = mean_val[2]

(2)RGB转CIE

根据"国际电工委员会(IEC)在 IEC 61966-2-1:1999 标准中精确定义。"进行计算:

复制代码
#将 sRGB 颜色值(0–255) 转换到 CIE 1931 xy 色度坐标。
def RGBtoCIE(blue,green,red):
    var_R = red / 255
    var_G = green / 255
    var_B = blue / 255

    if (var_R > 0.04045):

        var_R = pow((var_R + 0.055) / 1.055, 2.4)
    else:
        var_R = var_R / 12.92


    if (var_G > 0.04045):

        var_G=pow((var_G + 0.055) / 1.055, 2.4)
    else:
        var_G = var_G / 12.92


    if (var_B > 0.04045):

        var_B=pow((var_B + 0.055) / 1.055, 2.4)
    else:
        var_B = var_B / 12.92

    # 这些数字是sRGB(标准红绿蓝颜色空间)官方标准中定义的核心参数,用于将存储的图像数据转换为物理线性的光强度数据,以便进行精确的颜色计算。
    # 在色彩科学里被称为sRGB逆向伽马校正或sRGB解码。它由国际电工委员会(IEC)在IEC61966 - 2 - 1: 1999标准中精确定义,是所有显示器、打印机、互联网图像等遵循的统一规范
    var_R = var_R * 100
    var_G = var_G * 100
    var_B = var_B * 100

    X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805
    Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722
    Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505

    if (X + Y + Z == 0):
        CIEx = 0
        CIEy = 0
    else:
        CIEx = X / (X + Y + Z)
        CIEy = Y / (X + Y + Z)




    return round(CIEx,3),round(CIEy,3)
归一化与反伽马校正(sRGB 解码)

var_R = red / 255

var_G = green / 255

var_B = blue / 255

if var_R > 0.04045:

var_R = pow((var_R + 0.055) / 1.055, 2.4)

else:

var_R = var_R / 12.92

G 和 B 同样处理

  • 将 0--255 的整数颜色值映射到 0--1 的线性光强度

  • 这一步称为 sRGB 反向伽马校正 ,公式来自 IEC 61966-2-1 标准

    • 若数值 ≤ 0.04045,按线性缩放;

    • 若 > 0.04045,按幂函数校正,指数为 2.4,并加一个小的偏移量。

X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805

Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722

Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505

  • 这是 sRGB → XYZ (D65 白点) 的标准转换矩阵。

  • 矩阵数值来源于 国际照明委员会 (CIE) 定义的标准观察者函数与 sRGB 原色坐标的结合。

3.判断与显示

绘制合格区域(本文是三角形区域)

在cie.png上绘制点和区域,并判断是否在区域内

代码如下:

复制代码
#三角形三个顶点坐标
x1,y1=0.3,0.3
x2,y2=0.5,0.3
x3,y3=0.4,0.4


#-----在色坐标图上显示色坐标----
def showCIEXY(ciex, ciey):
    img = cv2.imread("cie.png")
    height, width, _ = img.shape

    k_x = 750
    k_y = -750
    b_x = 0
    b_y = 700

    # 转换三角形顶点坐标到像素坐标
    pts = np.array([
        [round(x1 * k_x + b_x), round(y1 * k_y + b_y)],
        [round(x2 * k_x + b_x), round(y2 * k_y + b_y)],
        [round(x3 * k_x + b_x), round(y3 * k_y + b_y)]
    ], np.int32)

    # 绘制三角形轮廓(绿色,线宽2)
    cv2.polylines(img, [pts], isClosed=True, color=(0, 255, 0), thickness=2)

    # 绘制色坐标点(黑色实心圆)
    x = round(ciex * k_x + b_x)
    y = round(ciey * k_y + b_y)
    cv2.circle(img, (x, y), 10, (0, 0, 0), thickness=-1)

    cv2.imshow('CIE Diagram', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()





#判断色坐标是否合格
def IsInRegion(ciex, ciey):
    """
    判断 CIE 色坐标 (ciex, ciey) 是否在预定义的三角形区域内。
    三角形顶点:(0.3,0.3), (0.33,0.3), (0.315,0.315)
    返回值:True(在区域内),False(不在区域内)
    """


    # 计算各边向量与点P到起点向量的叉积
    def cross_product(ax, ay, bx, by, px, py):
        """返回向量 AB × AP 的 z 分量"""
        return (bx - ax) * (py - ay) - (by - ay) * (px - ax)

    # 计算三个叉积
    cp1 = cross_product(x1, y1, x2, y2, ciex, ciey)
    cp2 = cross_product(x2, y2, x3, y3, ciex, ciey)
    cp3 = cross_product(x3, y3, x1, y1, ciex, ciey)

    # 容差处理,绝对值小于 1e-9 视为 0(点在边上)
    eps = 1e-9
    sign = lambda v: 0 if abs(v) < eps else (1 if v > 0 else -1)

    s1, s2, s3 = sign(cp1), sign(cp2), sign(cp3)

    # 如果所有符号非负 或 所有符号非正,则点在三角形内(包括边界)
    # 注意:若某个叉积为0,则点在对应的边上,仍算区域内
    if s1 >= 0 and s2 >= 0 and s3 >= 0:
        return True
    if s1 <= 0 and s2 <= 0 and s3 <= 0:
        return True
    return False

4.完整代码

复制代码
import cv2
import numpy as np



#----计算色坐标---
def getCIE(img,roi):
    #抠图
    x, y, w, h = roi
    cropped_img = img[y:y + h, x:x + w]
    height, width, channels = img.shape
    if( channels==3):
        #获取均值
        mean_val = cv2.mean(cropped_img)
        blue=mean_val[0]
        green = mean_val[1]
        red = mean_val[2]
        return RGBtoCIE(blue,green,red)
    else:

        return 0,0




#将 sRGB 颜色值(0--255) 转换到 CIE 1931 xy 色度坐标。
def RGBtoCIE(blue,green,red):
    var_R = red / 255
    var_G = green / 255
    var_B = blue / 255

    if (var_R > 0.04045):

        var_R = pow((var_R + 0.055) / 1.055, 2.4)
    else:
        var_R = var_R / 12.92


    if (var_G > 0.04045):

        var_G=pow((var_G + 0.055) / 1.055, 2.4)
    else:
        var_G = var_G / 12.92


    if (var_B > 0.04045):

        var_B=pow((var_B + 0.055) / 1.055, 2.4)
    else:
        var_B = var_B / 12.92

    # 这些数字是sRGB(标准红绿蓝颜色空间)官方标准中定义的核心参数,用于将存储的图像数据转换为物理线性的光强度数据,以便进行精确的颜色计算。
    # 在色彩科学里被称为sRGB逆向伽马校正或sRGB解码。它由国际电工委员会(IEC)在IEC61966 - 2 - 1: 1999标准中精确定义,是所有显示器、打印机、互联网图像等遵循的统一规范
    var_R = var_R * 100
    var_G = var_G * 100
    var_B = var_B * 100

    X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805
    Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722
    Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505

    if (X + Y + Z == 0):
        CIEx = 0
        CIEy = 0
    else:
        CIEx = X / (X + Y + Z)
        CIEy = Y / (X + Y + Z)




    return round(CIEx,3),round(CIEy,3)

#三角形三个顶点坐标
x1,y1=0.3,0.3
x2,y2=0.5,0.3
x3,y3=0.4,0.4


#-----在色坐标图上显示色坐标----
def showCIEXY(ciex, ciey):
    img = cv2.imread("cie.png")
    height, width, _ = img.shape

    k_x = 750
    k_y = -750
    b_x = 0
    b_y = 700

    # 转换三角形顶点坐标到像素坐标
    pts = np.array([
        [round(x1 * k_x + b_x), round(y1 * k_y + b_y)],
        [round(x2 * k_x + b_x), round(y2 * k_y + b_y)],
        [round(x3 * k_x + b_x), round(y3 * k_y + b_y)]
    ], np.int32)

    # 绘制三角形轮廓(绿色,线宽2)
    cv2.polylines(img, [pts], isClosed=True, color=(0, 255, 0), thickness=2)

    # 绘制色坐标点(黑色实心圆)
    x = round(ciex * k_x + b_x)
    y = round(ciey * k_y + b_y)
    cv2.circle(img, (x, y), 10, (0, 0, 0), thickness=-1)

    cv2.imshow('CIE Diagram', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()





#判断色坐标是否合格
def IsInRegion(ciex, ciey):
    """
    判断 CIE 色坐标 (ciex, ciey) 是否在预定义的三角形区域内。
    三角形顶点:(0.3,0.3), (0.33,0.3), (0.315,0.315)
    返回值:True(在区域内),False(不在区域内)
    """


    # 计算各边向量与点P到起点向量的叉积
    def cross_product(ax, ay, bx, by, px, py):
        """返回向量 AB × AP 的 z 分量"""
        return (bx - ax) * (py - ay) - (by - ay) * (px - ax)

    # 计算三个叉积
    cp1 = cross_product(x1, y1, x2, y2, ciex, ciey)
    cp2 = cross_product(x2, y2, x3, y3, ciex, ciey)
    cp3 = cross_product(x3, y3, x1, y1, ciex, ciey)

    # 容差处理,绝对值小于 1e-9 视为 0(点在边上)
    eps = 1e-9
    sign = lambda v: 0 if abs(v) < eps else (1 if v > 0 else -1)

    s1, s2, s3 = sign(cp1), sign(cp2), sign(cp3)

    # 如果所有符号非负 或 所有符号非正,则点在三角形内(包括边界)
    # 注意:若某个叉积为0,则点在对应的边上,仍算区域内
    if s1 >= 0 and s2 >= 0 and s3 >= 0:
        return True
    if s1 <= 0 and s2 <= 0 and s3 <= 0:
        return True
    return False





if __name__ == "__main__":
    img = cv2.imread("testimg.png")
    #print(img.shape)
    #在窗口上画框,获取region
    # 按下回车或空格或esc确认
    roi = cv2.selectROI("Select ROI", img, showCrosshair=True, fromCenter=False)

    print(f"选取的区域为: {roi}")  # 返回 (x, y, w, h)
    ciex, ciey = getCIE(img,roi)

    print(ciex,ciey)
    cv2.destroyAllWindows()

    showCIEXY(ciex, ciey)

    if IsInRegion(ciex, ciey):
        print("色坐标在指定三角形区域内,合格!")
    else:
        print("色坐标不在区域内,不合格。")

testimg.png如下:

相关推荐
欧特克_Glodon5 小时前
OpenCV计算机视觉开发入门与实践<三十五>:开发视频播放器
c++·opencv·计算机视觉·音视频
leoZ2316 小时前
2026-09-08-mysql-57-init-walkthrough
前端·javascript·数据库·vue.js·opencv·mysql·adb
大熊背6 小时前
冯‑克里斯映射估计算法逻辑
深度学习·机器学习·计算机视觉·白平衡·色调映射·冯-克里斯映射估计
差不多的周周6 小时前
《MoChat:面向多转弯动作理解和描述的关节分组时空接地多通道大语言模型》论文核心部分详解
人工智能·深度学习·机器学习·计算机视觉·语言模型·自然语言处理
kyle~8 小时前
标注平台---CVAT
人工智能·目标检测·计算机视觉·机器视觉
szxinmai主板定制专家8 小时前
基于 RK3576 的智能割草机器人解决方案,从样机到量产
人工智能·嵌入式硬件·计算机视觉·fpga开发·机器人·rk3588+fpga·割草机器人
AI云海8 小时前
计算机视觉之-YOLO目标检测
yolo·目标检测·计算机视觉
YOLO数据集集合8 小时前
红外热成像人员检测数据集 |红外检测 白热模式 人员检测 夜间监控 目标检测 YOLO格式 深度学习数据集 计算机视觉9067期
数据库·深度学习·yolo·目标检测·计算机视觉·红外人员·红外数据
埃科光电1 天前
16K万兆网口彩色线阵相机:四倍带宽 高速真彩检测新方案
网络·图像处理·数码相机·计算机视觉·制造·相机
学术 学术 Fun1 天前
612 次图表重建实验告诉我们的:O612 次图表重建实验告诉我们的:OCR、图形与连接线CR、图形与连接线
机器学习·计算机视觉·ocr·图表