创建基于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、在第一次创建的过程出现了LPCTSTRconst 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); }#endif
view.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进行图像的相关操作。




0 0
原创粉丝点击