当前位置: 首页 > news >正文

《OpenCV 基础全攻略:从入门到精通》

《OpenCV 基础全攻略:从入门到精通》

  • 一、OpenCV 简介
    • (一)特点
    • (二)优势
    • (三)应用场景
  • 二、安装与配置
  • 三、OpenCV 函数详解
    • 1. 图像读取函数 cv2.imread ()
    • 2. 图像显示函数 cv2.imshow ()
    • 3. 图像保存函数 cv2.imwrite ()
  • 四、基本教程
    • 1. opencv 配置
    • 2. 加载、修改、显示及保存图像
    • 3. 图像像素及掩膜操作详解
    • 4. Mat 对象
  • 五、应用教程
    • 1. 摄像头基本操作
    • 2. 彩色目标追踪(Camshift)
    • 3. 光流(optical flow)
    • 4. 点追踪(lkdemo)
  • 六、基础运用
    • 1. 读取图像
    • 2. 显示图像
    • 3. 写入图像
    • 4. 访问图像
    • 5. 改变图像大小
  • 七、基础概念介绍
    • 1. 像素的数据类型
    • 2. OpenCV 模块介绍
      • 一、core 模块
      • 二、imgproc 模块
      • 三、video 模块
      • 四、calib3d 模块
      • 五、features2d 模块
      • 六、objdetect 模块
      • 七、highgui 模块
      • 八、gpu 模块
      • 九、其他模块
    • 3. cv::NAryMatIterator
      • 1. 基本概念:
      • 2. 构造函数:
      • 3. 成员变量:
      • 4. 成员函数:
      • 5. 使用方法:
      • 6. 应用场景:
  • 八、知识讲解
    • 1. 图像的加法运算
    • 2. 图像融合
    • 3. 图像的类型转换
    • 4. 图像缩放
    • 5. 图像翻转
  • 九、总结

一、OpenCV 简介

OpenCV(Open Source Computer Vision Library)作为热门的计算机视觉库,自 1999 年由英特尔公司首次发布以来,在计算机视觉领域发挥着至关重要的作用。它具有诸多特点和优势,广泛应用于各个领域。

(一)特点

  1. 跨平台支持:OpenCV 支持多个操作系统,包括 Windows、Linux、macOS、Android 和
    iOS。这使得开发者可以在不同的平台上使用相同的代码,大大提高了开发效率。
  2. 多语言接口:除了 C++,OpenCV 还提供了 Python、Java 和 MATLAB
    等多种编程语言的接口。这使得不同编程语言的开发者都可以轻松地使用 OpenCV 进行计算机视觉和图像处理任务。
  3. 丰富的功能:OpenCV 包含了超过 2500
    个优化的算法,涵盖了从基本的图像处理到复杂的机器学习模型。例如,在图像处理方面,它提供了滤波、边缘检测、形态学操作等算法;在视频分析方面,提供了运动检测、对象跟踪等功能;在特征检测和描述方面,提供了 SIFT、SURF、ORB 等算法;在对象检测方面,包含了人脸检测、行人检测等预训练模型;在机器学习方面,提供了各种机器学习算法,如 KNN、SVM、决策树等。
  4. 高效性:OpenCV 的许多核心功能都经过高度优化,能够在实时应用中高效运行。例如,在工业检测中,OpenCV
    可以快速地检测产品的缺陷、进行产品分类和机器视觉等任务,提高生产效率。
  5. 社区支持:作为一个开源项目,OpenCV
    拥有一个活跃的开发者和用户社区,提供了丰富的文档和教程。开发者可以在社区中交流经验、分享代码和解决问题,促进了 OpenCV
    的不断发展和完善。

(二)优势

  1. 编程语言:OpenCV 基于 C++ 实现,同时提供 Python、Ruby、Matlab 等语言的接口。OpenCV-Python 是
    OpenCV 的 Python API,结合了 OpenCV C++ API 和 Python 语言的最佳特性。Python
    语言本身简洁易懂,结合 OpenCV 的强大功能,使得图像处理和计算机视觉的开发变得更加简单。
  2. 跨平台:可以在不同的系统平台上使用,包括 Windows,Linux,OS X,Android 和 iOS。基于 CUDA 和
    OpenCL 的高速 GPU 操作接口也在积极开发中,进一步提高了 OpenCV 的性能和跨平台性。
  3. 丰富的
    API:完善的传统计算机视觉算法,涵盖主流的机器学习算法,同时添加了对深度学习的支持。这使得开发者可以在一个库中完成多种任务,无需切换不同的库和工具,提高了开发效率。

(三)应用场景

  1. 计算机视觉:OpenCV
    可用于计算机视觉任务,如目标检测、图像分类、人脸识别、姿态估计、运动估计、光流估计等。例如,在人脸识别方面,OpenCV
    可以快速准确地检测和识别出图像中的人脸,广泛应用于安防监控、门禁系统等领域。
  2. 视频分析:OpenCV 可用于视频分析任务,如视频跟踪、行为识别、动作识别等。例如,在智能交通系统中,OpenCV
    可以检测和跟踪车辆、识别车牌和行人,统计交通流量,提高交通管理效率。
  3. 机器学习:OpenCV
    集成了各种机器学习算法,如支持向量机、随机森林、朴素贝叶斯等,可以用于图像分类、目标检测等任务。例如,在医学影像处理中,OpenCV
    可以使用机器学习算法对医学图像进行分类和识别,辅助医生进行诊断。
  4. 医学影像处理:OpenCV 可以用于医学影像处理,如医学图像分割、医学图像配准、医学图像增强等。例如,在肺部结节检测中,OpenCV
    可以通过图像分割和特征提取算法,快速准确地检测出肺部结节,提高诊断准确性。
  5. 自动驾驶:OpenCV 可以用于自动驾驶,如车道检测、交通标志识别、障碍物检测等。例如,在自动驾驶汽车中,OpenCV
    可以实时检测车道线、交通标志和障碍物,为汽车提供导航和安全保障。
  6. 工业检测:OpenCV 可以用于工业检测,如缺陷检测、产品分类、机器视觉等。例如,在电子产品制造中,OpenCV
    可以检测产品的外观缺陷,提高产品质量。
  7. 游戏开发:OpenCV 可以用于游戏开发,如虚拟现实、增强现实等。例如,在增强现实游戏中,OpenCV
    可以通过摄像头实时捕捉现实场景,将虚拟物体与现实场景融合,提供更加真实的游戏体验。

二、安装与配置

  1. 在 pycharm 中的安装 在 Pycharm 中安装 OpenCV 有多种方法。 一种方法是直接在 Pycharm 中进行安装。进入
    Pycharm 后,选择 “File”——“Settings”,然后选择 “Project Interpreter” 右上方的符号
    “+”。在搜索框中输入 opencv,选择 py-opencv,如下显示 “installing”,等待安装即可。
  2. 使用 pip 安装。在命令行中执行 “pip install python-opencv”。但在网络距离美国较远的情况下,或 PIP
    版本未达到要求的情况下,可能会安装失败。解决方法有:一是重试;二是使用科学方法,但要注意使用科学方法的端口问题,切记不要和本地计算机使用同一个端口,容易造成
    Pycharm 未知错误;三是手动去官网下载文件。有两种类型的手动安装文件,setup.py 和 XXXX.whl。这两种文件都可以通过
    Pycharm 的命令行工具直接 cd 到目录进行直接安装。方法一是 “python setup.py install”,pip
    安装较为简单;方法二是 “pip install C:windows/system/001/002.whl”,后面的路径为
    XXXX.whl 文件的所在地址,如果地址不知道,可以通过属性查看。
  3. 安装成功后,可以通过以下代码段进行验证:
import numpy as np
import cv2 as cv
original = cv.imread('gongjiaoka.jpg')
grayImg = cv.imread('gongjiaoka.jpg', cv.IMREAD_GRAYSCALE)
cv.imwrite('mygray.jpg', grayImg)
cv.imshow('mygray.jpg',grayImg)
cv.imshow('gongjiaoka.jpg',original)
cv.waitKey(0)

三、OpenCV 函数详解

1. 图像读取函数 cv2.imread ()

  1. 参数介绍:
    • cv2.imread () 函数用于读取图像文件,它有两个主要参数。第一个参数是要读入图片的完整路径,比如
      “dot.jpg”。第二个参数是读入方式,有三种选择:
      • cv2.IMREAD_COLOR:默认参数,以彩色模式读取图像,忽略 alpha 通道。对应的数值是
        1。此模式下读取的图像是一个三维数组,前两维表示图像的像素坐标,最后一维表示图像的颜色通道(通常是 BGR 三个通道)。
      • cv2.IMREAD_GRAYSCALE:以灰度模式读取图像,将图像转换为单通道灰度图像。对应的数值是
        0。读取后的图像是一个二维数组,每个元素表示对应像素的灰度值。 cv2.IMREAD_UNCHANGED:读取包括 alpha
        通道在内的所有图像信息。对于带有 alpha 通道的图像(如 PNG 图像),将保持完整信息。对应的数值是
        -1。这种模式下读取的图像可能是一个四维数组,前两维表示像素坐标,第三维表示颜色通道,第四维表示 alpha 通道(透明度信息)。
  2. 代码示例:img = cv2.imread
    (‘dot.jpg’,cv2.IMREAD_COLOR)。此代码将以彩色模式读取名为‘dot.jpg’的图像,并将其存储在变量 img
    中,img 是一个 numpy 数组,可用于后续的图像处理操作。

