Switch Algorithm gray (transfer) from the RGB color

First, the basis 
  for the color to gray scale, there is a very well-known psychology formula:

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

Second, the integer arithmetic

  The practice, want to avoid the low-speed floating-point, integer arithmetic is required.
  Notes that all three precision coefficient is not, we can scale them 1000 times the integer arithmetic algorithms to achieve:

                          Gray = (R*299 + G*587 + B*114 + 500) / 1000

  RGB is an 8-bit precision is generally now scaled 1000, so the above calculation are 32-bit integer arithmetic. Note that behind the division is integer division, so the need to add 500 to achieve rounding.
  This is because the algorithm needs 32-bit computing, so another variant of this formula is very popular:

                          Gray = (R*30 + G*59 + B*11 + 50) / 100

  However, although the formula is a 32-bit integer arithmetic, but according to the characteristics of 80x86 Integer multiply and divide instructions system, can be a 16-bit integer arithmetic multiplication and division instructions. And now the popularity of the early 32 (AMD64 are out), it is recommended to use a formula.

Third, the integer arithmetic shift

  The above integer arithmetic has been very fast, but one thing is still restricted speed, is the last of that division. Shifting much faster than division, the coefficients can be scaled to an integer power of two.
  Using the customary 16-bit precision, 2 to the power 16 is 65536, so this factor is calculated:

                          0.299 * 65536 = 19595.264 ≈ 19595
                          0.587 * 65536 + (0.264) = 38469.632 + 0.264 = 38469.896 ≈ 38469
                          0.114 * 65536 + (0.896) =   7471.104 + 0.896 = 7472

  Many people saw it, rounding the way I used is not rounded. Rounding errors have a greater, should the computing error calculation result with the previous in, the end rounding process is to:

  Written expression is:

                          Gray = (R*19595 + G*38469 + B*7472) >> 16

  2-20 precision coefficients:

                          Gray = (R*1 + G*2 + B*1) >> 2
                          Gray = (R*2 + G*5 + B*1) >> 3
                          Gray = (R*4 + G*10 + B*2) >> 4
                          Gray = (R*9 + G*19 + B*4) >> 5
                          Gray = (R*19 + G*37 + B*8) >> 6
                          Gray = (R*38 + G*75 + B*15) >> 7
                          Gray = (R*76 + G*150 + B*30) >> 8
                          Gray = (R*153 + G*300 + B*59) >> 9
                          Gray = (R*306 + G*601 + B*117) >> 10
                          Gray = (R*612 + G*1202 + B*234) >> 11
                          Gray = (R*1224 + G*2405 + B*467) >> 12
                          Gray = (R*2449 + G*4809 + B*934) >> 13
                          Gray = (R*4898 + G*9618 + B*1868) >> 14
                          Gray = (R*9797 + G*19235 + B*3736) >> 15
                          Gray = (R*19595 + G*38469 + B*7472) >> 16
                          Gray = (R*39190 + G*76939 + B*14943) >> 17
                          Gray = (R*78381 + G*153878 + B*29885) >> 18
                          Gray = (R*156762 + G*307757 + B*59769) >> 19
                          Gray = (R*313524 + G*615514 + B*119538) >> 20

  Carefully observed form above, these are in fact the same accuracy: 3 and 4, 7 and 8, 10 and 11, 13 and 14, 19 and 20
  it is best calculated using 16-bit arithmetic precision 7, than previous scaling factor 100 times higher that the accuracy and speed:

                          Gray = (R*38 + G*75 + B*15) >> 7

  其实最有意思的还是那个2位精度的,完全可以移位优化:

                          Gray = (R + (WORD)G<<1 + B) >> 2

========================

