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. VS2010/MFC对话框二:为对话框添加控件)

    为对话框添加控件 创建对话框资源需要创建对话框模板.修改对话框属性.为对话框添加各种控件等步骤,前面一讲中已经讲了创建对话框模板和修改对话框属性,本节继续讲如何为对话框添加控件. 上一讲中创建了一个名 ...

  2. icon-font图标介绍

    前言 像素完美(Pixel Perfection).分辨率无关(Resolution Independent)和多平台体验一致性是设计师们的追求. 可访问性(Accessability).加载性能和重 ...

  3. HtmlAgilityPack 抓取页面的乱码处理

    HtmlAgilityPack 抓取页面的乱码处理 用来解析 HTML 确实方便.不过直接读取网页时会出现乱码. 实际上,它是能正确读到有关字符集的信息,怎么会在输出时,没有取到正确内容. 因此,读两 ...

  4. 在Update Panel 控件里面添加 File Upload 控件 上传文件

    Detail Information:http://www.codeproject.com/Articles/482800/FileplusUploadplusinplusUpdateplusPane ...

  5. [Swust OJ 465]--吴奶奶买鱼(0-1背包+dfs)

    题目链接:http://acm.swust.edu.cn/problem/465/ 还有一道题只是描述不一样,方法一模一样(http://acm.swust.edu.cn/problem/644/) ...

  6. WPF中StringFormat 格式化 的用法

    原文 WPF中StringFormat 格式化 的用法 网格用法 <my:DataGridTextColumn x:Name="PerformedDate" Header=& ...

  7. c# 数据库编程(通过SqlCommand 执行数据库查询)

    前面一篇文章,我们介绍了如何在c#中对数据库进行更新操作.主要是利用SqlCommand 对象的ExecuteNonQuery方法. 这篇文章介绍,如何进行查询操作.本文给出的例子仍然是针对sql s ...

  8. python _thread模块使用

    python关于线程管理的有2个类,_thread(在2.x的版本中叫thread)和threading. # encoding: UTF-8 import thread import time   ...

  9. win7删除桌面文件需要刷新才会消失(2种解决方法)

    有没有遇到过这种情况,删除桌面文件没有效果,要点右键的刷新删除过的文件才会在桌面上消失!解决方法有两种: 第一种方法 点击"开始→运行",在对话框中输入"regedit& ...

  10. Axis2(10):使用soapmonitor模块监视soap请求与响应消息

    在Axis2中提供了一个Axis2模块(soapmonitor),该模块实现了与<WebService大讲堂之Axis2(9):编写Axis2模块(Module)>中实现的logging模 ...