CImg库介绍
转自:http://www.cppprog.com/2009/0424/106.html
CImg是一个跨平台的C++的图像处理库,提供了加载、处理、显示、保存等一系列功能,其中的图像处理功能尤其强大。
首先,建议先到这里欣赏一下使用CImg代码做的Demo,就是它使我这个没有图像处理经验的童鞋也心动得以致于研究了一星期^_^
主页地址:http://cimg.sourceforge.net/
下载地址:http://cimg.sourceforge.net/download.shtml
下载时注意应该下载源码包,里面附带的大量的例程。而实际上CImg库只是一个头文件CImg.h,这个头文件里包含了CImg库所有的代码。
另外不要错过下载列表中的一个部分完成的《CImg中文参考手册》。
CImg的Hello World
这段代码是从《CImg参考手册》里抄的,可以大致了解一下CImg的框架。
以VC为例:新建控制台程序,输入下面的代码。项目属性的链接器附加依赖项加入kernel.lib user32.lib gdi32.lib。最后,把CImg.h拷贝到项目路径下,即可成功编译运行
- #include "CImg.h"
- using namespace cimg_library;
- int main()
- {
- // 定义一个每个颜色 8 位(bit)的 640x400 的彩色图像
- CImg<unsigned char> img(640,400,1,3);
- //将像素值设为 0(黑色)
- img.fill(0);
- // 定义一个紫色
- unsigned char purple[] = { 255,0,255 };
- // 在坐标(100, 100)处画一个紫色的“Hello world”
- img.draw_text(100,100,"Hello World",purple);
- // 在一个标题为“My first CImg code”的窗口中显示这幅图像
- img.display("My first CImg code");
- return 0;
- }
运行这段代码,显示结果:
在CImg体系中,图像有x,y,z,v四个轴,前三个当然是3维空间的三个方向(知道了吧?CImg可以处理3维图像),第四个v一般表示色彩通道数,比如RGB三色就是3。
上面的代码每行的注释已经写得很详细,从代码里可以看出CImg处于namespace cimg_library名空间之下;模板类CImg<>是主要的图像类,提供了大量的图像处理方法。
在CImg库里,还有一个重要的类是CImgDisplay,它提供了一个显示窗口,不仅可以显示CImg的内容,还可以接收键盘鼠标事件,我们可以暂时把它看成是一个CImg专用窗体类。
CImg类介绍
CImg类提供的方法非常多,为了便于查阅,我用Doxygen重新生成了一份CImg库的说明文档,并做成chm格式,可以本文后面找到下载地址。
CImg模板类提供了图像的载入、保存、处理功能,是整个库的核心组件。它的声明如下:
template<typename T>
struct cimg_library::CImg;
<typename T>
struct cimg_library::CImg;
模板参数T指明CImg中元素的类型。在自带的参考手册中称这些元素为像素(pixel),不过因为这里的像素和我们平时的像素概念稍微有点不同。因为前面说过CImg体系中有xyzv四个轴,CImg手册称它为4维图像,把4维图像里的单个元素称为像素。而事实上第四维的v通常就是我们的色彩通道,所以要在屏幕上显示出一个真正的像素往往要取同一xyz轴上所有v轴的点(所有色彩通道合成一个真正的彩色像素)。在本文中我决定把这个组成图像的最小单位称为元素,由所有色彩通道v组成一个像素。
CImg类中的6个成员变量:
- // 分别对应x,y,z,v四个轴的大小,即宽度、高度、深度和通道数。
- unsigned int width, height, depth, dim;
- // 指向内存中的图像数据
- T *data;
- // 指明data是否是共用的,即是否有data的拥有权。
- bool is_shared;
CImg类里的成员变量都是public的,我们可以直接存取它们,不过为了防止破坏完整性,建议使用成员方法如dimx(), dimy(), dimz(), dimv() 和ptr()来操作。
CImg的构造函数,大部分构造函数都很直白,就不列出了,可以查看手册,下面列出的是一些特殊的构造函数。
- // 以字符串指定的数据填充,其中的values字符串包含了一串十进制数字表示的数据。
- // 比如参数values为字符串"20,30,40,50", repeat_pattern为true时
- // 图像内的数据就以20,30,40,50,20,30,40,50,20...填充。
- CImg (
- const unsigned int dx,
- const unsigned int dy,
- const unsigned int dz,
- const unsigned int dv,
- const char *const values,
- const bool repeat_pattern)
- // 由shared参数决定是否直接引用img中的data数据还是自己持有一份拷贝(是否共享)
- CImg (const CImg< T > &img, const bool shared)
- // 参考img的大小构造一个新的CImg对象
- CImg (const CImg< t > &img, const char *const dimensions)
这个构造函数的dimensions参数由一串数字或转义符组成,分别对应x,y,z,v的大小。比如:
参数为"20 20 1 3"时新CImg对象的x,y,z,v的大小分别是20 20 1 3。
转义符以%开头,后缀可以是:
x, dx, dimx, width 表示img.width
y, dy, dimy, height 表示img.height
z, dz, dimz, depth 表示img.depth
v, dv, dimv, dim 表示img.dim
比如CImg(img, "%y %x 1 3");可以生成一个和img的宽高正好互换的CImg对象。
- // 从文件里载入图像,文件类型由扩展名确定
- CImg (const char *const filename)
CImg库本身支持BMP,RAW,HDR,INR,PGM,PPM,PAN,DLM格式
安装了ImageMagick(Unix系)后可支持JPG,GIF,PNG,TIF等多种格式
CImg也能使用jpeg库,zlib/png库,tiff库等来支持多种图像格式,只需编译时加入这些库即可。可以到这里下载这些库文件。
- // 从CImgDisplay对象的内容创建图像
- CImg (const CImgDisplay &disp)
CImg部分成员方法
CImg提供了丰富的成员方法,在这里全部列出是不可能的,这里只作一些简单介绍。更多方法请参考手册。
- // 赋值,它有多个重载的版本,参数和构造函数一样,实际上构造函数最终都是调用它来实现的。
- CImg< T > & assign ();
- // 把data数据转交给img,自己不再有data数据的拥有权
- CImg< T > & transfer_to (CImg< T > &img);
- // 清除数据
- CImg< T > & clear ();
- // 获得所有元素总数
- unsigned long size () const
- // 获得某个轴向的大小
- int dimx () const;
- int dimy () const;
- int dimz () const;
- int dimv () const;
- // 取得遍历元素的迭代器,这里的iterator其实就是T*。
- iterator begin ();
- iterator end ();
- // 取得首尾数据
- T & first ();
- T & last ();
- // 取得图像内部数据(第二个版本取得数据并定位到指定位置)
- T * ptr ();
- T * ptr (
- const unsigned int x,
- const unsigned int y=0,
- const unsigned int z=0,
- const unsigned int v=0);
- // 快速存取指定位置上的数据
- T & operator() (
- const unsigned int x,
- const unsigned int y=0,
- const unsigned int z=0,
- const unsigned int v=0);
- // 按索引直接存取data数组
- T & operator[] (const unsigned long off)
- // 得到指定位置的索引
- long offset (
- const int x,
- const int y=0,
- const int z=0,
- const int v=0) const;
- // 存取指定位置上的数据,当指定的轴的超出边界时返回最边上的值
- T & at (const int off);
- T& atX(const int x, const int y, const int z, const int v);
- T& atXY(const int x, const int y, const int z, const int v);
- T& atXYZ(const int x, const int y, const int z, const int v);
- T& atXYZV(const int x, const int y, const int z, const int v);
- // 存取指定位置上的数据,当指定的轴的超出边界时返回out_val
- T & at (const int off, const T out_val);
- T& atX(const int x, const int y, const int z, const int v, const T out_val);
- T& atXY(const int x, const int y, const int z, const int v, const T out_val);
- T& atXYZ(const int x, const int y, const int z, const int v, const T out_val);
- T& atXYZV(const int x, const int y, const int z, const int v, const T out_val);
值得一提的是还有两种插值版本的at方法,分别是线性插值和三次插值。其中线性插值以linear_作为前缀,三次插值以cubic_作为前缀。参数和上面的类似,只是各轴位置的类型不是int而是float,这批方法会按插值法算出小数点位置上的数据。
到这里可以发现CImg类实际上提供了类似于vector容器的编程接口,这样我们的STL算法也能用于CImg的操作了,随后就可以看到库里有时也会把CImg类直接当作数据容器来使用。比如下面CImg中就有这个方法:
- // 返回字符串的形式的图像中的数据,默认是逗号分隔的一长串数字。
- //这里返回的CImg<charT>不代表图像,而是一个一维的字符串数据,这时它只是一个容器而已,可以把它看作是vector<charT>。
- CImg< charT > value_string (const char separator=',', const unsigned int max_size=0);
CImg类的画图方法
draw_point
draw_line
draw_polygon
draw_spline
draw_arrow
draw_image
draw_rectangle
draw_triangle
draw_ellipse
draw_circle
draw_text
draw_quiver
draw_graph
draw_axis
draw_grid
draw_fill
draw_plasma
draw_mandelbrot
draw_gaussian
draw_object3d
CImg的画图方法真的是非常多,每种方法都有2D和3D的重载,具体可以参考手册。
CImg类的图像处理方法
CImg类的图像处理方法分两种版本:一种是直接在自己的数据上计算和保存;另一种是返回一个计算后的CImg对象,自己的数据不会改变,这个版本以get_作为前缀并且总是const方法。
- // 填充图像,其中的valx参数用于顺序填充图像,最多可以有15个。
- CImg< T > & fill (const T val0, const T val1, ...);
- // 以values指定的字符串来填充图像,values格式参考上文的构造函数参数
- CImg< T > & fill (const char *const values, const bool repeat_pattern)
- // 以values图像里的值填充。
- CImg< T > & fill (const CImg< t > &values, const bool repeat_pattern=true)
相应的,有get_fill方法,返回填充后的新CImg对象。后面的方法同相也有get_方法,不再累述。
- // 只填充指定的yzv位置上的x轴的数据
- CImg< T > & fillX (
- const unsigned int y,
- const unsigned int z,
- const unsigned int v,
- const int a0,...);
当然,也有fillY,fillZ,fillV。
- // 线性规格化图像,即把图像中的所有元素数值线性放大或减小到a和b之间。
- CImg< T > & normalize (const T a, const T b)
- // 把图像中的所有元素数值大小限制在a和b之间,若有超出,则直接限制在边界上。
- CImg< T > & cut (const T a, const T b);
- // 把图像像素数据数字化到n级上,即图像元素数值从小到大被分成n个级别。(类似AD转换)
- CImg< T > & quantize (const unsigned int n, const bool keep_range=true)
- // 阈值化图像,小于value的为0,大于value的为1。
- // 若soft=true,则小于value元素加上value,大于value的元素减去value。
- // strict决定比较时使用<操作还是<=操作。
- CImg< T > & threshold (const T value, const bool soft=false, const bool strict=false)
- // 旋转图像,以cx,cy指定点为中心,旋转angle度,放大zoom倍。
- CImg< T > & rotate (
- const float angle,
- const float cx,
- const float cy,
- const float zoom,
- const unsigned int border_conditions=3,
- const unsigned int interpolation=1);
参数border_conditions指定怎样处理边界外的值,0-边界以外以0值填充,1-重复边界点的值,2-重复图像
参数interpolation指定采用何种插值方法,0-不插值,1-线性插值,2-三次插值
- // 改变大小
- CImg< T > & resize (
- const int pdx,
- const int pdy=-100,
- const int pdz=-100,
- const int pdv=-100,
- const int interpolation_type=1,
- const int border_condition=-1,
- const bool center=false)
改变图像到指定大小,当pdx,pdy,pdz或pdv<0时,使用百分比。interpolation_type指定插值方法,分别是:
-1 = 不插值 : 图像直接按大小剪切
0 = 不插值 : 多余空间依据border_condition决定。
1 = 临近点插值。
2 = 移动平均数插值。
3 = 线性插值。
4 = 删格插值。
5 = 双三次插值。
另外,还有几个优化的resize版本:
- // 优化的缩小至原来的1/2
- CImg< T > & resize_halfXY ()
- // 优化的放大至原来的2倍
- CImg< T > & resize_doubleXY ()
- // 优化的放大至原来的3倍
- CImg< T > & resize_tripleXY ()
- // 扭曲图像,由参数warp中相同位置的数据决定该位置元素的去向。
- CImg< T > & warp (
- const CImg< t > &warp,
- const bool relative=false,
- const bool interpolation=true,
- const unsigned int border_conditions=0)
参数warp在这里只是一个容器(不要把它看成图像)的作用,其x,y,z点上的数据决定了当前图像x,y,z点上元素的新位置,这个新位置由warp的x,y,z点上的v轴数据给出。如果warp的v轴长度是1时,当前图像元素只会在x轴上移动。如果warp的v轴长度是2时,当前图像元素在x,y轴上移动...relative=ture时,表示wrap中的数据是相对位置。
- // 按指定轴镜像,axis可以是'x','y','z','v'
- CImg< T > & mirror (const char axis);
- // 偏移图像
- CImg< T > & translate (
- const int deltax,
- const int deltay=0,
- const int deltaz=0,
- const int deltav=0,
- const int border_condition=0)
- // 取原图像中的一块子图
- CImg< T > & crop (
- const int x0, const int y0, const int z0, const int v0,
- const int x1, const int y1, const int z1, const int v1,
- const bool border_condition=false)
crop方法还有其它的版本,分别是省略v轴,z轴和y轴的版本。
- // 把3D图像转成2D视图。
- CImg< T > & projections2d (
- const unsigned int x0, const unsigned int y0, const unsigned int z0,
- const int dx=-100, const int dy=-100, const int dz=-100);
最后,下面的这些方法提供类似Photoshop的滤镜功能,强啊~~:
noise 噪声
deriche Canny-Deriche算法
blur 模糊
blur_anisotropic 各向异性模糊
blur_bilateral 对称模糊
blur_patch 面片模糊
blur_median 中值模糊
sharpen 尖锐
haar 小波分析
...还有好多
看了上面的介绍,我想大家肯定对CImg的强大能力有了初步的了解(要知道上面列出的方法只是CImg方法中的冰山一角,而且更强的是CImg库还能通过指定Plugin宏的方式插入新的方法,当CImg自带的方法不能满足我们的要求时,也许已经有人提供了对应的插件了),下次我们开始学习CImg的具体使用吧^_^
最后放上前面说的CImg的Doxygen手册,猛击这里下载。
相关文章:

