Qt生成灰度图(转载)

 

项目中用到大量基础图像处理知识,其中灰度图的生成是很重要的一环。

先补充一些基础知识:

----------------------------------------------------------------------------------------------------------------------------

一:灰度图

灰度图就是黑白图,整幅图片只有不同程度的黑白两色。灰度也可认为是亮度,简单的说就是色彩的深浅程度 !

1:如果我们用八位来存储灰度图。则共有256种组合。那相当于:我们把从:纯黑 到 纯白 之间区分成了256种灰度。从而对应256种灰度值! 而如果用一个数字来表示的话:则0-255每个数字对应一种灰度!

2:灰度就是没有色彩,它的RGB色彩分量全部相等。 比如 rgb(20,20,20)。  既然这样:我们完全可以用rgb中的某一个分量的值 来代替这个实际的灰度值! 比如上边这个例子:我们完全可以用20来代替这个灰度! 这是一个一一映射关系!

--------------------------------------------------------------------------------------------------------------

二:色彩表

色彩表就是表示当前所有颜色的一张表。 而我们知道任何一种颜色都可以用rgb值来表示。如此我们完全可以设计一张表,里边每个元素都是一个rgb值,从而将所有的颜色都用rgb值表示出来!

--------------------------------------------------------------------------------------------------------------

三:颜色索引模式

在一张图片的每个像素中可以直接存放其rgb值!当然:我们也可以存放一个索引值,通过这个索引值去其对应的颜色表中去查找对应的颜色的rgb值来进行绘制。这种像素中存放索引值而不是实际rgb值的模式在Qt中有:QImage::Format_Indexed8,亦即:用8位来存放一个索引值。

--------------------------------------------------------------------------------------------------------------

四:灰度索引图:

对于8阶灰度图而言:由于其一共有256种灰度,所以我们可以设计一个颜色表:里边存放256个rgb值!每个rgb值的三个分量都是相等的。这样:这张表就可以用来表示所有的灰度!

灰度索引图中存放的是各个整数索引值,这些图片数据本身是无法显示的,因为其没有实际的rgb值。当实际构图时:是用该索引值在上边创建的颜色表中进行查找,找到对应的灰度rgb值,而后才能进行实际的绘图等操作。

有了上两步基础,问题的关键就在于:这个灰度索引值是如何获得的?

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

有了上述基础知识,下一步可以来看一下如何从彩色图转为灰度图了。

一:整体流程:

1:依据某一个算法:将rgb32彩色图像的每个像素中的rgb值转为一个整数灰度值。

2:用这个计算获得的值来替代原图中的每个rgb。

这样就可以将一张彩色图转为灰度图了。

但是这个过程中存在以下问题:

1:如何从彩色图原本的rgb值计算出灰度值?

2:因为每个像素的rgb都被灰度值取代,其都是一样的,这完全可以用一个灰度值取代,而不是用三个。用三个有点浪费空间。

--------------------------------------------------------------------------------------------------------------

对于问题1:灰度值的计算方法有以下几种:

1.浮点算法:Gray=R*0.3+G*0.59+B*0.11

2.整数方法:Gray=(R*30+G*59++B*11)/100

3.移位方法:Gray =(R*28+G*151+B*77)>>8;

4.平均值法:Gray=(R+G+B)/3;

5.仅取绿色:Gray=G;

而各种方法之间的区别在于:精确度! 亦即:得到的灰度图的效果不同!浮点数运算得到的效果最好,而仅仅取绿色得到的效果最差。至于取哪一种,则取决于实际需要!

--------------------------------------------------------------------------------------------------------------

对于问题2:我们可以每个像素中只存唯一一个灰度值,而后设计一个色彩表,通过这个灰度值去对应查找其真实的颜色。那这样就可以                 用到上边所的灰度索引图了。亦即:此时图中存放的不是真实的rgb值,而是一个灰度所以值;而后设计一张其对应的颜色      表。这样二者便可以完全代表整张灰度图了。而且二者加起来的空间也比非索引模式要小的多,而且查找速度会更快。

所以:最好是将灰度图用索引模式进行存储,这在Qt中是指定QImage格式为Index8实现。亦即:有8位索引,可以指定256种灰度值。

那么:我们从彩色图转为灰度索引图的整体流程为:

(以rgb32转为index8为例)

1:首先我们要创建一张空的index8图像。

2:依据某一个算法:将rgb32彩色图像的每个像素中的rgb值转为一个整数值,存储在index8灰度图的每个像素中。

3:构建颜色表。

4:依据存储在index图像中的整数值,去灰度表中查找对应的灰度来进行实际的构图!

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

OK,现在方法有了,下边我们可以来实现了。

1:最简单的方法:

  1. for(int i =0;i<width;i++)
  2. {
  3. for(int j=0;j<height;j++)
  4. {
  5. QRgb pixel=iImage->pixel(i,j);
  6. int r=qRed(pixel);
  7. int g=qGreen(pixel);
  8. int b=qBlue(pixel);
  9. iGray->setPixel(i,j,qGray(r,g,b));
  10. }
  11. }

