初识openCV & VS编译C++项目

0 OpenCV概览

OpenCV是一个开源的计算机视觉库,可以从 http://opencv.org 获取。

1999 年,Gary Bradski(加里·布拉德斯基)当时在英特尔任职,怀着通过为计算机视觉和人工智能的从业者提供稳定的基础架构并以此来推动产业发展的美好愿景,他启动了 OpenCV 项目。OpenCV 自项目成立以来获得了来自英特尔和谷歌的大力支持,尤其需要感谢 Itseez(俄罗斯的一家视觉公司,专门从事计算机视觉算法),该公司完成了早期开发的大部分工作。此后,Arraiy 团队加入该项目并负责维护始终开源和免费的 OpenCV。

OpenCV 设计用于进行高效的计算,十分强调实时应用的开发。它由 C++ 语言编写并进行了深度优化,从而可以享受多线程处理的优势。它的目标是提供易于使用的计算机视觉接口,从而帮助人们快速建立精巧的视觉应用。

因为计算机视觉和机器学习经常在一起使用,所以 OpenCV 也包含一个完备的、具有通用性的机器学习库(ML模块)。这个子库聚焦于统计模式识别以及聚类。ML 模块对 OpenCV 的核心任务(计算机视觉)相当有用,但是这个库也足够通用,可以用于任意机器学习问题。

什么是计算机视觉(CV)?

计算机视觉这种技术可以将静止图像或视频数据转换为一种决策或新的表示。所有这样的转换都是为了完成某种特定的目的而进行的。

区别于人类视觉,在机器视觉系统中,计算机会从相机或者硬盘接收栅格状排列的数字,也就是说,最关键的是,机器视觉系统不存在一个预先建立的模式识别机制。没有自动控制焦距和光圈,也不能将多年的经验联系在一起。大部分的视觉系统都还处于一个非常朴素原始的阶段。

视觉的不适定问题,物体的二维表示可能随着视点的不同完全改变(如上图),给定一个对于 3D 世界的二维(2D)观测,就不存在一个唯一的方式来重建三维信号。即使数据是完美的,相同的二维图像也可能表示一个无限的 3D 场景组合中的任一种情况。

而且,数据会被噪声和畸变所污染。这样的污染源于现实生活中的很多方面(天气、光线、折射率和运动),还有传感器中的电路噪声以及其他的一些电路系统影响,还有在采集之后对于图像压缩产生的影响。

1 OpnCV安装与visual studio环境配置

操作系统:Windows 11 or 10

visual studio 2022安装

官网下载2022 Community windows版,工作负载主要选择通用Windows平台开发使用C++的桌面开发,我还下载了其他工具集-->Visual Studio扩展开发

创建新项目

  • 选择"空项目 使用C++ for Windows 从头开始操作不提供基础文件";

  • 勾选"将解决方案和项目放在同一目录中";

  • 解决方案资源管理器(可从选项卡“视图”中添加)中右键单击源文件添加新建项

  • 分别使用 ”Debug/Release“配置和”x64“平台本地Windows调试器运行测试以下代码:

    #include <stdio.h> 
    int main()
    {
        printf("Hello, World! \n");
        return 0;
    }
    
    #include <iostream>
    using namespace std;  // 不加该行,cout要使用std::cout
    int main()
    {
        cout << "Hello, world!" << endl;
        return 0;
    }
    

OpenCV安装(简单)

参考博文-CSDN

  • opencv官网下载windows最新版的4.5.5,将其extractD:\C_Env\openCV,主要文件:sourcebuild

  • 环境变量配置:添加pathD:\C_Env\openCV\build\x64\vc15\bin,在cmd窗口使用opencv_version命令,输出版本号即为配置成功。

Opencv安装(复杂)【未实现】

opencv源码压缩包下载

参考博文①参考博文②

github上的openCV仓库

  • opencv仓库中包含了opencv的源码。相当于上述简单安装中sources文件夹中的内容,只不过由于版本原因,可能稍有不同;
  • opencv_contrib仓库包含了还未测试稳定的新功能。

