Make your own MFC MDI OPENCV program Framework

Source: Internet
Author: User

PS: I recorded this process, both a learning process, but also want to share to everyone. Because it is an attempt, there may be errors in the middle. I try to write it down. And I make as far as possible every step can be run, easy to test. To put it simply, I want to learn digital image processing with VC6.0 and open CV 1.0, and write my own complete program. If you use the open CV directly, it looks less intuitive and unprofessional. "Using OpenCV in MFC" should be the best learning materials and routines, but I am neither familiar with VC, nor familiar with open CV, the difficulty of entry is relatively large, here to my study and analysis of the process, experience and results to share to everyone, I hope to help you.

First, the environment

1, VC6.0

2, OPENCV 1.0

3, adapted from the "use of OpenCV in MFC", from:

Http://wiki.opencv.org.cn/index.php/%E5%9C%A8MFC%E4%B8%AD%E4%BD%BF%E7%94%A8OpenCV

4, VC2010 OPENCV2.4.9 environment under the establishment process is basically the same, only a little change. (VC2013 below if use 2010 this project, first it will automatically upgrade, then compile fails, need to download a multibyte MFC Library for Visual Studio 2013, connect as)

About vc2013 directly set up the project, because the project is the default Unicode, so if not set into multibyte mode, there is a serious problem: OpenCV many of the functions of the file operation is not Unicode, and LPCTSTR to the const char *  Such conversions are cumbersome (and can of course be done with functions like widechartomultibyte), so if you use vc2013, you should not use Unicode, and the rest of the vc2010 is the same.  

Note: This primitive program is estimated to have changed the class name, but some of the message map's things have not changed, resulting in a failure to process some classes in the Class Wizard. I have fixed this error.

The annex will provide: "Using OpenCV in MFC" original program and documentation, VC6.0 OPENCV1.0 version, VC2010 OPENCV2.4.9 version 3 kind of East, is expected to be placed in the CSDN download channel. However, this blog does not know why it is in the audit status, and so on after the lifting of the upload.

Ii. references

1, "Use Opencv.doc in MFC", the above article and the program works. These things are finally available to everyone, you may need to study carefully.

2, "MFC Multi-document OPENCV processing image Open, save", from:

http://blog.csdn.net/abcjennifer/article/details/7313711

This mm blog is good ah, we can seriously study.

Third, new MFC. EXE project MYCV (this project deliberately took a new name, and the original program is not the same.) ), MDI, note the final step of the wizard our view class Cmycvview base class should choose CScrollView, because we do image processing do not want to zoom in the display, it needs to be displayed as is, so the scrollbar is necessary.

Iv. adding OpenCV and DirectShow-related stuff

1, to add to the project OpenCV several libraries

Cxcore.lib cv.lib ml.lib cvaux.libhighgui.lib cvcam.lib

2. Copy CameraDS.h, CameraDS.cpp, corresponding header files and directory DirectShow to your project

3. Additional Include Directories

Project->settings->settings for: (All configurations)->c/c++->category (preprocessor)

->additional include Directories is set to: /directshow/include

4, Additional Library directories

Project->settings->settings for: (allconfigurations)->link->category (Input)

->additional Library Directories is set to: /directshow/lib

Ps:2, 3, 43 points in the CameraDSA.cpp, note that the above Green section and the directory structure.

4, Tools->option in the Lib file to the Lib folder of the routine to the top of the head

The routines contain strmiid.lib that contain these external symbols, and the Windows System SDK also contains Strmiid.lib, which takes precedence over DirectShow, otherwise it is not compiled. See:

http://blog.csdn.net/makenothing/article/details/8750703

5. Copy Processing.cpp and Processing.h to your project

The idea of this program is this: the graphics processing itself uses OPENCV, and the display results use Windows ' own way. Because of the different storage formats, some conversions are required. Another way to implement MFC is to use the Cvvimage class, which we don't use here.

