Python计算机视觉第十章-OpenCV

news/2024/9/22 19:09:29/

目录

10.1 OpenCV的Python接口

10.2 OpenCV基础知识

        10.2.1 读取和写入图像

10.2.2 颜色空间

10.2.3 显示图像及结果

10.3 处理视频

        10.3.1 视频输入

10.3.2 将视频读取到NumPy数组中

10.4 跟踪

        10.4.1 光流

10.4.2 Lucas-Kanade算法


10.1 OpenCVPython接口

        OpenCV 是一个 C++ 库,它包含了计算机视觉领域的很多模块。除了 C++ C, Python 作为一种简洁的脚本语言,在 C++ 代码基础上的 Python 接口得到了越来越广泛的支持。

        OpenCV 2.3.1 版本实际上提供了两个 Python 接口。旧的 cv 模块使用 OpenCV 内部 数据类型,并且从 NumPy 使用起来可能需要一些技巧。新的 cv2 模块用到了 NumPy 数组,并且使用起来更加直观 1 ,可以通过以下方式导入新的 cv2 模块:

        import cv2

10.2 OpenCV基础知识

        10.2.1 读取和写入图像

        载入一张图像,打印出图像大小,对图像进行转换并保存为 .png 格式:

实验代码:

python">import cv2# 读取图像
im = cv2.imread('suiyuan.jpg')# 获取图像尺寸
h, w = im.shape[:2]
print(h, w)# 保存图像为 .png 格式
cv2.imwrite('suiyuanresult.png', im)

 分析:

  1. 读取图像:使用 cv2.imread 函数加载图像文件。
  2. 获取尺寸:通过 im.shape[:2] 获取图像的高度和宽度。
  3. 打印尺寸:输出图像的高度和宽度。
  4. 保存图像:使用 cv2.imwrite 函数将原图保存为 PNG 格式。

结果:

        

10.2.2 颜色空间

        实验代码:

python">import cv2# 读取图像
im = cv2.imread('suiyuan.jpg')# 创建灰度图像
gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)# 获取原图像尺寸
h, w = im.shape[:2]
print(f'Original Image Size: {h}x{w}')# 保存灰度图像
cv2.imwrite('gray_image.png', gray)# 将原图像转换为 RGB 格式
rgb_image = cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
cv2.imwrite('result_rgb.png', rgb_image)

  分析:

  1. 图像读取:使用 cv2.imread 函数加载图像文件 "suiyuan.jpg"。
  2. 颜色空间转换
    • 将原图像从 BGR 转换为灰度图像,使用 cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
    • 还可以将 BGR 图像转换为 RGB 格式,使用 cv2.cvtColor(im, cv2.COLOR_BGR2RGB)
  3. 打印图像尺寸:输出原图像的高度和宽度。
  4. 保存图像
    • 保存灰度图像为 "gray_image.png"。
    • 保存 RGB 图像为 "result_rgb.png"。

结果:

        原图像:

灰度图像:

RGB图像

10.2.3 显示图像及结果

        实验代码:

python">import cv2# 读取图像
im = cv2.imread('guimie.jpg')# 转换为灰度图像
gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)# 计算积分图像
intim = cv2.integral(gray)# 归一化积分图像并保存
intim_normalized = (255.0 * intim) / intim.max()
cv2.imwrite('result.jpg', intim_normalized)

分析:

  1. 图像读取:使用 cv2.imread 函数读取图像文件 "guimie.jpg"。
  2. 颜色空间转换:将图像转换为灰度图像,使用 cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
  3. 计算积分图像:通过 cv2.integral(gray) 创建积分图像,计算每个像素值为原图左上方所有像素强度的和,这在特征评估中非常有效。
  4. 归一化和保存:将积分图像归一化到 0-255 范围,并使用 cv2.imwrite 保存为 "result.jpg"。

结果:

        

10.3 处理视频

        10.3.1 视频输入

实验代码:

        

python">import cv2# 打开视频文件
cap = cv2.VideoCapture('wanjia.mp4')# 获取视频的宽度和高度
frame_width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
frame_height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))# 定义视频编码和输出文件
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output_video.avi', fourcc, 20.0, (frame_width, frame_height))while True:ret, frame = cap.read()if not ret:break  # 如果没有读取到帧,结束循环# 在帧上添加文本cv2.putText(frame, 'Video Output Experiment', (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)# 写入输出视频out.write(frame)# 显示当前帧cv2.imshow('Video', frame)# 按 'q' 键退出if cv2.waitKey(1) & 0xFF == ord('q'):break# 释放资源
cap.release()
out.release()
cv2.destroyAllWindows()

