栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

Python+OpenCV实用案例应用教程:深度估计和分割

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Python+OpenCV实用案例应用教程:深度估计和分割

章首先将展示如何使用深度摄像头的数据识别前景和背景区
域,这样我们就可以把效果只限制在前景或背景上。
介绍完深度摄像头后,本章将介绍深度估计的其他技术,即立体
成像以及运动结构(Structure from Motion,SfM)。运动结构技术
并不需要深度摄像头,相反,这些技术利用一台或多台普通摄像头从
多个角度捕捉主体的图像。
最后,本章将介绍允许我们从单幅图像提取前景对象的分割技
术。本章结尾处,将介绍一些把图像分割成多个深度或多个对象的方
法。
本章将介绍以下主题:
·利用深度摄像头捕捉深度图、点云图、视差图、基于可见光的
图像以及基于红外光的图像。
·将10位图像转换成8位图像。
·将视差图转换成区分前景和背景区域的掩模图像。
·利用立体成像或SfM创建视差图。
·利用GrabCut算法将图像分割成前景和背景区域。
·利用分水岭(Watershed)算法将图像分割成可能是不同对象的
多个区域。
4.1  技术需求
本章使用了Python、OpenCV以及NumPy。本章的一些部分使用了华
硕Xtion PRO等深度摄像头,以及OpenCV对OpenNI 2的可选支持(以便
从深度摄像头捕捉图像)。安装说明请参阅第1章。本章还使用了
Matplotlib来进行图表制作。要安装Matplotlib,请运行$pip
install matplotlib(或者根据环境运行$pip3 install
matplotlib)。
本章的完整代码可以在本教程的GitHub库
(https://github.com/PacktPublishing/Learning-OpenCV-4-
Computer-Vision-with-Python-Third-Edition)的chapter04文件夹
中找到。示例图像在本教程GitHub库的images文件夹中。
4.2  创建模块
为了帮助构建深度摄像头的交互式demo,我们将重用在第2章和第
3章中开发的Cameo项目的大部分。大家应该还记得,我们设计了Cameo
来支持各种输入,因此可以轻松地对其进行调整以支持特定的深度摄
像头。我们将添加代码来分析图像中的深度层,以便找到主区域,如
坐在摄像头前的人的脸。找到这个区域后,将其余的全都涂成黑色。
有时把这种类型的效果应用于聊天应用程序来隐藏背景,以便用户有
更多的隐私。
在Cameo.py外部会重用操控深度摄像头数据的代码,因此我们应
该将其分到一个新的模块。在Cameo.py的同一目录下创建文件
depth.py。在depth.py中,我们需要使用下面的import语句:

应用程序会使用与深度相关的功能,因此将下面的import语句添
加到Cameo.py:

 

我们还将修改CaptureManager.py,但是不需要向其添加任何新的
import语句。
既然我们已经对将要创建或者修改的模块有了一个简单的了解,
那么让我们更深入地了解深度这一主题吧。

