RGB与HSB
rgb三个分量的值相等时即为灰度图,值的大小体现了图的灰度。
彩图的颜色就是通过rgb值的差异进行体现的,rgb不等值的情况,只说明这不是完全的灰度图,
或者叫做彩色饱和度不高的彩图,只是肉眼分辨不出来。
为此,要将rgb模式转换为hsb模式再去判断,其中:h色相,s饱和度,b对比度。
转换为hsb后,判断饱和度,如果s<10%即可认为是灰度图,至于这个阈值是10%还是15%,需要根据实际情况来做判断;
RGB与HSB是什么
1.RGB是一种加色模型,就是将不同比例的Red/Green/Blue混合在一起得到新颜色.通常RGB颜色模型表示为:
2.HSB(HSV) 通过色相/饱和度/亮度三要素来表达颜色.
H(Hue):表示颜色的类型(例如红色,绿色或者黄色).取值范围为0—360.其中每一个值代表一种颜色.
S(Saturation):颜色的饱和度.从0到1.有时候也称为纯度.(0表示灰度图,1表示纯的颜色)
B(Brightness or Value):颜色的明亮程度.从0到1.(0表示黑色,1表示特定饱和度的颜色)
RGB到HSV(HSB)的转换 公式
HSV(HSB)到RGB的转换公式 写道
代码:
Java代码
读取一张图片的RGB值
Java代码
package com.main; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.Arrays; import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.imgcodecs.Imgcodecs; public class ImageColorArea { public static void main(String[] args) { // TODO Auto-generated method stub System.loadLibrary(Core.NATIVE_LIBRARY_NAME); // System.out.println("Welcome to OpenCV " + Core.VERSION); // 读入图片D:\\test\\imgs\\scsc.png Mat image = Imgcodecs.imread("D:\\test\\imgs\\zqzm.png"); if (image.empty()) return; Mat newimage = colorArea(image); } public static Mat colorArea(Mat image) { int width = image.cols(); int height = image.rows(); int dims = image.channels(); byte[] data = new byte[width * height * dims]; image.get(0, 0, data); int index = 0; int r = 0, g = 0, b = 0; long allpoint = width*height; long whitepoint = 0; long blackpoint = 0; long colorpoint = 0; long redpoint = 0; for (int row = 0; row < height; row++) { for (int col = 0; col < width * dims; col += dims) { index = row * width * dims + col; b = data[index] & 0xff; g = data[index + 1] & 0xff; r = data[index + 2] & 0xff; // float[] cmyklist = ColorUtils.getCMYK(r, g, b); // if(cmyklist[3]>0&&cmyklist[0]==0&&cmyklist[1]==0&&cmyklist[2]==0){ // System.out.println("什么颜色:"+r+","+g+","+b+"cmyk:"+cmyklist[0]+","+cmyklist[1]+","+cmyklist[2]+","+cmyklist[3]); // blackpoint++; // } if(r==255 && g==255 &&b==255){ whitepoint++; }else{ float[] hsb = rgb2hsb(r,g,b); if(hsb[1]==0 || hsb[2]==0 ||(hsb[1]<0.15 && hsb[2]<0.15)){ blackpoint++; }else{ colorpoint++; } // long colorsum = (long) (0.2126 * r + 0.7152 * g + 0.0722 * b); // if(colorsum<40){ // blackpoint++; // }else{ // colorpoint++; // } } // if(r==255 && g==255 &&b==255){ // whitepoint++; // }else // if(r==0 && g==0 &&b==0){ // blackpoint++; // }else // if(r==255 && g==0 &&b==0){ // redpoint++; // }else{ //// float[] cmyklist = ColorUtils.getCMYK(r, g, b); //// System.out.println("什么颜色:"+r+","+g+","+b+"cmyk:"+cmyklist[0]+","+cmyklist[1]+","+cmyklist[2]+","+cmyklist[3]); // } } } BigDecimal allpoint_bd = new BigDecimal(allpoint); BigDecimal whitepoint_bd = new BigDecimal(whitepoint); BigDecimal blackpoint_bd = new BigDecimal(blackpoint); BigDecimal colorpoint_bd = new BigDecimal(colorpoint); BigDecimal redpoint_bd = new BigDecimal(redpoint); System.out.println("总点数:"+allpoint_bd+"白色点数:"+whitepoint_bd+"黑色点数:"+blackpoint_bd+"彩色点数:"+colorpoint_bd); System.out.println("白色区域比例:"+whitepoint_bd.divide(allpoint_bd,10,RoundingMode.HALF_UP)+"黑色区域比例:"+blackpoint_bd.divide(allpoint_bd,10,RoundingMode.DOWN)+"彩色区域比例:"+colorpoint_bd.divide(allpoint_bd,10,RoundingMode.DOWN)); image.put(0, 0, data); return image; } public static float[] rgb2hsb(int rgbR, int rgbG, int rgbB) { assert 0 <= rgbR && rgbR <= 255; assert 0 <= rgbG && rgbG <= 255; assert 0 <= rgbB && rgbB <= 255; int[] rgb = new int[] { rgbR, rgbG, rgbB }; float[] hsb = new float[5]; Arrays.sort(rgb); int max = rgb[2]; int min = rgb[0]; float hsbB = max / 255.0f; float hsbS = max == 0 ? 0 : (max - min) / (float) max; float hsbH = 0; if (max == rgbR && rgbG >= rgbB) { hsbH = (rgbG - rgbB) * 60f / (max - min) + 0; } else if (max == rgbR && rgbG < rgbB) { hsbH = (rgbG - rgbB) * 60f / (max - min) + 360; } else if (max == rgbG) { hsbH = (rgbB - rgbR) * 60f / (max - min) + 120; } else if (max == rgbB) { hsbH = (rgbR - rgbG) * 60f / (max - min) + 240; } hsb[0] = hsbH; hsb[1] = hsbS; hsb[2] = hsbB; return hsb; } }