分析:

  1. 视频读取:使用 cv2.VideoCapture 打开视频文件。
  2. 获取视频信息:通过 get 方法获取视频的宽度和高度。
  3. 视频输出设置:使用 cv2.VideoWriter 定义输出视频文件,设置编码方式、帧率和帧大小。
  4. 处理每一帧
    • 在每帧上添加文本,使用 cv2.putText
    • 将处理后的帧写入输出视频。
    • 实时显示当前帧。
  5. 退出条件:用户可以按 'q' 键退出视频播放。
  6. 资源释放:在结束时释放视频捕获和写入资源,并关闭所有窗口。

结果:

        

10.3.2 将视频读取到NumPy数组中

实验代码:

python">import cv2
import numpy as np# 打开视频文件
cap = cv2.VideoCapture('wanjia.mp4')# 创建一个空的列表来存储视频帧
frames = []# 读取视频帧
while True:ret, frame = cap.read()if not ret:break  # 如果没有读取到帧,结束循环# 将帧添加到列表中frames.append(frame)# 关闭视频文件
cap.release()# 将列表转换为 NumPy 数组
video_array = np.array(frames)# 打印视频数组的形状
print("视频数组形状:", video_array.shape)# 可选:显示第一帧
cv2.imshow('First Frame', video_array[0])
cv2.waitKey(0)
cv2.destroyAllWindows()

分析:

  1. 打开视频文件:使用 cv2.VideoCapture 打开指定的视频文件。
  2. 读取视频帧:通过循环读取视频中的每一帧,使用 cap.read()
    • 如果读取成功,ret 为 Trueframe 为当前帧。
    • 将每一帧添加到 frames 列表中。
  3. 释放资源:在读取完视频后,调用 cap.release() 释放视频文件。
  4. 转换为 NumPy 数组:使用 np.array(frames) 将帧列表转换为 NumPy 数组。
  5. 打印形状:输出视频数组的形状,可以看到数组的维度,形状为 (帧数, 高度, 宽度, 通道数)
  6. 显示第一帧:可选地展示第一帧,确保读取成功。

结果:

10.4 跟踪

        10.4.1 光流

        光流是目标、场景或摄像机在连续两帧图像间运动时造成的目标的运动。它是图像在平移过程中的二维矢量场。

光流法主要依赖于三个假设。

(1) 亮度恒定  图像中目标的像素强度在连续帧之间不会发生变化。
(2) 时间规律  相邻帧之间的时间足够短,以至于在考虑运行变化时可以忽略它们之间的差异。该假设用于导出下面的核心方程。
(3) 空间一致性  相邻像素具有相似的运动。
实验代码:
python">import cv2
import numpy as npdef draw_flow(im, flow, step=16):""" 在间隔分开的像素采样点处绘制光流 """h, w = im.shape[:2]y, x = np.mgrid[step/2:h:step, step/2:w:step].reshape(2, -1)fx, fy = flow[y.astype(int), x.astype(int)].T# 创建线的终点lines = np.vstack([x, y, x + fx, y + fy]).T.reshape(-1, 2, 2)lines = lines.astype(int)# 创建图像并绘制vis = cv2.cvtColor(im, cv2.COLOR_GRAY2BGR)for (x1, y1), (x2, y2) in lines:cv2.line(vis, (x1, y1), (x2, y2), (0, 255, 0), 1)cv2.circle(vis, (x1, y1), 1, (0, 255, 0), -1)return vis# 设置视频捕获
cap = cv2.VideoCapture(0)# 读取第一帧
ret, im = cap.read()
if not ret:print("无法读取视频流")exit()prev_gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)while True:# 获取灰度图像ret, im = cap.read()if not ret:breakgray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)# 计算光流flow = cv2.calcOpticalFlowFarneback(prev_gray, gray, None, 0.5, 3, 15, 3, 5, 1.2, 0)prev_gray = gray# 画出光流cv2.imshow('Optical Flow', draw_flow(gray, flow))if cv2.waitKey(10) == 27:  # 按 'ESC' 退出breakcap.release()
cv2.destroyAllWindows()

分析:

  1. 引入库

  2. 函数 draw_flow

    • 输入图像和光流数据,在采样点处绘制光流矢量。
    • 通过 np.mgrid 生成采样点,并利用光流计算终点。
    • 绘制线条和圆点以可视化流动。
  3. 视频捕获

    • 使用 cv2.VideoCapture 捕获视频流。
    • 读取第一帧并转换为灰度图。
  4. 光流计算

    • 在循环中读取新帧,计算光流并更新前一帧的灰度图。
    • 调用 draw_flow 函数可视化光流。
  5. 退出条件

    • 通过按 ESC 键退出循环,并释放视频捕获资源

结果:

        

10.4.2 Lucas-Kanade算法

        跟踪最基本的形式是跟随感兴趣点,比如角点。对此,一次流行的算法是 Lucas-Kanade 跟踪算法,它利用了稀疏光流算法。

实验代码:

        