4.3  从深度摄像头捕捉帧
回到第2章,我们讨论过计算机可以有多个视频捕捉设备,并且每
个设备可以有多个通道等概念。假设给定的设备是深度摄像头。每个
通道可能对应不同的镜头和传感器。此外,每个通道可能对应不同类
型的数据,例如,普通彩色图像和深度图。OpenCV(通过其可选支持
OpenNI 2)允许我们从深度摄像头请求以下任一通道(尽管给定的摄
像头可能只支持其中一些通道):
·cv2.CAP_OPENNI_DEPTH_MAP:这是一张深度图——一幅灰
度图像,其中每个像素是从摄像头到曲面的估计距离。具体来说,每
个像素值是一个16位无符号整数,表示深度测量结果(以毫米为单
位)。
·cv2.CAP_OPENNI_POINT_CLOUD_MAP:这是一张点云图
——一幅彩色图像,其中每种颜色都对应一个x、y或者z的空间维度。
具体来说,通道产生一幅BGR图像,从摄像头的角度来看,B是x(蓝
色是右)、G是y(绿色是上面)、R是z(红色是深度)。数值以米为
单位。
·cv2.CAP_OPENNI_DISPARITY_MAP或
cv2.CAP_OPENNI_DISPARITY_MAP_32F:这些是视差图——灰度图
像,其中每个像素值是一个曲面的立体视差。为了概念化立体视差,
假设叠加了从不同视角拍摄的一个场景的两幅图像。结果会类似于看
到重影。对于场景中任意一对孪生物体上的点,我们可以用像素来度
量距离。此度量结果就是立体视差。近的物体比远的物体表现出更大
的立体视差。因此,在视差图中,近的物体显得更亮。
cv2.CAP_OPENNI_DISPARITY_MAP是用8位无符号整数值表示的视差
图,cv2.CAP_OPENNI_DISPARITY_MAP_32F是用32位浮点值表示的
视差图。
·cv2.CAP_OPENNI_VALID_DEPTH_MASK:这是一个有效的深
度掩模,用于显示给定像素处的深度信息是有效的(显示为非零值)
还是无效的(显示为零值)。例如,如果深度摄像头依赖于红外发光
器(红外闪光灯),在该光线遮挡(阴影)的区域深度信息是无效
的。
·cv2.CAP_OPENNI_BGR_IMAGE:这是捕捉可见光的摄像头采
集的一幅普通BGR图像,每个像素的B、G和R值都是8位无符号整数。
·cv2.CAP_OPENNI_GRAY_IMAGE:这是捕捉可见光的摄像头采
集的一幅普通单色图像,每个像素值都是一个8位无符号整数。
·cv2.CAP_OPENNI_IR_IMAGE:这是捕捉红外(Infrared,IR)
光(特别是光谱的近红外(Near Infrared,NIR)部分)的摄像头拍摄
的一幅单色图像。每个像素值都是一个16位无符号整数。通常情况
下,摄像头实际上不会使用整个16位范围,而是使用其中的一部分
(比如10位范围),但数据类型仍然是16位整数。虽然近红外光对人眼
来说是看不见的,但是在物理上近红外光与红光非常相似。因此,对
人来说,摄像头的近红外图像看上去并不一定很奇怪。但是,典型的
深度摄像头不仅采集近红外光,而且还能投射出网格状近红外光模
式,从而有利于使用深度搜索算法。因此,我们可能会在深度摄像头
的近红外图像中看到可识别的人脸,但是脸部可能点缀着明亮的白
光。
我们来看其中一些图像类型的示例。图4-1显示了一个点云图,图
中一个男人坐在一只猫的雕塑后面。

 

同一场景下的视差图,如图4-2所示。图4-3是大家熟悉的猫雕塑
和男人的一个有效的深度掩模图。

 

 

接下来,我们来考虑一下如何在交互式应用程序(如Cameo)中,
使用深度摄像头中的一些通道。
4.4  将10位图像转换成8位图像
正如前面提到的,深度摄像头的某些通道使用大于8位的数据范
围。大的范围对于计算是有用的,但是不方便显示,因为大多数计算
机显示器只能使用每个通道8位(范围是[0,255])的格式。
OpenCV的cv2.imshow函数重新缩放并截断给定的输入数据,以便
转换为可显示的图像。具体来说,如果输入图像的数据类型是16位无
符号整数或者32位有符号整数,那么cv2.imshow会将数据除以256并将
其截断成8位无符号整数范围[0,255]。如果输入图像的数据类型是32
位或者64位浮点数,cv2.imshow将假设数据范围是[0.0,1.0],因此它
将数据乘以255,并将其截断为8位无符号整数范围[0,255]。通过重新
缩放数据,cv2.imshow依赖于它对原始尺度的朴素假设。这些假设在
某些情况下是错误的。例如,如果图像的数据类型是16位无符号整
数,但是实际数据范围是10位无符号整数(范围是[0,1023]),使用
cv2.imshow来转换这个图像就会使图像看起来很暗。
考虑图4-4所示的用10位灰度摄像头拍摄的一只眼睛的图像。在图
4-4的左边,我们可以看到从10位尺度到8位尺度的转换结果正确。在
图4-4的右边,我们看到基于图像使用16位尺度的错误假设的转换结果
错误。
转换不正确的图像看起来是全黑色的,因为我们对尺度的假设相
差很大:6位或者64的倍数。如果依赖cv2.imshow来自动转换为8位尺
度,那么就可能会发生这样的错误。

 