2. 图像显示函数 cv2.imshow ()

  1. 参数介绍: cv2.imshow ()
    函数用于显示图像,它有两个参数。第一个参数是显示图像的窗口的名字,这个名字可以是任意字符串,用于唯一标识一个窗口。例如,可以命名为
    “显示图”。第二个参数是要显示的图像,通常是一个 numpy 数组,表示图像的像素数据。
  2. 窗口调整: cv2.WINDOW_AUTOSIZE
    会根据自动图像大小调整窗口,这意味着窗口的大小会自动适应图像的尺寸,用户无法手动调整窗口大小。 cv2.WINDOW_NORMAL
    允许修改窗口大小。使用此模式,用户可以通过鼠标拖动窗口边框来调整窗口的大小,以适应不同的显示需求。
  3. 代码示例:cv2.imshow (‘显示图’,img)。此代码将在名为 “显示图” 的窗口中显示图像
    img。如果没有其他操作,窗口会一直保持显示状态,直到用户手动关闭窗口或通过代码进行关闭。

3. 图像保存函数 cv2.imwrite ()

  1. 参数介绍: cv2.imwrite ()
    函数用于保存图像,它有两个参数。第一个参数是要保存的路径,可以是一个字符串,表示图像文件的完整路径和文件名,包括文件扩展名(如
    “myimage.jpg”)。第二个参数是要保存的图像,通常是一个 numpy 数组,表示图像的像素数据。
  2. 代码示例:cv2.imwrite (‘path’,name_1)。此代码将图像 name_1
    保存到指定的路径‘path’中。保存的图像格式由路径中的文件扩展名决定,例如,如果路径是 “myimage.jpg”,则图像将以 JPEG
    格式保存。

四、基本教程

1. opencv 配置

可参考链接:https://blog.csdn.net/shuiyixin/article/details/80386022。

2. 加载、修改、显示及保存图像

  1. 加载图像:cv2.imread () 是 OpenCV
    中用于读取图像文件的函数。它有两个主要参数,第一个参数是要读入图片的完整路径,比如
    “dot.jpg”;第二个参数是读入方式,有三种选择:
    • cv2.IMREAD_UNCHANGED(<0)表示加载原图,不做任何改变。OpenCV 支持
      JPG、PNG、TIFF等常见格式图像文件加载。
    • cv2.IMREAD_GRAYSCALE(0)表示把原图作为灰度图加载进来。
    • cv2.IMREAD_COLOR(>0)表示把原图作为 RGB 图像加载进来。
  2. 修改图像:cv2.cvtColor ()
    可把图像从一个色彩空间转换到另一个色彩空间。它具有三个参数,第一个参数是源图像,第二个参数是目标图像,第三个参数是源图像和目标图像的色彩空间转换方式,如COLOR_BGR2GRAY(从
    RGB 转化到 Gray,从彩色转换为灰色)。
  3. 显示图像:cv2.imshow
    ()用于显示图像,它有两个参数。第一个参数是显示图像的窗口的名字,这个名字可以是任意字符串,用于唯一标识一个窗口;第二个参数是要显示的图像,通常是一个numpy
    数组,表示图像的像素数据。窗口特性可以通过参数设置,如
    WINDOW_AUTOSIZE会自动根据图像的大小调整窗口大小,不能人为改变窗口大小;WINDOW_NORMAL 允许修改窗口大小。
  4. 保存图像:cv2.imwrite ()
    用于保存图像文件到指定目录路径。它有两个参数,第一个参数是要保存的路径,可以是一个字符串,表示图像文件的完整路径和文件名,包括文件扩展名(如 “myimage.jpg”);第二个参数是要保存的图像,通常是一个 numpy 数组,表示图像的像素数据。只有 8 位、16 位的 PNG、JPG、Tiff 文件格式而且是单通道或者三通道的 BGR 的图像才可以通过这种方式保存。保存 PNG格式的时候可以保存透明通道的图片,同时可以指定压缩参数。