分别在https://github.com/opencv/opencv/tagshttps://github.com/opencv/opencv_contrib/tags页面,下载opencv的.zip压缩包。

下载好后,将解压好的两个文件夹放在D:\C_Env\openCV里。

Cmake下载与配置生成

CMake这个名字是“cross platform make”的缩写,它是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性。只是 CMake 的组态档取名为 CMakeLists.txt。Cmake 并不直接建构出最终的软件,而是产生标准的建构档(如 Unix 的 Makefile 或 Windows Visual C++,然后再依一般的建构方式使用。这使得熟悉某个集成开发环境(IDE)的开发者可以用标准的方式建构他的软件。

CMake快速入门

  • 下载

官网地址https://cmake.org/,【2022-04】下载的是3.23版本,在cmd窗口使用cmake --version命令查看版本。

  • 配置(configure)生成(generate)

注意: cmake 在配置过程中,会自动下载一些文件,例如 opencv_ffmpeg.dll 等,因此需要保持网络畅通。

打开在下载文件bin中的cmake_gui.exe

where is the source code 即为上文解压出的opencv源码;

where to build the binaries 即为cmake后的文件保存路径。

设置好路径之后,点击 Configure ,弹出窗口:

点击 Finish 按钮,此时主界面的 Configure 按钮变为 Stop,表示配置进行中

注意:如遇到问题,先检查错误信息;再点击File -> Delete Cache,退出 cmake-gui,并将 build 文件夹下的内容清空,再重复以上步骤。

Configure 依次结束后,如果 cmake 的主界面仍有红色区域,则再次点击 Configure 进行配置,直到红色区域完全消失:

下图是 Configure 完成后的界面,红色消失,只剩白色的区域:

找到 Name 下的 OPENCV_EXTRA_MODULES_PATH,为其设置 opencv_contrib-4.3.0 的路径 ,精确到 /modules 目录:

再次点击 Configure 进行配置,可能需要两三次之后,红色区域才能完全消失。

最后,点击 Generate,出现 “Generating done” 则意味着 cmake 的工作结束了。

VS编译

博文:OpenCV 之 编译配置 4.6.0的步骤如下:

用 Visual Studio 打开 OpenCV.sln,分别在 Debug 和 Release 配置下【debug版与release版的区别:debug版有检测数据是否溢出的功能,release相对反应速度快。】,点击生成—>重新生成解决方案,编译该工程,顺利完成后的效果:

编译完成后,在相应的 libbin 文件夹中,分别找到 debug/release.lib 静态库 和 .dll 动态库,拷贝到 3rdparty\opencv 中。

博文:opencv安装和配置完整版教程还有以下几个步骤(感觉多出这几步靠谱点):

解决方案资源管理器—>CMakeTargets—>ALL_BUILD—>生成

生成Intall安装文件解决方案资源管理器—>CMakeTargets—>INSTALL—>仅用于项目—>仅生成INSTALL(B)

最后到自定义的build文件夹确认一下,找到install文件夹,进去查看里面的内容(如下图

环境变量配置同简单配置

Visual Studio项目属性表

在新项目中使用opencv依赖库和include文件需要配置项目属性

  • 属性管理器【单击 visual studio 上方的视图,在下拉栏里找到其他窗口下的属性管理器】,右键Debug | x64 —> 添加新项目属性表

  • 双击新建的项目属性表,配置属性

    • 包含目录的配置

    • 库目录的配置

  • 附加依赖项(链接器)的配置

    输入上面lib目录下的**.lib**文件名,如opencv_world455d.lib

    这里455dd结尾代表Debug配置,配置Release去掉d

    配置Release | x64同理

OpenCV测试程序

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/core/utils/logger.hpp>

using namespace std;
using namespace cv;

int main() {

    utils::logging::setLogLevel(utils::logging::LOG_LEVEL_ERROR);//只输出错误日志

    Mat image = imread("D:\\lenna.png");
    if (image.empty())
    {
        cout << "could not open or find the image..." << endl;
        return -1;
    }

    imshow("window", image);

    waitKey(0);

    cout << "hello world" << endl;

    return 0;
}

2 初识C++项目结构

VS项目基本信息

请添加图片描述

  • C++项目文件后缀为vcxproj,C#项目文件后缀为csproj,两者大同小异,都为xml格式;
  • 项目配置文件中包含对应项目依赖的编译器版本,项目环境配置,编译配置、包含文件等内容;
  • 官方不提倡直接修改项目文件内容,因为格式结构有很多规则,如果不了解格式结构和规则的话,很容易改出问题,尽可能用visual studio的属性配置页来更改.vcxproj文件;官方提倡用户配置自己的.props文件【可以复用】,并在项目文件中import进去即可,这样相当于给了一个“官方的”编辑入口;
  • .vcxproj.filters 用于项目下文件的虚拟目录;.vcxproj.user 是用户的一些相关配置;
  • .sln(.net解决方案文件)表示一个项目组,通常包含一个项目中所有的工程文件信息。一个sln文件通常由三部分组成:
    1. 文件版本;
    2. 工程信息;
    3. 全局设置。使用记事本打开可以看到 Visual Studio 2022 的 Version为 17

g++编译C++工程

对于一个helloworld.cpp程序,直接使用 g++ helloworld.cpp -o helloworld 命令编译为一个可执行文件helloworld

// helloworld.cpp
#include <iostream>
#include <vector>
#include <string>

using namespace std;

int main(){
    vector<string> msg{"hello", "c++", "world", "in", "aarch64"};
    for(const string& word:msg) cout<<word<<"";
    cout<<endl;
}

完整的步骤应该有四步——预处理,编译,汇编,链接。

前言:gcc和g++

GCC(GNU Compiler Collection,GNU编译器套件)是由GNU开发的编程语言译器。 对于用户能用的常用命令, 有 gcc 和 g++。无论是 gcc 还是 g++, 他们的定位都是 driver
driver 负责调用编译器(狭义),,把源码编译到汇编代码。比如 C 语言的编译器(狭义)是 cc1, 而 C++ 语言的编译器(狭义)是 cc1plus.
driver 再调用 as(as 命令是二进制工具集 GNU Binutils 的一员,是 GNU 推出的一款汇编语言编译器集,用于将汇编代码编译为二进制代码,它支持多种不同类型的处理器), 把汇编代码变成二进制代码。 最后调用 ld(ld 合并一组目标文件(object)和 库文件(archive), 重定位 数据部分,构建符号引用(symbol reference).一般说来说,编译生成可执行文件的最后步骤就是调用 ld),把二进制代码拼在一起。

gcc 和 g++ 的区别无非就是调用的编译器不同,并且传递给链接器的参数不同。

g++ 会把 .c 文件当做是 C++ 语言 (在 .c 文件前后分别加上 -xc++-xnone, 强行变成 C++), 从而调用 cc1plus 进行编译.

g++ 遇到 .cpp 文件也会当做是 C++, 调用 cc1plus 进行编译.

g++ 还会默认告诉链接器, 让它链接上 C++ 标准库.

gcc 会把 .c 文件当做是 C 语言. 从而调用 cc1 进行编译.

gcc 遇到 .cpp 文件, 会处理成 C++ 语言. 调用 cc1plus 进行编译.

gcc 默认不会链接上 C++ 标准库.

编译过程

  1. 预处理——.cpp文件–>.i文件
//将输入的.cpp文件预处理成.i文件
//注意-o选项后面接生成的文件名
g++ -E hello.cpp -o hello.i
//可以在linux终端使用cat语句查看hello.i文件
  1. 编译——.i文件–>.s文件
//将.i文件编译为汇编代码文件.s
g++ -S hello.cpp -o hello.s
  1. 汇编——.s文件–>.o文件
//将.s汇编文件再次编译为机器代码文件.o文件
g++ -c hello.s -o hello.o
  1. 链接——.o文件–>bin文件
//将.o机器代码文件链接起来(如果有多个cpp文件就需要链接)
g++ hello.o -o hello

编译过程中的一些重要参数

  • -g,该选项告诉GCC产生能被GNU调试器GDB使用的调试信息,以调试程序

    产生带调试信息的可执行文件g++ -g hello.cpp -o hello,注意到这个-g选项加在了g++后面,其实这个参数的位置放哪里都无所谓,也可以这样g++ hello.cpp -o hello -g,下面要讲的其他的参数的位置也是同样无所谓的。

  • -0,优化源代码

    例如省略掉代码中从未使用过的变量、直接将常量表达式用结果值代替等等。
    -01为默认优化;-02除了完成-01的优化之外,还进行一些额外的调整工作,如指令调整等。g++ -O2 hello.cpp -o hello
    -03则包括循环展开和其他一些与处理特性相关的优化工作。

  • -l或者-L,指定库文件|指定库文件路径
    -l(小写)指定程序要链接的库,然后不用带空格直接写要连接的库名(在/lib/usr/lib/usr/local/lib里的库直接用-l参数就能链接,不用后面的-L参数指定库文件所在目录)
    -L参数跟着就是库文件所在的目录名。
    例如:

    ​ 1)g++ -lglog hello.cpp -o hello链接glog库

    ​ 2)g++ -L/home/dir1/test -ltest hello.cpp -o hello链接/home/dir1/test -ltest目录下的test库

  • -I系统里的inlude头文件,一般是不用指定的,gcc知道去哪里找,但是如果不是系统头文件的话,就需要指定include文件所在目录。

    例如我们的某一个C++项目的文件结构如下:可以看到要编译这个工程需要编译两个cpp文件,而且还要注意到有一个头文件在当前项目的根目录下的include目录下,因此编译这个工程的的语句g++ -Iinclude main.cpp src/add.cpp -o main这也是我们使用g++编译一般多文件C++工程的方法。

  • -Wall打印警告信息

  • -w关闭警告信息

  • -std==C++11使用C++11标准编译

  • -o指定输出文件名

  • -D定义宏,例如-DDebug定义Debug宏,可能文件中有Debug宏部分的相关信息,用个Gebug来选择开启或关闭Debug