The module adds 4 functions, namely Ctreatemapinfo, ImageType, Imageclone, and Imagereplace. The Ctreatemapinfo function is used to establish bitmap information m_lpbmi for work bitmap workimg, which is characterized by the ability to set two color palettes for single-channel bitmaps, the black and white grayscale palette and the VGA default palette. Because the binary image is displayed as a grayscale image in OpenCV, the ImageType function can recognize a two-value bitmap from a single-channel bitmap. The Imageclone and Imagereplace functions use the OPENCV function to replicate the bitmap, automatically releasing the storage unit pointed to by the old pointer to prevent a memory leak, and returning the M_DIBFLAG flag that can be used to fire the bitmap information for the refresh work bitmap workimg m_ Lpbmi. Imagereplace is similar to Imageclone, but does not create a new bitmap, only replaces the output bitmap with an input bitmap.

These four functions and other conventional image processing are placed in two files: Processing.h and Processing.cpp, copied and added to the project. Compiled with 17 errors, checked, these two files do not contain OpenCV header file (by the way, the previous project should be referenced cxcore.lib cv.lib ml.lib cvaux.lib highgui.lib Cvcam.lib these several library files, hurriedly add). It is found in the stdafx.h include:

#include "MyCV.h"                          //  window management

#include "cv.h"                             //  OpenCV file header
#include "highgui.h"
 
#include " CameraDS.h "                       //  DirectShow (based on OpenCV)
#include" CVDSCap.h "                        //  video Capture interface

#include" Processing.h "                     //  additional helper function

#endif 

//{{afx_insert_location}}
//Microsoft Visual C + + would Insert additional declarations immediately before the previous line.
  
!defined (Afx_stdafx_h__1836cf0c_3704_4215_8745_f068486288d6__included_)

Modify the Idd_aboutbox dialog box and add your own copyright information. Modifying the caption of Idr_mainframe and Afx_ids_app_title in the string table is: "OpenCV MFC MDI Image processing program framework" to change the name of the application to what we need.

Six, modify the CMainFrame::OnCreate, comment out the tool bar (mainfrm.cpp file), because we need to do a big thing on the menu, if it is too complicated to keep the toolbar, there is a lot of work to do, leaving only the menu is much simpler.

int CMainFrame::OnCreate (lpcreatestruct lpcreatestruct)
{
	if (cmdiframewnd::oncreate (lpcreatestruct) = =-1)
		return-1;

Remove the toolbar/
*	
	if (!m_wndtoolbar.createex (this, Tbstyle_flat, Ws_child | ws_visible | Cbrs_top
		| Cbrs_gripper | Cbrs_tooltips | cbrs_flyby | cbrs_size_dynamic) | |
		! M_wndtoolbar.loadtoolbar (idr_mainframe))
	{
		TRACE0 ("Failed to create toolbar\n");
		return-1;      Fail to create
	}

	if (!m_wndstatusbar.create (this) | |
		! M_wndstatusbar.setindicators (indicators,
		  sizeof (indicators)/sizeof (UINT)))
	{
		TRACE0 ("Failed to Create status bar\n ");
		return-1;      Fail-to-create
	}

	//Todo:delete These three lines if you don ' t want the toolbar to
	/Be  dockable< C24/>m_wndtoolbar.enabledocking (cbrs_align_any);
	EnableDocking (cbrs_align_any);
	DockControlBar (&m_wndtoolbar);
*/
	return 0;
}

Seven, modify the menu

1. Main Menu Idr_mainframe

Delete the View menu first

File menu, delete the new, Print settings menu (while removing the extra separator for beauty), leaving only the open, recent file, exit three menus

2. Submenu Idr_mycvtype (for the sake of simplicity, we consider all images to be of a type), so this is the only one.

"Edit", "View" are deleted, only "file", "Window", "Help" three menu

