Python 进行目标检测
一、前言
从学单片机开始鼓捣C语言,到现在为了学CV鼓捣Python,期间在CSDN、简书、博客园和github这些地方得到了很多帮助,所以也想把自己做的一些小东西分享给大家,希望能帮助到别人。记录人生的第一篇博客,mark。
二、图像检测步骤
1. 读取两张图片
第一张是需要检测的小物体,第二章图片是小物体放置在大场景中。代码与输出结果如下所示:
import numpy as np
import matplotlib.pyplot as plt
import cv2 def my_show(img):
plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
return # 读取图片
img_small=cv2.imread('small.jpg',1)
img_big=cv2.imread('big.jpg',1) # 显示图片
plt.figure(figsize=(10,10))
plt.subplot(121)
my_show(img_small)
plt.subplot(122)
my_show(img_big)

2. 提取图片中的特征点
这一步就像我们在区分不同的人的时候,一眼看到外貌就知道此人是谁,而外貌就是这个人的特征。我们希望提取该物体的特征点,以便在不同的场景中识别出来。图片是由像素点构成,但是像素点包含的信息太零散了,一般是识别物体的边缘或者角点作为特征信息。常用的特征描述算法如下:
SIFT:https://blog.csdn.net/zddblog/article/details/7521424
harris corner detection: https://www.jianshu.com/p/efc81fdb8afb
Hog: https://lear.inrialpes.fr/people/triggs/pubs/Dalal-cvpr05.pdf
SURF: https://www.vision.ee.ethz.ch/~surf/eccv06.pdf
BRISK: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.371.1343&rep=rep1&type=pdf
Orb: http://www.willowgarage.com/sites/default/files/orb_final.pdf
我们项目中用到的是SIFT算法,SIFT精确度高,对尺度、亮度以及旋转的鲁棒性强,不过计算时间长,所需的计算资源较多。SURF是SIFT的加速版本,有兴趣的小伙伴可以了解一下。SIFT算法运行后,可以得到的特征点的位置以及特征向量。(PS:SIFT算法申请了专利,所以在opencv3.4.2版本后不能使用了,需要用SIFT的请安装3.4.2的opencv)
import numpy as np
import matplotlib.pyplot as plt
import cv2 def my_show(img):
plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
return # 读取图片
img_small=cv2.imread('small.jpg',1)
img_big=cv2.imread('big.jpg',1) # 提取特征点
sift=cv2.xfeatures2d.SIFT_create()
kp1,des1=sift.detectAndCompute(img_small,None)
kp2,des2=sift.detectAndCompute(img_big,None) # 在图中显示特征点
img_small_sift=cv2.drawKeypoints(img_small,kp1,outImage=np.array([]),flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
img_big_sift=cv2.drawKeypoints(img_big,kp2,outImage=np.array([]),flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS) plt.figure(figsize=(15,15))
plt.subplot(121)
my_show(img_small_sift)
plt.subplot(122)
my_show(img_big_sift)

3.特征点匹配
在分别提取了两张图的特征点后,就需要进行特征点匹配啦。这里需要注意的是,两张图的特征点数量一般情况下是不一样的,opencv算法里默认用第一张图的特征点来匹配,所以匹配矩阵的行数与第一张图特征点的行数一致。常用的匹配方法:
Brute-Force: 暴力搜索,用图1的特征点逐一与图二的特征点比较,找到欧式距离最小的点作为匹配点。不过这样匹配的错误点就会很多,所以常用交叉匹配法消除错误匹配。交叉匹配法指的是,反过来匹配一次,用匹配到图2的点反过来匹配图1的点,如果匹配结果与原来相同,则认为是正确匹配。
KNN: K近邻匹配,在匹配的时候选择K个和特征点最相似的点,如果这K个点之间的区别足够大,则选择最相似的那个点作为匹配点,通常选择K = 2。KNN匹配也会出现一些误匹配,这时候需要对比第一邻近与第二邻近之间的距离大小,假如 distance_1< (0.5~0.7)*distance_2, 则认为是正确匹配。
FLANN: FLANN是快速最近邻搜索包(Fast Library for Approximate Nearest Neighbors)的简称,是最近邻搜索的算法的集合。
一般我们会选择调用cv2.Brute-Force或者cv2.FlannBasedMatcher来进行特征点匹配,FLANN里边就包含的KNN、KD树还有其他的最近邻算法。
4.计算单应性矩阵
这里我们需要在大场景中用矩形框出匹配的小物体,所以就要计算单应性矩阵,然后做投影变换。RANSAC(Random Sample Consensus)随机抽样一致性算法是计算单应性矩阵的有效方法,并且在寻找单应性矩阵的过程中可以进一步剔除错误匹配点。RANSAC算法的步骤如下:
- 随机抽取四个匹配点对计算投影矩阵,需要检验四个点是否共线
- 图片1特征点坐标齐次变换后(3,1)乘上投影矩阵(3,3),然后计算变换后的特征点坐标与图片2特征点坐标的欧氏距离,小于设定的阈值则记录为内点,反之则为内点
- 判断此次内点的数量是否比以往记录的内点最大值多,如果是,则更新投影矩阵,如果不是,则不更新
- 判定循环次数是够达到设定次数或内点数占全部匹配点的比例达到设定比例,则跳出循环,否则跳到步骤1继续循环
寻找到最优的单应性矩阵后,将框住物体一的矩阵经投影变换后在图片二上画出来,完成目标检测框选。以下代码摘自
Brook@CV的博客并修改,如有侵权,请通知删除
import numpy as np
import cv2
from matplotlib import pyplot as plt MIN_MATCH_COUNT = 10 img1 = cv2.imread('small.jpg',1)
img2 = cv2.imread('big.jpg',1) # 使用SIFT检测角点
sift = cv2.xfeatures2d.SIFT_create()
# 获取关键点和描述符
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None) # 定义FLANN匹配器
index_params = dict(algorithm = 1, trees = 5)
search_params = dict(checks = 50)
flann = cv2.FlannBasedMatcher(index_params, search_params)
# 使用KNN算法匹配
matches = flann.knnMatch(des1,des2,k=2) # 去除错误匹配
good = []
for m,n in matches:
if m.distance <= 0.7*n.distance:
good.append(m) # 单应性
if len(good)>MIN_MATCH_COUNT:
# 改变数组的表现形式,不改变数据内容,数据内容是每个关键点的坐标位置
src_pts = np.float32([ kp1[m.queryIdx].pt for m in good ]).reshape(-1,1,2)
dst_pts = np.float32([ kp2[m.trainIdx].pt for m in good ]).reshape(-1,1,2)
# findHomography 函数是计算变换矩阵
# 参数cv2.RANSAC是使用RANSAC算法寻找一个最佳单应性矩阵H,即返回值M
# 返回值:M 为变换矩阵,mask是掩模
M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC,5.0)
# ravel方法将数据降维处理,最后并转换成列表格式
matchesMask = mask.ravel().tolist()
# 获取img1的图像尺寸
h,w,dim = img1.shape
# pts是图像img1的四个顶点
pts = np.float32([[0,0],[0,h-1],[w-1,h-1],[w-1,0]]).reshape(-1,1,2)
# 计算变换后的四个顶点坐标位置
dst = cv2.perspectiveTransform(pts,M) # 根据四个顶点坐标位置在img2图像画出变换后的边框
img2 = cv2.polylines(img2,[np.int32(dst)],True,(0,0,255),3, cv2.LINE_AA) else:
print("Not enough matches are found - %d/%d") % (len(good),MIN_MATCH_COUNT)
matchesMask = None # 显示匹配结果
draw_params = dict(matchColor = (0,255,0), # draw matches in green color
singlePointColor = None,
matchesMask = matchesMask, # draw only inliers
flags = 2)
img3 = cv2.drawMatches(img1,kp1,img2,kp2,good,None,**draw_params)
plt.figure(figsize=(20,20))
plt.imshow(cv2.cvtColor(img3,cv2.COLOR_BGR2RGB))
plt.show()