编译链接生成静态链接库和动态链接库

对于上文提到的项目结构

  1. 将add.h与add.cpp编译链接生成静态库
##进入src目录下
$cd src
#汇编,生成add.o文件
g++ add.cpp -C -I../include
#生成静态库libadd.a
ar rs 1ibadd.a add.o 
##回到上级目录
$cd ..
#链接,生成可执行文件: staticmain
g++ main.cpp -Iinclude -Lsrc -1add -o stati_cmain
  1. 将add.h头文件与add.cpp编译链接为动态链接库
##进入src目录下
$cd src
#生成动态库libadd.so
g++ add.cpp -I../include -fPIC -shared -o 1ibadd.so
##上面命令 等价于以下两条命令
# gcc add.cpp -I../include -c -fPIC
# gcc -shared -o libadd.so add.o
##回到上级目录
$cd ..
#链接,生成可执行文件:sharemain
g++ main.cpp -Iinclude -Lsrc -1add -o sharemain

3 OpenCV基础入门【C++】

简单的说,OpenCV就是将众多图像处理模块,集成在一起的 软件开发工具包(Software Development Kit, SDK),其自身并不复杂。

.hpp文件

hpp(是Header Plus Plus 的简写),其实质就是将.cpp的实现代码混入.h头文件当中,定义与实现都包含在同一文件,则该类的调用者只需要include该hpp文件即可,无需再 将cpp加入到project中进行编译。而实现代码将直接编译到调用者的obj文件中,不再生成单独的obj,采用hpp将大幅度减少调用 project中的cpp文件数与编译次数,也不用再发布烦人的lib(静态库)与dll(动态库),因此非常适合用来编写公用的开源库。