3. 图像像素及掩膜操作详解

  1. 方法一:直接手写获取图像矩阵的宽度、高度和指针,进行像素值计算。获取图像像素指针可以通过 Mat.ptr(int i =
    0) 来获取像素矩阵的指针,索引 i 表示第几行,从 0 开始计数。获取点 P (row, col) 的像素值可以通过
    Mat.ptr(row)[col]。同时,还可以通过获取图像的长和宽(Mat.cols 输出图像 x 轴的像素个数,即
    Width;Mat.rows 输出图像 y 轴的像素个数,即 Height;Mat.channels ()
    输出每个像素点的通道个数)以及使用 saturate_cast控制像素值的取值不超过 uchar 所能表示的范围(0 -
    255)。
  2. 方法二:使用 filter2D ()
    定义掩膜进行操作。图像掩膜是用选定的图像、图形或物体,对处理的图像(全部或局部)进行遮挡,来控制图像处理的区域或处理过程。在
    OpenCV 中,对应的 API 是 filter2D (InputArray src, OutputArray dst, int
    ddepth, InputArray kernel,…)。其中 src 为输入图像,dst
    为目标图像,其尺寸和通道与输入图像一致,ddepth 期望的目标图像类型,即位图深度,定义掩膜如 Mat Kernel =
    (Mat(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0)。
  3. 显示程序运行时间:使用 getTickCount () 和 getTickFrequency ()。getTickCount ()
    用于返回从操作系统启动到当前所经过的计时周期数,即计时次数;getTickFrequency () 用于返回 CPU
    的频率,单位是秒,也就是一秒内重复的次数。通过总次数除以一秒内重复的次数可以得到时间(s)。

4. Mat 对象

  1. 拷贝:
    • clone () 拷贝矩阵本身,会创建一个新的 Mat 对象,并复制原始 Mat 的数据。修改原始 Mat 不会影响深拷贝的 Mat。
    • copyTo () 拷贝矩阵本身,也会创建一个新的 Mat 对象,并复制原始 Mat 的数据。复制之后 MM 与 M 完全相同,带第二参数
      mask 可以进行更多控制。
    • 拷贝构造函数和赋值运算符只拷贝信息头,创建一个新的 Mat 对象,这个对象与原始 Mat 共享同一数据。当原始 Mat
      被修改时,浅拷贝也会反映这些更改。
  2. 创建 Mat 对象:多种方式创建,如指定大小、类型和初始值等。
    • 使用 Mat () 构造函数,如 Mat M (2, 2, CV_8UC3, Scalar (0, 0, 255)),创建一个 2x2
      的三通道矩阵,每个像素由三个元素组成,初始值为 Scalar (0, 0, 255)。
    • 在 C/C++ 中构造函数进行初始化,如 int sz [3] = {2, 2, 2 };Mat L (3, sz, CV_8UC,
      Scalar::all (0)),创建一个超过两维的矩阵。
    • 为已存在的 IplImage 指针创建信息头,如 IplImage* img = cvLoadImage (“1.jpg”,1);Mat
      mtx (img),将 IplImage 转换为 Mat(在 OpenCV3.0 版本应使用 Mat mat = cvarrToMat
      (img))。
    • 利用 Mat 类中的 Create () 函数,如 M.create (4,4, CV_8UC
      (2)),不能为矩阵设置初始值,只是在改变尺寸时重新为矩阵数据开辟内存。
    • 采用 Matlab 式的初始化,如 Mat E = Mat::eye (4,4, CV_64F) 创建一个 4x4 的单位矩阵;Mat X
      = Mat::ones (2,2, CV_32F) 创建一个 2x2 的全 1 矩阵;Mat Z = Mat::zeros (3,3, CV_8UC1) 创建一个 3x3 的全 0 矩阵。
    • 对小矩阵使用逗号分隔式初始化函数,如 Mat C = (Mat(3,3) <<
      0,-1,0,-1,5,-1,0,-1,0)。
    • 使用成员函数 clone () 或者 copyTo () 为一个已存在的 Mat 对象创建一个新的信息头。
  3. 格式化打印:调用 randu () 对矩阵填充随机数。(此处可根据实际需求进一步扩展描述如何使用 randu () 函数进行格式化打印)
  4. 颜色空间缩减:用特定值代替一定范围内的值。(此处可进一步解释颜色空间缩减的具体应用场景和方法)

五、应用教程

1. 摄像头基本操作

可参考链接:https://blog.csdn.net/shuiyixin/article/details/82949396。OpenCV 通过 VideoCapture 类,来对视频进行读取,调用摄像头。读取视频可以使用 VideoCapture capture;Capture.open (“1.avi”) 或者 VideoCapture capture (“1.avi”);打开 / 关闭摄像头:打开摄像头可以使用 VideoCapture capture (0)(括号内为摄像头设备号,0 表默认内置摄像头)或者 VideoCapture capture;capture.open (0);关闭摄像头使用 capture.release ()。摄像头调参方面,可以使用 isOpened () 判断摄像头是否成功初始化,open () 函数可以通过摄像头打开视频,默认为 0,如果是带前置摄像头的电脑,一般为前置摄像头。视频帧的读取可以通过 VideoCapture& VideoCapture::operator>>(Mat& image) 或者 bool VideoCapture::read (Mat& image),其中 read () 函数结合 VideoCapture::grab () 和 VideoCapture::retrieve () 其中之一被调用,用于捕获、解码和返回下一个视频帧。假如没有视频帧被捕获(相机没有连接或者视频文件中没有更多的帧)将返回 false。

2. 彩色目标追踪(Camshift)

  1. 算法原理:根据鼠标框选区域的色度光谱来进行摄像头读入的视频目标的跟踪。Camshift
    利用目标的颜色直方图模型将图像转换为颜色概率分布图,初始化一个搜索窗的大小和位置,并根据上一帧得到的结果自适应调整搜索窗口的位置和大小,从而定位出当前图像中目标的中心位置。Camshift
    的核心步骤仍然是 Meanshift,只是在距离相似性度量的基础之上,又增加了图像灰度相似性的度量。两者共同作用,实现了目标的跟踪。

具体步骤如下:

  • 准备样本数据:以矩形框选区域作为示例,准备包含目标区域的样本数据集。

  • 计算颜色直方图:对于给定的样本区域,计算其在 HSV 颜色空间中的颜色直方图。HSV 是一种常用的颜色空间,便于颜色的识别和处理。

  • 初始化窗口和帧:在待处理的输入视频帧中选取初始的目标矩形框,并将其转换为 HSV
    颜色空间的直方图。同时,创建一个与输入帧大小相同的输出帧。

  • 计算反向投影图:将输入帧转换到 HSV
    颜色空间,并使用计算得到的目标颜色直方图创建一个模板。然后,将模板与输入帧进行归一化互相关操作,得到一个与输入帧相同大小的反向投影图。在反向投影图中,像素值越高表示该像素点与目标颜色的相似度越大。

  • 运行 Meanshift
    算法:从初始目标位置开始,计算目标的质心(即均值),并将质心作为新的目标位置。重复这个过程,直到目标的位置稳定或达到最大迭代次数。

  • 调整窗口大小:通过计算目标的协方差矩阵来调整窗口的大小,以适应目标的形状变化。

  • 更新目标颜色直方图:取目标位置周围的像素点,重新计算其在 HSV 颜色空间中的颜色直方图。

  • 显示结果:将跟踪结果显示在输出帧上,可视化跟踪效果。

  1. 代码实现:包括设置回调函数、创建窗口、设置滑动条等。

    • 设置鼠标回调函数 onMouse (),用于响应鼠标事件,当用户在图像上框选目标区域时,触发 Camshift 算法开始跟踪。
    • 创建窗口 “CamShift Demo” 和 “Histogram”,分别用于显示跟踪结果和目标的颜色直方图。
    • 设置滑动条 “Vmin”、“Vmax” 和 “Smin”,用于调整跟踪的参数。
    • 在主循环中,首先读取视频帧,如果帧为空则退出循环。然后将帧复制到 image 中,并根据不同的条件进行处理。
    • 如果 trackObject 为 1,表示已经选择了目标,进行 Camshift 算法的处理。首先计算目标区域的掩码 mask,然后创建
      hue 图像,从 hsv 图像中提取 H 通道。接着,如果是用户首次选择目标,计算目标区域的颜色直方图
      hist,并进行归一化处理。然后进行反向投影 calcBackProject (),并与掩码进行与操作 backproj &=
      mask。最后使用 CamShift () 算法找到目标的新位置 trackBox,并在图像上绘制椭圆表示目标。
    • 如果 trackObject 小于 0,表示用户正在选择目标,将选择区域进行反色处理。
    • 如果 selectObject 为真且选择区域不为空,则在选择区域进行反色处理。
    • 在主循环中,还处理了用户的键盘输入,包括退出程序、切换反向投影模式、显示 / 隐藏直方图、暂停视频等。

3. 光流(optical flow)

  1. 介绍:目前图像分析的重要方法,用来表示图像中模式的运动速度。光流的概念是 Gibson 于 1950
    年提出的。所谓光流是指图像中模式运动的速度,光流场是一种二维 (2D)
    瞬时速度场,其中二维速度向量是可见的三维速度向量在成像平面上的投影。光流法是把检测区域的图像变为速度的矢量场,每一个向量表示了景物中一个点在图像中位置的瞬时变化。因此,光流场携带了有关物体运动和景物三维结构的丰富信息,通过对速度场
    (光流场) 的分析可以判断在检测区域内车辆的有无。

思路:求得整个图像检测区域的速度场,根据每个像素点的速度向量特征,可以对图像进行分析。如果是静止背景即无车通过时,则光流向量在整个检测区域是连续变化的;当有车通过时,光流向量必然和其邻域背景的光流向量不同,从而检测出车辆及其出现的位置。
光流法的前提假设:

  • 相邻帧之间的亮度恒定值。
  • 相邻视频帧的取帧的时间连续,或者相邻帧之间物体的运动比较 “微小”。
  • 保持空间一致性,即,同一子图像的像素点具有相同的运动。

原理:

  • 对一个连续的视频帧序列进行处理。
  • 针对每一个视频序列,利用一定的目标检测方法,检测可能出现的前景目标。
  • 如果某一帧出现了前景目标,找到其具有代表性的关键特征点(如 shi-Tomasi 算法)。
  • 对之后的任意两个相邻视频帧而言,寻找上一帧中出现的关键特征点在当前帧中的最佳位置,从而得到前景目标在当前帧中的位置坐标。
  • 如此迭代进行,便可实现目标的跟踪。
  1. 代码实现可以参考以下步骤:

    • 使用 cvGoodFeaturesToTrack () 函数找到图像中的特征点,这是 shi-Tomasi 算法,用于 feature

    • selection,即一张图中哪些是我们感兴趣需要跟踪的点 (interest point)。

    • 定义迭代算法的终止准则,使用 CvTermCriteria 结构体。

    • 使用 cvCalcOpticalFlowPyrLK () 函数计算一个稀疏特征集的光流,使用金字塔中的迭代 Lucas-Kanade
      方法。该函数根据给出的前一帧特征点坐标计算当前视频帧上的特征点坐标,函数寻找具有子象素精度的坐标值。

4. 点追踪(lkdemo)

原理:Lukas-Kanade 光学流算法。Lukas-Kanade 算法是一种基于光流的点追踪算法,通过计算图像中像素点的运动来实现点的追踪。该算法假设相邻帧之间的亮度恒定,小运动,并且空间一致。通过这些假设,可以建立光流方程,然后使用最小二乘法求解光流向量。
代码实现:包括鼠标事件处理、自动初始化跟踪等。
设置鼠标回调函数 onMouse (),用于响应鼠标事件,当用户在图像上点击时,可以添加或删除特征点。
在主循环中,首先读取视频帧,如果帧为空则退出循环。然后将帧复制到 image 中,并根据不同的条件进行处理。
如果 needToInit 为真,表示需要自动初始化跟踪,使用 goodFeaturesToTrack () 函数找到图像中的特征点,然后使用 cornerSubPix () 函数对特征点进行亚像素级精度的调整。
如果 points [0] 不为空,表示已经有特征点,使用 calcOpticalFlowPyrLK () 函数计算光流,找到特征点在当前帧中的位置。然后根据状态向量 status 和误差向量 err,筛选出有效的特征点。如果 addRemovePt 为真,表示用户正在添加特征点,并且当前点击的位置与某个特征点的距离小于 5,则将该特征点添加到 points [1] 中。如果 points [1] 的大小小于最大特征点数 MAX_COUNT,并且 addRemovePt 为真,则将当前点击的位置作为新的特征点添加到 points [1] 中。
在主循环中,还处理了用户的键盘输入,包括自动初始化跟踪、删除所有点、开启 / 关闭夜晚模式等。

六、基础运用

1. 读取图像

OpenCV 中使用cv2.imread()函数读取图像,该函数可指定读取方式。它有两个主要参数,第一个参数是要读入图片的完整路径,比如 “dot.jpg”;第二个参数是读入方式,有多种选择:
cv2.IMREAD_COLOR:默认参数,以彩色模式读取图像,忽略 alpha 通道。对应的数值是 1。此模式下读取的图像是一个三维数组,前两维表示图像的像素坐标,最后一维表示图像的颜色通道(通常是 BGR 三个通道)。
cv2.IMREAD_GRAYSCALE:以灰度模式读取图像,将图像转换为单通道灰度图像。对应的数值是 0。读取后的图像是一个二维数组,每个元素表示对应像素的灰度值。
cv2.IMREAD_UNCHANGED:读取包括 alpha 通道在内的所有图像信息。对于带有 alpha 通道的图像(如 PNG 图像),将保持完整信息。对应的数值是 -1。这种模式下读取的图像可能是一个四维数组,前两维表示像素坐标,第三维表示颜色通道,第四维表示 alpha 通道(透明度信息)。
例如:img = cv2.imread(‘example.jpg’, cv2.IMREAD_COLOR),此代码将以彩色模式读取名为‘example.jpg’的图像,并将其存储在变量 img 中,img 是一个 numpy 数组,可用于后续的图像处理操作。

2. 显示图像

OpenCV 使用cv2.imshow()在窗口中显示图像,该函数可设置窗口大小和是否可调整。它有两个参数,第一个参数是显示图像的窗口的名字,这个名字可以是任意字符串,用于唯一标识一个窗口。例如,可以命名为 “显示图”。第二个参数是要显示的图像,通常是一个 numpy 数组,表示图像的像素数据。
窗口调整有两种模式:
cv2.WINDOW_AUTOSIZE会根据自动图像大小调整窗口,这意味着窗口的大小会自动适应图像的尺寸,用户无法手动调整窗口大小。
cv2.WINDOW_NORMAL允许修改窗口大小。使用此模式,用户可以通过鼠标拖动窗口边框来调整窗口的大小,以适应不同的显示需求。
例如:cv2.imshow(‘显示图’,img)。此代码将在名为 “显示图” 的窗口中显示图像 img。如果没有其他操作,窗口会一直保持显示状态,直到用户手动关闭窗口或通过代码进行关闭。

3. 写入图像

OpenCV 使用cv2.imwrite()保存图像。它有两个参数,第一个参数是要保存的路径,可以是一个字符串,表示图像文件的完整路径和文件名,包括文件扩展名(如 “myimage.jpg”)。第二个参数是要保存的图像,通常是一个 numpy 数组,表示图像的像素数据。
例如:cv2.imwrite(‘path’,name_1)。此代码将图像 name_1 保存到指定的路径‘path’中。保存的图像格式由路径中的文件扩展名决定,例如,如果路径是 “myimage.jpg”,则图像将以 JPEG 格式保存。

4. 访问图像

访问像素值:
可通过坐标访问像素值,也可修改像素值。OpenCV 提供了多种方式访问像素值,例如:
利用指针访问:通过调用函数Mat::ptr(i)来得到第 i 行的首地址地址,然后在行内访问像素。例如:
for (int i = 0; i < Row; i++){
for (int j = 0; j < Col; j++){
Scr.ptr(i)[j][0] = 0;
}
}

利用迭代器访问:创建一个Mat::Iterator对象it,通过it = Mat::begin()来得到迭代首地址,递增迭代器直到it == Mat::end()结束迭代。例如:
while (it!= Scr.end()){
//(*it)[0] = 0;//蓝色通道置零;
//(*it)[1] = 0;//绿色通道置零;
//(*it)[2] = 0;//红色通道置零;
it++;
}

动态访问:使用at函数来得到像素,Mat::at(i,j)为一个像素点的像素值数组,是一个大小为 3 的数组。从 0 到 2 存放了 BGR 三种颜色的灰度值。例如:
for (int i = 0; i < Row; i++){
for (int j = 0; j < Col; j++){
Scr.at(i, j)[2] = 0;
}
}

访问图像属性:
包括形状、像素总数、数据类型等。可以通过以下方式访问图像属性:
image.shape:返回一个包含图像行数、列数和通道数的元组。
image.size:返回图像的像素总数。
image.dtype:返回图像的数据类型。
设置感兴趣区域(ROI):
可选择图像的特定区域进行操作。通过定义一个矩形区域的坐标,可以设置感兴趣区域。例如:
roi = image[y:y+h, x:x+w]

其中,(x,y)是矩形区域的左上角坐标,w和h分别是矩形的宽度和高度。

5. 改变图像大小

OpenCV 中图像的大小可以通过cv2.resize()函数调整:
void resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR );

