qt之图像处理

摘要:
毕业两年后,我一直在用qt做桌面程序,很少接触图像算法。最近,由于项目原因,我不得不了解图像处理,但它也是一些简单的图像处理,只是为了记录,我希望它可以帮助正在学习qt图像处理的朋友。如果您不了解Qt图像存储的相关类,可以在QPixmap/QImage/QPicture中看到解释,它准确地描述了Qt设计的这些类的用途,其中QImage类可以执行图像转换,QPixmap可以执行向量拉伸等。

    毕业2年了,一直使用的qt做桌面程序,很少接触图像算法类的东西,最近由于项目的原因,不得不了解下图像处理,不过也是一些简单的图像处理,仅此作为记录,并希望能帮助初学qt图像处理的朋友。

    首先我推荐一篇文章,高斯模糊算法的实现和优化 这篇文章也是我理解图片模糊的开始,我个人觉得讲的相当清楚明了。因此如果对原理或者名词不理解的同学可以进去一看究竟。下面我说下我自己在项目运用过程中的一心心得,就包括对图片处理的一些操作,做一记录。

    如果对Qt的图像储存相关类不了解,可以看QPixmap/QImage/QPicture 中的讲解,比较准确的描述了qt设计这几个类的目的,其中QImage类可以对图像进行镜像转换、QPixmap可以进行矢量拉伸等。不过这些都是qt自带的一些操作,但是还有一些特殊处理需要我们自己实现,接下来我就说下图片模糊处理图片圆角处理

一、图片模糊处理

    图片模糊处理说白了就是需要寻找一套模糊算法来生成模糊滤镜,然后对图像上的每一个像素进行处理,问题的关键在于模糊算法的实现,本篇开始推荐的文章中高斯模糊其实就是使用高斯函数生成模糊滤镜的过程,并对图片进行处理。既然知道了原理,那么其实图片模糊也就可以用很多方式来做了,毕竟替换高斯函数的方法有很多。文章最后有我自己整理的一个小demo,可以供大家参考。

    下面我先贴上几种模糊函数下的实现效果,为什么要实现这样的效果呢,呵呵。。因为mac上的qq在换头像时背景色会自动切换,背景色应该就是通过模糊算法自动生成。

image图1 高斯函数模糊

image图2 直线函数模糊

image图3 算术平均值模糊

    这3种模糊都是使用了Blur1D方法进行滤镜处理,通过测试Blur1D方法比Blur2D方法快接近10倍。这个方法的优化,在本文推荐的第一篇文章中就有详细说明,如图4所示

image

图4 高斯优化说明

具体细节处理请看原文中描述。在这里我只贴出使用高斯一维函数处理的滤镜,和使用滤镜对照片上每一个像素进行处理的代码,代码如下:

 1 //高斯模糊算法 一维(O(2*x*y*2r))形式的高斯函数 比二维(O(x*y*(2r)^2))效率高 对应Blur1D滤镜算法
 2     void Gauss(filter_t& kernel, long radius)
 3     {
 4         kernel.set(radius, Diamet(radius));
 5 
 6         static const double SQRT2PI = sqrt(2.0 * PI);
 7 
 8         double sigma = (double)radius / 3.0;
 9         double sigma2 = 2.0 * sigma * sigma;
10         double sigmap = sigma * SQRT2PI;
11 
12         for (long n = 0, i = -kernel.radius(); i <= kernel.radius(); ++i, ++n)
13             kernel[n] = exp(-(double)(i * i) / sigma2) / sigmap;
14     }

