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

Python计算机视觉第十章-OpenCV

目录

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 格式:

实验代码:

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 颜色空间

        实验代码:

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 显示图像及结果

        实验代码:

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 视频输入

实验代码:

        

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数组中

实验代码:

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) 空间一致性  相邻像素具有相似的运动。
实验代码:
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. 引入库

    • cv2 用于计算机视觉处理。
    • numpy 用于处理数组和矩阵。
  2. 函数 draw_flow

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

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

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

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

结果:

        

10.4.2 Lucas-Kanade算法

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

实验代码:

        

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. 绿色线条表示跟踪的运动轨迹,红色圆点表示当前跟踪的角点。

        

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 开源项目 face parsing 人脸区域分割 人像区域分割 人脸分割 人像区域分割 BiSeNet
  • [mysql]mysql排序和分页
  • 9.18 微信小程序开发笔记
  • vue-ts-demo
  • 二十种编程语言庆祝中秋节
  • 若依笔记(六):前后端token鉴权体系
  • 初始爬虫1(补充)
  • 【YashanDB认证】探索YashanDB的学习历程
  • QT学习与数据库连接
  • 鸿蒙Harmony应用开发,数据驾驶舱网络请求(Axios) 封装
  • 数据库事务的详解
  • Apache Cordova开发教程-入门基础
  • eth-trunk 笔记
  • 电源模块启动过冲测试项目该如何在ATECLOUD中搭建?
  • a√斗地主之顺子
  • $translatePartialLoader加载失败及解决方式
  • 【剑指offer】让抽象问题具体化
  • Android路由框架AnnoRouter:使用Java接口来定义路由跳转
  • ES6 ...操作符
  • ES6核心特性
  • FastReport在线报表设计器工作原理
  • JAVA 学习IO流
  • Linux各目录及每个目录的详细介绍
  • markdown编辑器简评
  • MD5加密原理解析及OC版原理实现
  • Sass Day-01
  • STAR法则
  • uva 10370 Above Average
  • Vue.js 移动端适配之 vw 解决方案
  • 官方新出的 Kotlin 扩展库 KTX,到底帮你干了什么?
  • 力扣(LeetCode)357
  • 驱动程序原理
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 在weex里面使用chart图表
  • 中文输入法与React文本输入框的问题与解决方案
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • ​​快速排序(四)——挖坑法,前后指针法与非递归
  • ​Java并发新构件之Exchanger
  • ​ssh免密码登录设置及问题总结
  • ​经​纬​恒​润​二​面​​三​七​互​娱​一​面​​元​象​二​面​
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • !$boo在php中什么意思,php前戏
  • #git 撤消对文件的更改
  • #ubuntu# #git# repository git config --global --add safe.directory
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • (11)MATLAB PCA+SVM 人脸识别
  • (Matalb分类预测)GA-BP遗传算法优化BP神经网络的多维分类预测
  • (ZT)出版业改革:该死的死,该生的生
  • (八)Docker网络跨主机通讯vxlan和vlan
  • (八)Flink Join 连接
  • (苍穹外卖)day03菜品管理
  • (附源码)spring boot基于Java的电影院售票与管理系统毕业设计 011449
  • (一)使用IDEA创建Maven项目和Maven使用入门(配图详解)
  • (原創) 如何動態建立二維陣列(多維陣列)? (.NET) (C#)
  • (转)memcache、redis缓存