RGB图像转为灰度图

2024-05-11 11:18
文章标签 图像 灰度 转为 rgb

本文主要是介绍RGB图像转为灰度图,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最后结论:

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

代码

[cpp]  view plain copy
  1. #include <cv.h>  
  2. #include <highgui.h>  
  3.    
  4. using namespace cv;  
  5. int main(){  
  6.          Mat src= imread("C:\\Users\\Poplar\\Pictures\\ff.jpg");  
  7.          Mat grey(src.rows, src.cols, CV_8UC1, Scalar(0));  
  8.          for (inty = 0; y < src.rows; y++)  
  9.          {  
  10.                    uchar*cp = src.ptr<uchar>(y);  
  11.                    uchar*gp = grey.ptr<uchar>(y);  
  12.                    for(int x = 0; x < src.cols; x++){  
  13.                             *gp= (15*cp[0] + 75*cp[1] + 38*cp[2]) >> 7;  
  14.                             cp+= 3;  
  15.                             gp++;  
  16.                    }  
  17.          }  
  18.          imshow("src",src);  
  19.          imshow("grey",grey);  
  20.          waitKey(0);  
  21.          return0;  
  22. }  

效果如图


 

下面具体解释


RGB彩色图像中,一种彩色由R(红色),G(绿色),B(蓝色)三原色按比例混合而成。

图像的基本单元是一个像素,就像一个巨幅电子广告屏上远处看是衣服图像,走近你会看到一个一个的方格,这个方格的颜色是一种,从远处看,觉察不到这个方格的存在。

一个像素需要3块表示,分别代表R,G,B,如果8为表示一个颜色,就由0-255区分不同亮度的某种原色。

一张9像素的8位RGB图像,在计算机内存中的分布大概示意如下:


实际中数都是二进制形式的,并且未必按照R,G,B顺序,比如OpenCV是按照B,G,R顺序将三个色值保存在3个连续的字节里

 

灰度图像是用不同饱和度的黑色来表示每个图像点,比如用8位 0-255数字表示“灰色”程度,每个像素点只需要一个灰度值,8位即可,这样一个3X3的灰度图,只需要9个byte就能保存

RGB值和灰度的转换,实际上是人眼对于彩色的感觉到亮度感觉的转换,这是一个心理学问题,有一个公式:

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

根据这个公式,依次读取每个像素点的RGB值,进行计算灰度值(转换为整型数),将灰度值赋值给新图像的相应位置,所有像素点遍历一遍后完成转换。

一张500X500的图像转换为同样大小的灰度图需要进行25万次上述公式的计算。进行优化是很有必要的,这个简单的算法是O(n)复杂度的,应该是不能优化了(或者用并行进行优化,本文不涉及),但是Grey = 0.299*R + 0.587*G + 0.114*B有更加高效的等价形式。

ALU中,位操作快于整数加法,整数加法快于整数乘法(快多少取决于有没有乘法电路,乘法电路的结构),整数运算又比浮点数运算快得多。

所以可以通过将浮点数运算转化为整数运算,整数运算转换为位操作进行优化

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

可以转化为

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

整数运算会截断小数部分,加上500是为了四舍五入(找两个例子便可理解),减少精度损失。

这里的除法即使是整数除法计算也是很耗时,转换为移位操作可以优化,那么怎么转换为位操作?左右移位对应于乘除2的幂,为了把除法转为右移操作,做如下处理:

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

Grey = 299*R+ 587*G + 114*B÷ 1000

Grey = 1024*299*R+ 1024*587*G + 1024*114*B÷1024*1000

Grey = 306176*R+601088*G + 116736*B÷1024*1000

Grey = 306.176*R+601.088*G + 116.736*B÷1024

Grey = 306*R+601*G + 116*B÷1024//截断误差

Grey = 306*R+601*G + 116*B >> 10;

误差最大是多少?

(0.176*255+0.088*255 + 0.736*255) ÷1024 = 255÷1024=0.249,可能会导致1个灰度值的波动

有一种计算方法可以降低误差

的系数  =1024*0.229= 306.176306

G的系数   =1024*0.587 + 0.176 =601.264 ≈601

B的系数   =1024*0.114 + 0.264 = 117

保留了小数部分的作用,可以得到一个误差较小的公式:

Grey = 306*R +601*G + 117*B >> 10;

这样得来的是10位精度的。

同样的方法可以获得其他精度的,比如

Grey = (R*1 + G*2 + B*1) >> 2  ( Grey = (R + G<<1 + B) >> 2 )

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

Grey= (R*76 + G*150 + B*30) >> 8

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

可以看出来,7位和8位精度是一样的,比较好用的是7位精度的公式。

 

实际编写代码时,还要考虑图像文件的读取问题,不同格式的RGB位图,结构不同,读取时也不同,本文不涉及图像读取问题,这里以openCV提供的图像读取方式,展示转灰度图的实际代码,见文章开头。


 2-10位精度的公式

Grey = (R*1 + G*2 + B*1) >> 2

Grey= (R*2 + G*5 + B*1) >> 3

Grey= (R*4 + G*10 + B*2) >> 4

Grey = (R*9 + G*19 + B*4) >> 5

Grey = (R*19 + G*37 + B*8) >> 6

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