"Window": Keep only "cascade", "tile" two, the rest of the deletion. PS: I feel I can keep it all, leave it to the back to verify, and then delete it. The conclusion is: the other two is useless, delete)

"File":

(1) "New" Delete

(2) "Open" id_file_open, change to "open image"

(3) Create a "restore image", Id_refresh

(4) Insert a separator below

(5) "Close" id_file_close, change to "close Current Window"

(6) Create a "save current bitmap", Id_conservation_image

(7) Delete "Save", "Save As", "separator", "print", "Print Preview", "Print settings"

(8) "Exit" before inserting a "restore original image", Id_color_image_refresh

(9) "Exit" before inserting a "current screen disk", Id_file_save_as

(10) Insert a separator before "exit"

(11) Temporarily to this, after adding the specific function to join the other menu

Eight, "software lock"

There are many features in this demo program that need to open the windows of OpenCV settings, and performing other functions without closing these windows can cause a program failure. In order to avoid this situation, special in the use of such a window program to add " software lock ", that is, in the corresponding function of the program to set the parameter m_imagetype value is -3. The Enable function (ONUPDATEXXX) (m_imagetype!=-3), which requires a lock function, is limited by conditions. Therefore, when the menu is not available during the execution of the program, it must be that the open window is closed, please close these windows before you run the required features or exit the demo program.

Specifically, modify the definition of the Cmycvview class in MyCVView.h:

#ifdef _DEBUG
	virtual void AssertValid () const;
	virtual void Dump (cdumpcontext& dc) const;
#endif

protected:
	iplimage* saveimg;
	iplimage* workimg;
 
	Lpbitmapinfo M_lpbmi;
 
	int     M_captflag;
	int     M_dibflag;
	int     M_saveflag;
 	int     M_imagetype;
 
Generated message map functions

The corresponding constructors also initialize them

CFile fcapture;
CFileException ecapture;
Char pbuf[20];
int  captsetflag=0;

Cmycvview::cmycvview ()
{
	//Todo:add Construction code here
	saveimg    = NULL;
	Workimg    = NULL;
  
	M_lpbmi    = 0;

	M_captflag = 0;
	M_dibflag  = 0;
 	M_imagetype= 0;
  
	CSize sizetotal;
	sizetotal.cx = Sizetotal.cy = +;
	SetScrollSizes (Mm_text, sizetotal);

	if (Fcapture.open ("CaptSetup.txt", Cfile::moderead, &ecapture))
	{
		fcapture.read (pbuf);  Remove resolution setting Data
 		sscanf (pbuf, "%d  %d", &framesetw,&frameseth);
		Fcapture.close ();
	}

}


In the definition of the Cmycvdoc class:

