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如下:

相关推荐
派葛穆2 小时前
Python-OpenCV打开海康机器人黑白相机
python·opencv·机器人
m0_743106462 小时前
【浙大&南洋理工最新综述】Feed-Forward 3D Scene Modeling(五)
人工智能·算法·计算机视觉·3d·几何学
ZPC821017 小时前
fanuc 机器人通过PR寄存器实现轨迹控制
人工智能·算法·计算机视觉·机器人
AI人工智能+19 小时前
文档抽取系统结合OCR技术与大语言模型,有效解决档案数字化与知识化利用之间的矛盾
人工智能·计算机视觉·ocr·文档抽取
深度学习lover20 小时前
<数据集>yolo 焊接缺陷识别<目标检测>
人工智能·python·yolo·目标检测·计算机视觉·焊接缺陷检测
军军君0120 小时前
【人工智能/AI】项目实战二:AI视频生成产品汇总(非完全)
图像处理·人工智能·计算机视觉·ai作画·视觉检测·文心一言
一休哥※20 小时前
YOLOv11改进系列 | 引入EMO ICCV2023的C3k2_iRMB模块,轻量注意力残差混合块增强C3k2,多尺度分割更稳更准
深度学习·yolo·计算机视觉
森诺Alyson1 天前
前沿技术借鉴研讨-2026.4.16(视觉语言模型/医学影像文本多模态对齐)
论文阅读·人工智能·经验分享·计算机视觉·语言模型
jay神1 天前
鸟类识别数据集 - CUB_200
人工智能·深度学习·目标检测·计算机视觉·目标跟踪·毕业设计