当然,为了避免此类问题,我们可以自己进行图像转换,然后将
生成的8位图像传递给cv2.imshow。修改managers.py(Cameo项目中已
有的一个脚本),以便提供一个把10位图像转换成8位图像的选项。我
们会提供shouldConvertBitDepth10To8变量,开发者可以将其设置为
True或者False。下面的代码块(修改的内容为粗体)显示了如何初始
化这个变量:

 

接下来,修改frame属性的getter以支持转换。如果
shouldConvertBit-Depth10To8是True,且帧的数据类型是16位无符号
整数,那么我们将假设帧实际为10位范围,并将其转换成8位。转换
时,我们将应用向右移位操作“>>2”,截断两个最低有效位。这等价
于整数除以4。下面是有关代码:

 

有了这些修改,我们将能够更容易地操纵和显示来自某些通道的
帧,尤其是cv2.CAP_OPENNI_IR_IMAGE。接下来,我们来看一个函数的
示例,利用cv2.CAP_OPENNI_DISPARITY_MAP和
cv2.CAP_OPENNI_VALID_DEPTH_MASK通道操控帧,以便创建隔离某物
(比如用户的脸部)的掩模。之后,我们将考虑如何在Cameo中一起使
用这些通道。
4.5  由视差图创建掩模
假设用户的脸部或者其他感兴趣的对象占据了深度摄像头的大部
分视野。但是,图像还包括一些其他非感兴趣内容。通过分析视差
图,我们可以知道矩形内的一些像素是异常值——太近或者太远,不
可能真正成为脸部或者其他感兴趣的对象的一部分。我们可以制作掩
模来排除这些异常值。但是,我们应该只在数据有效的地方应用这个
测试,如有效深度掩模所示。
我们编写一个函数来生成掩模,图像中被拒绝区域的掩模值为0,
被接受区域的掩模值为255。函数应该使用视差图、有效深度掩模以及
可选的矩形作为参数。如果指定了矩形,那么会制作与指定区域大小
相同的掩模。在稍后的第5章中,这会很有用,届时将利用人脸检测器
寻找包围人脸的矩形框。我们调用createMedianMask函数,并在
depth.py中对其进行实现,如下所示:

 

要想识别视差图中的异常值,首先,我们使用numpy.median(接
受数组作为参数)找到中位数。如果数组长度是奇数,median返回数
组(已排好序)的中间值。如果数组长度是偶数,median返回两个最
靠近数组中间位置的值的平均值。
要根据每个像素的布尔运算生成掩模,我们使用具有3个参数的
numpy.where。在第1个参数中,where接受一个数组,该数组元素值为
真或者假。返回相同维度的输出数组。只要输入数组中的元素为
True,where函数的第2个参数就分配给输出数组中对应的元素。相
反,只要输入数组中的元素为False,where函数的第3个参数就分配给
输出数组中对应的元素。
当一个像素的有效视差值与中位数视差值相差12或者更多时,实
现就将其视为异常值。通过实验,我们选择的值刚好为12。稍后,你
可以根据使用特定摄像头设置运行Cameo时遇到的结果随意调整此值。
4.6  修改应用程序
打开Cameo.py文件,该文件包含我们在第3章中最后修改的Cameo
类。这个类实现了一个可以很好处理普通摄像头的应用程序。我们不
一定要替换这个类,但是我们想创建这个类的一种变体,改变一些方
法的实现,以便用深度摄像头。为此,创建一个子类,继承一些Cameo
行为并重载其他行为。我们称它为CameoDepth子类。将下面的代码行
添加到Cameo.py(Cameo类之后,__mail__代码块之前)以将
CameoDepth声明为Cameo的子类:

 

我们将重载或者重新实现CameoDepth中的__init__方法。因此
Cameo用普通摄像头的设备索引来实例化CaptureManager类,
CameoDepth则需要使用深度摄像头的设备索引。CameoDepth可以是
cv2.CAP_OPENNI2(代表微软Kinect的设备索引)或者
cv2.CAP_OPENNI2_ASUS(代表华硕Xtion PRO或者Occipital结构的设
备索引)。下面的代码块展示了CameoDepth的__init__方法的示例实
现(与Cameo的__init__方法的不同之处用粗体表示),但是你可以修
改它,取消对设置的相应设备索引的注释:

 