谷歌、阿里们的杀手锏:三大领域,十大深度学习CTR模型演化图谱
作者 | 王喆来源 | 转载自知乎专栏王喆的机器学习笔记今天我们一起回顾一下近3年来的所有主流深度学习CTR模型,也是我工作之余的知识总结,希望能帮大家梳理推荐系统、计算广告领域在深度学习方面的前沿进展。随着微软的Deep Crossing,Google的…

MariaDB 基金会 CEO 宣布将于 10 月 1 日卸任
开发四年只会写业务代码,分布式高并发都不会还做程序员? 近日,MariaDB 基金会 CEO Otto Keklinen 在官网宣布自己将在今年 10 月 1 日正式卸任 CEO,转而退居后线,以 CEO 特别顾问的身份辅助新 CEO 顺利渡过过渡期。从…

思科生成树命令之debug spanning-tree(本文转载自:www.91ccie.coml
debug spanning-tree 命令:debug spanning-treeno debug spanning-tree功能:打开MSTP 的调试信息;本命令的no 操作为关闭MSTP 调试信息。参数:无命令模式:特权模式使用指南:该命令是MSTP 庞大复杂debug 功能…

CImg库中CImg,CImgList,CImgDisplay三个类的介绍
转自:http://www.cppprog.com/2009/0426/108.html 本文简单介绍了CImg库中的三个大类:CImg,CImgList,CImgDisplay。然后给出了让CImg在HDC上绘图以及与HBITMAP互换的方法,为部署CImg到Windows GUI程序中提供了基本支持。 上回介绍了CImg模板…

这可能是Python面向对象编程的最佳实践
作者 | 崔庆才来源 | 进击的Coder(ID:FightingCoder)Python 是支持面向对象的,很多情况下使用面向对象编程会使得代码更加容易扩展,并且可维护性更高,但是如果你写的多了或者某一对象非常复杂了,其中的一些…

mysql之 CentOS系统针对mysql参数优化
内核相关参数(/etc/sysctl.conf) 以下参数可以直接放到sysctl.conf文件的末尾: net.core.somaxconn 65535 net.core.netdev_max_backlog 65535 net.ipv4.tcp_max_syn_backlog 65535 加快TCP连接的回收: net.i…

天猫双十一神话恐终结
2011年双十一大促,天猫商城创造了单日33.6亿的促销奇迹,是2010年同日交易额的近4倍。今年双十一即将来临,淘宝还能再创奇迹吗?何玺认为,淘宝双十一的神话恐终结,理由如下。 一、电商促销年消费被透支 年初 …

opencv图像旋转
转自:http://download.csdn.net/source/2642701 /* 程序名:rotate.c 功能:读入图像文件,做图像旋转转,然后显示图像在屏幕上 */ #include <stdlib.h> #include <stdio.h> #include <math.h> #inclu…

机器如何读懂人心:Keras实现Self-Attention文本分类
作者 | 小宋是呢转载自CSDN博客一、Self-Attention概念详解了解了模型大致原理,我们可以详细的看一下究竟Self-Attention结构是怎样的。其基本结构如下对于self-attention来讲,Q(Query), K(Key), V(Value)三个矩阵均来自同一输入,首先我们要计…

通俗易懂!使用Excel和TF实现Transformer
作者 | 石晓文转载自小小挖掘机(ID:wAIsjwj)本文旨在通过最通俗易懂的过程来详解Transformer的每个步骤!假设我们在做一个从中文翻译到英文的过程,我们的词表很简单如下:中文词表:[机、器、学、习] 英文词表…

通过注册表修改VC6.0的字体【转】
2019独角兽企业重金招聘Python工程师标准>>> 在VC6.0下更改字体,我们一般通过菜单-Tools-Options-Format来更改 但在我的win7 64位系统下这一选项下的字体和字体颜色是空的,无法选择 所以我想起来通过注册表来更改。 WinR输入“Regedit”&…

Java中创建String的两种方式差异
我们知道创建一个String类型的变量一般有以下两种方法: String str1 "abcd"; String str2 new String("abcd"); 那么为什么会存在这两种创建方式呢,它们在内存中的表现形式各有什么区别? 方法1: String a …

OpenCV支持的图像格式
OpenCV目前支持的图像格式包括: Windows位图文件 - BMP, DIB; JPEG文件 - JPEG, JPG, JPE; 便携式网络图片 - PNG; 便携式图像格式 - PBM,PGM,PPM; Sun rasters - SR,RASÿ…

Debian Linux下的Python学习——控制流
python中有三种控制流语句:if、for和while。 1. if语句用法( if..elif..else) 代码: 运行: 注意:raw_input函数要求输入一个字符串,int把这个字符串转换为整数 2.for语句用法 (for ... else) 代码: 运行: 注:else部分是可选的。如果包含else,它总是在for循环结束后…

如何运行ImageMagick的命令行工具
在http://www.imagemagick.org/script/index.php网站下载相应的执行文件,这里以下载ImageMagick-6.6.5-10-Q16-windows-static.exe为例说明。 将ImageMagick-6.6.5-10-Q16-windows-static.exe下载后,安装,然后将其中需要的命令行工具考到你需…

华为最强自研NPU问世,麒麟810“抛弃”寒武纪
整理 | 一一出品 | AI科技大本营(ID:rgznai100)“能效高、算子多、精度高”,华为消费者业务手机产品线总裁何刚用一句话总结了自研达芬奇架构给最新麒麟810芯片带来的变化。6 月 21 日,在 HUAWEI Nova 5 系列新品发布会上&#x…
调用 微信接口报错 {errcode:48001,errmsg:api unauthorized, hints: [ req_id: 1QoCla0699ns81 ]}...
如下截图,仅为备份,本文转载地址: http://www.cnblogs.com/liaolongjun/p/6080240.html 以下正文↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑…

javascript this用法小结
this是面向对象语言中的一个重要概念,在JAVA,C#等大型语言中,this固定指向运行时的当前对象。但是在javascript中,由于 javascript的动态性(解释执行,当然也有简单的预编译过程),this的指向在运…

在vc6控制台程序中如何调用运行ImageMagick命令行工具
在http://www.imagemagick.org/script/index.php网站下载相应的执行文件,这里以下载ImageMagick-6.6.5-10-Q16-windows-static.exe为例说明。 将ImageMagick-6.6.5-10-Q16-windows-static.exe下载后,安装,然后将其中需要的命令行工具考到你程…

高频数据交换下Flutter与ReactNative的对比
后端使用go写的socketio服务模拟期货行情数据,每10ms推送10条行情数据 ReactNative已经尽力优化了。 Flutter由于没flutter-socketio这个库不支持dart2.0以上的版本,所有用了安卓的socketio,通过事件与Flutter通讯。 1.内存占用 ReactNative …

6月技术福利限时免费领
《程序员大本营》6月刊来啦~更多福利限时免费领取:CSDN重磅技术大会精选视频以及200PPT;机器学习、知识图谱、计算机视觉、区块链等100技术公开课及PPT全奉送...识别海报二维码,邀请3位好友扫码助力,即可免费领取↓↓↓❤提示&…

我对bgwriter.c 与 guc 关系的初步理解
我用例子来说明:只是一个模拟,我自己做的 假的 bgwriter.c [rootlocalhost test]# cat bgwriter.c #include<stdio.h> #include<stdlib.h> #include<signal.h> #include "bgwriter.h" #include "guc.h" //some co…

媲美Pandas?一文入门Python的Datatable操作
作者 | Parul Pandey译者 | linstancy责编 | Jane出品 | Python大本营(id:pythonnews)【导读】工具包 datatable 的功能特征与 Pandas 非常类似,但更侧重于速度以及对大数据的支持。此外,datatable 还致力于实现更好的…

java并发编程——并发容器类介绍
2019独角兽企业重金招聘Python工程师标准>>> 并发容器的简单介绍 JDK5中添加了新的concurrent包,相对同步容器而言,并发容器通过一些机制改进了并发性能。因为同步容器将所有对容器状态的访问都串行化了,这样保证了线程的安全性&a…

CV_IMAGE_ELEM参数赋值时注意的问题
转自:http://hi.baidu.com/wangruiy01/blog/item/041ab03e8abd33c57d1e71a0.html CV_IMAGE_ELEM是一个宏, #define CV_IMAGE_ELEM( image, elemtype, row, col ) /(((elemtype*)((image)->imageData (image)->widthStep*(row)))[(col)])#define …

公司内部exchange2010 下删除误发邮件
1、Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E20102、get-mailbox | search-mailbox -SearchQuery 填写误发邮件标题 -TargetMailbox "administrator" -TargetFolder "SearchAndDeleteLog" -DeleteContent转载于:https://blog.51cto.com/wo…

从代码设计到应用开发,入坑深度学习看这本书就够了
深度学习(Deep Learning)是机器学习中一种基于对数据进行表征学习的方法。近年来,深度学习已经在科技界、工业界日益广泛地应用。随着全球各领域多样化数据的极速积累和计算资源的成熟化商业服务,深度学习已经成为人工智能领域最有…

小波矩特征提取matlab代码
这是我上研究生时写的小波矩特征提取代码: %新归一化方法小波矩特征提取---------------------------------------------------------- Fimread(a1.bmp);Fim2bw(F);Fimresize(F,[128 128]);%求取最上点for i1:128 for j1:128 if (F(i,j)1) yt…

hadoop生态搭建(3节点)-06.hbase配置
# http://archive.apache.org/dist/hbase/1.2.4/ # 安装 hbase tar -zxvf ~/hbase-1.2.4-bin.tar.gz -C /usr/local rm –r ~/hbase-1.2.4-bin.tar.gz # 配置环境变量# node1 node2 node3 vi /etc/profile# 在export PATH USER LOGNAME MAIL HOSTNAME HISTSIZE HISTCONTROL下添…

异类框架BigDL,TensorFlow的潜在杀器!
作者 | Nandita Dwivedi译者 | 风车云马责编 | Jane出品 | AI 科技大本营(id:rgznai100)【导读】你能利用现有的 Spark 集群构建深度学习模型吗?如何分析存储在 HDFS、Hive 和 HBase 中 tb 级的数据吗?企业想用深度学习…