第一步,先去Github上将两份源代码拷贝下来,以下是代码地址
opencv3.4.1源代码地址:https://github.com/opencv/opencv/tree/3.4.1
opencv_contrib3.4.1源代码地址:https://github.com/opencv/opencv_contrib/tree/3.4.1
注意,要保证两个版本是相同的。下载后,这里我将两份文件均放在E盘下的opencv文件夹中。并新建一个空文件夹opencv-3.4.1build
来存储cmake生成的文件。
第二步,需要安装一下CMake,CMake是一个跨平台的编译工具。
下载地址:https://cmake.org/files
这里,我选择3.18.2版本的cmake-3.18.2-win64-x64.msi
安装好cmake后,双击运行CMake,将开头两项填好,Where is the source code
是源路径,即opencv源码路径,where to build the binaries
是目的路径,即生成opencv的VS工程路径。
接着,点击configure,选择编译工程的平台,这里我选择VS2019和x64,点击finish即可开始配置
有很多红色选项,说明有问题,那么该怎么解决呢?首先我们去查看一下日志文件CMakeDownloadlog.txt
,在文件夹opencv-3.4.1build
中双击打开文件,会发现需要下载四个文件:opencv_ffmpeg.dll
,opencv_ffmpeg_64.dll
,ffmpeg_version.cmake
,ippicv_2017u3_win_intel64_general_20170822.zip
,对应网址如文件中所示
opencv_ffmpeg.dll下载地址:https://raw.githubusercontent.com/opencv/opencv_3rdparty/0a0e88972a7ea97708378d0488a65f83e7cc5e69/ffmpeg/opencv_ffmpeg.dll
opencv_ffmpeg_64.dll下载地址:
https://raw.githubusercontent.com/opencv/opencv_3rdparty/0a0e88972a7ea97708378d0488a65f83e7cc5e69/ffmpeg/opencv_ffmpeg_64.dll
ffmpeg_version.cmake下载地址:
https://raw.githubusercontent.com/opencv/opencv_3rdparty/0a0e88972a7ea97708378d0488a65f83e7cc5e69/ffmpeg/ffmpeg_version.cmake
ippicv_2017u3_win_intel64_general_20170822.zip下载地址:
https://raw.githubusercontent.com/opencv/opencv_3rdparty/dfe3162c237af211e98b8960018b564bc209261d/ippicv/ippicv_2017u3_win_intel64_general_20170822.zip
仔细观察一下会发现,配置opencv时,会先在源代码目录下建立.cache
目录,CMake从国外网站自动下载到E:\opencv\opencv-3.4.1\.cache
中,文件名为md5值+文件名,若是下载成功,会解压到目的路径E:\opencv\opencv-3.4.1bulid\3rdparty
中。打开.cache
目录会发现有的文件未下载成功,虽然有文件名,但是大小为0KB,见下面两张图
至此,可知,由于CMake从国外网站下载文件失败导致飘红,因此需要手动将文件全部下载下来。手动下载的文件并没有前缀md5值,如ippicv_2017u3_win_intel64_general_20170822.zip,为他手动加上前缀:0421e642bc7ad741a2236d3ec4190bdd-ippicv_2017u3_win_intel64_general_20170822.zip
然后将此文件放在E:\opencv\opencv-3.4.1\.cache\ippicv
下替换原来的0KB文件,之后让CMake自己处理。
而另外三个手动下载的文件,则直接放在E:\opencv\opencv-3.4.1bulid\3rdparty\ffmpeg
中
链接:https://pan.baidu.com/s/1A-Q68VTKevPLJPntY9tyYg 提取码:b1cd
于是,我们变相得帮助CMake下载好文件并放在了对应位置。删除E:\opencv\opencv-3.4.1bulid
中的内容,除了文件夹3rdparty
。重新启动CMake,再走一下上面流程,因为此时文件均已下载好,所以速度会很快。注意,再编译一次虽然依旧会显示飘红,但此时打开CMakeDownloadlog.txt
文件会发现四个文件均已匹配好,因此只要点击一下configure就可以了。
终于变白了,显示Configuring done
,于是接下来要配置opencv_contrib
BUILD_opencv_world
,将编译库为一个单独的opencv_worldxx.dll/lib文件OPENCV_ENABLE_NONFREE
,可使用需专利授权的算法,如SIFTOPENCV_EXTRA_MODULES_PATH
添加路径,E:/opencv/opencv_contrib-3.4.1/modules
,注意!这里不要直接拷贝路径,否则会变成E:\opencv\opencv_contrib-3.4.1\modules
然后,点击左下角configure,不出意外的话,会再次出现红色,表明文件下载失败,麻了!
失败文件还是记录在CMakeDownloadlog.txt
文件中,打开看一下究竟是哪些文件呢
可以看见,之前下载好的四个文件均已匹配好,但是下载新的文件又失败了,于是手动将需要的文件下载下来,并给他们添加好md5值,放在各自的位置上。
但在这里,我当个马后跑,若是仅仅将E:\opencv\opencv-3.4.1\.cache
中各文件夹的缺失文件都补充好,最后批生成时依旧会发生一大堆错误,失败一百多个,如下图所示,简直是血泪教训,这里检查了很多次!
因此这里我参考别人的博客多做了一步,将下载后的12份文件,拷贝到E:\opencv\opencv_contrib-3.4.1\modules\xfeatures2d\src
,具体原因不详。
12份文件【其实是13份,多了一个压缩包文件】百度云链接:
链接:https://pan.baidu.com/s/1jnp8FbMyZJnwNbN0hjur6A 提取码:lzaa
像之前流程一样,删除E:\opencv\opencv-3.4.1bulid
中的内容,除了文件夹3rdparty
。重新启动CMake,再走一下两步流程,因为此时两步文件均已下载好,天不怕地不怕,直接configure到底。最后点击Generate即可。
为了以防万一,最好检查一下CMakeDownloadlog.txt
文件,看一下有没有缺失文件,根据我的经验,第一步中四个文件一般不会缺失,可能第二步中补充opencv_contrib模块时会文件会提醒有文件未下载成功,你可能会问,不是我们已经将文件下载好并补充到文件夹了吗,但事实就是这样,你最好去目的文件夹中检查一下有没有对应文件,若是缺少,直接补上就行
在输出目录E:\opencv\opencv-3.4.1bulid
中,找到OpenCV.sln
文件,双击打开。
如下图所示,勾选上四个选项,再点击生成
耐心等待,直到输出以下信息
CMake编译生成的OpenCV库,在E:\opencv\opencv-3.4.1bulid\install
下,我发现它没有x64目录,取而代之只有一个lib目录,但根据我的研究,x64目录中bin文件夹里的文件,在这个bin目录里都有
至此,在VS2019环境下编译成功的install文件,同时包括Debug和Release的依赖库,这里放上百度云链接
链接:https://pan.baidu.com/s/14SEBWzHpOfemEvfGRTQeDQ 提取码:xkni
首先添加一下环境变量,我这里是D:\opencv3.4.1\install\bin
,更改好环境变量后重启电脑生效
双击打开VS2019,新建一个空项目,再新建一个新的cpp文件,选择Debug|x64
在解决方案中右击工程,打开工程属性,为工程配置包含目录
为工程配置库目录
添加附加依赖项,在Debug模式下添加opencv_world341d.lib
和opencv_img_hash341d.lib
在Release模式下添加opencv_world341.lib
和opencv_img_hash341.lib
在C++文件中写入如下代码
#include
#include
#include
#include
using namespace cv;
void draw_rectangle(int event, int x, int y, int flags, void*);
Mat firstFrame;
Point previousPoint, currentPoint;
Rect2d bbox;
int main(int argc, char* argv[])
{
//启用摄像头进行跟踪
//VideoCapture capture(0);
Mat frame;
//capture >> frame;
//使用事先录好的视频进行检验
VideoCapture capture;
frame = capture.open("D:\\1.mp4");
if (!capture.isOpened())
{
printf("can not open ...\n");
return -1;
} //获取视频的第一帧,并框选目标
capture.read(firstFrame);
if (!firstFrame.empty())
{
namedWindow("output", WINDOW_AUTOSIZE);
imshow("output", firstFrame);
setMouseCallback("output", draw_rectangle, 0);
waitKey();
}
//使用不同跟踪算法进行跟踪
//Ptr tracker= TrackerMIL::create();
//Ptr tracker= TrackerTLD::create();
Ptr tracker = TrackerKCF::create();
//Ptr tracker = TrackerMedianFlow::create();
//Ptr tracker= TrackerBoosting::create();
capture.read(frame);
tracker->init(frame, bbox);
namedWindow("output", WINDOW_AUTOSIZE);
while (capture.read(frame))
{
tracker->update(frame, bbox);
rectangle(frame, bbox, Scalar(255, 0, 0), 2, 1);
imshow("output", frame);
if (waitKey(20) == 'q') return 0;
}
capture.release();
destroyWindow("output"); return 0;
}
void draw_rectangle(int event, int x, int y, int flags, void*)
{
if (event == EVENT_LBUTTONDOWN) { previousPoint = Point(x, y); }
else if (event == EVENT_MOUSEMOVE && (flags & EVENT_FLAG_LBUTTON))
{
Mat tmp; firstFrame.copyTo(tmp);
currentPoint = Point(x, y);
rectangle(tmp, previousPoint, currentPoint, Scalar(0, 255, 0, 0), 1, 8, 0);
imshow("output", tmp);
}
else if (event == EVENT_LBUTTONUP)
{
bbox.x = previousPoint.x;
bbox.y = previousPoint.y;
bbox.width = abs(previousPoint.x - currentPoint.x);
bbox.height = abs(previousPoint.y - currentPoint.y);
}
else if (event == EVENT_RBUTTONUP) {
destroyWindow("output");
}
}