Qt

Qt 是一个1991年由Qt Company开发的跨平台]C++图形用户界面应用程序开发框架。它既可以开发GUI程序,也可用于开发非GUI程序,比如控制台工具和服务器。Qt是面向对象的框架,使用特殊的代码生成扩展(称为元对象编译器(Meta Object Compiler, moc))以及一些【(英语:Macro)是一种批量处理的称谓,宏是一种抽象(Abstraction),它根据一系列预定义的规则替换一定的文本模式。解释器或编译器在遇到宏时会自动进行这一模式替换】,Qt很容易扩展,并且允许真正地组件编程。

模块功能
imgcodecsimage file reading and writing
imgprocimage processing,重要的图像处理模块,主要包含:图像滤波、几何变换、直方图、特征检测、目标检测等
highguihigh-level GUI,包含创建和操作显示图像的窗口、处理鼠标事件及键盘命令、提高图形交互可视化界面等
calib3dcalibration(校准)和 3D 两个术语的缩写组合而成
core核心功能模块,主要包含 OpenCV库的基础结构以及基本操作
dnn深度学习模块,是 OpenCV4版的一个特色,目前仅适用与正向传递计算(测试网络),原则上不支持反向计算(训练网络)
feature2dfeature(特征)和 2D ,其功能主要为处理图像特征点
flann快速近似最邻近库(Fast Library for Approximate Nearest Neighbors),是高维的近似近邻快速搜索算法库,主要包含快速近似近邻搜索、聚类等
gapi是 OpenCV4.0 中新增模块,旨在加速常规的图像处理。与其他模块相比,这个模块主要充当框架,而不是某些特定的计算机视觉算法
ml机器学习模块,主要包括:统计分类、回归、数据聚类等
objdetect目标检测模块,主要用于图像的目标检测,如检测 Haar 特征
photo计算摄像模块,主要包含图像修复、去噪等
stitching图像拼接模块,主要包含:特征点寻找与匹配图像、估计旋转、自动校准、接缝估计等图像拼接过程的相关内容
video视频分析模块,主要包含:运动估计、背景分离、对象跟踪等视频处理等
videoio视频输入/输出模块,主要用于读取、写入视频 或者图像序列

