Fari

C

Windows下编译并测试OpenCV

注1:以下若不做说明默认将opencv下载编译到我本机 C:\Users\HuntZou\Downloads\ 目录下,您需根据您自己的情况做一些替换。

注2:以下若不做说明则都是我自己试过的方法

编译

1. 下载cmake

https://cmake.org/download/

2. 下载opencv源码

https://opencv.org/releases/

3. 解压缩opencv源码并进入到解压后的目录

4. 在解压后的目录创建一个build目录,用于存放cmake的输出文件

注:这是为了后面在命令行中使用cmake,你也可以直接使用cmake的gui

5. 在build目录中打开cmd,并使用下载好的cmake创建makefile

这一步需要下载一些东西,由于东西在外网,导致在这里卡半天,最终会报错

解决办法:

5.1 简单方法(使用代理):如果电脑上装了clash代理软件的话,直接开启clash的tun模式即可,我自己实验一次就成功了。

貌似windows命令行默认不走代理,clash开启该选项后会虚拟出一块网卡,所有流量都会经过该网卡,这样即使不走代理的软件也会被迫走代理。

貌似也可以直接设置命令行走代理,不过我没试 https://blog.csdn.net/u014723479/article/details/103698296

5.2 复杂方法(cmake期间不用下载):

5.2.1. 自己在下载好该文件

停止cmake,然后找到build目录下的 CMakeDownloadLog.txt 文件,在里面搜索关键字 ”https“ 可以找到文件的下载链接。

注:图示内容为可以正常下载情况下的截图,您该文件内容应该没这么完整,但也能找到一些url链接。

需要下载的文件一共有四个,共分为两类:

ffmpeg:opencv_videoio_ffmpeg.dll、opencv_videoio_ffmpeg_64.dll、ffmpeg_version.cmake

ippicv:ippicv_2020_win_intel64_20191018_general.zip

ippicv的链接直接下载即可

ffmpeg需要下载三个文件,但它们的url前缀都是一样的,将上述三个文件名替换一下下载即可

5.2.2. 将下载好的 ffmpeg 三个文件 放到 /3rdparty/ffmpeg/ 目录下

ippicv_2020_win_intel64_20191018_general.zip 放到 /3rdparty/ippicv/ 目录下

5.2.3. 打开opencv源码目录下的文件 /3rdparty/ippicv/ippicv.cmake/3rdparty/ffmpeg/ffmpeg.cmake

注释掉以下部分:

重新开始cmake

6. cmake结束后会在build目录下生成一个opencv的vs工程,用vs打开即可,然后再用vs编译。

C++、Qt编译相关概念

问题描述

使用vs2022创建了一个静态库,欲在qt程序中使用,结果报 undefined reference to xxx 错误,这里的xxx就是静态库中定义的方法。可以保证:

  1. 已经正确配置依赖并添加头文件

  2. 在vs中创建一个示例程序并引入该lib发现可以正常使用

由于对c++生态不太熟,做此记录

问题原因

vs使用的是msvc编译器,而qtcreator中使用的却是mingw编译器。两者并不兼容。

解决方案

qtcreator切换到msvc编译器,并且需要在电脑上正确安装与该msvc编译器对应的visual studio IDE。

概念区分

VC 和 VS

VC相关的概念在下面有详细说明,需要注意的是:除了下面说的它是一个C++编译器之外,在不同的语境下它也有可能是其他东西,例如一个名为VC++的IDE或者C语言等

可以简单理解为:vs(即Visual Studio IDE)是一个ide,对应java中的eclipse等。vc(即MSVC)是vindows下c++的编译环境,对应java中jdk的javac。

用vs开发时可以选择不同的vc版本

参考:https://zhuanlan.zhihu.com/p/497033106

MSVC、MSVC++、VC、VC++、Visual C++、Microsoft Visual C++

它们都是同一个东西

GNU、MinGW、GCC、gcc、g++(都带一个g)

GNU 简单理解为一个开源软件集合,其中有很多开源软件,例如 GNU/Linux,GNU/GCC 等

实际上GNU是一个单独的操作系统,拥有自己的内核 Hurd 和一些列周边软件,但在生产环境中常常将其替换成更成熟的 linux内核。如此,这种替换了linux内核但同时拥有GNU周边软件的GNU系统就被称为 GNU/Linux,它和linux其实是两个不同的系统,只不过很多时候直接将其简称为linux。

上面说的那个开源软件集合,其实指的就是GNU系统下的一些周边软件。

GCC 全称 GNU Compiler Collection,顾名思义,它是GNU系统下编译器的集合,它下面有各种语言的编译器,例如java编译器、c/c++编译器(gcc和g++)、OC编译器等