参数意思:
dsize:输出图像的大小。如果这个参数不为 0,那么就代表将原图像缩放到这个Size(width,height)指定的大小;如果这个参数为 0,那么原图像缩放之后的大小就要通过下面的公式来计算:
fx和fy:原图像宽度和高度的缩放比例。需要注意的是dsize与fx和fy必须不能同时为零,也就是说要么dsize不为零而fx与fy同时可以为 0,要么dsize为 0 而fx与fy不同时为 0。
例如:
import cv2

image = cv2.imread(‘original.jpg’)
resized = cv2.resize(image, (new_width, new_height), interpolation=cv2.INTER_LINEAR)

  1. 绘画图像
    OpenCV 介绍多种绘画方式,如绘制直线、矩形、圆形等,以及常见参数。
    绘制直线:使用cv2.line()函数。参数包括图像、起点坐标、终点坐标、颜色、线宽等。例如:
    cv2.line(image, (x1,y1), (x2,y2), (255,0,0), 2);

绘制矩形:使用cv2.rectangle()函数。参数包括图像、左上角坐标、右下角坐标、颜色、线宽等。例如:
cv2.rectangle(image, (x,y), (x+w,y+h), (0,255,0), 2);

绘制圆形:使用cv2.circle()函数。参数包括图像、圆心坐标、半径、颜色、线宽等。例如:
cv2.circle(image, (x,y), radius, (0,0,255), 2);

七、基础概念介绍

1. 像素的数据类型

OpenCV 像素的数据类型以特定方式表达,如表示每个像素 8 位,无正负号,用 char 表示像素,每个像素有三个通道。
在 OpenCV 中,常见的像素数据类型包括无符号 8 位整数(CV_8U)、有符号 8 位整数(CV_8S)、无符号 16 位整数(CV_16U)、有符号 16 位整数(CV_16S)、有符号 32 位整数(CV_32S)、32 位浮点数(CV_32F)和 64 位浮点数(CV_64F)等。对于图像数据类型,还可以分为单通道和多通道。例如,CV_8UC1 表示单通道无符号 8 位整数,常用于表示二值图像或灰度图像;CV_8UC3 表示三通道无符号 8 位整数,通常对应 BGR 颜色通道的彩色图像。

2. OpenCV 模块介绍

OpenCV 包含多个模块,每个模块都有特定的功能,为计算机视觉和图像处理任务提供了丰富的工具。

一、core 模块

core 模块是 OpenCV 的核心模块,提供了基本的数据结构和函数。
基本数据结构:包括向量、矩阵和图像等。例如,cv::Mat是一个多维数组,可以表示图像、特征矩阵等。
动态数据结构:在图像处理过程中,可能需要动态调整数据结构的大小和内容。core 模块提供了一些函数来实现动态数据结构的创建和管理。
绘图函数:可以在图像上绘制各种图形,如直线、矩形、圆形等。这些绘图函数对于标注图像和可视化结果非常有用。
数组操作相关函数:包括对数组的访问、遍历、复制和修改等操作。例如,可以通过索引或迭代器访问数组中的元素,对数组进行切片操作等。
辅助功能与系统函数和宏:提供了一些辅助功能,如时间测量、错误处理和系统信息获取等。此外,还包括一些宏定义,用于方便地进行编程。
与 OpenGL 的互操作:如果需要在 OpenGL 环境中显示 OpenCV 处理后的图像,可以使用 core 模块提供的函数进行互操作。

二、imgproc 模块

imgproc 模块提供了大量的图像处理函数。
图像滤波:包括线性和非线性滤波算法。线性滤波如均值滤波、高斯滤波等,可以平滑图像,去除噪声。非线性滤波如中值滤波、双边滤波等,可以在去除噪声的同时保留图像的边缘和细节。
边缘检测:用于检测图像中的边缘信息。常见的边缘检测算法有 Canny 边缘检测、Sobel 边缘检测等。边缘检测在目标检测、图像分割等任务中起着重要作用。
形态学操作:包括膨胀、腐蚀、开运算和闭运算等。形态学操作可以用于去除噪声、填充孔洞、连接断开的边缘等。
图像分割:将图像分割成不同的区域或对象。常见的图像分割算法有阈值分割、区域生长、分水岭算法等。
直方图:用于统计图像中像素值的分布情况。可以通过直方图均衡化等方法来增强图像的对比度。
结构分析和形状描述:可以分析图像中的物体形状和结构,提取特征描述子,用于目标识别和匹配等任务。
运动分析和对象跟踪:可以分析视频中的运动信息,实现对象跟踪。例如,光流法和帧差法等算法可以用于检测和跟踪运动对象。
特征检测:检测图像中的特征点,如角点、斑点等。常用的特征检测算法有 Harris 角点检测、SIFT、SURF 和 ORB 等。
目标检测:可以检测图像中的特定目标,如人脸检测、行人检测等。通常使用级联分类器或深度学习方法进行目标检测。

三、video 模块

video 模块提供了视频处理和分析的函数。
视频的读取和保存:可以读取视频文件或从摄像头捕获视频流,并将处理后的视频保存为文件。
帧差法:通过比较连续帧之间的差异来检测运动区域。帧差法简单快速,但对于复杂的运动场景可能不够准确。
光流法:用于估计视频中像素的运动速度。光流法可以提供更准确的运动信息,但计算复杂度较高。
背景建模:可以从视频中提取背景图像,用于运动检测和目标跟踪等任务。常见的背景建模算法有高斯混合模型(GMM)和码本算法等。
运动检测和物体跟踪:可以检测视频中的运动对象,并跟踪它们的位置和运动轨迹。运动检测和物体跟踪在视频监控、智能交通等领域有广泛的应用。

四、calib3d 模块