在计算机中使用最多的 RGB 彩色空间,分别对应红、绿、蓝三种颜色;通过调配三个分量的比例来组成各种颜色。一般可以使用 1 、 2 、 4 、 8 、 16 、 24 、 32 位来存储这三颜色,不过现在一个分量最大是用 8 位来表示,最大值是 255 ,对于 32 位的颜色,高 8 位是用来表示通明度的。彩色图一般指 16 位以上的图。灰度图有一个特殊之处就是组成颜色的三个分量相等;而一般灰度图是 8 位以下。

在彩色电视机系统中,通常使用一种叫 YUV 的色彩空间,其中 Y 表示亮度信号;也就是这个 YUV 空间解决了彩色电视机和黑白电视机的兼容问题。

对于人眼来说,亮度信号是最敏感的,如果将彩色图像转换为灰度图像,仅仅需要转换保存亮度信号就可以。

从 RGB 到 YUV 空间的 Y 转换公式为:

Y = 0.299R+0.587G+0.114B

在 WINDOWS 中,表示 16 位以上的图和以下的图有点不同; 16 位以下的图使用一个调色板来表示选择具体的颜色,调色板的每个单元是 4 个字节,其中一个透明度;而具体的像素值存储的是索引,分别是 1 、 2 、 4 、 8 位。 16 位以上的图直接使用像素表示颜色。

=================================================
那么如何将彩色图转换为灰度图呢?

灰度图中有调色板,首先需要确定调色板的具体颜色取值。我们前面提到了,灰度图的三个分量相等。

当转换为 8 位的时候,调色板中有 256 个颜色,每个正好从 0 到 255 个,三个分量都相等。

当转换为 4 位的时候,调色板中 16 个颜色,等间隔平分 255 个颜色值,三个分量都相等。

当转换为 2 位的时候,调色板中 4 个颜色,等间隔平分 255 个颜色,三个分量相等。

当转换为 1 位的时候,调色板中两个颜色,是 0 和 255 ,表示黑和白。

将彩色转换为灰度时候,按照公式计算出对应的值,该值实际上是亮度的级别;亮度从 0 到 255 ;由于不同的位有不同的亮度级别,所以 Y 的具体取值如下:

       Y = Y/ (1<<(8- 转换的位数 ));


最后一点需要注意,得到 Y 值存放方式是不同的;分别用对应的位数来存储对应的 Y 值。

//----------------------------------------------------------
//  RGB565 转 8位灰度图
//----------------------------------------------------------
   TUint8 gm_red,gm_green,gm_blue;
   TInt16 *des_ptr;
   TInt16 *pt;
   pt = (TInt16 *)p8;  //RGB565流

   for(TInt j=0;j<h;j++)
   {
         for(TInt i = w;i>0;i--)
         {
           gm_red       = ((*(TInt16 *)pt) & 0xF800) >> 8;
           gm_green     = ((*(TInt16 *)pt) & 0x07E0) >> 3;   
           gm_blue      = ((*(TInt16 *)pt) & 0x001F) <<  3;   
           p[0] = ( TUint8 )((gm_red*77 + gm_green*150 + gm_blue*29+128) / 256);
           p++;
           pt++;
        }
   }
   p = qt;   //灰度图指针

 

一道面试题

写一个函数,将一个32位RGB像素的色值转为灰度,RGB转灰度的公式:Grey=.03*red+0.59*green+0.11*blue;RGB像素格式(左边最高位,右边最低位):00000000RRRRRRRRGGGGGGGGBBBBBBBB.

unsigned int ToGrey(unsigned int rgb)
{ 请填 }
 
答案

unsigned int ToGrey(unsigned int rgb)
{
 unsigned int blue = (rgb & 0x000000FF)>>0;
 unsigned int green = (rgb & 0x0000FF00) >> 8;
 unsigned int red = (rgb & 0x00FF0000) >> 16;
 printf("\nred=%d,green=%d,blue=%d\n",red,green,blue);
 return ( red*38 +  green * 75 +  blue * 15 )>>7;
}

Guess you like

Origin www.cnblogs.com/djerly/p/12072761.html