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->PIMG,&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->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