Grey= (R*76 + G*150 + B*30) >> 8

Grey = (R*153 + G*300 + B*59) >> 9

Grey = (R*306 + G*601 + B*117) >> 10

Grey = (R*612 + G*1202 + B*234) >> 11

Grey = (R*1224 + G*2405 + B*467) >> 12

Grey= (R*2449 + G*4809 + B*934) >> 13

Grey= (R*4898 + G*9618 + B*1868) >> 14

Grey = (R*9797 + G*19235 + B*3736) >> 15

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

Grey = (R*39190 + G*76939 + B*14943) >> 17

Grey = (R*78381 + G*153878 + B*29885) >> 18

Grey =(R*156762 + G*307757 + B*59769) >> 19

Grey= (R*313524 + G*615514 + B*119538) >> 20

这篇关于RGB图像转为灰度图的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/979381

相关文章

音视频开发基础知识(1)——图像基本概念

像素 **像素是图像的基本单元,一个个像素就组成了图像。你可以认为像素就是图像中的一个点。**在下面这张图中,你可以看到一个个方块,这些方块就是像素。 分辨率 图像(或视频)的分辨率是指图像的大小或尺寸。我们一般用像素个数来表示图像的尺寸。比如说一张1920x1080的图像,前者1920指的是该图像的宽度方向上有1920个像素点,而后者1080指的是图像的高 度方向上有1080个像素点。

【Python机器学习】NMF——将NMF应用于人脸图像

将NMF应用于之前用过的Wild数据集中的Labeled Faces。NMF的主要参数是我们想要提取的分量个数。通常来说,这个数字要小于输入特征的个数(否则的话,将每个像素作为单独的分量就可以对数据进行解释)。 首先,观察分类个数如何影响NMF重建数据的好坏: import mglearn.plotsimport numpy as npimport matplotlib.pyplot as

AIGC-Animate Anyone阿里的图像到视频 角色合成的框架-论文解读

Animate Anyone: Consistent and Controllable Image-to-Video Synthesis for Character Animation 论文:https://arxiv.org/pdf/2311.17117 网页:https://humanaigc.github.io/animate-anyone/ MOTIVATION 角色动画的

什么是图像频率?

经常听到图像低频成份、高频成份等等,没有细想过,今天突然一想发现真的不明白是怎么回事,在知乎上发现某答案,引用如下: 首先说说图像频率的物理意义。图像可以看做是一个定义为二维平面上的信号,该信号的幅值对应于像素的灰度(对于彩色图像则是RGB三个分量),如果我们仅仅考虑图像上某一行像素,则可以将之视为一个定义在一维空间上信号,这个信号在形式上与传统的信号处理领域的时变信号是相似的。不过是一个是

【LocalAI】(13):LocalAI最新版本支持Stable diffusion 3,20亿参数图像更加细腻了,可以继续研究下

最新版本v2.17.1 https://github.com/mudler/LocalAI/releases Stable diffusion 3 You can use Stable diffusion 3 by installing the model in the gallery (stable-diffusion-3-medium) or by placing this YAML fi

matplotlib之常见图像种类

Matplotlib 是一个用于绘制图表和数据可视化的 Python 库。它支持多种不同类型的图形,以满足各种数据可视化需求。以下是一些 Matplotlib 支持的主要图形种类: 折线图(Line Plot): 用于显示数据随时间或其他连续变量的变化趋势。特点:能够显示数据的变化趋势,反映事物的变化情况。(变化)plt.plot() 函数用于创建折线图。  示例:

细粒度图像分类论文阅读笔记

细粒度图像分类论文阅读笔记 摘要Abstract1. 用于细粒度图像分类的聚合注意力模块1.1 文献摘要1.2 研究背景1.3 本文创新点1.4 计算机视觉中的注意力机制1.5 模型方法1.5.1 聚合注意力模块1.5.2 通道注意力模块通道注意力代码实现 1.5.3 空间注意力模块空间注意力代码实现 1.5.4 CBAM注意力机制CBAM注意力代码实现 1.5.5 本文模型整体架构 1.6

动手学深度学习(Pytorch版)代码实践 -计算机视觉-36图像增广

6 图片增广 import matplotlib.pyplot as pltimport numpy as npimport torch import torchvisionfrom d2l import torch as d2lfrom torch import nn from PIL import Imageimport liliPytorch as lpfrom tor

LVGL8.3动画图像(太空人)

LVGL8.3 动画图像 1. 动画图像本质 我们知道电影属于视频,而电影的本质是将一系列动作的静态图像进行快速切换而呈现出动画的形式,也就是说动画本质是一系列照片。所以 lvgl 依照这样的思想而定义了动画图像,所以在 lvgl 中动画图像类似于普通的静态图像对象。 唯一的区别是,动画图像设置了一个由多个源图像组成的数组,而不仅仅指定一个源图像。 2. 设置动画图像图片来源 不过在此之前

图像反转入门

文章目录 1.实验目的2.需求3.代码4.运行结果图 1.实验目的 熟练掌握图像像素操作API 2.需求 自己构造一个纯黑图像,通过多种方法进行反转,最终生成一个纯白图像 3.代码 """@Time : 2024/6/23 下午3:46@Author : chensong@File : 自己创建一个图像并反转.py@Desc : """im