OpenCV与MFC通用型图像处理开发实践

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)

添加遥感影像处理

时间: 2024-10-11 08:11:46

OpenCV与MFC通用型图像处理开发实践的相关文章

OpenCV与MFC实战之图像处理 样本采集小工具制作 c++MFC课程设计

原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/12111102.html 入门不久的人可以通过opencv实战来锻炼一下学习opencv的成果,百度云链接: 链接:https://pan.baidu.com/s/1jGOD97Zx96ZDAvlkQtaPYQ 提取码:afip 运行环境VS2017,需要配置库为:opencv 题目:样本采集小工具 需求: 用MFC和opencv完成样本采集小工具. 界面功能 1.选中原图片集的目录. 2.选

基于Opencv和Mfc的图像处理增强库GOCVHelper(索引)

GOCVHelper(GreenOpen Computer Version Helper )是我在这几年编写图像处理程序的过程中积累下来的函数库.主要是对Opencv的适当扩展和在实现Mfc程序时候的功能增强. 这里将算法库开放源代码,并且编写一系列blog对函数实现进行说明.目的是在于“取之于互联网,用之于互联网”.并且也希望该库能够继续发展下去. 由于算法库基于Opencv和Mfc进行编写,所以要求阅读使用者具备一定基础. 最终提交的是GOCVHelper.h 和GOCVHelper版本号.

lua游戏开发实践指南学习笔记1

本文是根据lua游戏开发实践指南做的一些学习笔记,仅用于继续自己学习的一些知识. Lua基础 1.  语言定义: 在lua语言中,标识符有很大的灵活性(变量和函数名),不过用户不呢个以数字作为起始符,也要避免下划线(_)接大写字母,因为这种格式为lua自身保留如_Start. 建议用户使用如下格式和命名规则来定义变量.常量和函数名: ①  常量用全大写和下划线,例如:MY_CONSTANT ②  变量第一个字母小写,例如:myVariable ③  全角变量第一个字母用小写g表示,例如:gMyG

使用ADO实现BLOB数据的存取 -- ADO开发实践之二

使用ADO实现BLOB数据的存取 -- ADO开发实践之二 http://www.360doc.com/content/11/0113/16/4780948_86256633.shtml 一.前言 在上一篇文章<>中我们详细介绍了ADO基本的操作方法,在实际的开发过程中我们常常需要存储较大的二进制数据对象,比如:图像.音频文件.或其它二进制数据,这些数据我们称之为二进制大对象BLOB(Binary Large Object),其存取的方式与普通数据有所区别.本文将介绍利用ADO在数据库中存取B

Android开发实践:利用ProGuard进行代码混淆

由于Android的代码大都是Java代码,所以挺容易被反编译的,好在Android ADT为我们集成了混淆代码的工具,一来可以混淆我们的代码,让程序被反编译后基本看不懂,另外还能起到代码优化的作用.发布项目前,建议打开Android的代码混淆功能. Android ADT主要通过ProGuard工具来提供代码混淆,网上也有挺多博客文章讲这个的,但感觉很多都介绍得太过于复杂,这里我就以问答的方式来更加简洁地介绍下ProGuard吧. 1. ProGuard是什么 ProGuard是一个工具,用来

Android软件安全开发实践(下)

Android开发是当前最火的话题之一,但很少有人讨论这个领域的安全问题.本系列将分两期,探讨Android开发中常见的安全隐患和解决方案.第一期将从数据存储.网络通信.密码和认证策略这三个角度,带你走上Android软件安全开发实践之旅. 过去两年,研究人员已发现Android上的流行软件普遍存在安全缺陷或安全漏洞.漏洞频发的原因可能有很多,例如以下几种. 与一切都是集中管理的iOS相比,Android提供了一种开放的环境,在获得了灵活性.可以满足各种定制需求的同时,也损失了部分安全性. 开发

vue 2.0 开发实践总结之疑难篇

续上一篇文章:http://www.cnblogs.com/beidan/p/6129891.html ,如果没有看过的可以移步看一下. 本篇文章目录如下: 1.  vue 组件的说明和使用 2.  vuex在实际开发中的使用 3.  开发实践总结 1.  vue 组件的说明和使用 一个组件实质上是一个拥有预定义选项的一个 Vue 实例 在header组件内部允许外部使用,需要导出属性,有2种导出方法 1.  默认导出(不用命名) 1 export default { 2 data () { 3

《JavaScript设计模式与开发实践》读书笔记之观察者模式

1.<JavaScript设计模式与开发实践>读书笔记之观察者模式 观察者模式定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都将得到通知. JavaScript中通常采用事件模型替代传统的观察者模式 1.1 逐步实现观察者模式 以客户看房为例 首先指定谁充当发布者,如售楼处 然后给发布者添加一个缓存列表,用于存放回调函数以便通知订阅者.这里为了让订阅者只接收自己感兴趣的消息,增加一个标识key 最后发布消息时候,发布者遍历缓存列表,依次触发里面存放的订阅者的回

JavaScript 设计模式与开发实践读书笔记 http://www.open-open.com/lib/view/open1469154727495.html

JavaScript 设计模式与开发实践读书笔记 最近利用碎片时间在 Kindle 上面阅读<JavaScript 设计模式与开发实践读书>这本书,刚开始阅读前两章内容,和大家分享下我觉得可以在项目中用的上的一些笔记. 我的 github 项目会不定时更新,有需要的同学可以移步到我的 github 中去查看源码: https://github.com/lichenbuliren/design-mode-notes 1.currying 函数柯里化 currying 又称 部分求值 .一个 cu