calib3d 模块提供了摄像机标定和三维重建的函数。
摄像机标定:通过拍摄多幅已知图案的图像,计算摄像机的内参和外参,从而实现从图像坐标到世界坐标的转换。摄像机标定在三维测量、增强现实等领域非常重要。
三维重建:利用多幅图像或深度信息,重建物体的三维模型。常见的三维重建算法有三角测量、立体视觉匹配等。
多视角几何算法:用于处理多个视角下的图像,计算相机之间的相对位置和姿态,以及三维点的坐标。
物体姿态估计:根据已知的物体模型和图像中的特征点,估计物体在摄像机坐标系下的姿态。
立体相似性算法:用于计算立体图像对之间的相似性,以实现立体匹配和深度估计。

五、features2d 模块

features2d 模块提供了图像特征检测和描述子计算的函数。
特征检测:检测图像中的特征点,如角点、斑点等。常用的特征检测算法有 Harris 角点检测、SIFT、SURF 和 ORB 等。这些算法可以在不同的光照、旋转和尺度变化下保持较好的稳定性。
特征描述子计算:为每个特征点计算一个描述子,用于描述特征点的局部特征。描述子可以是向量形式,具有旋转不变性和尺度不变性。常用的描述子有 SIFT 描述子、SURF 描述子和 ORB 描述子等。
特征检测器(Feature Detectors)通用接口:提供了一种统一的接口,方便用户使用不同的特征检测算法。用户可以根据具体需求选择合适的特征检测算法,并通过通用接口进行调用。
描述符提取器(Descriptor Extractors)通用接口:类似于特征检测器通用接口,为描述符提取算法提供了统一的调用方式。
描述符匹配器(Descriptor Matchers)通用接口:用于匹配不同图像中的特征描述子,找到对应关系。常见的描述符匹配算法有暴力匹配(Brute-Force Matcher)和快速近似最近邻搜索(FLANN)等。
通用描述符(Generic Descriptor)匹配器通用接口:提供了更灵活的描述符匹配方式,可以根据不同的需求进行定制。

六、objdetect 模块

objdetect 模块提供了目标检测的功能。
Cascade Classification(级联分类):使用级联分类器进行目标检测。级联分类器是由多个弱分类器组成的强分类器,可以快速检测出目标。常见的应用有人脸检测和行人检测等。
Latent SVM:潜在支持向量机(Latent SVM)是一种基于支持向量机的目标检测算法。它可以学习到目标的外观模型,并在图像中检测出目标的位置。

七、highgui 模块

highgui 模块提供了图形用户界面(GUI)相关的函数。
图像显示和交互:可以显示图像,并处理鼠标和键盘事件。用户可以通过鼠标点击、拖动等操作与图像进行交互,实现图像标注、目标选择等功能。
摄像头和视频捕获:可以从摄像头捕获实时视频流,并进行处理和显示。同时,也可以读取视频文件进行处理。
文件读取和保存:支持图像和视频文件的读取和保存操作。可以将处理后的图像或视频保存为文件,以便后续分析和使用。

八、gpu 模块

gpu 模块包含了一些 GPU 加速的接口,底层的加速是 CUDA 实现。
利用 GPU 进行图像处理和计算可以大大提高处理速度,特别是对于大规模数据和复杂算法。
GPU 加速的函数包括图像滤波、特征检测、目标检测等。用户可以根据自己的硬件环境和需求,选择使用 GPU 加速来提高程序的性能。

九、其他模块

除了上述主要模块外,OpenCV 还包括一些其他模块,如:
ml 模块:提供了机器学习相关的函数,包括统计模型、分类算法、聚类算法等。可以用于图像分类、目标检测等任务。
flann 模块:Fast Library for Approximate Nearest Neighbors,用于在多维空间进行聚类和检索,经常和关键点匹配搭配使用。
photo 模块:主要是图像修复和降噪。可以用于去除图像中的噪声、修复损坏的区域等。
stitching 模块:图像拼接模块,有了它可以自己生成全景照片。
nonfree 模块:受到专利保护的一些算法,其实就是 SIFT 和 SURF。
contrib 模块:一些实验性质的算法,考虑在未来版本中加入的。
legacy 模块:字面是遗产,意思就是废弃的一些接口,保留是考虑到向下兼容。
ocl 模块:利用 OpenCL 并行加速的一些接口。
superres 模块:超分辨率模块,其实就是 BTV-L1(Biliteral Total Variation – L1 regularization)算法。
viz 模块:基础的 3D 渲染模块,其实底层就是著名的 3D 工具包 VTK(Visualization Toolkit)。

3. cv::NAryMatIterator

1. 基本概念:

cv::NAryMatIterator 是 OpenCV 中用于高效遍历多个多维矩阵(cv::Mat)元素的迭代器。在 OpenCV 中,cv::Mat 是一个多维数组,可以表示图像、特征矩阵等。处理多个矩阵时,通常需要逐元素地操作这些矩阵。cv::NAryMatIterator 通过简化矩阵遍历的代码,提高了代码的可读性和效率。它允许将多个矩阵看作一个整体,并以统一的方式遍历它们的元素,特别适合需要对多个矩阵进行同步操作的场景。

2. 构造函数:

cv::NAryMatIterator 的构造函数有几种常见的形式,最常用的有:
cv::NAryMatIterator::NAryMatIterator(const cv::Mat** arrays, // 输入矩阵数组的指针
cv::Mat* planes, // 存储当前遍历到的元素块的数组
int narrays = -1); // 矩阵的数量

arrays:指向输入矩阵数组的指针,每个元素都是一个 cv::Mat 对象。
planes:存储当前遍历到的每个矩阵块的指针数组。注意,它们并不是原始矩阵的拷贝,而是指向相应的内存块。
narrays:要遍历的矩阵的数量。如果为 -1,则表示 arrays 中的所有矩阵。

3. 成员变量:

const cv::Mat** arrays:指向输入矩阵的数组。
cv::Mat* planes:指向当前处理的每个矩阵块的数组。
uchar* ptr:指向当前处理的矩阵块数据的指针。
int iterdepth:表示当前遍历的维度深度。
size_t nplanes:表示矩阵的维度积(即需要遍历的块的数量)。
size_t size:表示当前处理块的大小。

4. 成员函数:

bool next():使迭代器指向下一个矩阵块。如果已经遍历完所有块,则返回 false。
cv::Mat* operator*():返回当前的矩阵块。

5. 使用方法:

以下是 cv::NAryMatIterator 的一个基本使用示例:

cv::Mat mat1 =...;  // 初始化第一个矩阵
cv::Mat mat2 =...;  // 初始化第二个矩阵
const cv::Mat* arrays[] = {&mat1, &mat2, nullptr };
cv::Mat planes[2];
cv::NAryMatIterator it(arrays, planes);
for (size_t i = 0; i < it.nplanes; i++, ++it) {// 处理 planes[0] 和 planes[1]// 它们表示 mat1 和 mat2 当前遍历到的块
}

在这个示例中,mat1 和 mat2 是两个需要同步遍历的矩阵。NAryMatIterator 将它们分块处理,planes 数组存储了当前处理的块。++it 用于移动到下一个块,而 it.nplanes 表示总块数。

6. 应用场景:

cv::NAryMatIterator 特别适合以下应用场景:
多矩阵同步操作:例如需要同时对两张图像进行像素级别的操作。
高维矩阵的遍历:例如遍历多个 3D 矩阵或更高维的矩阵。
批量操作:例如对每个图像块应用同一个操作,而不是单独处理每个矩阵的每个元素。
cv::NAryMatIterator 的设计初衷是为了简化代码的结构,避免手动处理复杂的多维索引计算,并提高代码的效率。

八、知识讲解

1. 图像的加法运算

在图像处理中,图像的加法运算是一种常见的操作。OpenCV 提供了两种主要的加法运算方式:numpy 加法运算和 OpenCV 加法运算。
numpy 加法运算:加模运算,根据情况保留结果或进行取模。例如:

import numpy as np
import cv2 as cv
img1 = cv.imread('image1.jpg')
img2 = cv.imread('image2.jpg')
result_numpy = img1 + img2

在 numpy 加法运算中,如果两个像素值相加的结果超过了 255,会进行取模操作。比如,如果两个像素值分别为 250 和 10,相加结果为 260,对于 uint8 类型的数据,260 % 256 = 4。
OpenCV 加法运算:饱和运算,超过 255 直接保留 255。例如:
result_opencv = cv.add(img1, img2)

在 OpenCV 的加法运算中,如果两个像素值相加的结果超过了 255,会直接保留 255。比如,如果两个像素值分别为 250 和 10,相加结果为 260,最终结果会被截断为 255。
代码示例:对比 numpy 和 OpenCV 的加法运算。

import numpy as np
import cv2 as cvimg1 = cv.imread('image1.jpg')
img2 = cv.imread('image2.jpg')result_numpy = img1 + img2
result_opencv = cv.add(img1, img2)cv.imshow('Numpy Addition', result_numpy)
cv.imshow('OpenCV Addition', result_opencv)cv.waitKey(0)
cv.destroyAllWindows()

2. 图像融合

