前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【简单的CV】1.6 灰度图

【简单的CV】1.6 灰度图

作者头像
EdenChen
发布2019-11-06 13:34:00
8040
发布2019-11-06 13:34:00
举报
文章被收录于专栏:ROBOTEDUROBOTEDU

1.6 灰度图

01

灰度的范围

一般在计算机表示灰度的范围在0-255,即一个字节(1byte)

灰度值由255到0的变化

灰度为255时,表示亮度白色。

灰度为0时,表示黑色。

02

RBG转灰度

RBG和灰度是展示图片的两种常用方式

RGB彩色图

GRAY灰度图

RGB是由三个字节组成 R(1byte)\G(1byte)\B(1byte)

GRAY是由一个字节组成GRAY(1byte)

由RGB转GRAY的计算公式:

Gray = R*0.299 + G*0.587 + B*0.114

03

灰度计算公式的由来

三原色光模式(英语:RGB color model),又称RGB颜色模型或红绿蓝颜色模型,是一种加色模型,将红(Red)、绿(Green)、蓝(Blue)三原色的色光以不同的比例相加,以产生多种多样的色光。

实际上一个等量白光并不是由1:1:1的RGB光合成的,根据 国际照明委员会CIE的固定,这个比例更接近3:6:1,也就是我们上面公式的由来。

04

代码实现(来源网络)

代码语言:javascript
复制
        public static Bitmap RgbToGrayScale(Bitmap original)
        {
            if (original != null)
            {
                // 将源图像内存区域锁定
                Rectangle rect = new Rectangle(0, 0, original.Width, original.Height);
                BitmapData bmpData = original.LockBits(rect, ImageLockMode.ReadOnly,
                        PixelFormat.Format24bppRgb);

                // 获取图像参数
                int width = bmpData.Width;
                int height = bmpData.Height;
                int stride = bmpData.Stride;  // 扫描线的宽度,比实际图片要大
                int offset = stride - width * 3;  // 显示宽度与扫描线宽度的间隙
                IntPtr ptr = bmpData.Scan0;   // 获取bmpData的内存起始位置的指针
                int scanBytesLength = stride * height;  // 用stride宽度,表示这是内存区域的大小

                // 分别设置两个位置指针,指向源数组和目标数组
                int posScan = 0, posDst = 0;
                byte[] rgbValues = new byte[scanBytesLength];  // 为目标数组分配内存
                Marshal.Copy(ptr, rgbValues, 0, scanBytesLength);  // 将图像数据拷贝到rgbValues中
                // 分配灰度数组
                byte[] grayValues = new byte[width * height]; // 不含未用空间。
                // 计算灰度数组

                byte blue, green, red, YUI;



                for (int i = 0; i < height; i++)
                {
                    for (int j = 0; j < width; j++)
                    {

                        blue = rgbValues[posScan];
                        green = rgbValues[posScan + 1];
                        red = rgbValues[posScan + 2];
                        YUI = (byte)(0.229 * red + 0.587 * green + 0.144 * blue);
                        //grayValues[posDst] = (byte)((blue + green + red) / 3);
                        grayValues[posDst] = YUI;
                        posScan += 3;
                        posDst++;

                    }
                    // 跳过图像数据每行未用空间的字节,length = stride - width * bytePerPixel
                    posScan += offset;
                }

                // 内存解锁
                Marshal.Copy(rgbValues, 0, ptr, scanBytesLength);
                original.UnlockBits(bmpData);  // 解锁内存区域

                // 构建8位灰度位图
                Bitmap retBitmap = BuiltGrayBitmap(grayValues, width, height);
                return retBitmap;
            }
            else
            {
                return null;
            }
        }

PS:可以在代码中看到图像在计算机内存中实际保存的长度并不是我们一般认为的图像宽*图像长,要略大于这个值,是因为由于显示器的工作原理和芯片工作原理。

小结

1. RBG与灰度的换算

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-10-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 ROBOTEDU 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档