c# OpenCV 基于成像色度计的汽车氛围灯亮度色度计算

  • 时间:2025-11-07 15:33 作者: 来源: 阅读:0
  • 扫一扫,手机访问
摘要:        汽车产业(特别是新能源汽车和智能网联汽车)无疑是中国目前最耀眼、最具代表性的“旗舰产业”。它与半导体、人工智能、生物医药等一同,构成了支撑中国经济高质量发展的 “新支柱集群”。汽车氛围灯亮度和色度检测也已经成为了计算机视觉和工业质量控制的热门应用。     

        汽车产业(特别是新能源汽车和智能网联汽车)无疑是中国目前最耀眼、最具代表性的“旗舰产业”。它与半导体、人工智能、生物医药等一同,构成了支撑中国经济高质量发展的 “新支柱集群”。汽车氛围灯亮度和色度检测也已经成为了计算机视觉和工业质量控制的热门应用。

        本文重点是如何利用OpenCV这一强大工具,对汽车氛围灯的亮度和色度数据进行量化提取和计算,为您提供一个坚实的、基础的计算方法,为后续汽车氛围亮度色度检测和校准提供有力的支持,为主机厂和零部件供应商提供数据驱动的决策依据,是实现高品质氛围灯生产的核心技术保障。本文假设您已经利用成像色度计获取了XYZ三刺激值和RGB参照图像。
        计算举例,如下图:

一、实例说明

        1.1、左边是参考图像
        1.2、右边是CIE色度分析图
        1.3、底部是关注点数据列表
        1.4、鼠标跟随信息

二、上述图中主要计算的内容

        2.1、关注点的位置尺寸及形状:Left、Top、CenterX、CenterY、Width、Height、Radius、Area、ShapeType
        2.2、三刺激值值:X、Y、Z
        2.3、色度值:CIE-x、CIE-y、CIE-u'、CIE-v'
        2.4、色温:CCT

三、计算步骤

3.1、利用RGB参考图像,查询要测量的关注点

        这里就直接上代码,涉及到Opencv相关函数,在之前的文章中都有详细介绍。

        步骤:灰度图》滤波》二值化》边缘检测》获取轮廓。需要注意的2个参数:一是滤波值、二是二值化灰度值。这两个值根据实际情况调整。图像噪音大小就调整滤波值,亮度高低调整二值化灰度值。



/// <summary>
/// 查询关注点
/// </summary>
/// <param name="lstPoints">关注点边框点集合</param>
/// <returns></returns>
private List<OpenCvSharp.Rect> FindRoi(out List<OpenCvSharp.Point[]> lstPoints)
{
    lstPoints = new List<OpenCvSharp.Point[]>();
    //灰度图
    Mat gray = new Mat();
    Cv2.CvtColor(this.rgb, gray, ColorConversionCodes.BGR2GRAY);
 
    //参数依据拍摄的图像进行调整,当环境固定后参数不会变化
    int ksize = 5;
    double thresh = 30;
    //均值滤波
    Cv2.Blur(gray, gray, new OpenCvSharp.Size(ksize, ksize));
 
    //二值化
    Mat thresholdMat = new Mat();
    Cv2.Threshold(gray, thresholdMat, thresh, 255, ThresholdTypes.Binary);
 
    //Canny边缘检测
    Mat canny = new Mat();
    Cv2.Canny(thresholdMat, canny, thresh, 255);
 
    //获得轮廓
    OpenCvSharp.Point[][] contours;
    HierarchyIndex[] hierarchly;
 
    Cv2.FindContours(canny, out contours, out hierarchly, RetrievalModes.External, ContourApproximationModes.ApproxNone);
    int contourCount = contours.Length;
    List<OpenCvSharp.Rect> lstRoi = new List<Rect>();
    for (int i = 0; i < contourCount; i++)
    {
        Rect roiRect = Cv2.BoundingRect(contours[i]);
        lstRoi.Add(roiRect);
        lstPoints.Add(contours[i]);
    }
    return lstRoi;
}


3.2、读取XYZ数据,综合计算每个关注点的亮度、色度、色温      

        2.1、绘制掩膜,利用掩膜计算所以关注点XYZ图像数据的平均XYZ值。(此步骤可以省略)

        2.2、依据关注点的形状,计算每个关注点XYZ数据。

        2.3、依据XYZ数据,计算CIE-x,CIE-y,CIE-u',CIE-v',cct


3.3、显示关注点数据列表和CIE分析结果  

3.4、鼠标跟随信息

        3.4.1、显示鼠标当前位置所在的像素点的信息,例如:亮度、Cx,Cy,X,Z,鼠标屏幕位置,鼠标图像位置、RGB值。如下图:

        

        3.4.2、获取RGB值:参考图是一张RGB三通道图,At函数一次读取3通道值,然后将字节转换十进制值。代码如下:


var vec = rgb.At<Vec3b>(ty, tx);

       3.4.3、三刺激值(X,Y,Z),也可以先合并成一个三通道的图像,然后用AT函数一次读取X,Y,Z值。代码如下:



Cv2.Merge(new Mat[] { xmat, ymat, zmat } , xyzMat);
var vec = xyzMat.At<Vec3f>(ty,tx);