亦即:先用 pixel()获取每个像素点的QRgb值。而后分别用qRed(),qGreen(),qBlue()来获取rgb分量的值。而后进行上述灰度值的计算。之后再重新赋予给该像素点。

但是实际运行一下你会发现:对于600*800大小的图像:这个函数要运行30s+,这显然是不能容忍的。

--------------------------------------------------------------------------------------------------------------

上边这个方法很简单直接,但是效率上太失败,所以我们需要来优化效率,主要从以下两个方面实现:

1:要用pixel() ,qRed(),qGreen(),qBlue()来遍历获取每个像素的rgb分量。其函数实现时:肯定是一个查找过程,尤其是依据像素位置来获得rgb值的函数pixel()。每次都一个完整的查找,这显然效率较为低下,尤其是不断的大量查找! 由于数据都是连续存放在内存中的,我们完全可以通过移动指针的方式来获取rgb分量。每次只移动一个指针位置就可以了。这种移动指针的方式显然比全查找要快!

这块代码实现上:其是直接来取用green绿色分量值 来作为gray索引值!

其比上一个方法的优化之处在于:它没有使用系统函数,而是使用移动指针的方式来取得rgb分量。它把所有灰度索引值存放到index8灰度图中。最后创建了8阶灰度图的颜色表并赋予给该灰度图。这样:系统会自动(不需要我们手动去查找)依据存储在图像中的灰度索引值去 颜色表中查找对应灰度的rgb值来进行绘制!

--------------------------------------------------------------------------------------------------------------

2:计算灰度索引值的函数qGray(),按照Qt文档上所说:其计算过程为:(r*11+g*16+5*5)/32 .乘除法是一个很大的计算量,最好用移位操作来进行取代!

(这就牵扯一个问题:原本我以为:乘除法在寄存器中就算转为移位操作的,所以乘除法和移位操作在效率上应该没什么区别。但是实际不是这样的,因为:如果你使用乘除法,则其在运行时:转化成的乘法指令本身会消耗很多cpu周期,所以这无形中已经降低了效率!所以来说:在做高性能计算时:最好用移位操作来取代乘除法)

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

知道如何优化后,我们看下在Qt中如何实现,这个在网上我找到了一个方法,摘录如下

  1. QImage colourImg("colourImage.bmp");
  2. QSize colourImgSize = colourImg.size();
  3. int width = colourImgSize.rwidth();
  4. int height = colourImgSize.rheight();
  5. unsigned char *colourImgDataPtr = colourImg.bits();
  6. QImage grayImg(colourImgSize, QImage::Format_Indexed8);
  7. unsigned char *grayImgDataPtr = grayImg.bits();
  8. //下边这个for循环是直接取用green绿色分量值 来作为gray索引值
  9. for(int i = 0; i < height; i++)
  10. {
  11. for(int j = 0; j < width; j++)
  12. {
  13. *grayImgDataPtr = *(colourImgDataPtr + 1);      colourImgDataPtr += 4;          grayImgDataPtr++;
  14. }
  15. }
  16. QVector<QRgb> grayColourTable;
  17. unsigned int rgb = 0;
  18. for(int i = 0; i < 256; i++)
  19. {
  20. grayColourTable.append(rgb);
  21. rgb += 0x00010101;
  22. }
  23. grayImg.setColourTable(rayColourTable);
  24. graImg.save("grayImage.bmp", "bmp");

这块代码实现上:其是直接来取用green绿色分量值 来作为gray索引值!

其比上一个方法的优化之处在于:它没有使用系统函数,而是使用移动指针的方式来取得rgb分量。它把所有灰度索引值存放到index8灰度图中。最后创建了8阶灰度图的颜色表并赋予给该灰度图。这样:系统会自动(不需要我们手动去查找)依据存储在图像中的灰度索引值去 颜色表中查找对应灰度的rgb值来进行绘制!

--------------------------------------------------------------------------------------------------------------

在上述方法的基础上,我们在使用时:需要注意的是效果能不能达到需求,从而可能要用精确度更高的灰度索引值计算方法。那这就牵扯大量运算,此时记得要用移位操作 来取代 乘除法运算

  1. QBYTE RGBtoGRAY(QBYTE r, QBYTE g, QBYTE b)
  2. {
  3. return (QBYTE)((((QUINT32)((r << 5) + (r << 2) + (r << 1)))+ (QUINT32)((g << 6) + (g << 3) + (g << 1) + g)
  4. + (QUINT32)((b << 4) - b)) >> 7);
  5. }

这个是网上找到的最优化的实时计算灰度索引值算法。没有用到乘除法运算,转而使用大量移位操作。

--------------------------------------------------------------------------------------------------------------

暂且总结到这里,上述代码都实际测试过,没有问题。

追求永不止步