类似地,我们将重载run方法以便使用深度摄像头的一些通道。首
先,我们将试着检索视差图,然后是有效深度掩模,最后是BGR颜色图
像。如果没有可以检索的BGR图像,这可能意味着深度摄像头没有任何
BGR传感器,在这种情况下,我们会继续检索红外灰度图像。下面的代
码片段显示了CameoDepth的run方法的开始部分:

 

采集视差图、有效深度掩模以及BGR图像或者红外灰度图像后,
run方法通过调用depth.createMedianMask函数(4.5节实现的)来继
续执行。将视差图和有效深度掩模传递给后一个函数,作为回报,我
们得到一个掩模,在深度接近中位数深度的区域掩模是白色的,在其
他区域掩模是黑色的。无论掩模是否是黑色(mask==0),我们都想把
BGR或者红外图像涂成黑色,以模糊除了图像中的主要对象之外的内
容。最后,对于BGR图像,我们希望应用在第3章中实现的艺术滤波
器。下面的代码完成了CameoDepth run方法的实现:

 

CameoDepth自己不需要任何其他方法实现,它从父类或者Cameo超
类继承适当的实现。
现在,只需要修改Cameo.py的__main__部分,就可以运行
CameoDepth类的实例(而不是Cameo类的实例)。下面是相关代码:

 

插入深度摄像头,然后运行脚本。靠近或者远离摄像头,直到可
以清晰地看到你的脸,但是背景变黑了。图4-5是用CameoDepth和华硕
Xtion PRO摄像头拍摄的。我们可以看到作者约瑟夫·豪斯正在刷牙的
一幅红外图像。代码成功地将背景涂黑,因此图像无法显示他是在房
子里、火车上还是在帐篷里刷牙。仍然很神秘。
这是考虑createMedianMask函数(4.5节实现的)输出的一个好机
会。如果将掩模为0的区域可视化为黑色,掩模为1的区域可视化为白
色,那么约瑟夫·豪斯刷牙时候的掩模如图4-6所示。
结果很不错,但是并不完美。例如,在图像的右边(从读者的角
度来看),掩模错误地包含了头发后面的阴影区域,也错误地把肩部
排除在外了。后一个问题可以通过对createMedianMask实现中的
numpy.where使用的标准进行微调来解决。
如果你足够幸运拥有多个深度摄像头,试着尝试所有的摄像头,
看看它们在支持彩色图像方面的不同,以及它们在区分近层和远层方
面的有效性。此外,尝试不同的对象和光照条件,看看它们是如何影
响(或不影响)红外图像的。当你对测试结果感到满意时,让我们转
向深度估计的其他技术(我们将在后续章节中再次回到深度摄像头这
个内容)。

 

 

4.7  基于普通摄像头的深度估计
深度摄像头是一个令人印象深度的设备,但并不是每个开发人员
或者用户都有这样的工具,而且深度摄像头也有一定的局限性。值得
注意的是,典型的深度摄像头在户外的效果不是很好,因为阳光的红
外线分量比摄像头本身的红外光源要亮得多。因为阳光的遮挡,摄像
头无法看到通常用来估计深度的红外模式。
作为替代方法,我们可以使用一个或者多个普通摄像头,根据不
同摄像头视角的三角测量估计到对象的相对距离。如果同时使用两个
摄像头,就将此方法称为立体视觉。如果使用一个摄像头,但是随时
间移动摄像头以获取不同视角的图像,就将这种方法称为运动结构。
广义上说,立体视觉技术在运动结构中也很有帮助,但是在运动结构
中,如果处理的是一个移动的主体,我们还会面临其他问题。就本章
而言,我们假设正在处理一个静止的主体。
正如许多哲学家所认同的那样,几何学是我们理解世界的基础。
更确切地说,对极几何是立体视觉的基础。对极几何是如何工作的?
从概念上讲,它沿着虚线跟踪从摄像头到图像中的每个对象,然后对
第2幅图像做同样的操作,并根据对应于同一对象的线的交点计算到对
象的距离,如图4-7所示。

 

我们来看OpenCV如何应用对极几何计算视差图。这将使我们能够
将图像分割成前景和背景的不同层。作为输入,我们需要从不同角度
拍摄同一主体的两幅图像。
像许多脚本一样,这个脚本也从导入NumPy和OpenCV开始:

 

我们为立体视觉算法的几个参数定义了初始值,代码如下所示:

 

