转自:http://www.cppprog.com/2009/0426/108.html
本文简单介绍了CImg库中的三个大类:CImg,CImgList,CImgDisplay。然后给出了让CImg在HDC上绘图以及与HBITMAP互换的方法,为部署CImg到WindowsGUI程序中提供了基本支持。
上回介绍了CImg模板类的一些函数,象我这种不在图像处理行业混的人来说很多术语实在是太专业了-_-,不理不理,看不懂就直接写测试代码看它们的作用是什么不就知道啦~~嘿嘿^_^。
上测试代码先:
-
#include"CImg.h"
-
usingnamespacecimg_library;
-
-
intmain()
-
{
-
-
CImg<unsignedchar>src("test.bmp");
-
-
src.resize(src.width-src.width%4,src.height-src.height%4);
-
CImgList<unsignedchar>visu;
-
visu
-
<<src.get_crop(0,0,src.width/2,src.height/2)
-
<<src.get_quantize(5)
-
<<src.get_rotate(45,1)
-
<<src.get_permute_axes("yxzv")
-
<<src.get_erode(5)
-
<<src.get_haar()
-
<<src.get_dilate(3)
-
<<src.get_blur(3)
-
<<src.get_noise(3)
-
<<src.get_deriche(3)
-
<<src.get_blur_anisotropic(8)
-
<<src.get_blur_bilateral(1,2)
-
<<src.get_blur_patch(4,3)
-
<<src.get_sharpen(3)
-
<<src.get_blur_median(3)
-
;
-
-
-
CImgDisplaydisp(src.width*2,src.height);
-
inti=0;
-
unsignedchartextcolor[]={255,255,255};
-
while(!disp.is_closed&&!disp.is_keyQ&&!disp.is_keyESC)
-
{
-
i=i%visu.size;
-
charbuf[20];
-
::sprintf(buf,"img:%d",i);
-
-
-
disp.display(src<<(+visu[i]).draw_text(0,0,buf,textcolor)).wait();
-
-
if(disp.is_keyARROWDOWN)i++;
-
-
if(disp.is_keyARROWUP)
-
{
-
i--;
-
if(i<0)i=visu.size-1;
-
}
-
}
-
return0;
-
}
这个例子用到了CImg、CImgList、CImgDisplay三个类。
CImg类前面已有介绍。
CImgList是CImg的容器,用来保存一组CImg,主要方法有:
-
CImgList<T>&remove(constunsignedintpos)
-
CImgList<T>&pop_back()
-
CImgList<T>&pop_front()
-
CImgList<T>&push_back(constCImg<t>&img)
-
CImgList<T>&push_front(constCImg<t>&img)
-
CImgList<T>&insert(constCImg<t>&img,constunsignedintpos)
-
CImgList<T>&clear()
-
CImg<T>&operator[](constunsignedintpos)
上面这些是它作为容器的基本功能,同时它也重载了一些操作符以便于使用,比如本例中的"<<"操作其实就是push_back方法。另外,它还有大量的运算功能用于给容器中的图像批量运算。最后,还有一些好玩的方法不可错过:从视频中载入或把图像保存到视频中:
-
CImgList<T>&load_ffmpeg(constchar*constfilename,
-
constunsignedintfirst_frame=0,
-
constunsignedintlast_frame=~0U,
-
constunsignedintstep_frame=1,
-
constboolpixel_format=true,
-
constboolresume=false)
-
-
constCImgList<T>&save_ffmpeg(
-
constchar*constfilename,
-
constunsignedintfirst_frame=0,
-
constunsignedintlast_frame=~0U,
-
constunsignedintfps=25)
这两个方法要求链接ffmpeg库,如果没有这个库文件,还可以使用load_ffmpeg_external和save_ffmpeg_external方法调用已外部安装的ffmpeg程序编解码。
CImgDisplay类是一个窗口类,它主要用来显示CImg和CImgList。一般使用它的流程是:
- 新建CImgDisplay对象
- 设置它的大小,除直接输入宽高外也能用直接用CImg、CImgList或另一个CImgDisplay对象作为调整大小的依据。这时,CImgDisplay对象内部已经建立了一个窗口了。
- 使用display方法显示图像
- 使用wait方法等待事件发生(键盘、鼠标、超时等)
- 检查is_keyXXXX、is_closed、button、wheel等成员变量确定是什么事件,再决定我们该做什么操作。
- 如果需要,循环回第三步
- 析构时窗口收回。
在本例中,如果窗体关闭或按了Q键或按了ESC键则退出循环,程序结束。或者显示由原图和处理后的图组成的CImgList图像,如果按了上下方向键,则改变当前显示的处理图。
这是本例运行时的截图:
水墨画风格的《清明上河图》
CImg的图像处理方法绝不止上面例子中写的那么一点点,如果都写上去的话光运算就得等很长的时间,内存资源就更不用说了。所以建议大家一批批地写上去试验。或者可以修改一下代码,用逐次运算来试验效果。当然,如果你是图像处理领域的大牛,看方法名应试就知道是干啥的了,上面的代码就当熟悉一下CImg库吧。
在Windows里使用CImg
现在,我们已经可以使用CImg的现成方法做一些图像处理了。不过,有一个大问题需要解决,怎样把CImg的强大功能和我们的GUI程序相结合呢?我们总不能只使用CImgDisplay作为最终产品的显示界面吧?我们急需一个把CImg显示到指定HDC上的方法!
好在CImg库就一个头文件,所有的源代码都在这个头文件里。只要看一下它是怎么把CImg对象显示到CImgDisplay上的,我们就能依样画葫芦地把它显示到指定HDC上。
经过一番摸索,终于发现可以这样把一个CImg对象显示到HDC上:
-
template<classT>
-
voidDrawToHDC(HDCdc,constCImg<T>&src)
-
{
-
CImgDisplaydisp;
-
disp.assign(src,0,3,false,true);
-
disp.render(m_src);
-
SetDIBitsToDevice(dc,0,0,disp.width,disp.height,0,0,
-
0,disp.height,disp.data,&disp.bmi,DIB_RGB_COLORS);
-
}
CImgDisplay在显示过程中会填充bmi和data成员变量,而这两个变量正好是DIB数据,这段代码正好利用了这点。
但是它的运行效率实在是不怎样,经调试发现disp.assign方法会生成窗体、互斥量等东东,析构时又要删除它们,我们在这里根本用不着这些东西,浪费啊~~,于是不得不写一个新的画图方法了。
在说新版本的画图方法之前,得先说一下CImg库的另一个好功能:插件支持。只要在#include "CImg.h"之前
#define cimg_plugin "插件文件"
#define cimg_plugin1 "插件文件1"
#define cimg_plugin2 "插件文件2"
...
#define cimg_plugin8 "插件文件8"
CImg库就会把插件文件中的方法加入到CImg类中,看来起很酷,其实工作原理很简单,头文件中CImg类是这样定义的:
-
template<typenameT>
-
structCImg{
-
...
-
#ifdefcimg_plugin
-
#includecimg_plugin
-
#endif
-
#ifdefcimg_plugin1
-
#includecimg_plugin1
-
#endif
-
#ifdefcimg_plugin2
-
#includecimg_plugin2
-
#endif
-
#ifdefcimg_plugin3
-
#includecimg_plugin3
-
#endif
-
#ifdefcimg_plugin4
-
#includecimg_plugin4
-
#endif
-
#ifdefcimg_plugin5
-
#includecimg_plugin5
-
#endif
-
#ifdefcimg_plugin6
-
#includecimg_plugin6
-
#endif
-
#ifdefcimg_plugin7
-
#includecimg_plugin7
-
#endif
-
#ifdefcimg_plugin8
-
#includecimg_plugin8
-
#endif
-
...
-
}
当我们如下定义时
#define cimg_plugin "cimg4hdc.h"
cimg4hdc.h文件的内容就插入到了CImg类的定义中间。
我们现在就可以写一个插件文件为CImg类加入与Windows GUI交互的方法了,下面的代码是我写的插件文件,文件名为“cimg4hdc.h”,新加了五个方法:
-
HBITMAPto_bmp(HDCdc=0)const
-
CImg<T>&display(HDCdc,RECT&rc)
-
CImg(HBITMAPbmp)
-
CImg<T>&assign(HBITMAPbmp)
-
CImg<T>&load_bmp(HBITMAPbmp)
插件文件代码(点击下载,标准做法是右击,链接另存为...):
-
#ifndefcimg_plugin_cimg4hdc
-
#definecimg_plugin_cimg4hdc
-
-
HBITMAPto_bmp(HDCdc)const
-
{
-
CImgDisplaydisp;
-
disp.width=width;
-
disp.height=height;
-
disp.normalization=3;
-
disp.is_closed=true;
-
-
BITMAPINFObmi;
-
BITMAPINFOHEADER&bh=bmi.bmiHeader;
-
bh.biSize=sizeof(BITMAPINFOHEADER);
-
bh.biWidth=disp.width;
-
bh.biHeight=-(int)disp.height;
-
bh.biPlanes=1;
-
bh.biBitCount=32;
-
bh.biCompression=BI_RGB;
-
bh.biSizeImage=0;
-
bh.biXPelsPerMeter=1;
-
bh.biYPelsPerMeter=1;
-
bh.biClrUsed=0;
-
bh.biClrImportant=0;
-
void*pvBits;
-
-
HBITMAPbmp=CreateDIBSection(dc,
-
&bmi,
-
DIB_RGB_COLORS,
-
&pvBits,
-
NULL,0
-
);
-
if(bmp==NULL)returnbmp;
-
-
disp.bmi=bmi;
-
disp.data=(unsignedint*)pvBits;
-
disp.render(*this);
-
disp.width=disp.height=0;
-
disp.data=NULL;
-
returnbmp;
-
}
-
-
CImg<T>&display(HDCdc,RECT&rc)
-
{
-
CImgDisplaydisp;
-
-
disp.width=rc.right-rc.left;
-
disp.height=rc.bottom-rc.top;
-
disp.normalization=3;
-
disp.is_closed=true;
-
-
BITMAPINFOHEADER&bh=disp.bmi.bmiHeader;
-
bh.biSize=sizeof(BITMAPINFOHEADER);
-
bh.biWidth=disp.width;
-
bh.biHeight=-(int)disp.height;
-
bh.biPlanes=1;
-
bh.biBitCount=32;
-
bh.biCompression=BI_RGB;
-
bh.biSizeImage=0;
-
bh.biXPelsPerMeter=1;
-
bh.biYPelsPerMeter=1;
-
bh.biClrUsed=0;
-
bh.biClrImportant=0;
-
disp.data=newunsignedint[disp.width*disp.height];
-
-
disp.render(*this);
-
::SetDIBitsToDevice(dc,rc.left,rc.top,
-
disp.width,disp.height,0,0,
-
0,disp.height,disp.data,&disp.bmi,DIB_RGB_COLORS);
-
-
disp.width=disp.height=0;
-
delete[]disp.data;
-
-
return*this;
-
}
-
-
CImg(HBITMAPbmp)
-
:width(0),height(0),depth(0),dim(0),is_shared(false),data(0)
-
{
-
load_bmp(bmp);
-
}
-
-
CImg<T>&assign(HBITMAPbmp)
-
{
-
returnload_bmp(bmp);
-
}
-
-
CImg<T>&load_bmp(HBITMAPbmp)
-
{
-
BITMAPbmpobj;
-
if(!::GetObject(bmp,sizeof(bmpobj),&bmpobj)||bmpobj.bmBitsPixel<16)return*this;
-
-
LONGcbBuffer=bmpobj.bmWidthBytes*(bmpobj.bmHeight);
-
BYTE*lvbit=newBYTE[cbBuffer];
-
-
if(!::GetBitmapBits(bmp,cbBuffer,lvbit))
-
{
-
delete[]lvbit;
-
return*this;
-
}
-
-
unsignedchar*ptrs=lvbit;
-
intalign= (4 - bmpobj.bmWidthBytes%4)%4;
-
-
-
assign(bmpobj.bmWidth,bmpobj.bmHeight,1,3);
-
switch(bmpobj.bmBitsPixel){
-
case16:{
-
for(inty=height-1;y>=0;--y){cimg_forX(*this,x){
-
constunsignedcharc1=*(ptrs++),c2=*(ptrs++);
-
constunsignedshortcol=(unsignedshort)(c1|(c2<<8));
-
(*this)(x,y,2)=(T)(col&0x1F);
-
(*this)(x,y,1)=(T)((col>>5)&0x1F);
-
(*this)(x,y,0)=(T)((col>>10)&0x1F);
-
}ptrs+=align;}
-
}break;
-
case24:{
-
for(inty=height-1;y>=0;--y){cimg_forX(*this,x){
-
(*this)(x,y,2)=(T)*(ptrs++);
-
(*this)(x,y,1)=(T)*(ptrs++);
-
(*this)(x,y,0)=(T)*(ptrs++);
-
}ptrs+=align;}
-
}break;
-
case32:{
-
for(inty=height-1;y>=0;--y){cimg_forX(*this,x){
-
(*this)(x,y,2)=(T)*(ptrs++);
-
(*this)(x,y,1)=(T)*(ptrs++);
-
(*this)(x,y,0)=(T)*(ptrs++);
-
++ptrs;
-
}ptrs+=align;}
-
}break;
-
}
-
mirror('y');
-
-
delete[]lvbit;
-
return*this;
-
}
-
#endif
测试代码(在WTL里测试):
-
#definecimg_plugin"cimg4hdc.h"
-
#include"CImg.h"
-
usingnamespacecimg_library;
-
CImg<unsignedchar>m_show;
-
-
-
{
-
-
HDCdc=::CreateCompatibleDC(0);
-
HBITMAPbmp=::CreateCompatibleBitmap(::GetDC(0),100,100);
-
::SelectObject(dc,bmp);
-
::TextOut(dc,10,10,_T("HelloWorld"),11);
-
-
CImg<unsignedchar>src(bmp);
-
-
m_show=(src<<src.get_blur(2)).get_append('x');
-
-
::DeleteObject(bmp);
-
::DeleteDC(dc);
-
}
-
-
-
LRESULTOnPaint(UINT,WPARAM,LPARAM,BOOL&)
-
{
-
CPaintDCdc(m_hWnd);
-
RECTrc={
-
10,10,10+m_show.width,10+m_show.height
-
};
-
-
m_show.display(dc,rc);
-
return0;
-
}
效果如下:
分享到:
相关推荐
实验-三、数据库安全性(目的、要求和模板).doc
基于Docker搭建K8s集群离线包,包含部署时所需的全部文件,可在内网环境中使用,K8s为1.23.0版本,docker为20.10.9-3版本
基于springboot+vue实现的求职招聘类型网站源代码+数据库(优质毕设项目).zip个人经导师指导并认可通过的98分毕业设计项目,主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者。也可作为课程设计、期末大作业。包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 基于springboot+vue实现的求职招聘类型网站源代码+数据库(优质毕设项目).zip个人经导师指导并认可通过的98分毕业设计项目,主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者。也可作为课程设计、期末大作业。包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行! 基于springboot+vue实现的求职招聘类型网站源代码+数据库(优质毕设项目).zip个人经导师指导并认可通过的98分毕业设计项目,主要针对计算机相关专业的正在做毕设的学生和需要项目实战练习的学习者。也可作为课程设计、期末大作业。包含全部项目源码、该项目可以直接作为毕设使用。项目都经过严格调试,确保可以运行!基于springboot+vue实现的求
基于Android系统Api封装常用工具类.zip
svm 基于PCA(主成分分析)和SVM(支持向量机)的人脸识别是一种常见的方法。这里是一个简要说明: PCA(主成分分析): PCA是一种降维技术,它通过线性变换将高维数据转换为低维数据,同时保留最大的数据方差。 在人脸识别中,PCA被用来提取人脸图像中的主要特征,从而减少数据的维度,并保留最重要的信息。 SVM(支持向量机): SVM是一种监督学习算法,用于分类和回归分析。 在人脸识别中,SVM被用来构建一个分类器,以将提取的人脸特征映射到相应的人脸身份标签。 基于PCA和SVM的人脸识别流程: 训练阶段: 收集训练数据集,包括多个人的人脸图像和相应的标签。 对每个人脸图像应用PCA,将其转换为低维特征向量。 使用这些特征向量训练一个SVM分类器,使其能够将人脸特征向量与相应的人脸标签关联起来。 测试阶段: 对待识别的人脸图像应用相同的PCA转换,将其转换为与训练数据相同的低维特征向量。 使用训练好的SVM分类器,将待识别的人脸特征向量与已知的人脸标签进行比较,从而确定其身份。 优点: PCA可以有效地降低数据的维度,减少计算复杂度,并提取最相关的特征。 SVM在处理
PPT模板,答辩PPT模板,毕业答辩,学术汇报,母校模板,我给母校送模板作品,周会汇报,开题答辩,教育主题模板下载。PPT素材下载。
Java SE Development Kit 11.0.23 macOS x64 DMG Installer
【资源说明】【毕业设计】 1、该资源内项目代码都是经过测试运行成功,功能正常的情况下才上传的,请放心下载使用。 2、适用人群:主要针对计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、数学、电子信息等)的同学或企业员工下载使用,具有较高的学习借鉴价值。 3、不仅适合小白学习实战练习,也可作为大作业、课程设计、毕设项目、初期项目立项演示等,欢迎下载,互相学习,共同进步!
studyopencv2
实验五-使用matlab实现卷积的运算.pdf
2024年中国纸杯蛋糕盒行业研究报告
matplotlib绘图 通过 Matplotlib,开发者可以仅需要几行代码,便可以生成绘图、直方图、功率谱、条形图、错误图、散点图等。 Matplotlib基础知识 1.Matplotlib中的基本图表包括的元素 x轴和y轴 水平和垂直的轴线 x轴和y轴刻度 刻度标示坐标轴的分隔,包括最小刻度和最大刻度 x轴和y轴刻度标签 表示特定坐标轴的值 绘图区域 实际绘图的区域 2.hold属性 hold属性默认为True,允许在一幅图中绘制多个曲线;将hold属性修改为False,每一个plot都会覆盖前面的plot。 但是不推荐去动hold这个属性,这种做法(会有警告)。因此使用默认设置即可。 3.网格线 grid方法 使用grid方法为图添加网格线 设置grid参数(参数与plot函数相同) .lw代表linewidth,线的粗细 .alpha表示线的明暗程度 4.axis方法 如果axis方法没有任何参数,则返回当前坐标轴的上下限 5.xlim方法和ylim方法 除了plt.axis方法,还可以通过xlim,ylim方法设置坐标轴范围
高分设计源码,详情请查看资源内容中使用说明 高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明高分设计源码,详情请查看资源内容中使用说明
springboot框架 一、Spring Boot基础应用 Spring Boot特征 概念: 约定优于配置,简单来说就是你所期待的配置与约定的配置一致,那么就可以不做任何配置,约定不符合期待时才需要对约定进行替换配置。 特征: 1. SpringBoot Starter:他将常用的依赖分组进行了整合,将其合并到一个依赖中,这样就可以一次性添加到项目的Maven或Gradle构建中。 2,使编码变得简单,SpringBoot采用 JavaConfig的方式对Spring进行配置,并且提供了大量的注解,极大的提高了工作效率,比如@Configuration和@bean注解结合,基于@Configuration完成类扫描,基于@bean注解把返回值注入IOC容器。 3.自动配置:SpringBoot的自动配置特性利用了Spring对条件化配置的支持,合理地推测应用所需的bean并自动化配置他们。 4.使部署变得简单,SpringBoot内置了三种Servlet容器,Tomcat,Jetty,undertow.我们只需要一个Java的运行环境就可以跑SpringBoot的项目了
CUDA规约求和.cu
工程有限公司计算机信息系统数据信息安全管理办法.doc
小学教育信息化工作计划.doc
springboot停车位管理源码.rarspringboot停车位管理源码.rarspringboot停车位管理源码.rar
实验七-管道通信.doc
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明