最后给大家放上原图可以跑一下程序!
Python 进行目标检测的更多相关文章
- 深度学习 + OpenCV,Python实现实时视频目标检测
使用 OpenCV 和 Python 对实时视频流进行深度学习目标检测是非常简单的,我们只需要组合一些合适的代码,接入实时视频,随后加入原有的目标检测功能. 在本文中我们将学习如何扩展原有的目标检测项 ...
- 利用ImageAI库只需几行python代码超简实现目标检测
目录 什么是目标检测 目标检测算法 Two Stages One Stage python实现 依赖 安装 使用 附录 什么是目标检测 目标检测关注图像中特定的物体目标,需要同时解决解决定位(loca ...
- Python实现YOLO目标检测
作者:R语言和Python学堂 链接:https://www.jianshu.com/p/35cfc959b37c 1. 什么是目标检测? YOLO目标检测的一个示例 啥是目标检测? 拿上图 (用YO ...
- 10行Python代码实现目标检测
要知道图像中的目标是什么? 或者你想数一幅图里有多少个苹果? 在本文中,我将向你展示如何使用Python在不到10行代码中创建自己的目标检测程序. 如果尚未安装python库,你需要安装以下pytho ...
- 基于YOLO和PSPNet的目标检测与语义分割系统(python)
基于YOLO和PSPNet的目标检测与语义分割系统 源代码地址 概述 这是我的本科毕业设计 它的主要功能是通过YOLOv5进行目标检测,并使用PSPNet进行语义分割. 本项目YOLOv5部分代码基于 ...
- [目标检测]YOLO原理
1 YOLO 创新点: 端到端训练及推断 + 改革区域建议框式目标检测框架 + 实时目标检测 1.1 创新点 (1) 改革了区域建议框式检测框架: RCNN系列均需要生成建议框,在建议框上进行分类与回 ...
- TensorFlow + Keras 实战 YOLO v3 目标检测图文并茂教程
运行步骤 1.从 YOLO 官网下载 YOLOv3 权重 wget https://pjreddie.com/media/files/yolov3.weights 下载过程如图: 2.转换 Darkn ...
- 目标检测 IOU(交并比) 理解笔记
交并比(Intersection-over-Union,IoU): 目标检测中使用的一个概念 是产生的候选框(candidate bound)与原标记框(ground truth bound)的交叠率 ...
- 第十九节、基于传统图像处理的目标检测与识别(词袋模型BOW+SVM附代码)
在上一节.我们已经介绍了使用HOG和SVM实现目标检测和识别,这一节我们将介绍使用词袋模型BOW和SVM实现目标检测和识别. 一 词袋介绍 词袋模型(Bag-Of-Word)的概念最初不是针对计算机视 ...
随机推荐
- Java 从入门到进阶之路(二十一)
在之前的文章我们介绍了一下 Java 中的日期操作,本章我们来看一下 Java 集合框架中的Collection. 早在 Java 2 中之前,Java 就提供了特设类.比如:Dictionary, ...
- 从头学pytorch(十五):AlexNet
AlexNet AlexNet是2012年提出的一个模型,并且赢得了ImageNet图像识别挑战赛的冠军.首次证明了由计算机自动学习到的特征可以超越手工设计的特征,对计算机视觉的研究有着极其重要的意义 ...
- layui下拉选择框select不显示
弹层layer下拉框没有样式_不可点击_没有效果_渲染失效的解决办法 一.必须给表单体系所在的父元素加上 class="layui-form" 在一个容器中设定 class=&qu ...
- Mysql中使用mysqldump进行导入导出sql文件
纪念工作中的第一次删库跑路的经历 今天接到一个任务,是将一个测试库数据导到另一个测试库,然而我们公司的数据库是不让直连的,所以只能通过远程连接进行导库操作. 老大布置任务的时候让用dump命令进行操作 ...
- 奇葩的Failed to configure a DataSource: 'url' attribute is not specified and no embedded datasource could be configured.
启动springboot的时候莫名其妙出现这个错误,我properties里面也没配置数据源啥的,但就是出现这个错误 解决方法: 在启动类上加@SpringBootApplication(exclud ...
- KVM虚拟化基础
关于虚拟化 什么是虚拟化 在计算机技术中,虚拟化(技术)或虚拟技术(英语:Virtualization)是一种资源管理技术,是将计算机的各种实体资源(CPU.内存.磁盘空间.网络适配器等),予以抽象. ...
- matplotlib 散点图
一.特点 离散的数据,查看分布规律,走向趋势 二.使用 1.核心 plt.scatter(x, y) # x为x轴的数据,可迭代对象,必须是数字 # y为y轴的数据,可迭代对象,必须是数字 # x和y ...
- 【转】document.form.action,表单分向提交
document.form.action,表单分向提交,javascript提交表单 同一个表单可以根据用户的选择,提交给不同的后台处理程序.即,表单的分向提交.如,在编写论坛程序时,如果我们希望实现 ...
- (转) exp1-3://一次有趣的XSS漏洞挖掘分析(3)最终篇
这真是最后一次了.真的再不逗这个程序员了.和预期一样,勤奋的程序员今天又更新程序了.因为前面写的payload都有一个致命的弱点,就是document.write()会完全破坏DOM结构.而且再“ ...
- Kindle Unlimited 上线的最热书单
Kindle 也给出了一份,到现在为止,在 Kindle Unlimited 上线的最热书单: 1.岛上书店2.一个人的朝圣3.自控力4.嫌疑人 X 的献身5.沉默的大多数(王小波文集)6.跟任何人都 ...