有了这些参数,我们就创建了OpenCV的cv2.StereoSGBM类的一个
实例。SGBM表示半全局块匹配(semiglobal block matching),是一
种用于计算视差图的算法。下面是初始化对象的代码:

 

从文件中加载两幅图像:

 

我们想要提供几个滑块,让用户能够交互地调整计算视差图的算
法参数。当用户调整滑块时,我们将通过设置StereoSGBM实例的属性
更新立体视觉算法的参数,并通过调用StereoSGBM实例的compute方法
重新计算视差图。我们来看update函数(滑块的回调函数)的实现:

 

现在来看创建窗口和滑块的代码:

 

请注意,将update函数作为cv2.createTrackbar函数的一个参
数,以便在调整滑块时调用update。接下来,我们手动调用update来
初始化视差图:

 

 当用户按下任意键时,我们将关闭窗口:

我们来回顾一下这个示例的功能。我们取同一主体的两幅图像,
计算视差图,用较亮的色调显示图上离摄像头较近的点。用黑色标记
的区域代表差异。
图4-8和图4-9分别是示例中使用的第1幅图像和第2幅图像。

 

 

用户可以看到原始图像,以及一张很好且很容易解释的视差图,
如图4-10所示。
我们已经使用了许多(但不是全部)StereoSGBM支持的参数。
OpenCV文档提供了所有参数的描述,如表4-1所示。

 

 

表4-1  OpenCV中对Stereo SGBM参数的描述

 使用上述脚本,你将能够加载所选择的图像并对参数进行操作,
直到对由StereoSGBM生成的视差图满意为止。

4.8  基于GrabCut算法的前景检测
计算视差图是分割图像前景和背景的一种有效方法,但是
StereoSGBM并不是能完成这一任务的唯一算法,实际上,StereoSGBM
更多的是从二维图像中收集三维信息。但是,GrabCut是前景/背景分
割的完美工具。GrabCut算法包括以下步骤:
(1)定义包含图像主体的矩形。
(2)矩形以外的区域自动定义为背景。
(3)把包含在背景中的数据作为参考,区分用户定义的矩形内的
背景区域和前景区域。
(4)高斯混合模型(Gaussian Mixture Model,GMM)对前景和
背景建模,把未定义的像素标记为可能的背景或可能的前景。
(5)图像中的每个像素实际上都通过虚边与周围的像素相连,根
据每条边与周围像素颜色的相似程度,给出把每条边指定为前景或者
背景的概率。
(6)每个像素(或者算法中定义的节点)都连接到一个前景节点
或者背景节点。你可以将其可视化,如图4-11所示。
(7)在节点连接到任意一个终端之后(背景或者前景,也分别称
为源或者接收器),切割属于不同终端的节点之间的边(因此得名
GrabCut)。因此,图像分割成两个部分。
图4-12充分展示了该算法。

我们来看一个例子。我们从一个漂亮的天使雕像(见图4-13)开
始:
我们想抓取天使,丢弃背景。为此,创建一个相对较短的脚本,
该脚本将使用GrabCut分割图像,然后将生成的前景图像与原始图像并
排显示。我们会使用matplotlib(一个流行的Python库),它使显示
图表和图像成为一项非常简单的任务。

图4-12  GrabCut算法

 

 

实际上,代码非常简单。首先,加载希望处理的图像,然后创建
与加载的图像形状相同并用0填充的掩模:

 

然后,创建用0填充的背景和前景模型:

 

我们本可以用数据填充这些模型,但是我们将初始化GrabCut算
法,用一个矩形识别想要隔离的主体。因此,背景和前景模型将根据
初始矩形之外的区域来确定。下面的代码行定义了这个矩形:

 

现在,到了有趣的部分!我们运行GrabCut算法。我们指定空模
型、掩模以及想要用来初始化操作的矩形作为参数:

 

请注意整数参数5。它表示算法在图像上运行的迭代次数。你可以
增加迭代次数,但是在某些点,像素分类将收敛,因此实际上可能只
是增加迭代次数,而对结果没有任何进一步的改善。
在这之后,掩模将修改为包含0到3之间的值。这些值的含义如
下:

·0(也被定义为cv2.GC_BGD)是一个明显的背景像素。
·1(也被定义为cv2.GC_FGD)是一个明显的前景像素。
·2(也被定义为cv2.GC_PR_BGD)是一个可能的背景像素。
·3(也被定义为cv2.GC_PR_FGD)是一个可能的前景像素。