目的:将多张图像信息融合到一张图像上。图像融合可以将不同图像的特征或信息结合起来,创造出更丰富、更有表现力的图像。例如,可以将两张具有不同场景的图像融合在一起,以创建一个新的合成图像。
函数使用:addWeighted () 函数介绍及代码示例。
OpenCV 中的addWeighted()函数用于实现图像的线性融合。该函数的语法如下:
void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype = -1);

参数解释:
src1:要叠加的第一个图像,通常是背景图像。
alpha:标识第一个参数叠加的权重。
src2:表示第二个叠加的图像,它需要和第一个数组拥有同样的尺寸和通道数。
beta:表示第二个叠加图像的权重。
gamma:输出参数,需要和前两个图像拥有同样的通道数和尺寸,一般设置为 0。
dst:输出图像。
dtype:输出阵列的深度,有默认值 -1,当两张叠加图片深度相同时,参数为 -1。
代码示例:

import cv2img1 = cv2.imread('background.jpg')
img2 = cv2.imread('foreground.jpg')result = cv2.addWeighted(img1, 0.7, img2, 0.3, 0)cv2.imshow('Image Fusion', result)
cv2.waitKey(0)
cv2.destroyAllWindows()

3. 图像的类型转换

包括 BGR 转灰度图像、BGR 转 RGB、灰度图像转 BGR 等。在 OpenCV 中,图像的颜色空间可以通过cv2.cvtColor()函数进行转换。例如:
BGR 转灰度图像:gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)。
BGR 转 RGB:通常只在需要与非 OpenCV 库交互时才需要进行此转换,可以使用image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)。
灰度图像转 BGR:rgb = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)。
代码示例:使用cv2.cvtColor()进行类型转换。

import cv2image = cv2.imread('image.jpg')# BGR 转灰度图像
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# BGR 转 RGB
image_rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)# 灰度图像转 BGR
rgb = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)cv2.imshow('Original Image', image)
cv2.imshow('Gray Image', gray)
cv2.imshow('RGB Image', image_rgb)
cv2.imshow('Converted RGB to BGR', rgb)cv2.waitKey(0)
cv2.destroyAllWindows()

4. 图像缩放

函数介绍:resize 函数语法格式及参数解释。
OpenCV 中的cv2.resize()函数用于调整图像的尺寸。函数原型如下:
void resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR );

参数说明:
src:输入图像,Mat类型即可。
dst:输出图像,当其非零时,有着dsize(第三个参数)的尺寸或者有src.size()计算出来。
dsize:输出图像的大小。如果它等于 0,由下式计算:dsize = Size( round(fxsrc.cols), round(fysrc.rows));其中fx,fy,dsize都能不为 0。
fx:沿水平轴的缩放系数,默认值为 0,且等于 0 时,由下式计算:inv_scale_x =(double)dsize.width/ssize.width。
fy:沿垂直轴的缩放系数,默认值为 0,且等于 0 时,由下式计算:inv_scale_y =(double)dsize.height/ssize.height。
interpolation:用于指定插值方式,默认值为INTER_LINEAR(线性插值),可选插值方式如下:
INTER_NEAREST:最近邻插值。
INTER_LINEAR:线性插值(默认值)。
INTER_AREA:区域插值(利用像素区域关系的重采样插值)。
INTER_CUBIC:三次样条插值(超过 4×4 像素领域内的双三次插值)。
INTER_LANCZOS4:Lanczos 插值(超过 8×8 像素邻域的 Lanczos 插值)。
代码示例:不同方式的图像缩放。