下面的代码是对应高斯一维处理函数的图片像素点处理方法:

 1 void Blur1D(bitmap_t& bitmap, filter_t& kernel)
 2     {
 3         Normalization(kernel);
 4 
 5         buffer_t buff(bitmap);
 6 
 7         for (long inx = 0, y = 0; y < bitmap.h(); ++y)
 8         {
 9             for (long x = 0; x < bitmap.w(); ++x, ++inx)
10             {
11                 for (long n = 0, i = -kernel.radius(); i <= kernel.radius(); ++i, ++n)
12                 {
13                     long i_k = Edge(i, x, bitmap.w());
14                     long inx_k = inx + i_k;
15                     buff[inx].r += bitmap[inx_k].r * kernel[n];
16                     buff[inx].g += bitmap[inx_k].g * kernel[n];
17                     buff[inx].b += bitmap[inx_k].b * kernel[n];
18                 }
19             }
20         }
21 
22         for (long inx = 0, x = 0; x < bitmap.w(); ++x)
23         {
24             for (long y = 0; y < bitmap.h(); ++y)
25             {
26                 inx = y * bitmap.w() + x;
27                 double r = 0.0, g = 0.0, b = 0.0;
28                 for (long n = 0, i = -kernel.radius(); i <= kernel.radius(); ++i, ++n)
29                 {
30                     long i_k = Edge(i, y, bitmap.h());
31                     long inx_k = inx + i_k * bitmap.w();
32                     r += buff[inx_k].r * kernel[n];
33                     g += buff[inx_k].g * kernel[n];
34                     b += buff[inx_k].b * kernel[n];
35                 }
36                 bitmap[inx].r = Clamp<bitmap_t::channel_t>(r);
37                 bitmap[inx].g = Clamp<bitmap_t::channel_t>(g);
38                 bitmap[inx].b = Clamp<bitmap_t::channel_t>(b);
39             }
40         }
41     }

    理解了上边的代码后,只需要下面几行代码,就可以生成模糊后的图片,其中resultImage是输出型参数,模糊后的图片存放在其中。

1 filter::bitmap_t bmp;
2     bmp.set((filter::bitmap_t::pixel_t*)resultImage.bits(),
3         resultImage.width(), resultImage.height());
4 
5     filter::Filter(pair[4], bmp, radius);

    初次之外demo中还提到了一个检测算法时间复杂度的方法,通过调用该方法可以检测每个图片处理过程的时间长短。

1 #define CHECK_TIME(text, ...) 
2 { 
3     clock_t t1 = std::clock(); 
4     { __VA_ARGS__; } 
5     clock_t t2 = std::clock(); 
6     qDebug() << #__VA_ARGS__ << text << "->" << (long)((double)(t2 - t1) / (double)(CLOCKS_PER_SEC) * 1000.0); 
7 }

二、图片圆角处理

    上边讲述了图片的模糊处理,其实说白了也就是对图像的每一个像素进行指定的滤镜操作,最终形成 一张新的图片。接下来我们要讲述的是根据一张矩形图来生成一张圆角矩形图,方式有2种我将分别介绍,个人根据自己的情况使用。

1、纯代码处理

    纯代码处理,顾名思义也就是不需要外来的资源帮忙,其实原理也就是这样,通过给原来的图片设置掩码图像来生成圆角,也即我们需要自己从内存中绘制一张掩码图像,周围是透明的,里面是一个不透明的圆角矩形。效果如图5所示,实现代码如下:

 1 QPixmap PixmapToRound(const QPixmap & img, int radius)
 2 {
 3     if (img.isNull())
 4     {
 5         return QPixmap();
 6     }
 7 
 8     QSize size(img.size());
 9     QBitmap mask(size);
10     QPainter painter(&mask);
11     painter.setRenderHint(QPainter::Antialiasing);
12     painter.setRenderHint(QPainter::SmoothPixmapTransform);
13     painter.fillRect(mask.rect(), Qt::white);
14     painter.setBrush(QColor(0, 0, 0));
15     painter.drawRoundedRect(mask.rect(), radius, radius);
16 
17     QPixmap image = img;// .scaled(size);
18     image.setMask(mask);
19     return image;
20 }

image图5 圆角预览

