The OpenCV beta 2.1 has been used to produce the examples below with DirectX 8.1 and Visual C++ 6.0 service pack 5 under Windows 2000.
运行书中的程序需要安装opencv和directx
1. Creating a Dialog-based application 创建基于对话框的程序
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void CCvisionDlg::OnOpen()
{
CFileDialog dlg(TRUE, _T("*.bmp"), "",
OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY,
"image files (*.bmp; *.jpg) |*.bmp;*.jpg|
AVI files (*.avi) |*.avi|All Files (*.*)|*.*||",NULL);
char title[]= {"Open Image"};
dlg.m_ofn.lpstrTitle= title;
if (dlg.DoModal() == IDOK) {
CString path= dlg.GetPathName(); // contain the
// selected filename
}
}
Note how the extensions of interest (here .bmp .jpg and .avi) for the files to be opened are specified using the fourth argument of the CFileDialog constructor. Now, by clicking on the Open Image button, the following dialog appears:注意文件扩展名是如何通过cfiledialog构造函数的第四个参数指定的。
请确保之前已经在vc6里面对opencv的环境设置好了
首先创建一个ImageProcessor类,用来管理图像的显示
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
#if !defined IMAGEPROCESSOR
#define IMAGEPROCESSOR
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "cv.h" // include core library interface
#include "highgui.h" // include GUI library interface
class ImageProcessor {
IplImage* img; // Declare IPL/OpenCV image pointer
public:
ImageProcessor(CString filename, bool display=true) {
img = cvvLoadImage( filename ); // load image
if (display) {
// create a window
cvvNamedWindow( "Original Image", 1 );
// display the image on window
cvvShowImage( "Original Image", img );
}
}
~ImageProcessor() {
cvReleaseImage( &img );
}
};
#endif
然后修改刚才的文件打开函数成如下形式:
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
void CCvisionDlg::OnOpen()
{
CFileDialog dlg(TRUE, _T("*.bmp"), "",
OFN_FILEMUSTEXIST|OFN_PATHMUSTEXIST|OFN_HIDEREADONLY,
"BMP files (*.bmp) |*.bmp|AVI files (*.avi) |*.avi|
All Files (*.*)|*.*||",NULL);
char title[]= {"Open Image"};
dlg.m_ofn.lpstrTitle= title;
if (dlg.DoModal() == IDOK) {
CString path= dlg.GetPathName();
ImageProcessor ip(path); // call for imageprossor class in the openfile function
}
}
因此每次打开文件后就自动打开一个窗口了。
3. Processing an image 处理一幅图像
Now let’s try to call one of the OpenCV function. We rewrite the header as follows:下面就展示如何利用opencvfunction来处理图像
首先重写头文件:
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
#if !defined IMAGEPROCESSOR
#define IMAGEPROCESSOR
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "cv.h" // include core library interface
#include "highgui.h" // include GUI library interface
class ImageProcessor {
IplImage* img; // Declare IPL/OpenCV image pointer
public:
ImageProcessor(CString filename, bool display=true) {
img = cvvLoadImage( filename ); // load image
if (display) {
cvvNamedWindow( "Original Image", 1 );
cvvShowImage( "Original Image", img );
}
}
void display() {
cvvNamedWindow( "Resulting Image", 1 );
cvvShowImage( "Resulting Image", img );
}
void execute();
~ImageProcessor() {
cvReleaseImage( &img );
}
};
extern ImageProcessor *proc;
#endif
注意最后面定义的外部变量 *proc。这个变量很关键。
然后添加源文件:we add a C++ source file, here named cvapp.cpp, that contains the function that does the processing.
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
#include "stdafx.h"
#include "cvapp.h"
// A global variable
ImageProcessor *proc = 0;
// the function that processes the image
void process(void* img) {
IplImage* image = reinterpret_cast<IplImage*>(img);
cvErode( image, image, 0, 2 );
}
void ImageProcessor::execute() {
process(img);
}
这样写的好处文中是这样写的:
The process function is the one that calls the OpenCV function that does the processing. In this example, the processing consists in a simple morphological erosion (cvErode). Obviously, all the processing could have been done directly inside the execute member function. Also, there is no justification, at this point, to have use a void pointer as parameter for the process function. This has been done just for consistency with the examples to follow where the process function will become a callback function in the processing of a sequence. Note that for simplicity, we have added a global variable that points to the ImageProcessor instance that this application uses.
大意是这样:process是调用opencv函数进行图像处理的一个函数,其中包含一个简单的形态学处理函数cvErode. 并且可以明显的看出,之后所有关于图像处理的函数都可以简单的包含在execute这个成员函数里面了,所以也毫无疑问需要将返回值设为空了。这样一来process函数就成了一个简单的回调函数了。注意到为了简单起见,我们为这个程序添加了一个ImageProcessor类型的全局变量。
第三步处理图像:
![ContractedBlock.gif](/Images/OutliningIndicators/ContractedBlock.gif)
![ExpandedBlockStart.gif](/Images/OutliningIndicators/ExpandedBlockStart.gif)
if (proc != 0) {
// process and display
proc->execute();
proc->display();
}