四、计算关注点亮度色度

4.1、按矩形框计算关注点亮度色度

        循环统计矩形框中每个像素点的值,排查亮度为零的暗点。



/// <summary>
/// 获取矩形框关注点XYZ值
/// </summary>
/// <param name="xyzMat">XYZ数据</param>
/// <param name="minXZY">最低亮度值</param>
/// <param name="poi">关注点</param>
/// <returns></returns>
private double GetRectangleShapeXYZ(Mat xyzMat, double minXZY, Poi poi)
{
    int left = poi.CenterX - poi.Radius;
    int top = poi.CenterY - poi.Radius;
    int width = poi.CenterX + poi.Radius;
    int height = poi.CenterY + poi.Radius;
    double sumXYZ = 0;
    int sumCount = 0;
    OpenCvSharp.Point pc = new OpenCvSharp.Point(poi.CenterX, poi.CenterY);
    for (int x = left; x < width; x++)
    {
        for (int y = top; y < height; y++)
        {
            float xyzVal = xyzMat.At<float>(y, x);
            if (xyzVal > minXZY)
            {
                sumXYZ += xyzVal;
                sumCount++;
            }
        }
    }
    return sumXYZ / sumCount;
}

4.2、按圆形计算关注点亮度色度

        1、以关注点的中心点为圆心,半径范围内的点。

        2、循环统计圆框中每个像素点的值,排查亮度为零的暗点。



/// <summary>
/// 获取圆形关注点XYZ值
/// </summary>
/// <param name="xyzMat">XYZ数据</param>
/// <param name="minXZY">最低亮度值</param>
/// <param name="poi">关注点</param>
/// <returns></returns>
private double GetCircleShapeXYZ(Mat xyzMat, double minXZY, Poi poi)
{
    int left = poi.CenterX - poi.Radius;
    int top = poi.CenterY - poi.Radius;
    int width = poi.CenterX + poi.Radius;
    int height = poi.CenterY + poi.Radius;
    double sumXYZ = 0;
    int sumCount = 0;
    OpenCvSharp.Point pc = new OpenCvSharp.Point(poi.CenterX, poi.CenterY);
    for (int x = left; x <= width; x++)
    {
        for (int y = top; y <= height; y++)
        {
            float xyzVal = xyzMat.At<float>(y, x);
            if (xyzVal > minXZY)
            {
                OpenCvSharp.Point p1 = new OpenCvSharp.Point(x, y);
                double dist = Distance(p1, pc);
                if (dist <= poi.Radius)
                {
                    //圆内及边框上的点
                    sumXYZ += xyzVal;
                    sumCount++;
                }
            }
        }
    }
    return sumXYZ / sumCount;
}

4.3、按多边形计算关注点亮度色度


        1、函数Cv2.PointPolygonTest检测一个点是否在多边形框内。

        2、循环统计多边形框中每个像素点的值,排查亮度为零的暗点。



/// <summary>
/// 获取多边形关注点XYZ值
/// </summary>
/// <param name="xyzMat">XYZ数据</param>
/// <param name="minXZY">最低亮度值</param>
/// <param name="poi">关注点</param>
/// <returns></returns>
private double GetPolygonShapeXYZ(Mat xyzMat, double minXZY, Poi poi)
{
    List<OpenCvSharp.Point> lstPoints = poi.ShapePoints.Select(s => new OpenCvSharp.Point(s.X, s.Y)).ToList();
    OpenCvSharp.Rect poiRect = Cv2.BoundingRect(lstPoints);
    double sumXYZ = 0;
    int sumCount = 0;
    int left = poiRect.X;
    int top = poiRect.Y;
    int width = poiRect.X + poiRect.Width;
    int height = poiRect.Y + poiRect.Height;
    for (int x = left; x <= width; x++)
    {
        for (int y = top; y <= height; y++)
        {
            float xyzVal = xyzMat.At<float>(y, x);
            if (xyzVal > minXZY)
            {
                OpenCvSharp.Point2f p1 = new OpenCvSharp.Point2f(x, y);
                if (Cv2.PointPolygonTest(lstPoints, p1, false) >= 0)
                {
                    //多边形内及边框上的点
                    sumXYZ += xyzVal;
                    sumCount++;
                }
            }
        }
    }
    return sumXYZ / sumCount;
}

五、与ImageJ对比计算结果

        5.1、例如关注点P01的X值:5.571,与ImageJ读取的值一致。

六、扩展说明

        上述实例要达到实用的程度,还需要进一步扩展,例如:
        6.1、将关注点的亮度色度数据,增加上下限阈值。
        6.2、采集一个标准样品的数据,计算出亮度色度数据的上下限。
        6.3、生产线上获取的产品数据,与标准数据进行对比,亮度色度数据在标准范围内,即判断此产品合格,否则为不合格。
        6.4、上述工具在计算关注点的XYZ值时,采用循环矩形框面积算法,而不是采用Cv2.Mean函数掩膜计算,依据经验当图像越大,计算一个关注点的时间比循环面积的时间要长,所以不采用。

  • 全部评论(0)
手机二维码手机访问领取大礼包
返回顶部