Class Cmycvdoc:public CDocument
{
protected://Create from serialization only
	Cmycvdoc ();
	Declare_dyncreate (Cmycvdoc)

//Attributes public
:
	iplimage*	pImg;
	int			M_display;

The corresponding constructor

Cmycvdoc::cmycvdoc ()
{
	//Todo:add one-time construction code here
	pimg=null;
 	M_display=-1;

}

OK, now it's time to open the image file, but there's no drawing, which means there's still some work to do.

Nine, now need to open the image

Generate open functions for documents with the Class Wizard (Cmycvdoc::onopendocument)

BOOL cmycvdoc::onopendocument (LPCTSTR lpszpathname) 
{
	if (! Cdocument::onopendocument (lpszpathname))
		return FALSE;
	
	Todo:add your specialized creation code here
	bool bool;

    Load (&pimg,lpszpathname);
	if (pimg!=null) bool=true;
	else Bool=false;
	return (bool);


Then we need the member function load, simply add the Save function at the same time

BOOL cmycvdoc::load (iplimage** pp,lpctstr csfilename)
{
	iplimage* pimg=null;

	PIMG = Cvloadimage (csfilename,-1);  Read image file (DSCV)
	if (!pimg) return (false);
 	Cvflip (PIMG);  consistent with the DIB pixel structure
 	if (*pp) {
		cvreleaseimage (PP);
	}
	(*PP) =pimg;
   	m_display=0;
	return (true);


BOOL Cmycvdoc::save (LPCTSTR csfilename,iplimage* pImg)
{
	int   bl;

 	Cvflip (PIMG);  Restore the original OpenCV bitmap structure
  	bl=cvsaveimage (csfilename,pimg);  Image Save
 	return (BL);
}

Class, declare the following:

Class Cmycvdoc:public CDocument
{
protected://Create from serialization only
	Cmycvdoc ();
	Declare_dyncreate (cmycvdoc)
	BOOL Load (iplimage** pimg,lpctstr pszfilename);
	BOOL Save (LPCTSTR pszfilename,iplimage* pImg);

Attributes public
:
	iplimage*	pImg;
	int			M_display;

And this needs to go through the Class Wizard to open the menu plus

void Cmycvview::onupdatefileopen (ccmdui* pcmdui) 
{
	//todo:add Your command update UI handler code here
    pcmd Ui->enable (m_imagetype!=-3);
	
}

The OnDraw function of the Cmycvview class

Cmycvview drawing void Cmycvview:
	: OnDraw (cdc* pDC) {cmycvdoc* PDoc = GetDocument ();
	Assert_valid (PDOC); Todo:add draw code for native data here if (pdoc->pimg!=null) {//Have Disk input image if (pdoc->m_display=         =0) {//not shown imageclone (PDOC-&GT;PIMG,&AMP;SAVEIMG);  Copy to backup bitmap M_dibflag=imageclone (saveimg,&workimg);
			Copy to work bitmap M_imagetype=imagetype (workimg);
			M_saveflag=m_imagetype;
		pdoc->m_display=1;
		}} if (M_dibflag) {//DIB structure changes 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);
	Set scroll bar}//The following paragraph if not added to the camera related will compile, so here still add it in char *pbits;
	if (m_captflag==1) pbits=m_frame->imagedata;

	else if (workimg) pbits=workimg->imagedata; if (WORKIMG) {//Refresh window screen stretchdibits (PDC-&GT;M_HDC, 0,0,workimg->width,workimg->hei
	Ght, 0,0,workimg->width,workimg->height, pbits,m_lpbmi,dib_rgb_colors,srccopy);
 }

}

Okay, now you can open and display the image.

Xi. Current screen disk

Use the Class Wizard to generate a handler for the menu "Save current Screen" (Id_file_save_as)

void Cmycvview::onfilesaveas () {//Todo:add your command handler code here 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);
		File Save dialog box if (Filedlg.domodal () ==idok) {//Selected file name strFileName = FileDlg.m_ofn.lpstrFile;  if (FileDlg.m_ofn.nFileExtension = = 0) {No file suffix strextension = Name[filedlg.m_ofn.nfilterindex];
			                                strFileName = strFileName + '. ' + strextension;
		Add File suffix} cmycvdoc* pDoc = GetDocument ();

		Assert_valid (PDOC);   Pdoc->save (STRFILENAME,WORKIMG);

 Current screen Save}}

And

void Cmycvview::onupdatefilesaveas (ccmdui* pcmdui) 
{
	//todo:add Your command update UI handler code here
    PC Mdui->enable ((m_captflag!=1) && (m_imagetype!=-3));
}

12. Restore Image

Use the Class Wizard to generate a handler for the menu "restore Image" (Id_refresh)

void Cmycvview::onrefresh () 
{
	//todo:add your command handler code here
	M_dibflag=imageclone (saveimg, &WORKIMG);
	M_imagetype=m_saveflag;
  	Invalidate ();
}

And

void Cmycvview::onupdaterefresh (ccmdui* pcmdui) 
{
	//todo:add Your command update UI handler code here
    PC Mdui->enable ((m_captflag!=1) && (m_imagetype!=-3));
}

13. Save the current bitmap

Use the Class Wizard to create a handler for the menu "Save current Bitmap" (Id_conservation_image)

void Cmycvview::onconservationimage () 
{
	//todo:add your command handler code here
 	Imageclone (workimg, &SAVEIMG);
	M_saveflag=m_imagetype;
}


And

void Cmycvview::onupdateconservationimage (ccmdui* pcmdui) 
{
	//todo:add Your command update UI handler code here
   pcmdui->enable ((m_captflag!=1) && (m_imagetype!=-3));
}

14. Restore the original image

Use the Class Wizard to generate a handler for the menu "restore Original image" (Id_color_image_refresh)

void Cmycvview::oncolorimagerefresh () 
{
	//todo:add your command handler code here
	cmycvdoc* PDoc = getdo Cument ();
	Assert_valid (PDOC);
	pdoc->m_display=0;
	Invalidate ();
	
}

And

void Cmycvview::onupdatecolorimagerefresh (ccmdui* pcmdui) 
{
	//todo:add Your command update UI handler code here
    pcmdui->enable ((m_captflag!=1) && (m_imagetype!=-3));
}


At this end, the framework is basically complete, and the following is a real image processing to validate our results.

XV, Menu establishment

Set Menu "Point processing" first

New menu item "Color to gray scale", Id_color_to_gray

16, the establishment of color gray scale code

Use the Class Wizard to generate a handler for the menu "color Grayscale" (Id_color_to_gray)

void Cmycvview::oncolortogray ()             //  Image Color to gray scale 
{
	//todo:add your command handler code here
	iplimage* Pimage;
	iplimage* pimg8u = NULL;
 
	Pimage = workimg;  pending Image Change name

    //  build auxiliary bitmap
 	pimg8u = Cvcreateimage (Cvgetsize (pimage), ipl_depth_8u,1);

 	Cvcvtcolor (Pimage,pimg8u,cv_bgr2gray);  Color Change Gray order

	M_dibflag=imagereplace (pimg8u,&workimg);  output processing result
 
 	Imageclone (workimg,&saveimg);  saves the current bitmap
     
	m_saveflag=m_imagetype=1;  sets the grayscale bitmap flag
	Invalidate ();

}

And

void Cmycvview::onupdatecolortogray (ccmdui* pcmdui) 
{
	//todo:add Your command update UI handler code here
  pcmdui->enable ((m_captflag==0) && (m_imagetype>1));
	
}

Now, we can open an image, point "color to gray scale" can see the true gray scale success, to this program basically completed.

17. Let the MDI program do not open the new document when it is started

In *app::initinstance () (Our program is boolcmycvapp::initinstance ())

CCommandLineInfo   Cmdinfo;
ParseCommandLine (Cmdinfo); 

Add a sentence to the back

cmdinfo.m_nshellcommand=ccommandlineinfo::filenothing;

This is a small improvement to the original program.

18. Maximize the program when it is open

Because we do the image, nature is the full-screen display of good, do not want to often pull the scroll bar

BOOL cmycvapp::initinstance () makes the following modifications:

	The following sentence is annotated, the parameters are changed
	to sw_showmaximized//To achieve automatic maximization of
	//pmainframe->showwindow (m_nCmdShow) at startup;
	M_pmainwnd->showwindow (sw_showmaximized);   
	Pmainframe->updatewindow ();

The child window defaults to maximized display:

BOOL cchildframe::P Recreatewindow (createstruct& cs)
{
	//todo:modify the Window class or styles here by modif Ying
	//The  CREATESTRUCT CS
	cs.style=ws_child| ws_visible| ws_overlappedwindow| ws_maximize| Fws_addtotitle;

	if (! CMDIChildWnd::P Recreatewindow (CS))
		return FALSE;

	return TRUE;
}


This is also a small improvement of the original program.
Code download click to open link

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.