说明:关于OpenCV的教程和书籍已经很多了,所以,我不想重复别人已经做过的事情。如何系统全面的掌握OpenCV?我想这是每个学习OpenCV的人都想要做到的事情。说到底,OpenCV只是一个数字图像处理函数库,要全面掌握OpenCV的使用,只需要明白有哪些函数,每个函数怎么使用。这个系列教程要完成的事情,就是让大家系统的了解OpenCV有哪些函数,熟练掌握每个函数的作用和使用方法。因此,我不会花时间去详细介绍每个函数的算法原理。我重点介绍每个函数的作用和使用方法,同时利用详细的示例代码进行演示。示例代码包括c++、python、emgucv、OpenCVsharp四种。
一、OpenCV简介及功能模块
1、OpenCV简介
OpenCV(Open Source Computer Vision Library)是一个广泛使用的开源计算机视觉库,旨在提供丰富的图像和视频处理功能。它最初由Intel于1999年开发,并演变成为一个全球性的开源项目,得到了众多开发者的贡献和支持。OpenCV可以通过C++、Python、Java等编程语言调用,使得开发者能够在不同平台上进行图像处理和计算机视觉应用程序的开发。作为一个全面且强大的计算机视觉库,OpenCV包含了数百个用于图像处理、特征检测、对象识别、视频分析等领域的函数和工具。无论您是希望读取和显示图像、进行图像滤波、边缘检测、图像分割、特征提取,还是进行目标跟踪,OpenCV都能提供相应的功能丰富的API。
对于图像处理方面,OpenCV提供了各种各样的功能,例如色彩空间转换、图像滤波(平滑、锐化)、形态学操作、图像变换(旋转、缩放)、图像配准等。这些功能对于不同的图像处理任务非常有用。此外,OpenCV还支持直方图操作、二值化、形状描述符计算、图像轮廓提取等高级功能,用于更复杂的图像处理和分析。在特征检测和描述方面,OpenCV提供了一系列经典算法的实现,如Harris角点检测、SIFT(尺度不变特征变换)、SURF(速度ed特征变换)、ORB(Oriented FAST and Rotated BRIEF)等。这些算法可用于检测图像中的关键点,生成描述符,并进行特征匹配和对象识别。当涉及到视频处理时,OpenCV同样提供了丰富的功能。它可以从摄像头或视频文件中读取视频数据,并进行实时分析和处理。您可以使用OpenCV来捕获视频流、提取视频帧、进行视频编解码、计算光流、跟踪运动目标等。
此外,OpenCV还提供了相机标定、立体视觉、运动估计、光流分析等高级计算机视觉功能,以及实时图像处理和视频处理的支持。开发者可以利用这些功能构建各种应用程序,如机器人视觉导航、自动驾驶、安防监控系统、虚拟现实等。近年来,随着深度学习的广泛应用,OpenCV也提供了针对神经网络和深度学习的高级功能。通过集成Deep Learning模块,OpenCV支持常见的深度学习框架,如TensorFlow、PyTorch和Caffe,使开发者能够利用神经网络进行人脸检测、物体识别和语义分割等任务。这为计算机视觉的发展带来了更多的可能性。
OpenCV在各个领域得到了广泛的应用。在医疗领域,OpenCV可以帮助进行医学图像分析、病变检测和诊断。在工业领域,OpenCV可以应用于质量控制、产品检测和机器视觉系统。在娱乐领域,OpenCV可以用于实现增强现实、虚拟现实和交互式游戏等。OpenCV具有强大的跨平台性,可以在Windows、Linux、macOS等操作系统上运行。它还可以与其他流行的计算机视觉库和工具集成,如NumPy、SciPy、Matplotlib等,为开发者提供更多选择和更丰富的功能。
总之,OpenCV是一个功能强大且广泛使用的计算机视觉库,提供了丰富的图像处理和计算机视觉功能,帮助开发者解决各种图像处理和计算机视觉问题。无论是学术研究、教育或商业应用,OpenCV都是一个不可或缺的工具,为人们创造出更美好的视觉体验和智能化应用。
2、OpenCV的功能模块
OpenCV的组织关系如下图所示:
OpenCV的功能模块分为两部分,一部分是基本模块,一部分是扩展模块。
(1)基本模块主要有以下功能模块
calib3d:相机标定相关
core;核心功能模块,主要包含opencv库的基础结构和基本操作。
dnn:深度学习模块
features2d:二维特征检测点检测、描述、匹配等
flann;最近邻匹配、聚类等。
gapi:该模块对图像处理算法做了加速处理
highgui:图像显示、按钮、鼠标等操作。
imgcodecs:负责图像文件读写,如图像读取与保存
imgproc:图像处理函数
ml:机器学习相关算法
objdetect:目标检测,包括Cascade face detector; latent SVM; HOG等
photo:用于计算摄影处理和恢复照片的算法
stitching:图像拼接,利用图像特征点进行图像拼接
video:视频处理,包括背景分割、视频跟踪等
videoio:负责视频文件的读取和写入
在基本模块中,大家使用最多的是核心功能模块、图像处理模块、特征检测模块;其次是目标检测、相机标定、机器学习等功能。图像显示功能通常在上面功能完成后用来查看处理结果。
(2)扩展模块
除了上面的基本模块之外,OpenCV提供了更多的扩展模块
扩展模块包含在contrib中,扩展模块是对基本模块的补充,其中也包括了一些专利算法。扩展模块随着版本的不同可能会有些区别,新版本可能会增加一些新的功能。虽然如此,其每个模块的使用方法都是差不多的。OpenCV4.0提供的扩展模块如下:
aruco: ArUco和ChArUco标记。包括增强现实的ArUco标记和ChArUco标记
bgsegm:背景分割。改进的自适应背景混合模型,用于在不同照明条件下实时人体跟踪。
ccalib:自定义校准。用于3D重建、全景相机校准、随机模式校准和多摄像头校准的模式。
cnn_3dobj:深度物体识别与姿态。使用Caffe深度神经网络库构建、训练和测试视觉物体识别和姿态的CNN模型。
cuda:利用GPU处理图像的模块,包括下面部分:
cudaarithm:在CUDA架构上执行数学计算的库
cudabgsegm: 在CUDA架构上进行背景分割
cudacodec:在CUDA架构上进行编码解码
cudafeatures2d:在CUDA架构上进行特征检测
cudafilters:在CUDA架构上进行图像滤波
cudaimgproc:在CUDA架构上进行图像处理
cudalegacy:在CUDA架构上进行的传统处理支持
cudaobjdetect:在CUDA架构上进行目标检测
cudaoptflow:在CUDA架构上进行光流计算
cudastereo:基于CUDA技术的用于立体视觉任务的模块,它可以加速立体视觉算法的计算过程,提高处理速度和效率
cudawarping:利用NVIDIA的CUDA技术来进行图像畸变校正和图像重投影的计算,以实现更高效的处理速度和更好的性能
cudev;为OpenCV中的某些功能提供了CUDA实现,以加速这些操作。它可以与其他OpenCV模块配合使用,以利用GPU的并行计算能力来提高图像处理和计算的速度。
cvv:调试器, 弹出一个图形用户界面(GUI),能够交互式地进行视觉调试计算机视觉程序
datasets: 用于读取现有的计算机视觉数据库的代码,并且展示如何使用这些读取器来进行数据集的训练、测试和运行的示例。
dnn_objdetect: 用于对象检测和识别的深度学习模块
dnns_easily_fooled: 一种能够欺骗深度神经网络(DNNs)的代码或技术。这种方法利用网络中的激活值来欺骗网络,使其识别错误的目标或将某个目标识别为另一个目标。
dpm: 一种用于目标识别的算法,它基于 Felzenszwalb 的级联检测器(cascade detector)并添加了可变形对象检测和识别
face: 人脸识别,包括特征脸(Eigen)、Fisher和局部二值模式直方图(LBPH)方法。
freetype: 用于在图像上绘制文本的功能模块。它提供了一些函数和类,可用于在图像中添加文字,包括选择字体、设置字体大小、指定颜色、位置和对齐方式等。
fuzzy: 模糊数学的图像处理
hdf:: 分层数据存储。该模块包含用于分层数据格式的输入/输出(I/O)例程,旨在存储大量数据。
hfs: 层次特征选择,一种用于特征选择和降维的算法,可应用于计算机视觉和模式识别任务中
img_hash: 哈希算法来计算图像的哈希值,用来比较两个图像的相似性
line_descriptor: 用于线段提取和匹配的功能模块。提供了从图像中提取、描述和匹配线段的方法,使用二进制描述符来表示线段
matlab: MATLAB接口
optflow: 光流算法。用于运行和评估deepflow、simpleflow、sparsetodenseflow和motion templates(轮廓光流)的算法。
ovis: 用于渲染、可视化和交互式操作的工具包。它是基于OpenGL的一个功能模块,用于创建和展示3D场景、模型和虚拟现实(VR)环境
phase_unwrapping: 一个用于相位展开的功能模块
plot: 允许在一维或二维中绘制数据。
reg: 图像配准。基于像素的图像配准,用于精确对齐
rgbd: RGB深度处理模块。Linemod三维物体识别。
saliency: 显著性API。用于确定人眼在场景中的关注点。具有静态、运动和“物体性”显著性的计算例程。
sfm: 该模块包含从2D图像进行三维重建的算法。该模块的核心是Libmv的轻量级版本
shape: 提供了一些形状相关的功能和操作
stereo: 立体匹配。使用不同描述符进行的立体匹配:Census、CS-Census、MCT、BRIEF 和 MV。
structured_light: 生成结构光模式,投影结构光,解码结构光图像,三维重建等
superres: 超分辨率图像处理技术,旨在通过使用算法和图像处理方法将低分辨率图像恢复到高分辨率的过程
surface_matching: 用于三维物体检测和定位的功能
text: 视觉文本匹配,在一个视觉场景中检测文字,切分单词,并识别文字
tracking: 基于视觉的物体跟踪
videostab: 视频稳定功能。用于减少由于相机抖动或运动导致的视频剧烈晃动或抖动。
viz: 提供了三维可视化功能。该模块允许在应用程序中创建、渲染和交互式显示三维场景和对象。
xfeatures2d: 特征检测与描述符的扩展功能,包含了一些实验性的和付费的专利特征检测器/描述符算法
ximgproc: 扩展图像处理。包括结构化森林、域变换滤波器、引导滤波器、自适应流形滤波器、联合双边滤波器和超像素等算法。
xobjdetect: 增强的2D对象检测。使用Waldboost级联和计算作为积分特征的局部二值模式,用于2D对象检测。
xphoto: 扩展的计算摄影。提供额外的照片处理算法:色彩平衡、降噪和修复处理等功能。
二、常用函数目录
尽管OpenCV提供了众多的图像处理函数,但是对于大多数人而言,可能很多功能函数都用不到。OpenCV是一个包括了多个视觉方向的图像库,针对每个人自己感兴趣的方向,学习使用对应的功能函数即可。比如,做工业视觉检测方向的人,可能更关注常规的图像处理方法、机器学习、深度学习等功能;做三维视觉的人,可能更关注OpenCV的三维功能;专注做视觉算法的人,可能更关注某个方向的最新的图像处理算法。做人脸识别的人,可能关注点是OpenCV的人脸识别功能。
但是,不管利用OpenCV来实现什么功能,一些常用的图像处理函数还是需要熟悉怎么使用,下面是OpenCV的常用函数列表。如果熟悉了这些函数的使用方法,则可以快速实现自己想要的功能。
三、imread、imwrite、imshow、VideoCapture、VideoWriter
imread、imwrite、imshow、VideoCapture是OpenCV提供的最基本的功能,包括图像、视频的读取,显示和保存。
1、imread函数
用于读取图像,定义如下:
Mat imread( const String& filename, int flags = IMREAD_COLOR );
参数:
Filename:文件名
Flags:读取标识,枚举类型,可以取以下值
enum ImreadModes {
IMREAD_UNCHANGED = -1, //返回原始通道图像
IMREAD_GRAYSCALE = 0, //返回灰度图
IMREAD_COLOR = 1, //返回三通道BGR图像
IMREAD_ANYDEPTH = 2, //当输入具有相应的深度时返回16位/ 32位图像,否则将其转换为8位
IMREAD_ANYCOLOR = 4, //以任何可能的颜色格式读取图像
IMREAD_LOAD_GDAL = 8, //使用gdal的驱动加载图像
IMREAD_REDUCED_GRAYSCALE_2 = 16, //总是为灰度图像,并且图像大小为原来的1/2
IMREAD_REDUCED_COLOR_2 = 17, //总是为三通道BGR图像,并且图像大小为原来的1/2
IMREAD_REDUCED_GRAYSCALE_4 = 32, //总是为灰度图像,并且图像大小为原来的1/4.
IMREAD_REDUCED_COLOR_4 = 33, //总是为三通道BGR图像,并且图像大小为原来的1/4.
IMREAD_REDUCED_GRAYSCALE_8 = 64, //总是为灰度图像,并且图像大小为原来的1/8.
IMREAD_REDUCED_COLOR_8 = 65, //总是为三通道BGR图像,并且图像大小为原来的1/8.
IMREAD_IGNORE_ORIENTATION = 128 //不会根据EXIF的方向标志旋转图像.
};
flags参数取“0”或“1”比较常见,取“0”是得到的图像是灰度图像。取“1”得到三通道彩色图像。
2、imwrite函数
用于保存图像,定义如下:
bool imwrite( const String& filename, InputArray img, const std::vector& params = std::vector());
参数:
Filename:文件名
img:要保存的图像
params:表示为特定格式保存的参数编码,通常直接采用默认值。
3、imshow函数
用于显示图像,常和namedWindows函数同时使用,namedWindows函数用于创建一个显示窗体,如果不使用namedWindows函数,imshow函数将默认采用一个窗体显示图像。该函数定义如下:
void imshow(const String& winname, InputArray mat)
参数:
winname:显示图像的窗口名称,可以用namedWindow函数创建显示窗口。
mat:需要显示的Mat图像
如果用namedWindow函数创建窗体,namedWindow函数定义如下:
void namedWindow(const String& winname, int flags = WINDOW_AUTOSIZE);
其中参数winname, 用于设置窗口名,flags 参数表示窗口的样式,有以下几种值可以选择:
WINDOW_NORMAL、WINDOW_AUTOSIZE、WINDOW_FREERATIO、WINDOW_KEEPRATIO、WINDOW_FULLSCREEN、WINDOW_GUI_EXPANDED、WINDOW_GUI_NORMAL。
示例代码:
c++:读写图像、显示图像
#include <opencv2/opencv.hpp>
#include <iostream>
int main(int argc, char** argv)
{
Mat ReadImage = imread("E:/TestImage/data/aloeL.jpg", 1);
namedWindow("ReadImage", 0);
imwrite("E:/TestImage/test.png", ReadImage);
imshow("ReadImage", ReadImage);
waitKey(0);
return 0;
}
python:读写图像、显示图像
import cv2.cv2 as cv2
#如果支持中文路径,可以采用以下方式
#ReadImage=cv2.imread("E:/TestImage/data/aloeL.jpg",1)
#如果不支持中文,请采用以下方式
ReadImage = cv2.imdecode(np.fromfile("E:/TestImage/data/aloeL.jpg", dtype =np.uint8),1)
#如果支持中文路径,可以采用以下方式
#cv2.imwrite("E:/TestImage/test.png",ReadImage)
#如果不支持中文,请采用以下方式
fileName ="E:/TestImage/test.png"
cv2.imencode('.png',ReadImage)[1].tofile(fileName)
cv2.namedWindow("ReadImage",cv2.WINDOW_NORMAL)
cv2.imshow("ReadImage",ReadImage)
cv2.waitKey(0)
注意:如果读写图像不支持中文路径,OpenCV还提供了imdecode和imencode两个函数,用于编解码方法读写图像。
emgucv:读写图像、显示图像
using Emgu.CV.CvEnum;
namespace test
{
class Program
{
static void Main(string[] args)
{
Mat ReadImage = CvInvoke.Imread("E:/TestImage/data/aloeL.jpg", (ImreadModes)0);
CvInvoke.Imwrite("E:/TestImage/test.png", ReadImage);
CvInvoke.NamedWindow("ReadImage", 0);
CvInvoke.Imshow("ReadImage", ReadImage);
CvInvoke.WaitKey(0);
return;
}
}
}
OpenCVsharp:读写图像、显示图像
using OpenCvSharp;
namespace OpenCVSharpTestFunction
{
class Program
{
static void Main(string[] args)
{
Mat ReadImage = Cv2.ImRead("E:/TestImage/data/aloeL.jpg", (ImreadModes)0);
Cv2.ImWrite("E:/TestImage/test.png", ReadImage);
Cv2.NamedWindow("ReadImage", 0);
Cv2.ImShow("ReadImage", ReadImage);
Cv2.WaitKey(0);
return;
}
}
}
4、VideoCapture类
VideoCapture是OpenCV提供的用于读取视频的类。通过open函数可以打开摄像头或者视频文件,该类中还提供了set函数,设置摄像头图像采集参数的函数。
c++:读取视频
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
cv::VideoCapture cap; //声明相机捕获对象
cap.set(cv::CAP_PROP_FOURCC, cv::VideoWriter::fourcc('M', 'J', 'P', 'G'));
cap.set(cv::CAP_PROP_FRAME_WIDTH, 640); //图像的宽,需要相机支持此宽
cap.set(cv::CAP_PROP_FRAME_HEIGHT, 480); //图像的高,需要相机支持此高,图像分辨率640×480
int deviceID = 0; //相机设备号
cap.open(deviceID); //打开相机,如果打开视频文件,直接输入视频文件路径和文件名
if (!cap.isOpened()) //判断相机是否打开
{
std::cerr << "ERROR!!Unable to open camera\n";
return -1;
}
cv::Mat img;
while (true)
{
cap >> img; //以流形式捕获图像
cv::namedWindow("example", 1); //创建一个窗口用于显示图像,1代表窗口适应图像的分辨率进行拉伸。
if (img.empty() == false) //图像不为空则显示图像
{
cv::imshow("example", img);
}
int key = cv::waitKey(30); //等待30ms
if (key == int('q')) //按下q退出
{
break;
}
}
cap.release(); //释放相机捕获对象
cv::destroyAllWindows(); //关闭所有窗口
return 0;
}
python:读取视频
import numpy as np
import cv2.cv2 as cv2
#读取摄像头图像
# cap = cv2.VideoCapture(0)
cap = cv2.VideoCapture('E:/TestImage/test.mp4')
while cap.isOpened():
ret, frame = cap.read()
if ret:
# 在这里进行对帧的处理,比如展示、分析等
cv2.imshow("test",frame);
# 按下 'q' 键退出循环
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
cap.release()
cv2.destroyAllWindows()
emgucv:读取视频
using Emgu.CV;
using System;
namespace test
{
class Program
{
static void Main(string[] args)
{
// 视频文件路径
string videoPath = "E:/TestImage/test.mp4";
VideoCapture capture = new VideoCapture(videoPath);
if (!capture.IsOpened)
{
Console.WriteLine("无法打开视频文件!");
return;
}
// 创建一个窗口显示视频帧
CvInvoke.NamedWindow("Video", 0);
while (true)
{
// 从视频中读取下一帧
Mat frame = capture.QueryFrame();
if (frame == null)
break;
CvInvoke.Imshow("Video", frame);
if (CvInvoke.WaitKey(30) == 27)
break;
}
// 关闭视频窗口
CvInvoke.DestroyWindow("Video");
}
}
}
OpenCVsharp:读取视频
using OpenCvSharp;
using System;
namespace OpenCVSharpTestFunction
{
class Program
{
static void Main(string[] args)
{
string videoPath = "E:/TestImage/test.mp4";
VideoCapture capture = new VideoCapture(videoPath);
if (!capture.IsOpened())
{
Console.WriteLine("无法打开视频文件!");
return;
}
Cv2.NamedWindow("Video", WindowMode.AutoSize);
while (true)
{
Mat frame = new Mat();
if (!capture.Read(frame))
break;
Cv2.ImShow("Video", frame);
if (Cv2.WaitKey(30) == 'q')
break;
}
// 关闭视频窗口
Cv2.DestroyWindow("Video");
}
}
}
5、VideoWriter类
VideoWriter是OpenCV提供的用于保存视频的类。VideoWriter与VideoCapture类似。
c++:写视频
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
VideoCapture cap;
cap.open(0); // 打开摄像头,如果打开视频文件,直接输入文件路径和文件名
if (!cap.isOpened())
{
cout << "Couldn't open capture." << endl;
return -1;
}
double fps = 30;
cv::Size size(
(int)cap.get(cv::CAP_PROP_FRAME_WIDTH), (int)cap.get(cv::CAP_PROP_FRAME_HEIGHT)
);
cv::VideoWriter writer;
writer.open("E:/test/test.avi", VideoWriter::fourcc('M', 'J', 'P', 'G'), fps, size);
if (!writer.isOpened())
{
cout << "Could not open the output video file for write" << endl;
return -1;
}
cv::Mat bgr_frame;
for (;;)
{
cap >> bgr_frame;
if (bgr_frame.empty()) break;
writer << bgr_frame;
char c = cv::waitKey(10);
if (c == 27) break;
}
return 0;
}
python:写视频
import cv2.cv2 as cv2
cap = cv2.VideoCapture('E:/TestImage/test.mp4')
output_file = 'E:/TestImage/output.mp4'
codec = cv2.VideoWriter_fourcc(*'mp4v')
frame_width = int(cap.get(3))
frame_height = int(cap.get(4))
# 创建VideoWriter对象
out = cv2.VideoWriter(output_file, codec, 24,(frame_width, frame_height))
cv2.namedWindow("test", 0)
while cap.isOpened():
# 在这里获取当前帧
ret, frame = cap.read()
if frame is not None:
# 将帧写入视频
out.write(frame)
cv2.imshow("test", frame)
# 按下 'q' 键退出循环
if cv2.waitKey(1) & 0xFF == ord('q'):
break
else:
break
out.release()
cv2.destroyAllWindows()
emgucv:写视频
using Emgu.CV.CvEnum;
using Emgu.CV;
using System;
using System.Drawing;
namespace test
{
class Program
{
static void Main(string[] args)
{
string videoPath = "E:/TestImage/test.mp4";
VideoCapture capture = new VideoCapture(videoPath);
if (!capture.IsOpened)
{
Console.WriteLine("无法打开视频文件!");
return;
}
string outputPath = "E:/TestImage/output.mp4";
int width = (int)capture.GetCaptureProperty(CapProp.FrameWidth);
int height = (int)capture.GetCaptureProperty(CapProp.FrameHeight);
VideoWriter writer = new VideoWriter(outputPath, 24, new Size(width, height), true);
if (!writer.IsOpened)
{
Console.WriteLine("无法创建视频文件!");
return;
}
// 创建一个窗口显示视频帧
CvInvoke.NamedWindow("Video", 0);
while (true)
{
using (Mat frame = capture.QueryFrame())
{
if (frame == null)
break;
writer.Write(frame);
CvInvoke.Imshow("Video", frame);
if (CvInvoke.WaitKey(30) == 'q')
break;
}
}
}
}
}
OpenCVsharp:写视频文章来源:https://www.toymoban.com/news/detail-730580.html
using OpenCvSharp;
using System;
namespace OpenCVSharpTestFunction
{
class Program
{
static void Main(string[] args)
{
string videoPath = "E:/TestImage/test.mp4";
VideoCapture capture = new VideoCapture(videoPath);
if (!capture.IsOpened())
{
Console.WriteLine("无法打开视频文件!");
return;
}
string outputPath = "E:/TestImage/output.mp4";
int width = capture.FrameWidth;
int height = capture.FrameHeight;
VideoWriter writer = new VideoWriter(outputPath, VideoWriter.FourCC(@"MP4V"), 24, new Size(width, height));
if (!writer.IsOpened())
{
Console.WriteLine("无法创建视频文件!");
return;
}
Cv2.NamedWindow("Video", WindowMode.FreeRatio);
try
{
while (true)
{
Mat frame = new Mat();
if (!capture.Read(frame))
break;
writer.Write(frame);
Cv2.ImShow("Video", frame);
if (Cv2.WaitKey(30) == 'q')
break;
}
// 关闭视频窗口
Cv2.DestroyWindow("Video");
}
catch
{
}
}
}
}
OpenCV学习平台,是一个交互式可视化的操作平台,旨在让大家快速掌握OpenCV,代码自动生成,不需要写代码即可快速掌握OpenCV的使用。支持c++、python、opencvshape,emgucv、直接复制生成的代码就可以使用。
链接: https://pan.baidu.com/s/1XyotEmXLfD-XCNCYOiVUYg
提取码: aj9d文章来源地址https://www.toymoban.com/news/detail-730580.html
到了这里,关于OpenCV从入门到精通(一) ——OpenCV简介、模块、常用函数、图像视频读取显示保存的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!