先说用到的软件和函数库
- VS2017——我用VS2017社区版来开发,原因是软件免费而且好用,本项目用C++来做
- opencv——Open Computer Vision是计算机视觉的库,有多种语言的接口,而且函数库也很丰富
- dlib——Dlib是一个包含机器学习算法的C++开源工具包,提供大量的机器学习 / 图像处理算法(网上看的 :-) )
本项目用的是VS2017社区版+opencv3.4.2版本+dlib9.0.3 。用其它版本也可以,新一点的版本吧。
容易遇到的问题
- dlib 配置的时候是需要release|x64 的模式,因为debug模式会让程序运行得非常缓慢,这在dlib官网上有说明http://dlib.net/faq.html#Whyisdlibslow
opencv 在 VS2017 里面的配置
关于opencv的配置,这个文档已经非常清楚了,https://blog.csdn.net/qq_41175905/article/details/80560429,非常感谢这位作者的帮助。如果看不懂,多找几篇关于配置的来看,方法都一样,只是详细与否的区别。
总结是:
- 比如把opencv安装在了D:\opencv342\ ,安装好后
- 右键“我的电脑”->属性->高级系统设置->环境变量,在后面添加环境变量: D:\opencv342\opencv\build\x64\vc15\bin
- 配置好环境变量后,打开VS2017,新建一个C++空项目
- 打开属性管理器,菜单栏->视图->其他窗口->属性管理器,对release|X64进行配置:右键release|X64->新建一个属性表,重命名为opencv
- 双击opencv属性表,属性中的 VC++目录->包含目录
D:\opencv342\opencv\build\include
D:\opencv342\opencv\build\include\opencv
D:\opencv342\opencv\build\include\opencv2 - VC++目录->库目录
D:\opencv342\opencv\build\x64\vc15\lib - 链接器->输入->附加依赖项中加入
opencv_world341d.lib - 到这里,opencv就配置好了,第2步时配置环境变量的重点,第5、6、7步是配置vs的重点,第8步可有可无,只是为了未来方便。就是打开第3步的项目文件夹,把刚刚配置好的那个新建的opencv属性表保存在另外一个容易保存的地方就好,到时候要用就把它导入进来,就不用重新配置了。
配置好后测试一下:
- 新建一个C++空项目
- 打开属性管理表,右键release|X64,添加->现有项,然后把刚刚的opencv属性表导入进去
- 然后转到解决方案的管理器,右键源文件->添加新建项,然后添加一个cpp文件,比如是1.cpp
- 然后把下面的代码粘贴进去
#include "opencv2/core.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/videoio.hpp"
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
cout << "Built with OpenCV " << CV_VERSION << endl;
VideoCapture capture(0); // 打开摄像头
if(!capture.isOpened()) // 判断是否打开成功
{
cout << "open camera failed. " << endl;
return -1;
}
while(true)
{
Mat frame;
capture >> frame; // 读取图像帧至frame
if(!frame.empty()) // 判断是否为空
{
imshow("camera", frame);
}
if(waitKey(30) > 0) // delay 30 ms等待按键
{
break;
}
}
return 0;
}
- 这个代码的意思是打开笔记本电脑自带的摄像头,要是没有摄像头的话要借一个usb摄像头,然后把代码里的
VideoCapture capture(0);
改成VideoCapture capture(1);
,就可以打开usb摄像头。 - 如果可以,那么opencv的配置就成功了。
dlib 在 VS2017 里面的配置
关于dlib的配置,这个文档,https://www.cnblogs.com/dapeng-bupt/p/7807679.html和这个文档https://blog.csdn.net/czp19940223/article/details/78577570,啊也非常感谢这两位作者的帮助。
具体就是:
- 下载并且解压安装包
- cmake 编译dlib (这是为了得到dlib.lib)(比如编译报存的文件夹是D:\dlib-9.0.3\dlibmake)
- 打开vs,打开刚刚cmake编译的dlib项目,然后用release x64来重新编译dlib
- 然后新建空项目,然后release|x64 新建属性表
- VC++目录->包含目录,把dlib刚开始解压的目录写进去(比如D:\dlib-9.0.3)
- VC++目录->库目录,把刚刚生成的lib目录放进去(比如D:\dlib-9.0.3\dlibmake\release)
- 链接器->输入->附加依赖项,加入dlib.lib (如果不是这个名字就改成你文件夹里的那个lib的名字)
- 把属性表保存好
配置好后测试一下:
- 新建空项目,release|x64 导入刚刚的属性表
- 在源文件那里,新建一个cpp源文件
- 写入下面的代码
- 把这里的代码复制进去运行,(这位作者的代码)http://dlib.net/gui_api_ex.cpp.html,如果可以运行就行了。
- 为了方便也贴在下面,但是比较多
// The contents of this file are in the public domain. See LICENSE_FOR_EXAMPLE_PROGRAMS.txt
/*
This is an example illustrating the use of the gui api from the dlib C++ Library.
This is a pretty simple example. It makes a window with a user
defined widget (a draggable colored box) and a button. You can drag the
box around or click the button which increments a counter.
*/
#include <dlib/gui_widgets.h>
#include <sstream>
#include <string>
using namespace std;
using namespace dlib;
// ----------------------------------------------------------------------------
class color_box : public draggable
{
/*
Here I am defining a custom drawable widget that is a colored box that
you can drag around on the screen. draggable is a special kind of drawable
object that, as the name implies, is draggable by the user via the mouse.
To make my color_box draggable all I need to do is inherit from draggable.
*/
unsigned char red, green,blue;
public:
color_box (
drawable_window& w,
rectangle area,
unsigned char red_,
unsigned char green_,
unsigned char blue_
) :
draggable(w),
red(red_),
green(green_),
blue(blue_)
{
rect = area;
set_draggable_area(rectangle(10,10,400,400));
// Whenever you make your own drawable widget (or inherit from any drawable widget
// or interface such as draggable) you have to remember to call this function to
// enable the events. The idea here is that you can perform whatever setup you
// need to do to get your object into a valid state without needing to worry about
// event handlers triggering before you are ready.
enable_events();
}
~color_box (
)
{
// Disable all further events for this drawable object. We have to do this
// because we don't want any events (like draw()) coming to this object while or
// after it has been destructed.
disable_events();
// Tell the parent window to redraw its area that previously contained this
// drawable object.
parent.invalidate_rectangle(rect);
}
private:
void draw (
const canvas& c
) const
{
// The canvas is an object that represents a part of the parent window
// that needs to be redrawn.
// The first thing I usually do is check if the draw call is for part
// of the window that overlaps with my widget. We don't have to do this
// but it is usually good to do as a speed hack. Also, the reason
// I don't have it set to only give you draw calls when it does indeed
// overlap is because you might want to do some drawing outside of your
// widget's rectangle. But usually you don't want to do that :)
rectangle area = c.intersect(rect);
if (area.is_empty() == true)
return;
// This simple widget is just going to draw a box on the screen.
fill_rect(c,rect,rgb_pixel(red,green,blue));
}
};
// ----------------------------------------------------------------------------
class win : public drawable_window
{
/*
Here I am going to define our window. In general, you can define as
many window types as you like and make as many instances of them as you want.
In this example I am only making one though.
*/
public:
win(
) : // All widgets take their parent window as an argument to their constructor.
c(*this),
b(*this),
cb(*this,rectangle(100,100,200,200),0,0,255), // the color_box will be blue and 101 pixels wide and tall
mbar(*this)
{
// tell our button to put itself at the position (10,60).
b.set_pos(10,60);
b.set_name("button");
// let's put the label 5 pixels below the button
c.set_pos(b.left(),b.bottom()+5);
// set which function should get called when the button gets clicked. In this case we want
// the on_button_clicked member to be called on *this.
b.set_click_handler(*this,&win::on_button_clicked);
// Alternatively, if you have a compiler which supports the lambda functions from the
// new C++ standard then you can use a lambda function instead of telling the click
// handler to call one of the member functions. So for example, you could do this
// instead (uncomment the code if you have C++0x support):
/*
b.set_click_handler([&](){
++counter;
ostringstream sout;
sout << "Counter: " << counter;
c.set_text(sout.str());
});
*/
// In general, all the functions which register events can take either member
// functions or lambda functions.
// Let's also make a simple menu bar.
// First we say how many menus we want in our menu bar. In this example we only want 1.
mbar.set_number_of_menus(1);
// Now we set the name of our menu. The 'M' means that the M in Menu will be underlined
// and the user will be able to select it by hitting alt+M
mbar.set_menu_name(0,"Menu",'M');
// Now we add some items to the menu. Note that items in a menu are listed in the
// order in which they were added.
// First let's make a menu item that does the same thing as our button does when it is clicked.
// Again, the 'C' means the C in Click is underlined in the menu.
mbar.menu(0).add_menu_item(menu_item_text("Click Button!",*this,&win::on_button_clicked,'C'));
// let's add a separator (i.e. a horizontal separating line) to the menu
mbar.menu(0).add_menu_item(menu_item_separator());
// Now let's make a menu item that calls show_about when the user selects it.
mbar.menu(0).add_menu_item(menu_item_text("About",*this,&win::show_about,'A'));
// set the size of this window
set_size(430,380);
counter = 0;
set_title("dlib gui example");
show();
}
~win(
)
{
// You should always call close_window() in the destructor of window
// objects to ensure that no events will be sent to this window while
// it is being destructed.
close_window();
}
private:
void on_button_clicked (
)
{
// when someone clicks our button it will increment the counter and
// display it in our label c.
++counter;
ostringstream sout;
sout << "counter: " << counter;
c.set_text(sout.str());
}
void show_about(
)
{
message_box("About","This is a dlib gui example program");
}
unsigned long counter;
label c;
button b;
color_box cb;
menu_bar mbar;
};
// ----------------------------------------------------------------------------
int main()
{
// create our window
win my_window;
// wait until the user closes this window before we let the program
// terminate.
my_window.wait_until_closed();
return 0;
}
// ----------------------------------------------------------------------------
// Normally, if you built this application on MS Windows in Visual Studio you
// would see a black console window pop up when you ran it. The following
// #pragma directives tell Visual Studio to not include a console window along
// with your application. However, if you prefer to have the console pop up as
// well then simply remove these #pragma statements.
#ifdef _MSC_VER
# pragma comment( linker, "/entry:mainCRTStartup" )
# pragma comment( linker, "/SUBSYSTEM:WINDOWS" )
#endif
// ----------------------------------------------------------------------------
标签:box,ARS,VS2017,C++,opencv,window,include,dlib
From: https://www.cnblogs.com/atanchen/p/18428486