创建基于opencv库的MFC多文档图像处理框架
来源:互联网 发布:软件工程项目管理 编辑:程序博客网 时间:2024/06/02 07:12
一、学习参考文件
1、《学习OpenCV》参考书,用OpenCV对图像进行基本的打开,保存等处理。
2、《MFC多文档中OpenCV处理图像打开和保存》,http://blog.csdn.net/abcjennifer/article/details/7313711
二、环境搭建
1、安装VS2013和OpenCV库
详细参见:http://blog.csdn.net/lvhao578041381/article/details/18951071
2、在第一次创建的过程出现了LPCTSTR与const char *不能相互转换的问题。而OpenCV库中的函数又都不是Unicode的,导致两种数据类型不能相互转换。解决办法:
项目->属性->配置属性->字符集->使用多字节字符集
3、在配置之后出现了另外一个问题:error MSB8031: Building an MFC project for a non-Unicode character set MFC在查询资料后才知道VS2013中把multi-byte character set 支持移除了,解决办法:
在微软上下载一个组件Multibyte MFC Library for Visual Studio 2013 安装完成后基本配置就成功了。
三、框架实现
1、搭建一个多文档的MFC框架,并按照一般的OpenCV处理程序修改各种目录
2、在工程中添加Processing.h头文件和Processing.cpp(将cvload读到的各种格式的图像创建为位图)
// Processing.h// 2010.8.23#pragma once#ifndefPROCESSING#definePROCESSING#include "stdafx.h"//---------------------------------------------------------LPBITMAPINFO CtreateMapInfo(IplImage* workImg,int flag); //创建位图 int imageType(IplImage* p); //返回图像类型int imageClone(IplImage* pi,IplImage** ppo); // 复制 IplImage 位图int imageReplace(IplImage* pi,IplImage** ppo); // 位图替换 //---------------------------------------------------------// 常规图像处理void Histog(BYTE *buf,int *pg,int Dx,int Dy);int BasicGlobalThreshold(int *pg,int start,int end);int NextColor(int start,int k,int step); // 下一彩色号extern RGBQUAD VgaDefPal[256];#endif //PROCESSING
/ Processing.cpp// 2010.8.23#include "stdafx.h"#include "Processing.h"//---------------------------------------------------------LPBITMAPINFO CtreateMapInfo(IplImage* workImg,int flag){ // 建立位图信息 BITMAPINFOHEADER BIH={40,1,1,1,8,0,0,0,0,0,0};LPBITMAPINFO lpBmi;int wid,hei,bits,colors,i;RGBQUAD ColorTab[256]; wid =workImg->width;hei =workImg->height;bits=workImg->depth*workImg->nChannels;if (bits>8) colors=0;else colors=1<<bits;lpBmi=(LPBITMAPINFO) malloc(40+4*colors);BIH.biWidth =wid;BIH.biHeight =hei;BIH.biBitCount=(BYTE) bits; memcpy(lpBmi,&BIH,40); // 复制位图信息头if (bits==8) { // 256 色位图if (flag==1) { // 设置灰阶调色板for (i=0;i<256;i++) {ColorTab[i].rgbRed=ColorTab[i].rgbGreen=ColorTab[i].rgbBlue=(BYTE) i;}memcpy(lpBmi->bmiColors,ColorTab,1024);}else if (flag==2) { // 设置默认调色板memcpy(lpBmi->bmiColors,VgaDefPal,1024);}}return(lpBmi);}int imageType(IplImage* p) { int i,j,k,bpl,n,pg[256];BYTE *buf; k=p->nChannels;if (k==1) { // 检查二值图像 for (i=0;i<256;i++) pg[i]=0;buf=(BYTE*)p->imageData;bpl=p->widthStep; for (i=0;i<p->height;i++) {for (j=0;j<p->width;j++) pg[buf[j]]++;buf+=bpl;} for (i=0,n=0;i<256;i++) {if (pg[i]) n++;} if (n==2) k=-1; // 二值图像 } return(k);}int imageClone(IplImage* pi,IplImage** ppo) // 复制 IplImage 位图{if (*ppo) {cvReleaseImage(ppo); // 释放原来位图} (*ppo) = cvCloneImage(pi); // 复制新位图return(1);}int imageReplace(IplImage* pi,IplImage** ppo) // 位图替换{if (*ppo) cvReleaseImage(ppo); // 释放原来位图 (*ppo) = pi; // 位图换名return(1);}//---------------------------------------------------------// VGA 256色默认调色板数据(省略)//---------------------------------------------------------// 常规图像处理(省略)
3、修改**Doc.h和**Doc.cpp文档
Doc..h文件
// 生成的消息映射函数protected:DECLARE_MESSAGE_MAP()public:IplImage* pImg;//图像指针int m_Display;BOOL Load(IplImage** pp,LPCTSTR csFilename);//读入图片BOOL Save(LPCTSTR csFilename, IplImage* pImg);//保存图片BOOL OnOpenDocument(LPCTSTR lpszPathName);//打开文档#ifdef SHARED_HANDLERS
Doc..cpp文件
// CdemoDoc 构造/析构CdemoDoc::CdemoDoc():pImg(NULL),m_Display(0)<pre name="code" class="cpp">// CdemoDoc 命令BOOL CdemoDoc::Load(IplImage** pp, LPCTSTR csFilename){IplImage* pImg = NULL;pImg = cvLoadImage(csFilename, -1); // 读图像文件(DSCV) if (!pImg) return(false);cvFlip(pImg); // 将图像进行翻转,与 DIB 像素结构一致 if (*pp) {cvReleaseImage(pp);//若pp指针已有值,则先将其内存释放,在进行载入}(*pp) = pImg;m_Display = 0;return(true);}BOOL CdemoDoc::Save(LPCTSTR csFilename, IplImage* pImg){int bl;cvFlip(pImg); // 恢复原 OpenCV 位图结构 bl = cvSaveImage(csFilename, pImg); // 图像存盘 return(bl);}BOOL CdemoDoc::OnOpenDocument(LPCTSTR lpszPathName){if (!CDocument::OnOpenDocument(lpszPathName)) return false;Load(&pImg, lpszPathName);if (pImg) return true;return false;}
{// TODO: 在此添加一次性构造代码}4、修改**view.h和**view.cpp文档
view.h文档
// 实现public:virtual ~CdemoView();#ifdef _DEBUGvirtual void AssertValid() const;virtual void Dump(CDumpContext& dc) const;#endifprotected:IplImage* saveImg;IplImage* workImg;LPBITMAPINFO m_lpBmi;int m_CaptFlag;int m_dibFlag;int m_SaveFlag;int m_ImageType;// 生成的消息映射函数protected:afx_msg void OnFilePrintPreview();afx_msg void OnRButtonUp(UINT nFlags, CPoint point);afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);DECLARE_MESSAGE_MAP()public:virtual void OnInitialUpdate();afx_msg void OnSize(UINT nType, int cx, int cy);afx_msg void OnFileSaveAs();afx_msg void OnColorImageRefresh(); afx_msg void OnRefresh();afx_msg void OnConservationImage();afx_msg void OnUpdateRefresh(CCmdUI *pCmdUI);afx_msg void OnColorImageRefrsh();};#ifndef _DEBUG // demoView.cpp 中的调试版本inline CdemoDoc* CdemoView::GetDocument() const { return reinterpret_cast<CdemoDoc*>(m_pDocument); }#endifview.cpp文档
对于菜单栏,可惜删除不必要的按钮,然后按照自己的需要添加相应的按钮。此处主要是搭建基于OpenCV库的MFC框架,后续图像处理算法还在添加。对于
IMPLEMENT_DYNCREATE(CdemoView, CScrollView)BEGIN_MESSAGE_MAP(CdemoView, CScrollView)// 标准打印命令ON_COMMAND(ID_FILE_PRINT, &CScrollView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_DIRECT, &CScrollView::OnFilePrint)ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CdemoView::OnFilePrintPreview)ON_WM_CONTEXTMENU()ON_WM_RBUTTONUP()ON_COMMAND(ID_FILE_SAVE_AS, &CdemoView::OnFileSaveAs) //图像另存的事件ON_COMMAND(ID_REFRESH, &CdemoView::OnRefresh) //恢复图像的事件ON_COMMAND(ID_CONSERVATION_IMAGE, &CdemoView::OnConservationImage) //保存当前位图的事件ON_UPDATE_COMMAND_UI(ID_REFRESH, &CdemoView::OnUpdateRefresh)ON_COMMAND(ID_COLOR_IMAGE_REFRSH, &CdemoView::OnColorImageRefrsh) //恢复原始图像的事件END_MESSAGE_MAP()// CdemoView 构造/析构CFile fCapture;CFileException eCapture;char pbuf[20];int captSetFlag = 0;CdemoView::CdemoView(){// TODO: 在此处添加构造代码saveImg = NULL;workImg = NULL;m_lpBmi = 0;m_CaptFlag = 0;m_dibFlag = 0;m_ImageType = 0;CSize sizeTotal;sizeTotal.cx = sizeTotal.cy = 100;SetScrollSizes(MM_TEXT, sizeTotal);}CdemoView::~CdemoView(){if (saveImg)cvReleaseImage(&saveImg); // 释放位图 if (workImg)cvReleaseImage(&workImg);if (m_lpBmi)free(m_lpBmi); // 释放位图信息 }BOOL CdemoView::PreCreateWindow(CREATESTRUCT& cs){// TODO: 在此处通过修改// CREATESTRUCT cs 来修改窗口类或样式return CScrollView::PreCreateWindow(cs);}// CdemoView 绘制void CdemoView::OnDraw(CDC* pDC){CdemoDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);if (!pDoc)return;// TODO: 在此处为本机数据添加绘制代码/*if (pDoc->pImg){if (pDoc->m_Display == 0){saveImg = cvCloneImage(pDoc->pImg);//要保存的图片workImg = cvCloneImage(pDoc->pImg);//处理的图像//cvShowImage("test", saveImg);m_ImageType = workImg->ID;}}*/if (pDoc->pImg){if (pDoc->m_Display == 0){imageClone(pDoc->pImg, &saveImg);m_dibFlag = imageClone(saveImg, &workImg);m_ImageType = imageType(workImg);m_SaveFlag = m_ImageType;pDoc->m_Display = 1;}}if (m_dibFlag) { // DIB 结构改变 if (m_lpBmi)free(m_lpBmi);m_lpBmi = CtreateMapInfo(workImg, m_dibFlag);m_dibFlag = 0;CSize sizeTotal;sizeTotal = CSize(workImg->width, workImg->height);SetScrollSizes(MM_TEXT, sizeTotal);}char* pBits=NULL;if (workImg)pBits = workImg->imageData;if (workImg)StretchDIBits(pDC->m_hDC,0, 0, workImg->width, workImg->height,0, 0, workImg->width, workImg->height,pBits, m_lpBmi, DIB_RGB_COLORS, SRCCOPY);}// CdemoView 打印void CdemoView::OnFilePrintPreview(){#ifndef SHARED_HANDLERSAFXPrintPreview(this);#endif}BOOL CdemoView::OnPreparePrinting(CPrintInfo* pInfo){// 默认准备return DoPreparePrinting(pInfo);}void CdemoView::OnBeginPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/){// TODO: 添加额外的打印前进行的初始化过程}void CdemoView::OnEndPrinting(CDC* /*pDC*/, CPrintInfo* /*pInfo*/){// TODO: 添加打印后进行的清理过程}void CdemoView::OnRButtonUp(UINT /* nFlags */, CPoint point){ClientToScreen(&point);OnContextMenu(this, point);}void CdemoView::OnContextMenu(CWnd* /* pWnd */, CPoint point){#ifndef SHARED_HANDLERStheApp.GetContextMenuManager()->ShowPopupMenu(IDR_POPUP_EDIT, point.x, point.y, this, TRUE);#endif}// CdemoView 诊断#ifdef _DEBUGvoid CdemoView::AssertValid() const{CScrollView::AssertValid();}void CdemoView::Dump(CDumpContext& dc) const{CScrollView::Dump(dc);}CdemoDoc* CdemoView::GetDocument() const // 非调试版本是内联的{ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CdemoDoc)));return (CdemoDoc*)m_pDocument;}#endif //_DEBUG// CdemoView 消息处理程序void CdemoView::OnInitialUpdate(){CScrollView::OnInitialUpdate();CSize sizeTotal;// TODO: calculate the total size of this view sizeTotal.cx = sizeTotal.cy = 100;SetScrollSizes(MM_TEXT, sizeTotal);}void CdemoView::OnSize(UINT nType, int cx, int cy){CScrollView::OnSize(nType, cx, cy);if (workImg) { // 刷新窗口画面 CSize sizeTotal;sizeTotal = CSize(workImg->width, workImg->height);SetScrollSizes(MM_TEXT, sizeTotal); // 设置滚动条 }}void CdemoView::OnFileSaveAs(){CString csBMP = "BMP Files(*.BMP)|*.BMP|";CString csJPG = "JPEG Files(*.JPG)|*.JPG|";CString csTIF = "TIF Files(*.TIF)|*.TIF|";CString csPNG = "PNG Files(*.PNG)|*.PNG|";CString csDIB = "DIB Files(*.DIB)|*.DIB|";CString csPBM = "PBM Files(*.PBM)|*.PBM|";CString csPGM = "PGM Files(*.PGM)|*.PGM|";CString csPPM = "PPM Files(*.PPM)|*.PPM|";CString csSR = "SR Files(*.SR) |*.SR|";CString csRAS = "RAS Files(*.RAS)|*.RAS||";CString csFilter = csBMP + csJPG + csTIF + csPNG + csDIB+ csPBM + csPGM + csPPM + csSR + csRAS;CString name[] = { "", "bmp", "jpg", "tif", "png", "dib","pbm", "pgm", "ppm", "sr", "ras", "" };CString strFileName;CString strExtension;CFileDialog FileDlg(false, NULL, NULL, OFN_HIDEREADONLY, csFilter);// 文件存盘对话框 if (FileDlg.DoModal() == IDOK) { // 选择了文件名 strFileName = FileDlg.m_ofn.lpstrFile;if (FileDlg.m_ofn.nFileExtension == 0) { // 无文件后缀 strExtension = name[FileDlg.m_ofn.nFilterIndex];strFileName = strFileName + '.' + strExtension;// 加文件后缀 }CdemoDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);pDoc->Save(strFileName, workImg); // 当前画面存盘 }}void CdemoView::OnColorImageRefresh(){CdemoDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);pDoc->m_Display = 0;Invalidate();}void CdemoView::OnRefresh(){// TODO: 在此添加命令处理程序代码m_dibFlag = imageClone(saveImg, &workImg);m_ImageType = m_SaveFlag;Invalidate();}void CdemoView::OnUpdateRefresh(CCmdUI *pCmdUI){// TODO: 在此添加命令更新用户界面处理程序代码pCmdUI->Enable((m_CaptFlag != 1) && (m_ImageType != -3));}void CdemoView::OnConservationImage(){// TODO: 在此添加命令处理程序代码imageClone(workImg, &saveImg);m_SaveFlag = m_ImageType;}void CdemoView::OnColorImageRefrsh(){// TODO: 在此添加命令处理程序代码CdemoDoc* pDoc = GetDocument();ASSERT_VALID(pDoc);pDoc->m_Display = 0;Invalidate();}
通过上述几个步骤,先添加processing.h和processing.cpp文件,里面包含对图像进行位图转换的函数,然后修改Doc和View文件,在Doc进行文件打开和图像读取的操作,在View进行图像的相关操作。
- 创建基于opencv库的MFC多文档图像处理框架
- MFC多文档中opencv处理图像打开、保存
- 基于MFC和OpenCV的图像处理小软件
- VS2010+MFC+OpenCv处理图像的配置
- 基于MFC和OpenCV的图像处理小软件(续)
- openCV基于图像处理的自动聚焦
- 基于OpenCV的CT图像处理
- 基于OpenCV的图像形态学处理
- 基于opencv的图像去雾处理
- 基于opencv的Python图像处理
- MFC多文档模板手动创建框架的一个问题
- MFC多文档视图界面(MDI)搭建图像处理框架程序总结
- 创建基于opencv处理功能的动态链接库
- 基于MFC的OpenCV显示文件夹内图像
- 基于MFC的OpenCV图像显示并标定ROI区域
- 基于MFC和OpenCV的图像标注工具
- 创建MFC应用程序的类型:单文档+多文档+基于对话框
- OpenCV 利用MFC的Picture控件显示和处理图像
- IIS7.5 上配置FTP站点
- linux用户管理(2)----修改用户模式(usermod,sudo权限等)
- 多进程 多线程
- LSP (Liskov Substitution Principle)
- 像素和厘米互相转换
- 创建基于opencv库的MFC多文档图像处理框架
- iOS 键值观察(KVO)简述及实例理解
- Saving Data
- Android_study01
- 【C 基础】常见的str-函数
- eclipse中创建maven工程
- 内存映射文件
- /dev/mem
- Are you using SQL's Missing Index DMVs?