①读取图片/视频/摄像头

从文件读取图片

Mat cv::imread(const String &filename, int flags = IMREAD_COLOR)

从文件加载图像。函数imread从指定文件加载图像并返回。 如果无法读取图像(由于缺少文件、权限不正确、格式不受支持或无效),该函数将返回一个空矩阵( Mat::data==NULL )。在彩色图像的情况下,解码图像的通道将以 B G R 顺序存储

void cv::imshow(cosnst String &winnanme, InputArray mat)

在指定窗口中显示图像。这个函数后面应该是 cv::waitKey 函数,它显示指定毫秒的图像。否则,它不会显示图像。例如,waitKey(0) 将无限显示窗口,直到有任何按键(适用于图像显示)。 waitKey(25) 将显示一帧 25 毫秒,之后显示将自动关闭。(如果你把它放在一个循环中读取视频,它会逐帧显示视频)

int cv::waitKey(int delay = 0)

等待按下的键。函数 waitKey 无限等待按键事件(当 delay≤0 时)或延迟毫秒,当它为正时。由于操作系统在切换线程之间有最短时间,因此该函数不会完全等待延迟毫秒,它会至少等待延迟毫秒,具体取决于当时您计算机上正在运行的其他内容。如果在指定的时间过去之前没有按下任何键,则返回被按下键的代码或 -1。

waitKey(0)将无限显示窗口,直到任何按键(适合图像显示);waitKey(1)将显示一个帧,持续1毫秒,之后将自动关闭显示。

从文件读取视频

要捕获视频,需要创建一个VideoCapture对象。它的参数可以是视频文件的名称或设备索引。
OpenCV3.4.6中VideoCapture类构造函数及成员函数:

  • cv::VideoCapture::VideoCapture()
  • cv::VideoCapture::VideoCapture(const String &filename)
  • cv::VideoCapture::VideoCapture(const String &filename, int apiPreference)
  • cv::VideoCapture::VideoCapture(int index)
  • cv::VideoCapture::VideoCapture(int index, int apiPreference)