python">import cv2
import numpy as npdef lucas_kanade_optical_flow(video_path):cap = cv2.VideoCapture(video_path)ret, old_frame = cap.read()if not ret:print("无法读取视频")returnold_gray = cv2.cvtColor(old_frame, cv2.COLOR_BGR2GRAY)p0 = cv2.goodFeaturesToTrack(old_gray, mask=None, maxCorners=100, qualityLevel=0.3, minDistance=7, blockSize=7)mask = np.zeros_like(old_frame)while True:ret, frame = cap.read()if not ret:breakframe_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)p1, st, err = cv2.calcOpticalFlowPyrLK(old_gray, frame_gray, p0, None)# 检查 p1 是否为 Noneif p1 is None or st is None:print("光流计算失败")breakgood_new = p1[st[:, 0] == 1]  # 注意这里的索引good_old = p0[st[:, 0] == 1]for i, (new, old) in enumerate(zip(good_new, good_old)):a, b = map(int, new.ravel())c, d = map(int, old.ravel())mask = cv2.line(mask, (a, b), (c, d), (0, 255, 0), 2)frame = cv2.circle(frame, (a, b), 5, (0, 0, 255), -1)img = cv2.add(frame, mask)cv2.imshow('Optical Flow', img)old_gray = frame_gray.copy()p0 = good_new.reshape(-1, 1, 2)if cv2.waitKey(30) & 0xFF == 27:breakcap.release()cv2.destroyAllWindows()# 调用函数
video_path = 'wanjia.mp4'  # 替换为你的视频路径
lucas_kanade_optical_flow(video_path)

分析:

  1. 光流原理

    • Lucas-Kanade 算法基于局部平滑性假设和亮度恒定性假设,利用图像的亮度变化来估计光流场。算法通过对邻域内的像素点进行线性最小二乘拟合,得到物体的运动信息。
  2. 参数设置

    • maxCorners:检测到的最大角点数量。
    • qualityLevel:角点质量的最小阈值。
    • minDistance:检测角点之间的最小距离。

结果:

  1. 运行代码后,将打开一个窗口,显示视频中物体的跟踪效果。

  2. 绿色线条表示跟踪的运动轨迹,红色圆点表示当前跟踪的角点。

        


http://www.ppmy.cn/news/1528972.html

相关文章

【算法业务】互联网风控业务中的拒绝推断场景算法应用分享(涉及半监督算法、异常检测、变分自编码、样本权重自适应调整、迁移学习等)

1. 业务目标和任务描述 该项目是很早期的一个工作,属于互联网信贷风控场景,研究并应用信贷中的拒绝推断任务,处理方式也许对于目前的一些业务还有参考意义,因此这里做下分享。拒绝推断是指在信贷业务中,利用已知的接受…

Vue2学习笔记(02条件渲染 、监视数据的原理)

1、v-if和v-show的区别 2、Vue监视数据的原理

SystemVerilog中的Semaphores

SystemVerilog中Semaphore(旗语)是一个多个进程之间同步的机制之一,这里需要同步的原因是这多个进程共享某些资源。 举一个场景:SoC中的,CPU和DMA都希望去访问相同地址的内存空间。实际的情况可能是CPU的访问覆盖DMA的访问&#x…

linux系统蓝牙框架

一、前言 本文主要从大框架上介绍linux系统蓝牙功能架构,包括硬件架构以及软件架构。本文将从如下方面展开: 1.硬件选型及连接 2.软件架构。 二、硬件架构及连接 市面上带蓝牙功能的消费电子主要是采用soc 无线模组的硬件架构。很多无线模组都集成了…

人话学Python-循环语句

一&#xff1a;while语句 while语句的组成由判断条件和执行语句组成。当满足条件时会不断执行后续语句&#xff0c;然后再循环执行的语句结束之后再次回到条件判断&#xff0c;如此循环。 pos 0 ans 0 while pos < 6:ans pos * 4pos 1 print(ans)>>>84"&…

软件工程专业未来发展方向

1. 前端开发&#xff08;Front-end Development&#xff09; 简介&#xff1a; 前端开发者专注于网站和应用程序的用户界面和用户体验设计。他们使用HTML、CSS、JavaScript等基本技术&#xff0c;以及React、Angular、Vue.js等前端框架&#xff0c;来创建互动性强、响应迅速的…

20240922 每日AI必读资讯

OpenAI 首席科学家 MIT演讲&#xff01; - 揭示 o1模型训练核心秘密&#xff1a; 通过激励模型学习是培养 AGI 系统通用技能的最佳方式。 - 提出了类比“教人钓鱼”的方式&#xff0c;强调激励学习的重要性&#xff1a;“授人以鱼&#xff0c;不如授人以渔”&#xff0c;但是…

微信小程序点赞动画特效实现

这里提供两种实现点赞动画特效的方法&#xff1a; 方法一&#xff1a;使用 CSS 动画 wxml 文件: <view class"like-container"><image src"{{isLiked ? likedImg : unlikedImg}}" class"like-icon {{isLiked ? liked : }}" bindta…