gcc/g++ 全称 GNU C Compiler,就是上述GCC集合中的c/c++编译器。事实上,它们也并非真正的编译器,它们只是一个驱动,用于判断被编译文件类型或系统环境等,然后调用真正的c/c++编译器cc1或cc1plus。它们的区别是:g++不管遇到c或c++文件都当作c++文件,从而调用cc1plus编译器进行编译。而gcc则进行区分。再者g++在编译完成后会自动链接c++的标准库,gcc不会。

有些文章说g++会调用gcc或反过来都是错误的。

MinGW 全称 Minimalist GNU for Windows,它就是将GNU系统下的一些工具软件打包给windows用。其中就包含gcc。

详见:https://blog.csdn.net/lee_ham/article/details/81778581

MSVC 和 MinGW

可以简单认为两者都是c++的编译器(但上面说过MinGW是一个工具集,实际上编译器是gcc),区别在于:

MSVC是windows下独有的,全称:Microsoft Visual C++。它和VS是一一绑定的。可以简单认为,想用哪个版本的MSVC就需要下载安装对应版本的VS。

对C++引用库的理解

情景

创建两个静态库 libA 和 libB,libB依赖libA。创建一个程序App引用 libB

关系为:App -> libB -> libA

一般做法是:

创建完libA后编译生成静态库,创建libB时引用该静态库并将libA的头文件复制到libB项目中进行引用。

App对libB的引用也是导入它的静态库和头文件。

可不可以不用头文件?

可以,头文件只其申明作用,你完全可以自己写该声明。事实上,#include 只是在编译时起作用,它仅仅将include的文件全量复制到源文件中。故和你自己写是一样的。

头文件和源文件名称能否不同

可以,还是上面说的,include仅仅将内容原封不动复制进源文件,所以和头文件命名没有什么关系。

如何在App中使用libA中定义的类和方法

如果是java程序,那么你完全可以直接在App项目中声明和使用libA中的类和方法,我认为这也是符合直觉的。

但在c++中,貌似有一条不成文的规定就是任何东西都需要先声明再使用,所以,若想在App中调用libA中的方法,要么你include libA的头文件,要么你手动声明需要调用的方法,然后就可以直接调用,至于调用的方法体,c++程序会在链接步骤自动找到。

举例:

App.cpp(一个Qt的示例程序)

pch.h

libA.h

extern 关键字

我在libB中定义了一个变量,我想在App中使用它,如果你这个变量定义在libB的头文件中这样做是没问题的,但如果你将其定义在了cpp文件中,那你在App中仅引入libB的头文件还是访问不到该变量。

此时,你就可以在头文件中使用extern关键字再次声明定义在cpp中的变量,然后在App中就可以使用了。

例如:

# libB.h
...
class MyClass{...}
extern int num;
extern MyClass mc;
...
# libB.cpp
...
int num = 1;
MyClass mc = MyClass();
...
# App.cpp
#include "libB.h"
...
int main()
{
    std::cout << num << ", " << mc.somproperties;
}
...

但是我测试了下,貌似不能作用与class

visual studio如何使用第三方库

过程实际上很简单,就是两步

  1. 引入 .h 头文件告诉我第三方库提供了哪些方法(就好比是菜单)

  2. 引入 .lib 库文件告诉程序头文件的具体实现(就好比是具体的做菜过程)

至于 .dll 文件,你可以理解为它是对 lib 文件的补充,有的时候会没有

一般第三方库会提供三个文件 .h/.lib/.dll,有的时候也是两个 .h 和 .lib

在项目中,一般 .h 文件会放到 include 文件夹中,.lib 文件会放到 lib 文件夹中,.dll 或可执行文件会放到 bin 文件夹中

下文将介绍它们有什么用以及如何使用它们

1. 使用visual studio创建一个新的空项目

2. 创建一个 .cpp 文件(必须先于3执行)

在 Source Files 目录右键,选择添加新项目,并在弹出的对话框中选择 c++ 项目,然后输入一个文件名称

双击打开文件进行编辑,输入下面的代码并点击工具栏中的运行按钮看看能不能正常运行

#include <iostream>int main() {	printf("bingo");	return 0;}

3. 加载 .h 头文件

头文件就是 lib 文件中可用内容的声明,c++中,函数字段等都要先声明再使用,include头文件就是声明过程,你可以理解为它会把头文件的内容复制到你代码文件的顶部

项目上右键,选择属性

在弹出的页面中,下图所示位置添加 .h 文件所在目录

添加后,写c++代码时也会有相应的提示

4. 添加 .lib 依赖