imagehandler
该程序的起源说来话长,它起源自上课的一次作业,后来又由于接触了OpenCV这个开源库,我就试图将OpenCV和MFC搓到一块,毕竟微软近来在界面上也下了狠功夫,尤其是Windows 7大获成功,而WP7.5和Windows 8跃跃欲试。结合Windows桌面也不失为一个有益的尝试。
关于imagehandler
本程序是在 MFC 中使用 OpenCV 处理图像的演示程序,由2部分组成。
背景知识:
OpenCV是Intel?开源计算机视觉库。它由一系列 C 函数和少量 C++ 类构成,实现了图像处理和计算机视觉方面的很多通用算法。现在OpenCV已经发布了2.3.1版本,也就是本程序使用的版本。
本程序使用Visual Studio 2010开发环境在Windows 7 SP1 上开发完成,并采用了Microsoft 最新的Ribbon UI,界面友好,使用简便。
一、Windows 下用 MFC(Ribbon 界面) 编制的程序框架
采用设备无关位图DIB实现Windows多文档模式下图像的显示,实现显示的关键函数StretchDIBits的原型如下:
int StretchDIBits(
HDC hdc, // 显示设备句柄
int XDest, // 目标矩形区域左上角X坐标
int YDest, // 目标矩形区域左上角Y坐标
int nDestWidth, // 目标矩形区域宽度
int nDestHeight, // 目标矩形区域高度
int XSrc, // 源矩形区域左上角X坐标
int YSrc, // 源矩形区域左上角Y坐标
int nSrcWidth, // 源矩形区域宽度
int nSrcHeight, // 源矩形区域高度
CONST VOID *lpBits, // 位图的像素存放首地址
CONST BITMAPINFO *lpBitsInfo, // 位图信息存放地址
UINT iUsage, // 位图中的颜色类型,RGB模式用DIB_RGB_COLORS
DWORD dwRop // 像素操作码,简单复制用SRCCOPY
);
由于OpenCV中的位图结构中的像素数据与DIB中的像素具有相同的存储结构,见表1中的像素部分。所以,只要为它构造一个DIB的位图信息就可以调用API函数StretchDIBits实现它的显示了。
表1 DIB位图参数与IplImage结构参数
参 数 |
DIB (MFC) |
Mat (OpenCV) |
宽 度 |
biWidth |
Mat::cols |
高 度 |
biHeight |
Mat::rows |
像素位数 |
biBitCount (1,4,8,16,24,32) = elemSize1*nChannels*8 |
Mat::elemSize1() |
通道数 |
--- |
Mat::channels () |
(单通道位图) 调色板单元数 |
2biBitCount (2, 16, 256) |
二值图像显示为灰阶图像 256色彩色图像显示为真彩色图像 |
位图坐标原点 |
底-左 |
origin (0 顶-左,1 底-左) |
像素分量存放方式 |
交叉存取 (按像素为单位存放) |
0 交叉存取,1 位平面方式 |
对齐方式 (行像素数据凑整) |
4字节对齐 |
8字节对齐 |
每行字节数 |
(biWidth*biBitCount+31)/32*4 |
Mat::step |
像素字节数 |
((biWidth*biBitCount+31)/32*4)* biHeight |
---- |
像素存放地址 |
BYTE* pBits |
uchar*Mat::data |
感兴趣区域 |
--- |
roi |
表中正体字母部分表示相同的参数,粗体字母表示参数部分相同时的交集,斜体加下划线表示结构特有的参数。
位图的宽度、高度、像素存放首地址、每行字节数、像素总字节数等5个参数在两种结构中相同。
像素位数、通道数、坐标原点位置、像素分量存放方式、对齐方式等5个参数在两种结构中部分相同,使用时可以取其交集,表中用粗体字表示。
有2个参数是两种位图各自独有的,感兴趣区域为Mat类所独有,调色板单元为DIB所独有。
从表1中可以看出,除了高精度图像(位深度16,32,64)外,这两种位图结构在图像处理的绝大部分应用中可以通用。
从以上比较中也可看出,Mat类适用于高精度处理,并且可以限制处理的区域;而DIB适用于Windows图形操作,并且可以存储低位数图像文件,如每像素一位的二值图像与像素8位的索引图像等。
二、调用 OpenCV 函数实现处理
使用 OpenCV 函数处理图像在 MFC 环境下显示,实现功能为图像平移、图像翻转与镜像。
主要内容
下面列出stdafx.h尾部集中的几个头文件,程序结构由此可见一斑。
#include "imagehandler.h" // 窗口管理
#include "opencv2/core/core.h" // OpenCV 头文件
#include " opencv2/highgui/highgui.h" //OpenCV自带界面
#include "opencv2/imgproc/imgproc.h" //图像处理函数库,本来可以用上的但是
//功能没有写完
imagehandler的菜单结构
程序分为主功能和几何变换2部分,程序的菜单结构见表2,其中列出了演示程序的大多数功能。
表2 imagehandler菜单结构
main |
几何变换 |
打开 |
翻转 |
保存 |
镜像 |
平移 |
程序结构
程序采用VC++多文档结构,图像的存放与处理则采用OpenCV的结构与函数,图像的显示采用位图信息m_lpBmi实现,为了便于管理对m_lpBmi的操作集中在OnDraw程序中。待显示位图结构发生改变时用m_dibFlag标志激发m_lpBmi的刷新。除了文件结构与图像显示外,其余部分基本上是OpenCV程序。
主要功能区为mfcvProcess
CimagehandlerView
CimagehandlerDoc
mfcvProcess的基本功能
1实现读入图像写入到Mat中,
2 使用DIB在文档视图中显示,
3 进行几何变换,
4 进行裁剪,图像拼接操作,
5 将修改的数据保存到Mat 格式中,
6 将Mat写入到图像数据中并保存。
算法实现:
话说图像
BMP取自位图BitMap的缩写,也称为DIB(与设备无关的位图)是微软视窗图形子系统(GDI)内部使用的一种位图图形格式,它是微软视窗平台上的一个简单的图形文件格式。的图形文件格式。
位图像素宽度必须是4的倍数……
图像可以分解成多个通道存放在一个二维矩阵中,
Mat即矩阵的简称,它是OpenCV中一个基础的矩阵结构。在CV(computer vision)中,图像就是一个二维的矩阵,Mat的责任就是将图像数据读入到内存块中,并将图像每一个通道的数据通过特殊的数据结构进行表达。通常这些结构的原子就是简单的数字(usigned、double、int、float等)或是无符号的字符(usigned char)。一些常用的函数:
at模板函数,ptr模板函数,create函数,channels函数(获取图像通道数)。。。
图像显示
由于bmp要求图像单行所占字节数必须是4的倍数我于是在显示时都通过OpenCV处理成4的倍数在显示,但实际处理的图像始终按原来大小进行操作。
图像几何变换
概念:建立一种元图像像素与变换后的的图像像素之间的映射关系。
公式如下:(x、y表示输出图像像素坐标,x0,y0表示输入图像像素的坐标
;
采用统一的矩阵表示法:
向前映射 入射→输出
浮点数坐标(放大缩小),映射不完全和映射重叠(向后映射:输出图像的像素坐标来确定输入图像像素坐标)
图像放大缩小问题
第一位,确定所处理的对象是一个什么结构,在这里我使用了OpenCV中的C++接口,使用了微软的MFC程序框架,只有这两个东西可以提供数据结构容器,否则就只有用C++的标准函数(fopen)和数组(向量(vector.h))了。为了简化后续应用算法,这里采用OpenCV的矩阵结构Mat。这是一个以矩阵形式存储图像数据或矩阵的C++类。
其次要决定的是采用什么样的算法对图像进行处理。通常图像放大有:最近邻法、双线性插值法、二次卷积插值法、三次卷积插值法等。
图像的旋转
仍然采用向后映射,旋转的同时注意改变图像的大小和图像对齐的问题
图像平移
应用向后映射原理,通过目标图像象素点坐标计算出该点在原图中的坐标,如果坐标值存在,复制数据,否则什么也不干。因为在此之前,我已经缓存图像的所有像素都赋值了。
设 (x0,y0)为原图像上一点,图像水平平移量为tx,垂直平移量为ty,平移后的点为(x1,y1) x1=x0+tx;y1=y0+ty,转换后x0=x1-tx;y0=y1-ty这样平移后的图像上的每一点都可以在原图像中找到对应的点,可以根据x0和y0的值,判断原来的点是否在图像中,如果超出了原来图像的范围,就把点(x1,y1)的值设置成0(黑色)或255(白色)如果希望保留原图所有像素,则根据平移量增加相应的象素点即可。
参考文献:
算法学习:
[1] 左飞.万晋森.刘航 Visual C++数字图像处理开发入门与编程实践[M]. 北京:电子工业出版社, 2008
[2] [Laganière 2011] Robert Laganière Overview of OpenCV 2 Computer VisionApplication Programming Cookbook,Birmingham(UK):Packt Publishing Ltd;2011
OpenCV学习
[3] (美)布拉德斯基(Bradski G)(美)克勒(keahler,A).学习OpenCV[M] 于士祺 刘瑞祯译. 北京:清华大学出版社2009
[4] OpenCV Reference ,US,2011
其他:
百度空间,新浪博客,网易博客,CSDN以及Stackoverflow,Guru,CodeProject等社区。
目前的工作结果:
计划中的工作:(有兴趣的筒子可以一起学习QQ:547792075)
添加遥感影像处理