为了可视化GrabCut结果,将背景涂为黑色,保持前景不变。我们
可以制作另一个掩模来帮助我们完成这一任务。值0和2(明显和可能
的背景)将转换为0,值1和3(明显和可能的前景)将转换为1。其结
果会存储在mask2中。将原始图像乘以mask2,使背景变为黑色(乘以
0),同时保持前景不变(乘以1)。以下是相关代码:

 

脚本的最后一部分是并排显示图像:

 

结果如图4-14所示。

 

这是一个令人相当满意的结果。你会注意到天使手臂下方留下了
一个背景三角形。通过手动选择更多的背景区域并应用更多的迭代,
可以细化GrabCut结果。这项技术在OpenCV安装的samples/python文件
夹内的grabcut.py文件中进行了很好的说明。
4.9  基于分水岭算法的图像分割
最后,我们快速浏览一下分水岭算法。该算法之所以称为分水岭
是因为它的概念涉及水的概念。想象一下图像中的低密度区域(很少
或者没有变化)处于山谷,高密度区域(变化大)处于山峰。开始往
山谷里注水,直到两个不同山谷的水即将汇合。为了防止不同山谷的
水汇合,建造一道屏障对其进行分割。生成的屏障就是图像的分割
线。
以分割扑克牌的图像为例。我们想要将数字牌(大的可数符号)
从背景中分割出来:
(1)同样,通过导入numpy、cv2和matplotlib来开始脚本。然
后,从文件加载一张扑克牌的图像:

 

(2)把图像从彩色转换为灰度,对其进行阈值化。此操作将图像
分成黑色和白色两个区域:

 

(3)接下来,通过对其应用形态学变换去除阈值图像的噪声。形
态学是通过一系列步骤对图像的白色区域进行膨胀(扩张)或者腐蚀
(收缩)。我们将应用形态学开运算,包括腐蚀步骤和膨胀步骤。开
运算使大的白色区域吞噬小的黑色区域(噪声),大的黑色区域(真
实对象)相对不变。具有cv2.MORPH_OPEN参数的cv2.morphologyEx函
数可以执行此运算:

 

(4)通过开变换的膨胀结果,我们可以获取图像中最确定是背景
的区域:

 

相反,通过应用distanceTransform可以获得确定的前景区域。在
实践中,如果一个点离最近的前景–背景边缘很远,就可以确信这个
点确实是前景的一部分。
(5)一旦获得图像的distanceTransform表示,我们应用阈值来
选取最确定是前景部分的区域:

 

在这个阶段,我们有一些确定的前景和背景区域。
(6)那么中间区域呢?从背景中减去确定的前景,我们可以发现
这些不确定或未知的区域:

 

(7)既然有了这些区域,我们可以构建著名的“屏障”来阻止
“水”的合并。这是通过connectedComponents函数完成的。在分析
GrabCut算法并将图像概念化为由边连接的一组节点时,我们粗略地了
解了一下图论。有了确定的前景区域,其中一些节点会连接在一起,
但还有一些节点则不会连接起来。断开的节点属于不同的水谷,它们
之间应该有一个屏障:

 

(8)接下来,将所有区域的标签加1,因为我们只希望未知区域
为0:

 

(9)最后,打开闸门!让水流出来!cv2.watershed函数把标签
“-1”分配给分量之间边的像素。将原始图像中的这些边涂成蓝色:

 

使用matplotlib显示结果:

 

显示的结果如图4-15所示。

 

这种类型的分割可以作为识别扑克牌系统的一部分。类似地,分
水岭算法可以帮助我们对普通背景下任意类型的对象(例如放在纸上
的硬币)进行分割和计数。         

4.10  本章小结
本章,我们学习了如何分析图像内的简单空间关系,以便能够区
分多个对象,或者区分前景和背景。涉及的技术包括从二维输入(视
频帧或图像)提取三维信息。首先,我们讨论了深度摄像头。其次,
介绍了对极几何和立体图像,已能够计算视差图。最后,介绍了两种
最流行的图像分割方法:GrabCut和分水岭。
随着本教程的深入,我们将继续从图像中提取越来越复杂的信息。
接下来将探讨用于人脸及其他物体检测和识别的OpenCV功能。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1000847.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号