打开视频文件或捕获设备或 IP 视频流进行视频捕获

virtual bool cv::VideoCapture::isOpened() const

如果视频捕获已经初始化,则返回true。如果先前对 VideoCapture 构造函数或VideoCapture::open()的调用成功,则该方法返回 true。

virtual bool cv::VideoCapture::read(OutputArray image)

抓取、解码并返回下一个视频帧

virtual double cv::VideoCapture::get(int proId) const

返回指定的VideoCapture属性proId值参考博文:https://blog.csdn.net/weixin_41010198/article/details/88535234

virtual double cv::VideoCapture::set(int proId, double value)

VideoCapture中设置一个属性

②基础函数

void cv::cvtColor(InputArray src, OutputArray dst, int code, int dstCn = 0)

将图像从一种颜色空间转换为另一种颜色空间。在从 RGB 颜色空间转换的情况下,应明确指定通道的顺序(RGB 或 BGR)。OpenCV 中的默认颜色格式通常称为 RGB,但实际上是 BGR(字节反转)。因此,标准(24 位)彩色图像中的第一个字节将是 8 位蓝色分量,第二个字节将是绿色,第三个字节将是红色。 然后第四、第五和第六个字节将是第二个像素(蓝色,然后是绿色,然后是红色),依此类推。

void cv::GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, doube sigmaY = 0, int borderType = BORDER_DEFAULT)

使用高斯滤波器模糊图像。该函数将源图像与指定的高斯核进行卷积。

void cv::Canny(InputArray image, OutputArray edges, double threshold1, double threshold2, int apertureSize = 3, bool L2gradient = false)

使用 Canny 算法在图像中查找边缘

Mat cv::getStructuringElement(int shape, Size ksize, Point anchor = Point(-1, -1))

返回指定大小和形状的结构元素,用于形态学操作(???)。该函数构造并返回可以进一步传递给腐蚀、扩张或形态学的结构元素。 也可以自己构建任意二进制掩码并将其用作结构元素。

void cv::dilate(InputArray src, OutputArray dst, InuputArray kernel, Point anchor = Point(-1, -1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar &borderValue = morphologyDefaultBorderValue())

使用特定的结构元素膨胀图像

void cv::erode(InputArray src, OutputArray dst, InuputArray kernel, Point anchor = Point(-1, -1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar &borderValue = morphologyDefaultBorderValue())

使用特定的结构元素腐蚀图像

void cv::resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation = INTER_LINEAR)

调整图像的大小。函数 resize 将图像 src 的大小缩小到或放大到指定的大小。请注意,不考虑初始 dst 类型或大小。相反,大小和类型是从 src、dsize、fx 和 fy 派生的。

③绘制图像、文字

void cv::circle(InputOutputArray img, Point center, int radius, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)

函数 cv::circle 用给定的中心和半径绘制一个简单的或实心圆

void cv::rectangle(InputOutputArray img, Point pt1, Point pt2, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)

void cv::rectangle(Mat &img, Rect rec, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)

绘制一个简单的、粗的或填充的右上矩形。函数 cv::rectangle 绘制一个矩形轮廓或两个对角为 pt1 和 pt2 的填充矩形。

void cv::line (InputOutputArray img, Point pt1, Point pt2, const Scalar &color, int thickness=1, int lineType=LINE_8, int shift=0)

绘制连接两点的线段。函数line绘制图像中 pt1 和 pt2 点之间的线段。

void cv::putText (InputOutputArray img, const String &text, Point org, int fontFace, double fontScale, Scalar color, int thickness=1, int lineType=LINE_8, bool bottomLeftOrigin=false)

绘制一个文本字符串。函数 cv::putText 在图像中呈现指定的文本字符串。无法使用指定字体呈现的符号将替换为问号。

④透视变换

Mat cv::getPerspectiveTransform (const Point2f src[], const Point2f dst[])

返回相应 4 个点对的 3x3 透视变换

void cv::warpPerspective (InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar &borderValue=Scalar())

对图像应用透视变换

注:文档扫描用到这种变换技术

⑤颜色检测

void cv::inRange (InputArray src, InputArray lowerb, InputArray upperb, OutputArray dst)

检查数组元素是否位于其他两个数组的元素之间。

void cv::namedWindow (const String &winname, int flags = WINDOW_AUTOSIZE)

创建一个窗口。函数namedWindow创建一个可用作图像和轨迹栏占位符的窗口。创建的窗口由它们的名称引用。如果同名的窗口已经存在,则该函数不执行任何操作。

int cv::createTrackbar (const String &trackbarname, const String &winname, int *value, int count, TrackbarCallback onChange = 0, void *userdata = 0)

创建一个trackbar并将其附加到指定窗口。函数createTrackbar创建一个具有指定名称和范围的trackbar(滑块或范围控件),分配一个变量值作为与trackbar同步的位置,并指定回调函数onChange为 在跟踪栏位置变化时被调用。创建的轨迹栏显示在指定的窗口winname中。

⑥形状/轮廓检测

void cv::findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset = Point())

