Qt生成灰度图(转载)
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:最简单的方法:
- for(int i =0;i<width;i++)
- {
- for(int j=0;j<height;j++)
- {
- QRgb pixel=iImage->pixel(i,j);
- int r=qRed(pixel);
- int g=qGreen(pixel);
- int b=qBlue(pixel);
- iGray->setPixel(i,j,qGray(r,g,b));
- }
- }
亦即:先用 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中如何实现,这个在网上我找到了一个方法,摘录如下
- QImage colourImg("colourImage.bmp");
- QSize colourImgSize = colourImg.size();
- int width = colourImgSize.rwidth();
- int height = colourImgSize.rheight();
- unsigned char *colourImgDataPtr = colourImg.bits();
- QImage grayImg(colourImgSize, QImage::Format_Indexed8);
- unsigned char *grayImgDataPtr = grayImg.bits();
- //下边这个for循环是直接取用green绿色分量值 来作为gray索引值
- for(int i = 0; i < height; i++)
- {
- for(int j = 0; j < width; j++)
- {
- *grayImgDataPtr = *(colourImgDataPtr + 1); colourImgDataPtr += 4; grayImgDataPtr++;
- }
- }
- QVector<QRgb> grayColourTable;
- unsigned int rgb = 0;
- for(int i = 0; i < 256; i++)
- {
- grayColourTable.append(rgb);
- rgb += 0x00010101;
- }
- grayImg.setColourTable(rayColourTable);
- graImg.save("grayImage.bmp", "bmp");
这块代码实现上:其是直接来取用green绿色分量值 来作为gray索引值!
其比上一个方法的优化之处在于:它没有使用系统函数,而是使用移动指针的方式来取得rgb分量。它把所有灰度索引值存放到index8灰度图中。最后创建了8阶灰度图的颜色表并赋予给该灰度图。这样:系统会自动(不需要我们手动去查找)依据存储在图像中的灰度索引值去 颜色表中查找对应灰度的rgb值来进行绘制!
--------------------------------------------------------------------------------------------------------------
在上述方法的基础上,我们在使用时:需要注意的是效果能不能达到需求,从而可能要用精确度更高的灰度索引值计算方法。那这就牵扯大量运算,此时记得要用移位操作 来取代 乘除法运算
- QBYTE RGBtoGRAY(QBYTE r, QBYTE g, QBYTE b)
- {
- return (QBYTE)((((QUINT32)((r << 5) + (r << 2) + (r << 1)))+ (QUINT32)((g << 6) + (g << 3) + (g << 1) + g)
- + (QUINT32)((b << 4) - b)) >> 7);
- }
这个是网上找到的最优化的实时计算灰度索引值算法。没有用到乘除法运算,转而使用大量移位操作。
--------------------------------------------------------------------------------------------------------------
暂且总结到这里,上述代码都实际测试过,没有问题。
Qt生成灰度图(转载)的更多相关文章
- opencv生成灰度图并保存
#include <opencv2/opencv.hpp>#include <iostream> using namespace cv;using namespace std; ...
- 图像分割利用KMeans生成灰度图
import numpy as np import PIL.Image as image from sklearn.cluster import KMeans def loadData(filePat ...
- 【Qt开发】QImage设置为8-bit灰度图
项目中用到大量基础图像处理知识,其中灰度图的生成是很重要的一环. 先补充一些基础知识: -------------------------------------------------------- ...
- Qt 中彩色图像转换为灰度图
近期在做几个图像处理相关的项目.里面有一个操作就是须要先将彩色图像转换为灰度图像. QImage 有一个convertToFormat方法.最開始一直用这个函数来实现. 可是今天细致看了看,发现这个函 ...
- unity 读取灰度图生成按高程分层设色地形模型
准备灰度图 1.高程按比例对应hue色相(hsv)生成mesh效果 o.color = float4(hsv2rgb(float3(v.vertex.y/100.0, 0.5, 0.75)), 1.0 ...
- unity读取灰度图生成等值线图
准备灰度图 grayTest.png,放置于Assets下StreamingAssets文件夹中. 在场景中添加RawImage用于显示最后的等值线图. 生成等值线的过程,使用Marching ...
- unity读取灰度图生成三维地形mesh
准备灰度图 IGray.png及草地贴图 IGrass.jpg ,放入Assets下StreamingAssets文件夹中. 创建空材质,用作参数传入脚本. 脚本如下,挂载并传入材质球即可 ...
- Qt 怎样生成带图标的exe
一.问题描述 当我们在 Windows 下用 VS 生成 exe 程序时,如果窗口程序指定了图标,那么生成的 exe 程序便是指定的图标模样. 但是,当使用 Qt Creator 编译程序却不同.即使 ...
- blender导入灰度图生成地形模型
安装软件 在此处下载blender并安装. 添加平面 1.打开blender,右键删除初始的立方体. 2.shift+a选择平面添加进场景: 3.按下s键鼠标拖动调节平面大小确定后按下鼠标左键: 4. ...
随机推荐
- VS2010/MFC对话框二:为对话框添加控件)
为对话框添加控件 创建对话框资源需要创建对话框模板.修改对话框属性.为对话框添加各种控件等步骤,前面一讲中已经讲了创建对话框模板和修改对话框属性,本节继续讲如何为对话框添加控件. 上一讲中创建了一个名 ...
- icon-font图标介绍
前言 像素完美(Pixel Perfection).分辨率无关(Resolution Independent)和多平台体验一致性是设计师们的追求. 可访问性(Accessability).加载性能和重 ...
- HtmlAgilityPack 抓取页面的乱码处理
HtmlAgilityPack 抓取页面的乱码处理 用来解析 HTML 确实方便.不过直接读取网页时会出现乱码. 实际上,它是能正确读到有关字符集的信息,怎么会在输出时,没有取到正确内容. 因此,读两 ...
- 在Update Panel 控件里面添加 File Upload 控件 上传文件
Detail Information:http://www.codeproject.com/Articles/482800/FileplusUploadplusinplusUpdateplusPane ...
- [Swust OJ 465]--吴奶奶买鱼(0-1背包+dfs)
题目链接:http://acm.swust.edu.cn/problem/465/ 还有一道题只是描述不一样,方法一模一样(http://acm.swust.edu.cn/problem/644/) ...
- WPF中StringFormat 格式化 的用法
原文 WPF中StringFormat 格式化 的用法 网格用法 <my:DataGridTextColumn x:Name="PerformedDate" Header=& ...
- c# 数据库编程(通过SqlCommand 执行数据库查询)
前面一篇文章,我们介绍了如何在c#中对数据库进行更新操作.主要是利用SqlCommand 对象的ExecuteNonQuery方法. 这篇文章介绍,如何进行查询操作.本文给出的例子仍然是针对sql s ...
- python _thread模块使用
python关于线程管理的有2个类,_thread(在2.x的版本中叫thread)和threading. # encoding: UTF-8 import thread import time ...
- win7删除桌面文件需要刷新才会消失(2种解决方法)
有没有遇到过这种情况,删除桌面文件没有效果,要点右键的刷新删除过的文件才会在桌面上消失!解决方法有两种: 第一种方法 点击"开始→运行",在对话框中输入"regedit& ...
- Axis2(10):使用soapmonitor模块监视soap请求与响应消息
在Axis2中提供了一个Axis2模块(soapmonitor),该模块实现了与<WebService大讲堂之Axis2(9):编写Axis2模块(Module)>中实现的logging模 ...