2、蒙版实现

    所谓蒙版实现其实原理和方式1类似,只是上图上的掩码图片需要设计师类提供,这样的设计就需要设计师设计出多套蒙版,效果和图5一样,diamante如下:

 1 QPixmap PixmapToRound(const QPixmap & img, const QPixmap & mengban, QSize size)
 2 {
 3     if (img.isNull())
 4     {
 5         return QPixmap();
 6     }
 7     QImage resultImage(size, QImage::Format_ARGB32_Premultiplied);
 8     QPixmap mask(mengban.scaled(size)); //蒙层图片
 9 
10     QPainter painter(&resultImage);
11     painter.setRenderHints(QPainter::SmoothPixmapTransform);
12     painter.setCompositionMode(QPainter::CompositionMode_Source);
13     painter.fillRect(resultImage.rect(), Qt::transparent);
14     painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
15     painter.drawPixmap(0, 0, mask);
16     painter.setCompositionMode(QPainter::CompositionMode_SourceOut);
17     painter.drawPixmap(0, 0, img.scaled(size));
18     painter.setCompositionMode(QPainter::CompositionMode_DestinationOver);
19     painter.end();
20 
21     return QPixmap::fromImage(resultImage);
22 }

demo下载链接:http://download.csdn.net/detail/qq_30392343/9591008

如果您觉得文章不错,不妨给个打赏,写作不易,感谢各位的支持。您的支持是我最大的动力,谢谢!!! 

 
qt之图像处理第6张qt之图像处理第7张

  


很重要--转载声明

  1. 本站文章无特别说明,皆为原创,版权所有,转载时请用链接的方式,给出原文出处。同时写上原作者:朝十晚八 or Twowords
  2. 如要转载,请原文转载,如在转载时修改本文,请事先告知,谢绝在转载时通过修改本文达到有利于转载者的目的。 

奋斗中的无名小卒。。。

免责声明:文章转载自《qt之图像处理》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇实现Excel文件的上传和解析citi velocity下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

as3.0 Flex 图像处理

as3.0 Flex 图像处理 已知的一些图像处理,主要是得到颜色过滤矩阵,不完整,大家一起来补充。 //颜色转换数组,所有的0都是可调值public var colorArray:Array = [1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0]; 1.处理图像为灰度://取值范围0~3colorArray...

CentOS 7磁盘寻找不到,卡在sulogin,造成的开机失败问题--Error getting authority...

今天早上使用内网gitlab仓库的时候,发现页面无法打开,ssh也无法连接。 到机房接上显示器,发现如下错误: Error getting authority: Error initializing authority: Could not connect: No such file or directory (g-io-error-quark, 1)...

Ubantu 16.04升级内核版本和还原到升级之前的内核版本的方法

一、查看系统信息 1、查看发布版本: 命令: lsb_release -a 运行结果: / 2、查看内核版本: 命令: uname -sr 运行结果: 二、升级内核的方法 1、内核下载地址:http://kernel.ubuntu.com/~kernel-ppa/mainline/ 。打开地址后,拖动鼠标到网页最底端,找到最新版本的内核v4.15...

内核打印等级

内核打印日志等级配置存放在/proc/sys/kernel/printk,默认6   4   1   7 上面显示的4个数据分别对应: 控制台日志级别:优先级高于该值的消息将被打印至控制台 默认的消息日志级别:将用该优先级来打印没有优先级的消息 最低的控制台日志级别:控制台日志级别可被设置的最小值(最高优先级) 默认的控制台日志级别:控制台日志级别的缺省...

CentOS7 初始化配置

一、在安装的时候配置网卡名称的参数 1. 选择“Install Centos 7” 2. 按Tab,打开kernel启动选项后,增加 net.ifnames=0 biosdevname=0 二、最小化安装完成之后必备安装软件 # 添加epel源,安装基础软件,设置主机名rpm -ivh http://mirrors.aliyun.com/epel/epe...

BitBlt 函数 详解, StretchBlt、SetStretchBltMode、SetBrushOrgEx 按句柄截图、直接截取缩略图

BitBlt 该函数对指定的源设备环境区域中的像素进行位块(bit_block)转换,以传送到目标设备环境。 函数原型 [DllImport("gdi32.dll")] public static extern bool BitBlt(IntPtr hObject, int nXDest, intnY...