在二值图像中查找轮廓。从OpenCV3.2开始源图像不会被这个函数修改。

  • image:二值输入图像
  • contours:检测到的轮廓,每个轮廓都存储为点向量(例如 std::vector<std::vector<cv::Point> >
  • hierarchy:可选的输出向量(例如 std::vector<cv::Vec4i>),包含有关图像拓扑的信息
  • mode:轮廓检索模式
  • method:轮廓近似方式
  • offset:每个轮廓点移动的可选偏移量

double cv::contourArea(InputArray contour, bool oriented=false)

计算轮廓区域

double cv::arcLength(InputArray curve, bool closed)

计算曲线长度或闭合轮廓周长

void cv::approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool closed)

函数cv::approxPolyDP用另一个具有较少顶点的曲线/多边形来逼近一条曲线或多边形,以使它们之间的距离小于或等于指定的精度

Rect cv::boundingRect(InputArray array)

计算并返回指定点集或灰度图像非零像素的最小上边界矩形

void cv::drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar &color, int thickness = 1, int lineType = LINE_8, InputArray hierarchy = noArray(), int maxLevel = INT_MAX, Point offset = Point())

绘制轮廓轮廓或填充轮廓。如果厚度≥0,该函数在图像中绘制轮廓轮廓,如果厚度<0,则填充轮廓所包围的区域。

Point_< _Tp > tl() constPoint_< _Tp > br() const

左上角右下角

//rect
template<typename _Tp> class cv::Rect_< _Tp >
typedef Rect_<int> cv::Rect2i
typedef Rect2i cv::Rect
//point
template<typename _Tp> class cv::Point_< _Tp >
typedef Point_<int> cv::Point2i
typedef Point2i cv::Point
    