import cv2image = cv2.imread('original.jpg')# 缩小图像尺寸为原尺寸的一半
height, width = image.shape[:2]
new_size = (width // 2, height // 2)
resized_img_linear = cv2.resize(image, new_size, interpolation=cv2.INTER_LINEAR)# 使用区域插值缩小图像
resized_img_area = cv2.resize(image, new_size, interpolation=cv2.INTER_AREA)# 放大图像尺寸为原尺寸的两倍
new_size_large = (width * 2, height * 2)
resized_img_cubic = cv2.resize(image, new_size_large, interpolation=cv2.INTER_CUBIC)cv2.imshow('Original Image', image)
cv2.imshow('Resized Image (Linear)', resized_img_linear)
cv2.imshow('Resized Image (Area)', resized_img_area)
cv2.imshow('Resized Image (Cubic)', resized_img_cubic)cv2.waitKey(0)
cv2.destroyAllWindows()

5. 图像翻转

语法:指定flipcode的值进行不同方式的翻转。
OpenCV 中使用cv2.flip()函数对图像进行翻转操作。flipcode参数决定了翻转的方式:
flipcode = 0表示上下翻转。
flipcode > 0表示左右翻转。
flipcode < 0上下 + 左右翻转。
代码示例:

import cv2image = cv2.imread('image.jpg')# 上下翻转
flipped_up_down = cv2.flip(image, 0)# 左右翻转
flipped_left_right = cv2.flip(image, 1)# 上下+左右翻转
flipped_both = cv2.flip(image, -1)cv2.imshow('Original Image', image)
cv2.imshow('Flipped Up Down', flipped_up_down)
cv2.imshow('Flipped Left Right', flipped_left_right)
cv2.imshow('Flipped Both', flipped_both)cv2.waitKey(0)
cv2.destroyAllWindows()

九、总结

OpenCV 作为强大的计算机视觉库,提供了丰富的功能和灵活的操作方式。通过本文的介绍,读者可以对 OpenCV 的基础有更深入的了解,为进一步的学习和应用打下坚实的基础。
在前面的章节中,我们详细介绍了 OpenCV 的各个方面,包括简介、安装与配置、函数详解、基本教程、应用教程、基础运用、基础概念介绍以及知识讲解。
OpenCV 具有跨平台支持、多语言接口、丰富的功能、高效性以及活跃的社区支持等特点和优势。它广泛应用于计算机视觉、视频分析、机器学习、医学影像处理、自动驾驶、工业检测、游戏开发等领域。
在安装与配置方面,我们介绍了在 Pycharm 中的安装方法,包括直接在 Pycharm 中安装和使用 pip 安装,以及在安装失败时的解决方法。同时,我们还通过代码示例验证了安装是否成功。
OpenCV 的函数详解部分,我们深入探讨了图像读取函数 cv2.imread ()、图像显示函数 cv2.imshow ()、图像保存函数 cv2.imwrite () 等常用函数的参数和用法。此外,我们还介绍了图像像素及掩膜操作详解、Mat 对象的拷贝和创建方法、格式化打印以及颜色空间缩减等内容。
在基本教程中,我们涵盖了 opencv 配置、加载修改显示及保存图像、图像像素及掩膜操作详解、Mat 对象等内容。同时,我们还介绍了摄像头基本操作、彩色目标追踪(Camshift)、光流(optical flow)、点追踪(lkdemo)等应用教程。
在基础运用部分,我们介绍了读取图像、显示图像、写入图像、访问图像、改变图像大小、绘画图像等内容。同时,我们还介绍了像素的数据类型、OpenCV 模块以及 cv::NAryMatIterator 等基础概念。
在知识讲解部分,我们深入探讨了图像的加法运算、图像融合、图像的类型转换、图像缩放、图像翻转等内容。
总之,OpenCV 是一个功能强大的计算机视觉库,它为开发者提供了丰富的工具和算法,使得图像处理和计算机视觉任务变得更加简单和高效。通过学习和掌握 OpenCV,我们可以在各个领域中实现各种有趣和实用的应用。

相关文章:

《OpenCV 基础全攻略:从入门到精通》

《OpenCV 基础全攻略&#xff1a;从入门到精通》 一、OpenCV 简介&#xff08;一&#xff09;特点&#xff08;二&#xff09;优势&#xff08;三&#xff09;应用场景 二、安装与配置三、OpenCV 函数详解1. 图像读取函数 cv2.imread ()2. 图像显示函数 cv2.imshow ()3. 图像保…...

spring ai如何使用function call调用第三方模型

这里写自定义目录标题 背景什么是function call怎么用function call&#xff1f;总结 背景 一直困惑于ai是如何使用插件或者其他一些功能的&#xff0c;后来发现&#xff0c;很多大模型都支持function call功能&#xff0c;如何让大模型能够联网查询呢&#xff0c;function ca…...

2024 数学建模国一经验分享

2024 数学建模国一经验分享 背景&#xff1a;武汉某211&#xff0c;专业&#xff1a;计算机科学 心血来潮&#xff0c;就从学习和组队两个方面指点下后来者&#xff0c;帮新人避坑吧 2024年我在数学建模比赛中获得了国一&#xff08;教练说论文的分数是湖北省B组第一&#xff0…...

javaweb-Mybaits

1.Mybaits入门 &#xff08;1&#xff09;介绍 &#xff08;2&#xff09; 2.Mybaits VS JDBC 3.数据库连接池 &#xff08;1&#xff09;SpringBoot默认连接池为hikari&#xff0c;切换为Druid有两种方式 方式一&#xff1a;加依赖 方式二&#xff1a;直接修改配置文件 …...

108.【C语言】数据结构之二叉树查找值为x的节点

目录 1.题目 代码模板 2.分析 分类讨论各种情况 大概的框架 关键部分(继续递归)的详解 递归调用展开图 3.测试结果 其他写法 4.结论 5.注意事项 不推荐的写法 1.题目 查找值为x的节点并返回节点的地址 代码模板 typedef int BTDataType; typedef struct BinaryT…...

Ant-Design-Vue 全屏下拉日期框无法显示,能显示后小屏又位置错乱

问题1&#xff1a;在全屏后 日期选择器的下拉框无法显示。 解决&#xff1a;在Ant-Design-Vue的文档中&#xff0c;很多含下拉框的组件都有一个属性 getPopupContainer可以用来指定弹出层的挂载节点。 在该组件上加上 getPopupContainer 属性,给挂载到最外层盒子上。 <temp…...

sec啥意思

sec的基本含义是秒&#xff0c;是时间的基本单位之一&#xff1b;在数学中表示正割函数&#xff1b;在计算机科学中有时指安全&#xff1b;在法语中意为干的等。 sec的多重含义与应用 sec在数学中的定义 在数学领域&#xff0c;尤其是三角学中&#xff0c;sec代表正割函数&a…...

云计算vspere 安装过程

1 材料的准备 1 安装虚拟机 vmware workstation 2 安装esxi 主机 3 在esxi 主机上安装windows 2018 dns 服务器 4 在虚拟机上安装windows 2018 服务器 6 安装vcenter 5 登入界面测试 这里讲一下&#xff0c;由于部署vspere 需要在windows 2012 服务器上部…...

spring-boot打包前重新拉取maven依赖

在使用 Maven 构建 Spring Boot 项目时&#xff0c;如果希望在每次打包时都强制拉取依赖&#xff0c;可以通过以下方法实现。 方法一&#xff1a;在命令行强制更新依赖 在执行 mvn package 或 mvn install 等命令时&#xff0c;添加 -U 参数&#xff1a; mvn clean package -…...

华为云域名网站,域名切换到Cloudflare CDN出现访问报错:DNS 重定向次过多

网站域名切换到Cloudflare出现访问报错&#xff1a;重定向次过多&#xff0c;应该如何处理&#xff1f; 最近我自己已经遇到很多次这个情况了&#xff0c;将网站域名DNS切换到Cloudflare之后&#xff0c;网站会打不开&#xff0c;出现重定向次数过多报错。 网站域名切换到Clo…...

浔川AI翻译v5.1.0版本正式亮相!

浔川 AI 翻译 v5.1.0 版本正式亮相&#xff01; 在科技浪潮汹涌澎湃的今天&#xff0c;浔川 AI 翻译以其卓越的技术实力和对用户需求的精准把握&#xff0c;自豪地向全球用户宣布&#xff1a;浔川 AI 翻译 v5.1.0 版本正式闪耀登场&#xff01;这一全新版本在继承以往优势的基础…...

Merkle 树 应用在 代码工程

将 Merkle 树 应用在 代码工程 中&#xff0c;尤其是在大型项目中&#xff0c;可以帮助管理和验证代码的完整性、追踪代码变更、提高版本控制的效率等。通过将代码文件、类、函数等结构映射到 Merkle 树中&#xff0c;我们可以高效地验证代码库的任何变更&#xff0c;确保每个部…...

如何将表中存储的 JSON 数据转换为新表

如何将表中存储的 JSON 数据转换为新表 引言 本文介绍如何使用 PostgreSQL 的 JSON 函数&#xff0c;将 log_table 表中的 param_json 字段&#xff08;存储为 JSON 数组&#xff09;转换为一张新的表&#xff0c;并提取出具体的字段值。 表结构说明 假设 log_table 表的结…...

鸿蒙开发——使用ArkTs处理XML文本

1、概 述 XML&#xff08;可扩展标记语言&#xff09;是一种用于描述数据的标记语言&#xff0c;旨在提供一种通用的方式来传输和存储数据&#xff0c;特别是Web应用程序中经常使用的数据。XML并不预定义标记。因此&#xff0c;XML更加灵活&#xff0c;并且可以适用于广泛的应…...

借助vector实现进制转换详解

进制转换&#xff0c;没什么可说的&#xff0c;大一级别的水平&#xff0c;不过在某些考研题目中可能会涉及到顺序栈的实现&#xff0c;本贴不使用顺序栈&#xff0c;用STL里面的vector模拟一下&#xff1a;关键在于想清楚【除留取余】的逻辑&#xff0c;至于用什么结构存放中间…...

混合云策略在安全领域受到青睐

Genetec 发布了《2025 年物理安全状况报告》&#xff0c;该报告根据超过 5,600 名该领域领导者&#xff08;其中包括 100 多名来自澳大利亚和新西兰的领导者&#xff09;的回应&#xff0c;揭示了物理安全运营的趋势。 报告发现&#xff0c;澳大利亚和新西兰的组织采用混合云策…...

Jackson - 序列化和反序列化Java集合对象

在本文中&#xff0c;我将向您展示如何使用Jackson API来序列化和反序列化Java集合对象&#xff0c;如List、Set和Map。 我们将通过具体的示例演示如何利用ObjectMapper类的方法进行这些操作。 主要内容 添加Maven依赖项使用Jackson API进行List序列化使用Jackson API进行Se…...

No.26 笔记 | 信息收集与工具实践指南

渗透测试的第一步&#xff1a;信息收集背后的“侦察艺术” 在网络安全的世界里&#xff0c;信息就是武器。 无论是追踪隐藏的漏洞&#xff0c;还是找到不被注意的入口&#xff0c;信息收集就像一场现代化的“谍战片”。而作为渗透测试的开场白&#xff0c;信息收集不仅考验技…...

使用倒排索引法解决分库分表后查询问题

数据进行了分库分表后&#xff0c;要查询某一条数据的信息&#xff0c;事先是不清楚该条数据在哪台服务器上的&#xff0c;这时候可以使用倒排索引法&#xff0c;将数据的关键信息存储到Redis中&#xff0c;然后从Redis中获取到数据所在的服务器信息和数据ID。 Redis倒排索引示…...

Linux操作系统--文件的重定向以及文件缓冲区

目录 前言 一、文件描述符的分配规则 二、重定向 三、系统中的重定向接口 1、dup2()介绍 2、dup2()使用 1&#xff09;输出重定向和追加重定向 2&#xff09;输入重定向 四、文件缓冲区 1、定义 2、缓冲区刷新的条件 1&#xff09;文件缓冲区存在的意义 2&…...

Linux 远程连接服务

远程连接服务器简介 什么是远程连接服务器 远程连接服务器通过文字或图形接口方式来远程登录系统&#xff0c;让你在远程终端前登录linux主机以取得可操 作主机接口&#xff08;shell&#xff09;&#xff0c;而登录后的操作感觉就像是坐在系统前面一样。 远程连接服务器的功…...

Chrome控制台 网站性能优化指标一览

打开chrome-》f12/右键查看元素-》NetWrok/网络 ctrlF5 刷新网页&#xff0c;可以看到从输入url到页面资源请求并加载网页&#xff0c;用于查看资源加载&#xff0c;接口请求&#xff0c;评估网页、网站性能等&#xff0c;如下图&#xff1a; request、stransferred、resour…...

【SpringBoot】使用IDEA创建SpringBoot项目

1、使用SpringBoot脚手架创建 我们使用SpringBoot的脚手架Spring Initializr创建&#xff0c;如图所示&#xff1a; 2、选择SpringBoot版本 最开始做项目时候&#xff0c;组长说创建一个 springboot 2.5.4 的项目&#xff0c;mysql使用 5.6.X &#xff0c;maven使用是3.6.X…...

Mysql锁

锁的分类 基于锁的属性分类&#xff1a;共享锁、排它锁。基于锁的粒度分类&#xff1a;表锁、行锁、记录锁、间隙锁、临键锁。基于锁的状态分类&#xff1a;意向共享锁、意向排它锁。 排他锁与任何的锁都不兼容&#xff0c;共享锁仅和共享锁兼容。由于MVCC的存在&#xff0c;…...

深入浅出:PHP中的数据类型全解析

文章目录 引言理解数据类型标量类型整数 (integer)浮点数 (float)布尔值 (boolean)字符串 (string) 复合类型数组 (array)对象 (object)资源 (resource)NULL 特殊类型Callable强制类型转换 实战案例总结与展望参考资料 引言 在编程的世界里&#xff0c;数据类型是构建任何应用…...

030.随机指纹chromium编译-修改windows操作系统版本

一、目标&#xff1a; 1.了解js是如何获取windows版本的。2.如何从c层面修改chromium源码&#xff0c;修改win系统版本 二、js是如何获取windows系统版本&#xff1a; 将下面的js复制到F12控制台 async function detectWindowsVersion() {let userAgent navigator.userAge…...

IP 协议

IP协议 一、介绍1、IP协议2、IPv43、IPv6 二、主要功能三、协议格式1、示意图2、说明 四、网段划分1、介绍2、目的3、方法4、步骤 五、基于类别的IP地址分配方式1、示意图2、范围 六、CIDR1、介绍2、组成3、优点4、示意图 七、子网掩码1、介绍2、功能3、表示方法4、CIDR表示法5…...

【Docker】创建Docker并部署Web站点

要在服务器上创建Docker容器&#xff0c;并在其中部署站点&#xff0c;你可以按照以下步骤操作。我们将以Flask应用为例来说明如何完成这一过程。 1. 准备工作 确保你的服务器已经安装了Docker。如果没有&#xff0c;请根据官方文档安装&#xff1a; Docker 安装指南 2. 创…...

【C语言的奥秘9】数据类型总结

一、数据类型的介绍 数据类型是按被定义变量的性质&#xff0c;表示形式&#xff0c;占据存储空间的多少&#xff0c;构造特点来划分的。在C语言中&#xff0c;数据类型可分为:基本数据类型&#xff0c;构造数据类型&#xff0c;指针类型&#xff0c;空类型四大类。 基本数据类…...

EasyExcel注解使用

上接《Springboot下导入导出excel》&#xff0c;本篇详细介绍 EasyExcel 注解使用。 1. ExcelProperty value&#xff1a;指定写入的列头&#xff0c;如果不指定则使用成员变量的名字作为列头&#xff1b;如果要设置复杂的头&#xff0c;可以为value指定多个值order&#xff…...

什么是多模态和模态

文章目录 前言一、定义1. 模态 (Modal)2. 非模态 (Non-modal) 二、GUI中1. 模态&#xff08;Modal&#xff09;对话框2. 非模态&#xff08;Modeless&#xff09;对话框 三、模态 vs 非模态 的对比四、何时使用模态和非模态对话框&#xff1f;五、Qt 中 exec() 与 show() 的区别…...

【系统架构设计师】真题论文: 论NoSQL数据库技术及其应用(包括解题思路和素材)

更多内容请见: 备考系统架构设计师-专栏介绍和目录 文章目录 真题题目(2018年 试题4)解题思路论文素材参考真题题目(2018年 试题4) 随着互联网 web2.0 网站的兴起,传统关系数据库在应对 web2.0 网站,特别是超大规模和高并发的 web2.0 纯动态 SNS 网站上已经显得力不从心…...

TCP/IP 协议图--计算机网络体系结构分层

计算机网络体系结构分层 计算机网络体系结构分层 不难看出&#xff0c;TCP/IP 与 OSI 在分层模块上稍有区别。OSI 参考模型注重“通信协议必要的功能是什么”&#xff0c;而 TCP/IP 则更强调“在计算机上实现协议应该开发哪种程序”...

【Android】Intent类详解

目录 引言 一、Intent的定义 二、Intent的用途 三、Intent的七大属性 四、Intent的种类 4.1 显式Intent 4.2 隐式Intent 五、代码示例 5.1 activity_intent.xml 5.2 IntentActivity.java 5.3 AndroidManifest.xml 5.4 实现效果 结语 引言 Intent在Android开发…...

【LeetCode刷题之路】64.最小路径和 (动态规划入门)

LeetCode刷题记录 &#x1f310; 我的博客主页&#xff1a;iiiiiankor&#x1f3af; 如果你觉得我的内容对你有帮助&#xff0c;不妨点个赞&#x1f44d;、留个评论✍&#xff0c;或者收藏⭐&#xff0c;让我们一起进步&#xff01;&#x1f4dd; 专栏系列&#xff1a;LeetCode…...

Facebook:筑牢隐私安全堡垒,守护社交净土

在全球社交媒体平台中&#xff0c;Facebook一直是风靡全球的佼佼者。然而&#xff0c;随着数字化信息的迅速膨胀&#xff0c;用户隐私保护的重要性日益凸显。面对用户对数据安全性的高度重视&#xff0c;Facebook致力于通过一系列措施来确保隐私保护&#xff0c;守护每位用户的…...

MongoDB 索引类型详解

MongoDB 索引类型详解 在 MongoDB 中&#xff0c;索引是提高查询效率、优化数据库性能的重要手段。MongoDB 支持多种类型的索引&#xff0c;每种索引类型适用于不同的查询需求和场景。本文将详细介绍 MongoDB 中几种常见的索引类型、示例及其限制。 1. 单字段索引&#xff08…...

国家信息中心单志广:智慧城市转型中的数据要素价值释放

今日&#xff0c;由中国电信集团主办的2024数字科技生态大会数据要素合作论坛在广州市举办。国家发改委国家信息中心信息化和产业发展部主任单志广在论坛发展主旨演讲&#xff1a;智慧城市转型中的数据要素价值释放&#xff0c;主要包括发展新形势、数据新要素、数据新产权、数…...

底层逻辑之:欧拉-拉格朗日方程(Euler-Lagrange equations)变分法(Calculus of Variations)的核心思想

0前言&#xff1a; 0.1 17世纪的泛函&#xff08;Functional&#xff09;分析与变分法&#xff08;Calculus of Variations&#xff09; 在17世纪&#xff0c;数学家们开始遇到一些需要处理函数集合的问题&#xff0c;这些问题涉及到函数的极值、曲线的长度、曲面的面积等。这…...

2024-12-03OpenCV图片处理基础

OpenCV图片处理基础 OpenCV的视频教学&#xff1a;https://www.bilibili.com/video/BV14P411D7MH 1-OpenCV摄像头读取 OpenCV使用摄像头读取图片帧&#xff0c;点击S保存当前帧到指定文件夹&#xff0c;点击Q关闭窗口&#xff0c;点击其他按钮打印按钮的值 要实现这个功能&…...

【汇编语言】标志寄存器(二) —— 标志位驱动的计算:ADC、SBB 和 CMP 的巧妙应用

前言 &#x1f4cc; 汇编语言是很多相关课程&#xff08;如数据结构、操作系统、微机原理&#xff09;的重要基础。但仅仅从课程的角度出发就太片面了&#xff0c;其实学习汇编语言可以深入理解计算机底层工作原理&#xff0c;提升代码效率&#xff0c;尤其在嵌入式系统和性能优…...

Java刷题训练第一期

个人主页&#xff1a;手握风云 专栏&#xff1a;Java刷题训练营 1. 字符转ASCII码 问题描述&#xff1a;BoBo教KiKi字符常量或字符变量表示的字符在内存中以ASCII码形式存储。BoBo出了一个问题给KiKi&#xff0c;输入一个字符&#xff0c;输出该字符相应的ASCII码。 输入描述…...

【leetcode100】矩阵置零

1、题目描述 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用原地算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]] 2、初始思路 2…...

