利用 OpenCV 库进行实时目标物体检测
一、代码概述
此代码利用 OpenCV 库实现了基于特征匹配的实时物体检测系统。通过摄像头捕获实时视频帧,将其与预先加载的参考图像进行特征匹配,从而识别出视频帧中是否存在与参考图像匹配的物体。
二、环境依赖
- OpenCV:用于图像处理、特征提取和匹配等操作。
- NumPy:用于数值计算,OpenCV 依赖于 NumPy 进行数组操作。
可以使用以下命令安装所需库:
bash
pip install opencv-python numpy
三、代码详细解释
1. 导入必要的库
python
import cv2
import numpy as np
cv2:OpenCV 库,用于计算机视觉任务。np:NumPy 库,用于高效的数值计算。
2. 初始化摄像头
python
cap = cv2.VideoCapture(0)
cv2.VideoCapture(0):打开默认的摄像头设备(通常为计算机内置摄像头),用于捕获实时视频帧。
3. 加载所有参考图像
python
reference_images = []
for img_name in ['Black speaker.jpg', 'remote.jpg', 'fan.jpg', 'tempo.jpg']:img_path = f'Target_object/{img_name}'img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)if img is None:print(f"无法加载图像: {img_path}")continue# 图像预处理img = cv2.GaussianBlur(img, (5, 5), 0)img = cv2.equalizeHist(img)# 存储图像信息reference_images.append({'name': img_name,'image': img,'kp': None,'des': None})
- 遍历指定的参考图像文件名列表,尝试从
Target_object文件夹中加载图像。 cv2.imread:以灰度模式读取图像。cv2.GaussianBlur:对图像进行高斯模糊处理,以减少噪声。cv2.equalizeHist:对图像进行直方图均衡化,增强图像的对比度。- 将处理后的图像信息存储在
reference_images列表中,每个元素是一个字典,包含图像名称、图像数据、关键点和描述符。
4. 初始化 SIFT 特征检测器
python
sift = cv2.SIFT_create(nfeatures=1000)
cv2.SIFT_create:创建一个 SIFT(尺度不变特征变换)特征检测器,nfeatures=1000表示最多检测 1000 个特征点。
5. 提取所有参考图像特征
python
for ref in reference_images:ref['kp'], ref['des'] = sift.detectAndCompute(ref['image'], None)
- 遍历
reference_images列表,对每个参考图像使用 SIFT 检测器提取关键点(kp)和描述符(des)。
6. 设置匹配阈值
python
MATCH_THRESHOLD = 100
MATCH_THRESHOLD:用于判断是否匹配成功的阈值,当匹配的特征点数量超过该阈值时,认为检测到匹配的物体。
7. 主循环:实时物体检测
python
while True:# 读取摄像头帧ret, frame = cap.read()if not ret:break# 转换为灰度图像并进行预处理gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)gray_frame = cv2.GaussianBlur(gray_frame, (5, 5), 0)gray_frame = cv2.equalizeHist(gray_frame)# 提取当前帧特征kp2, des2 = sift.detectAndCompute(gray_frame, None)# 特征匹配if des2 is not None:# 使用FLANN匹配器FLANN_INDEX_KDTREE = 1index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)search_params = dict(checks=100)flann = cv2.FlannBasedMatcher(index_params, search_params)# 遍历所有参考图像for ref in reference_images:if ref['des'] is None:continuetry:matches = flann.knnMatch(ref['des'], des2, k=2)# 检查是否有足够匹配对if len(matches) < 1 or len(matches[0]) < 2:continue# 应用比率测试good_matches = [m for m,n in matches if m.distance < 0.7*n.distance]# 如果匹配点超过阈值if len(good_matches) > MATCH_THRESHOLD:print(f"检测到匹配物体: {ref['name']}")cv2.putText(frame, f"Match: {ref['name']}", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)# 可视化匹配结果match_img = cv2.drawMatches(ref['image'], ref['kp'],frame, kp2,good_matches[:50], None,flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)cv2.imshow('Matches', match_img)breakexcept Exception as e:print(f"匹配错误: {str(e)}")continue# 显示结果cv2.imshow('Object Detection', frame)# 按q退出if cv2.waitKey(1) & 0xFF == ord('q'):break
cap.read():从摄像头读取一帧图像。cv2.cvtColor:将彩色图像转换为灰度图像。sift.detectAndCompute:对当前帧提取关键点和描述符。cv2.FlannBasedMatcher:使用 FLANN(快速最近邻搜索库)匹配器进行特征匹配。flann.knnMatch:对参考图像的描述符和当前帧的描述符进行 k 近邻匹配,k=2表示为每个查询描述符找到两个最近邻。- 应用比率测试(
m.distance < 0.7*n.distance)筛选出好的匹配点。 - 如果好的匹配点数量超过
MATCH_THRESHOLD,则认为检测到匹配的物体,在帧上绘制匹配信息并显示匹配结果图像。 cv2.imshow:显示当前帧和匹配结果图像。cv2.waitKey(1) & 0xFF == ord('q'):等待用户按下q键退出循环。
8. 释放资源
python
cap.release()
cv2.destroyAllWindows()
cap.release():释放摄像头资源。cv2.destroyAllWindows():关闭所有 OpenCV 窗口。
四、注意事项
- 确保
Target_object文件夹存在,并且包含指定的参考图像文件。 - SIFT 算法在 OpenCV 4.x 版本中需要额外安装
opencv-contrib-python库,因为它属于非免费的专利算法。 - 特征匹配的准确性受光照、物体姿态、遮挡等因素的影响,可以根据实际情况调整匹配阈值和预处理步骤。
完整代码:
import cv2
import numpy as np# 初始化摄像头
cap = cv2.VideoCapture(0)# 加载所有参考图像
reference_images = []
for img_name in ['Black speaker.jpg', 'remote.jpg', 'fan.jpg', 'tempo.jpg']:img_path = f'Target_object/{img_name}'img = cv2.imread(img_path, cv2.IMREAD_GRAYSCALE)if img is None:print(f"无法加载图像: {img_path}")continue# 图像预处理img = cv2.GaussianBlur(img, (5, 5), 0)img = cv2.equalizeHist(img)# 存储图像信息reference_images.append({'name': img_name,'image': img,'kp': None,'des': None})# 初始化SIFT特征检测器
sift = cv2.SIFT_create(nfeatures=1000)# 提取所有参考图像特征
for ref in reference_images:ref['kp'], ref['des'] = sift.detectAndCompute(ref['image'], None)# 设置匹配阈值
MATCH_THRESHOLD = 100while True:# 读取摄像头帧ret, frame = cap.read()if not ret:break# 转换为灰度图像并进行预处理gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)gray_frame = cv2.GaussianBlur(gray_frame, (5, 5), 0)gray_frame = cv2.equalizeHist(gray_frame)# 提取当前帧特征kp2, des2 = sift.detectAndCompute(gray_frame, None)# 特征匹配# 在特征匹配部分添加调试信息if des2 is not None:for ref in reference_images:if ref['des'] is None:continuetry:matches = flann.knnMatch(ref['des'], des2, k=2)print(f"参考图像 {ref['name']} 的匹配点数量: {len(matches)}")if len(matches) < 1 or len(matches[0]) < 2:continuegood_matches = [m for m,n in matches if m.distance < 0.7*n.distance]print(f"参考图像 {ref['name']} 的良好匹配点数量: {len(good_matches)}")if len(good_matches) > MATCH_THRESHOLD:print(f"检测到匹配物体: {ref['name']}")cv2.putText(frame, f"Match: {ref['name']}", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)match_img = cv2.drawMatches(ref['image'], ref['kp'], frame, kp2, good_matches[:50], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)cv2.imshow('Matches', match_img)breakexcept Exception as e:print(f"匹配错误: {str(e)}")continue# 使用FLANN匹配器FLANN_INDEX_KDTREE = 1index_params = dict(algorithm=FLANN_INDEX_KDTREE, trees=5)search_params = dict(checks=100)flann = cv2.FlannBasedMatcher(index_params, search_params)# 遍历所有参考图像for ref in reference_images:if ref['des'] is None:continuetry:matches = flann.knnMatch(ref['des'], des2, k=2)# 检查是否有足够匹配对if len(matches) < 1 or len(matches[0]) < 2:continue# 应用比率测试good_matches = [m for m,n in matches if m.distance < 0.7*n.distance]# 如果匹配点超过阈值if len(good_matches) > MATCH_THRESHOLD:print(f"检测到匹配物体: {ref['name']}")cv2.putText(frame, f"Match: {ref['name']}", (50, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)# 可视化匹配结果match_img = cv2.drawMatches(ref['image'], ref['kp'],frame, kp2,good_matches[:50], None,flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)cv2.imshow('Matches', match_img)breakexcept Exception as e:print(f"匹配错误: {str(e)}")continue# 显示结果cv2.imshow('Object Detection', frame)# 按q退出if cv2.waitKey(1) & 0xFF == ord('q'):break# 释放资源
cap.release()
cv2.destroyAllWindows()
相关文章:
利用 OpenCV 库进行实时目标物体检测
一、代码概述 此代码利用 OpenCV 库实现了基于特征匹配的实时物体检测系统。通过摄像头捕获实时视频帧,将其与预先加载的参考图像进行特征匹配,从而识别出视频帧中是否存在与参考图像匹配的物体。 二、环境依赖 OpenCV:用于图像处理、特征提…...
深度学习笔记(37周)
目录 摘要 Abstracts 1. 介绍 2. 相关工作 3. 模型 3.1 时序段网络TSN 3.2 学习时序段网络 4. 训练结果 5. 结论 摘要 本周阅读的论文是《Temporal Segment Networks: Towards Good Practices for Deep Action Recognition》。作者主要想通过较少的训练样本ÿ…...
Vue2+Vant2 项目初学
Vant 2 - Mobile UI Components built on Vue Vue.js 安装 | 菜鸟教程 // 通过脚手架安装 // 在新项目中使用 Vant 时,推荐使用 Vue 官方提供的脚手架 Vue Cli 创建项目并安装 Vant。 // # 安装 Vue Cli // npm install -g vue/cli // # 创建一个项目 // vue …...
ELK+Filebeat+Kafka+Zookeeper安装部署
1.安装zookeeper zookpeer下载地址:apache-zookeeper-3.7.1-bin.tar.gzhttps://link.csdn.net/?targethttps%3A%2F%2Fwww.apache.org%2Fdyn%2Fcloser.lua%2Fzookeeper%2Fzookeeper-3.7.1%2Fapache-zookeeper-3.7.1-bin.tar.gz%3Flogin%3Dfrom_csdn 1.1解压安装zookeeper软件…...
【接口封装】——21、解析Json对象数组的文本块
解释: 1、封装内容:Json数组的数据处理 Json 数组:[[ {"txt" : "你好"}, { "img", "1"} , {"txt" : "世界"} ], [ {"txt" : "你好"} ]] 数组内的文本块&am…...
【软考-架构】3.3、模式分解-事务并发-封锁协议
✨资料&文章更新✨ GitHub地址:https://github.com/tyronczt/system_architect 文章目录 模式分解(难点)无损分解💯考试真题并发控制封锁协议💯考试真题第一题第二题 模式分解(难点) 保持函…...
审批工作流系统xFlow
WorkFlow-审批流程系统 该项目为完全开源免费项目 可用于学习或搭建初始化审批流程系统 希望有用的小伙伴记得点个免费的star gitee仓库地址 仿钉钉飞书工作审批流系统 介绍 前端技术栈: vue3 ts vite arcodesign eslint 后端技术栈:springbootspring mvc mybatis mavenmysq…...
【数据结构初阶第十九节】八大排序系列(下篇)—[详细动态图解+代码解析]
hello,好久不见! 云边有个稻草人-CSDN博客 上篇内容,回顾一下吧【数据结构初阶第十八节】八大排序系列(上篇)—[详细动态图解代码解析]-CSDN博客 今天我们来学习下篇 目录 (2)快速排序 【挖坑法】 —思路 —思路…...
定制开发开源 AI 智能名片 S2B2C 商城小程序源码在小程序直播营销中的应用与价值
摘要: 本文主要探讨了定制开发开源 AI 智能名片 S2B2C 商城小程序源码在小程序直播营销中的应用与价值。首先详细阐述了小程序直播的基本概念、特点、发展历程及营销意义,包括其便捷性、广泛的受众连接能力以及对企业推广的重要作用。接着深入剖析了定制…...
蓝桥杯Python赛道备赛——Day3:排序算法(二)(归并排序、堆排序、桶排序)
本博客是蓝桥杯备赛系列中排序算法的第二期,包括:归并排序、堆排序和桶排序。每一个算法都在给出概念解释的同时,给出了示例代码,以供低年级师弟师妹们学习和练习。 由于本期的三个算法的复杂度相对来说要高于上一期的三个算法&am…...
Type-C:智能家居的电力革命与空间美学重构
在万物互联的时代浪潮中,家居空间正经历着从功能容器到智慧终端的蜕变。当意大利设计师安东尼奥奇特里奥提出"消失的设计"理念二十年后,Type-C充电技术正以润物无声的方式重塑着现代家居的形态与内核,开启了一场静默的居住革命。 【…...
第十五届蓝桥杯C/C++组:宝石组合题目(从小学奥数到编程题详解)
这道题目真的一看就不好做,如果直接暴力去做百分之90必挂掉,那么这道题目到底应该怎么去做呢?这我们就得从小学奥数开始聊了。(闲话:自从开始蓝桥杯备赛后,每天都在被小学奥数震惊,为什么我小的…...
@RequestParam、@RequestBody、@PathVariable
1. RequestParam RequestParam:重要的是它的属性,如果它的属性用不到,这个注解可以不用 要点: 可用于任何类型的请求(get请求数据在请求行中, post请求数据在请求体中)无论时在请求行还是请求体…...
ECharts中Map(地图)样式配置、渐变色生成
前言 ECharts是我们常用的图表控件,功能特别强大,每次使用都要查API比较繁琐,这里就记录开发中常用的配置。 官网:https://echarts.apache.org/handbook/zh/get-started 配置项:https://echarts.apache.org/zh/opti…...
什么是 slot-scope?怎么理解。
1. 什么是 slot-scope? slot-scope 是 Vue 2 中用于作用域插槽的语法。它的作用是让子组件可以把一些数据传递给父组件,父组件可以根据这些数据自定义渲染内容。 简单来说: 子组件:负责提供数据。 父组件:负责根据数…...
MySQL | MySQL表的增删改查(CRUD)
目录 前言:什么是 CRUD ?一、Creat 新增1.1 语法1.2 示例1.2.1 单行数据全列插入1.2.2 单行数据指定列插入1.2.3 多行数据指定列插入 二、Retrieve 检索2.1 语法2.2 示例2.2.1 全列查询2.2.2 指定列查询2.2.3 查询字段为表达式2.2.4 结果去重查询2.2.5 where条件查…...
电子电气架构 --- 分布到集中的动カ系统及基于域控制器的架构
我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 所有人的看法和评价都是暂时的,只有自己的经历是伴随一生的,几乎所有的担忧和畏惧,都是来源于自己的想象,只有你真的去做了,才会发现有多快乐。…...
Docker系列——从零开始打包FunASR的Http服务
一、项目结构准备 funasr-docker/ ├── Dockerfile ├── requirements.txt ├── models/ # 预下载模型目录(可选) ├── config/ # 自定义配置文件 │ └── server_config.py └── run.sh # 服务…...
基于微信小程序开发的宠物领养平台——代码解读
项目前端 一、项目的技术架构概况 一句话概括:该项目是基于微信小程序开发的宠物领养平台,采用原生小程序框架进行用户界面的构建,使用 wx.request 进行 API 请求,并通过 getApp() 和本地存储来管理全局状态和用户信息。 一&am…...
基于SpringBoot的“考研互助平台”的设计与实现(源码+数据库+文档+PPT)
基于SpringBoot的“考研互助平台”的设计与实现(源码数据库文档PPT) 开发语言:Java 数据库:MySQL 技术:SpringBoot 工具:IDEA/Ecilpse、Navicat、Maven 系统展示 系统整体功能图 局部E-R图 系统首页界面 系统注册…...
基于javaweb的SpringBoot足球俱乐部管理系统设计与实现(源码+文档+部署讲解)
技术范围:SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论…...
DQN 玩 2048 实战|第一期!搭建游戏环境(附 PyGame 可视化源码)
视频讲解: DQN 玩 2048 实战|第一期!搭建游戏环境(附 PyGame 可视化源码) 代码仓库:GitHub - LitchiCheng/DRL-learning: 深度强化学习 2048游戏介绍,引用维基百科 《2048》在44的网格上进行。…...
高频面试题(含笔试高频算法整理)基本总结回顾24
干货分享,感谢您的阅读! (暂存篇---后续会删除,完整版和持续更新见高频面试题基本总结回顾(含笔试高频算法整理)) 备注:引用请标注出处,同时存在的问题请在相关博客留言…...
大模型token和字符串的关系
一 主要区别 token 是使用分词器拆分后的最小单位,不同的分词方式会导致同样的字符具有不同的token数量。如你好,可以拆分为【你、好】两个token, 【你好】一个token。 同一个文本的 Token 数量可能远少于字符数(英文)…...
第八节:红黑树(初阶)
【本节要点】 红黑树概念红黑树性质红黑树结点定义红黑树结构红黑树插入操作的分析 一、红黑树的概念与性质 1.1 红黑树的概念 红黑树 ,是一种 二叉搜索树 ,但 在每个结点上增加一个存储位表示结点的颜色,可以是 Red和 Black 。 通过对 任何…...
【动态规划】- 线性dp
目录 第 N 个泰波那契数 三步问题 使用最小花费爬楼梯 解码方法 第 N 个泰波那契数 1137. 第 N 个泰波那契数 - 力扣(LeetCode) 状态表示 是什么?dp表里面的值所表示的含义怎么来?①题目要求->dp[ i ]表示第 i 个泰波那契…...
Python Cookbook-4.3 若列表中某元素存在则返回之
任务 你有一个列表L,还有一个索引号i,你希望当i是L,的有效索引时获取L[i],若不是有效索引,则返回一个默认值v。如果L是字典,可以使用L.get(i,v)来满足需求,可是列表并没有 get这个方法。 解决方案 很明显…...
Webpack vs Rollup vs Parcel:构建工具深度对比
文章目录 1. 核心特性对比1.1 功能定位1.2 技术架构对比 2. 配置与使用2.1 Webpack 配置示例2.2 Rollup 配置示例2.3 Parcel 使用示例 3. 性能对比3.1 构建速度3.2 输出质量 4. 生态系统4.1 插件生态4.2 学习曲线 5. 适用场景分析5.1 Webpack 适用场景5.2 Rollup 适用场景5.3 P…...
Centos7使用docker搭建redis集群
前置准备: Centos7安装docker就不多说了… 本次目的是搭建3主3从(当然你也可以按需扩展)准备三台服务器,假定IP分别为:192.168.75.128、192.168.75.129、192.168.75.130安装 redis: #拉取redis docker p…...
蓝桥杯备赛-二分-跳石头
问题描述 一年一度的"跳石头"比赛又要开始了! 这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有 NN 块岩石(不含起点和终点的岩石&a…...
