美文网首页
Android 获取图片的亮度

Android 获取图片的亮度

作者: ChineseBoy | 来源:发表于2018-06-13 09:46 被阅读125次
    方案一:

    总体思路:Bitmap可以返回某个点的RGB值bitmap.getPixel),对当前区域取一些特定点获取其RGB值,bitmap.getPixel返回的是ARGB值,通过移位操作获取到R、G、B的值,使用亮度=0.229×R + 0.587G + 0.114B进行亮度值计算,将所有点的亮度值相加后取一个平均值,如果这个值比128大,则这个图片较亮,如果这个值比128小,则这个图比较暗。
    亮度公式怎么来的呢?看两张图吧,其实就是YUV里面的Y分量

    image.png
    image.png
    public int getBright(Bitmap bm) {
            if(bm == null) return -1;
            int width = bm.getWidth();
            int height = bm.getHeight();
            int r, g, b;
            int count = 0;
            int bright = 0;
            for (int i = 0; i < width; i++) {
                for (int j = 0; j < height; j++) {
                    count++;
                    int localTemp = bm.getPixel(i, j);
                    r = (localTemp | 0xff00ffff) >> 16 & 0x00ff;
                    g = (localTemp | 0xffff00ff) >> 8 & 0x0000ff;
                    b = (localTemp | 0xffffff00) & 0x0000ff;
                    bright = (int) (bright + 0.299 * r + 0.587 * g + 0.114 * b);
                }
            }
            return bright / count;
        }
    
    方案二:

    通过牛逼的OpenCV库处理:

    double getAvg(Mat img)  
    {
     Mat gray;
        cvtColor(img, gray, CV_RGB2GRAY);  
     Scalar scalar = mean(gray);  
        return scalar.val[0];
    }  
    
    void setAvg(Mat scr,Mat dst, double avg)  
    {  
        double fpreAvg = getAvg(scr);  
        scr.convertTo(dst,scr.type(),avg/fpreAvg);  
    }  
    

    接下来再科普下Android用的多的一种数据格式:NV21(Camera预览的回调数据)
    NV21是一种YUV格式的(YUV420SP),YUV主要用于优化彩色视频信号的传输,使其向后相容老式黑白电视。与RGB视频信号传输相比,它最大的优点在于只需占用极少的频宽(RGB要求三个独立的视频信号同时传输)。其中“Y”表示明亮度(Luminance或Luma),也就是灰阶值;而“U”和“V” 表示的则是色度(Chrominance或Chroma),作用是描述影像色彩及饱和度,用于指定像素的颜色。至于它跟RGB之间的关系,上文中已经提到。

    NV12格式: YYYYYYYY UVUV,
    I420格式: YYYYYYYY UU VV
    NV21存储: YYYYYYYY VUVUVUVU 前面都是Y(width * height),后面是VU交错。

            int width = camera.getParameters().getPreviewSize().width;
            int height = camera.getParameters().getPreviewSize().height;
            //像素点的总亮度  
            long pixelLightCount = 0L;
            //像素点的总数  
            long pixeCount = width * height;
            //采集步长,因为没有必要每个像素点都采集,可以跨一段采集一个,减少计算负担,必须大于等于1。  
            int step = 10;
            //data.length - allCount * 1.5f的目的是判断图像格式是不是YUV420格式,只有是这种格式才相等  
            //因为int整形与float浮点直接比较会出问题,所以这么比  
            if (Math.abs(data.length - pixeCount * 1.5f) < 0.00001f) {
                for (int i = 0; i < pixeCount; i += step) {
                    //如果直接加是不行的,因为data[i]记录的是色值并不是数值,byte的范围是+127到—128,  
                    // 而亮度FFFFFF是11111111是-127,所以这里需要先转为无符号unsigned long参考Byte.toUnsignedLong()  
                    pixelLightCount += ((long) data[i]) & 0xffL;
                }
                //平均亮度  
                long cameraLight = pixelLightCount / (pixeCount / step)
            }
    

    相关文章

      网友评论

          本文标题:Android 获取图片的亮度

          本文链接:https://www.haomeiwen.com/subject/tcodeftx.html