【MySQL 进阶之路】SQL 优化

6.SQL 性能分析笔记 在现代数据库的高并发环境下&#xff0c;SQL 查询优化成为提升系统性能和响应速度的关键。本文将总结常见的 SQL 优化策略&#xff0c;包括插入优化、主键设计、排序优化、GROUP BY 优化等&#xff0c;帮助你在面对大规模数据时&#xff0c;做到高效查询和…...

本地部署开源趣味艺术画板Paint Board结合内网穿透跨网络多设备在线绘画

文章目录 前言1.关于Paint Board2.本地部署paint-board3.使用Paint Board4.cpolar内网穿透工具安装5.创建远程连接公网地址6.固定Paint Board公网地址 前言 大家好&#xff0c;是不是每次想要在电脑上画画时&#xff0c;都被那些笨重的专业绘图软件搞得头大如斗呢&#xff1f;…...

位图(bitmap)和布隆过滤器(bloom_filter)

1.位图-Bitmap 1.1问题引入 :给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无符号整数&#xff0c;如何快速判断一个数是否在这40亿个数中&#xff1f; 40亿个无符号整数大约16G的大小&#xff0c;用map或者set显然是无法支持海量数据的存储。那么我们能否不存储数…...

如何使用JDBC向数据库中插入日期数据???

在学习JDBC 的过程中很多小明有疑问在IDEA编辑器是如何插入一个日期类型的数据的&#xff0c;此篇一些方法希望可以帮助到你。 示例&#xff1a; import java.text.ParseException; import java.text.SimpleDateFormat; import java.sql.Date; import java.util.Scanner;publi…...

电子系统设计实验4 信号发生电路设计实验

一、实验目的 1. 掌握正弦信号发生器的设计方法。 2. 掌握方波发生器的设计方法。 二、实验内容及结果 1. 实验内容 设计一用于RFID读卡器测试的幅移键控发生器&#xff08;ASK&#xff09;&#xff0c;其结构如图4-1所示。正弦振荡器输出频率为150kHz&#xff0c;幅度为3V…...

【Docker】Linux与Windows系统安装Docker+Docker上简单安装MySQL

一、Windows安装Docker 由于我在许多平台搜索Windows下安装Docker的方法&#xff0c;都提到了Win10家庭版无法直接安装Docker。个人电脑就是Win10家庭版&#xff0c;本着实践出真知的想法&#xff0c;个人在本机Win10家庭版实验结果为需要采用下述传统手动安装的办法&#xff…...

linux更新镜像源

镜像源地址 1 阿里云 http://mirrors.aliyun.com/ubuntu/ 2 网易源 http://mirrors.163.com/ubuntu/ 3 浙大源 http://mirrors.zju.edu.cn/ubuntu 4 中科大源 http://mirrors.ustc.edu.cn/ubuntu/ 5 清华源 http://mirrors.tuna.tsinghua.edu.cn/ubuntu/ 更新镜像源 此处…...