likes
comments
collection
share

java基于hsv识别红绿灯的逻辑

作者站长头像
站长
· 阅读数 2

背景

项目中有一个场景需要判断红绿灯的状态。并且代码是java开发的,考虑了良久,决定使用像素点的rgb值来做,但是rgb值的颜色范围不好判断,所以就想到把rgb转成hsv来判断。那么会有如下问题:

  • rbg如何转hsv
  • hsv如何判断红绿灯的颜色

RGB转HSV

首先解决一个问题,就是java中RGB怎么转HSV。

HSV(Hue, Saturation, Value)是一种描述颜色的模型,与常见的RGB(Red, Green, Blue)颜色模型不同。HSV模型更贴近人类感知颜色的方式,因为它将颜色的属性分解为更容易理解的部分。

这三个分量的含义如下:

  1. Hue(色调): 表示颜色的种类或名称。它是一个从0到360度的角度值,其中0和360是红色,120是绿色,240是蓝色,以此类推。色调决定了颜色是红色、绿色、蓝色等等。

java基于hsv识别红绿灯的逻辑 2. Saturation(饱和度): 表示颜色的鲜艳程度或灰度。它是一个百分比值,从0%(灰度)到100%(全彩)变化。饱和度为0%时,颜色是灰阶的。

java基于hsv识别红绿灯的逻辑 3. Value(明度): 表示颜色的亮度。它也是一个百分比值,从0%(黑色)到100%(最大亮度)变化。明度为0%时,颜色是黑色的。

java基于hsv识别红绿灯的逻辑

HSV模型的优势之一是,通过调整这三个参数,可以更直观地控制颜色的外观。在某些情况下,人们更容易使用HSV来选择或描述颜色,因为它更符合我们对颜色的主观感受。

java基于hsv识别红绿灯的逻辑

opencv官网给出了RGB转HSV的公式

java基于hsv识别红绿灯的逻辑

下面是我基于公式写的java代码,供参考:

public static float[] rgbToHsv(Color color) {

    //切割rgb数组
    int R = color.getRed();
    int G = color.getGreen();
    int B = color.getBlue();
    //公式运算 /255
    float R_1 = R / 255f;
    float G_1 = G / 255f;
    float B_1 = B / 255f;
    //重新拼接运算用数组
    float[] all = {R_1, G_1, B_1};
    float max = all[0];
    float min = all[0];
    //循环查找最大值和最小值
    for (float v : all) {
        if (max <= v) {
            max = v;
        }
        if (min >= v) {
            min = v;
        }
    }
    float C_max = max;
    float C_min = min;
    //计算差值
    float diff = C_max - C_min;
    float hue = 0f;
    //判断情况计算色调H
    if (diff == 0f) {
        hue = 0f;
    } else {
        if (C_max == R_1) {
            hue = (((G_1 - B_1) / diff) % 6) * 60f;
        }
        if (C_max == G_1) {
            hue = (((B_1 - R_1) / diff) + 2f) * 60f;
        }
        if (C_max == B_1) {
            hue = (((R_1 - G_1) / diff) + 4f) * 60f;
        }
    }
    if (hue < 0f){
        hue += 360f;
    }
    //计算饱和度S
    float saturation;
    if (C_max == 0f) {
        saturation = 0f;
    } else {
        saturation = diff / C_max;
    }
    //计算明度V
    return new float[]{hue, saturation, C_max};
}

hsv如何判断红绿灯的颜色

经过多次测试和对比,我得出如下数据阈值的范围可以表达红色

h(0,50)and (300,360)
s (0.50,1.0)
v (0.50,1.0)

绿色的阈值如下:

h (80,180)
s (0.50,1.0)
v (0.50,1.0)

测试工具网站:可以直观的看到hsv值对应的颜色 HSV到RGB转换| 颜色转换 (rapidtables.org)

java基于hsv识别红绿灯的逻辑

业务逻辑判断红绿灯的颜色

首先是需要对红绿灯进行画框表示 下面是简单的代码demo

public static boolean judeRedLight(String url, List<Integer> rectList){
    try {
        URL myurl = new URL(url);
        BufferedImage srcImg = ImageIO.read(myurl);
        return judeRedLight(srcImg, rectList.get(0), rectList.get(1), rectList.get(2), rectList.get(3));

    } catch (IOException e) {
        log.error("图片地址访问异常,url:" + url );
    }
    return false;
}
// 判断红绿灯
public static boolean judeRedLight(BufferedImage bi,int x1, int y1, int x2, int y2){

    int red = 0;
    int green = 0;
    try{
        for (int i = x1; i < x2; i++) {
            for (int j = y1; j < y2; j++) {
                Color color = new Color(bi.getRGB(i, j));
                float[] hsv = rgbToHsv(color);
                if (isRed(hsv)){
                    red++;
                }
                if (isGreen(hsv)){
                    green++;
                }
            }
        }
    }catch (Exception e){
        log.info("判断红绿灯异常:{}",e.getMessage());
    }
    log.info("判断结果:red:{} green:{}",red,green);
    return red > green;
}

经过上述的两个方法即可判断出当前的红绿灯。但是需要提前获取到红绿灯框的坐标