/*
cv::Rect_< _Tp >类属性
	height:矩形高度
	width:矩形宽度
	x:左上角的x坐标
	y:左上角的y坐标
*/
  • 5
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: OpenCV是一个开源的计算机视觉库,可以应用于人脸识别、图像处理、目标检测等领域。在面部识别项目中,使用C语言可以实现高效的算法和优化。 首先,我们需要安装OpenCV,并在C语言中包含对应的头文件。可以使用相机或者视频录像来捕捉人脸图像。OpenCV提供了许多人脸识别的算法,包括基于统计模型的方法和机器学习方法,如Haar级联分类器、LBPH算法等。 人脸识别的主要步骤是:人脸检测、人脸对齐和特征提取、特征匹配和识别。 在人脸检测阶段,可以使用Haar级联分类器或者基于深度学习的方法来检测人脸区域。这些方法可以检测出图像中的人脸,从而进行后续的处理。 在人脸对齐和特征提取阶段,我们可以使用一些几何变换方法来对人脸进行归一化,以便后续的特征提取和匹配。通过对齐的人脸图像,可以提取出辨别人脸的关键特征点,如眼睛、鼻子、嘴巴等。 特征匹配和识别阶段是通过比较提取出的人脸特征与已知的人脸特征进行匹配来识别人脸。可以使用各种分类器方法来进行特征匹配和识别,如支持向量机(SVM)、K最近邻(KNN)等。 最后,在程序中使用OpenCV提供的函数和算法,实现人脸识别功能,将识别结果可视化或者保存下来。 总结来说,通过使用OpenCV的人脸识别算法,结合C语言的高效性能,可以实现一个功能强大的人脸识别工程,用于各种场景中,如人脸门禁系统、表情识别、人脸表情合成等。 ### 回答2: OpenCV是一种开源的编程库,可用于进行图像处理和计算机视觉方面的应用开发。其中一个常见的应用便是人脸识别。 人脸识别是利用计算机视觉技术来识别和验证人脸的过程。通过OpenCV提供的人脸识别功能,我们可以实现以下步骤: 1. 获取图像:首先,我们需要从摄像头或文件中获取图像数据。OpenCV提供了相应的函数来读取图像数据。 2. 人脸检测:接下来,我们需要使用OpenCV的人脸检测器来检测图像中的人脸。这个功能基于机器学习算法,可以自动识别图像中的人脸位置。 3. 特征提取:在检测到人脸之后,我们可以使用OpenCV提供的函数来提取人脸的特征。这些特征可以用于将每个人脸区分开来,例如眼睛位置、嘴巴形状等。 4. 人脸识别:将特征应用于人脸识别算法,该算法可以根据人脸特征来辨识不同的个体。OpenCV提供了多种人脸识别算法,例如Eigenfaces、Fisherfaces和LBPH(Local Binary Patterns Histograms)。 5. 结果显示:最后,我们可以使用OpenCV提供的图像处理函数将识别结果显示在图像上。例如,将识别到的人脸用边框标记出来,或者在图像上标注人脸的姓名等信息。 总结来说,通过OpenCV人脸识别功能,我们可以实现从图像中检测、提取和识别人脸的过程。这种技术广泛应用于安全监控、人脸解锁、人脸支付等领域。并且,OpenCV提供了丰富的函数和算法来实现这些功能,为人脸识别应用开发提供了便利。 ### 回答3: OpenCV是一款广泛应用于计算机视觉领域的开源库,它提供了一系列用于图像处理和机器学习的函数和算法。其中,人脸识别是OpenCV中的一个重要应用之一。 OpenCV人脸识别C工程是基于OpenCV库开发的一个C语言工程,用于识别和分析人脸。它可以通过摄像头或已保存的图像,实现从图像中识别出人脸,并进行相应的特征提取、比对和识别。 该工程主要包括以下几个步骤: 1. 人脸检测:通过使用OpenCV中的人脸检测器,如Haar级联分类器或深度学习模型(如基于卷积神经网络的人脸检测器),对输入图像进行人脸检测。这一步骤主要用于确定图像中可能存在的人脸位置。 2. 人脸对齐:在检测到人脸后,需要将人脸对齐到一个标准姿势,这可以通过对检测到的人脸进行旋转、缩放和平移等操作来实现。人脸对齐可以提高后续的人脸特征提取和比对的准确性。 3. 人脸特征提取:对已对齐的人脸图像进行特征提取,常用的方法包括主成分分析(PCA)、线性判别分析(LDA)等。这一步骤将人脸图像转换为一个高维特征向量,以表示人脸的唯一特征。 4. 人脸比对和识别:将已提取的人脸特征与已有的人脸特征库进行比对,通过计算特征向量之间的相似度,确定图像中的人脸是否匹配已有的人脸信息,以实现人脸识别的功能。 在实际应用中,OpenCV人脸识别C工程可以应用于各种场景,如人脸解锁、人脸考勤、人脸验证等。它具有较高的准确性和实时性,并且可以在嵌入式设备上运行,满足不同领域的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值