Qt生成灰度图(转载)的更多相关文章

  1. opencv生成灰度图并保存

    #include <opencv2/opencv.hpp>#include <iostream> using namespace cv;using namespace std; ...

  2. 图像分割利用KMeans生成灰度图

    import numpy as np import PIL.Image as image from sklearn.cluster import KMeans def loadData(filePat ...

  3. 【Qt开发】QImage设置为8-bit灰度图

    项目中用到大量基础图像处理知识,其中灰度图的生成是很重要的一环. 先补充一些基础知识: -------------------------------------------------------- ...

  4. Qt 中彩色图像转换为灰度图

    近期在做几个图像处理相关的项目.里面有一个操作就是须要先将彩色图像转换为灰度图像. QImage 有一个convertToFormat方法.最開始一直用这个函数来实现. 可是今天细致看了看,发现这个函 ...

  5. unity 读取灰度图生成按高程分层设色地形模型

    准备灰度图 1.高程按比例对应hue色相(hsv)生成mesh效果 o.color = float4(hsv2rgb(float3(v.vertex.y/100.0, 0.5, 0.75)), 1.0 ...

  6. unity读取灰度图生成等值线图

    准备灰度图 grayTest.png,放置于Assets下StreamingAssets文件夹中.   在场景中添加RawImage用于显示最后的等值线图.   生成等值线的过程,使用Marching ...

  7. unity读取灰度图生成三维地形mesh

    准备灰度图 IGray.png及草地贴图 IGrass.jpg ,放入Assets下StreamingAssets文件夹中.     创建空材质,用作参数传入脚本.   脚本如下,挂载并传入材质球即可 ...

  8. Qt 怎样生成带图标的exe

    一.问题描述 当我们在 Windows 下用 VS 生成 exe 程序时,如果窗口程序指定了图标,那么生成的 exe 程序便是指定的图标模样. 但是,当使用 Qt Creator 编译程序却不同.即使 ...

  9. blender导入灰度图生成地形模型

    安装软件 在此处下载blender并安装. 添加平面 1.打开blender,右键删除初始的立方体. 2.shift+a选择平面添加进场景: 3.按下s键鼠标拖动调节平面大小确定后按下鼠标左键: 4. ...

随机推荐

  1. 手把手教你在Windows端搭建Redmine项目管理软件

    1.Redmine介绍 Redmine是用Ruby开发的基于web的项目管理软件,是用ROR框架开发的一套跨平台项目管理系统,据说是源于Basecamp的ror版而来,支持多种数据库,有不少自己独特的 ...

  2. Win7安装IIS

    非常明显的,我们做系统是用来给人用的,所以这就涉及到对系统的公布问题.仅仅有公布之后.别人才干通过訪问你的IP和port号来訪问你的程序. 而系统公布一般都是在IIS上面进行系统公布,所以我们就必需要 ...

  3. SQL Server 2008 还原数据库

    1.得到数据库备份文件,怎么得到的,[能够看这里]~ 2.把备份文件加个.bak 的后缀,比如: 3.打开SQL , 你能够新建一个空数据库 , 或者利用原有的数据库 , 点击右键>>任务 ...

  4. windows 下一个mysql password忘记改变

    到场mysql简介 my.ini 于[mysqld]以下被加入 skip-grant-tables win+R 热键 进cmd 然后输入命令net stop mysql  最后一点,使文件夹mysql ...

  5. javascript学习(10)——[知识储备]链式调用

    上次我们简单的说了下单例的用法,这个也是在我们java中比较常见的设计模式. 今天简单说下链式调用,可能有很多人并没有听过链式调用,但是其实只要我简单的说下的话,你肯定基本上都在用,大家熟知的jQue ...

  6. 【转】管理员必备的Linux系统监控工具

    原文连接: 管理员必备的Linux系统监控工具 #1: top - 进程活动 top提供一个当前运行系统实时动态的视图,也就是正在运行进程.在默认情况下,显示系统中CPU使用率最高的任务,并每5秒钟刷 ...

  7. a='1,2,3,4,5'如何转换为['1','2','3','4','5']

    a='1,2,3,4,5'如何转换为['1','2','3','4','5'] b=a.split(',') split函数自动将分隔后的元素以逗号为分隔符存放到列表中 用处:有时需要用户输入多个数字 ...

  8. QDebug &operator<<出错(根据QString来找,是不得要领的,而是应该根据QString所在的对象来思考)

    程序运行后,总是崩溃在这个地方:inline QDebug &operator<<(const QString & t) 我应该用什么办法找出是哪个QString出了问题呢 ...

  9. Nutch 是一个开源Java 实现的搜索引擎

    Nutch 是一个开源Java 实现的搜索引擎.它提供了我们运行自己的搜索引擎所需的全部工具.包括全文搜索和Web爬虫. Nutch的创始人是Doug Cutting,他同时也是Lucene.Hado ...

  10. MySQL教程及经常使用命令1.1

    在线教程 21分钟 MySQL 新手教程 w3school在线教程(MYSQL) 变量 查看系统变量 show global variables 查看详细变量 show global variable ...