OpenCV-Python中的图像处理-图像特征
OpenCV-Python中的图像处理-图像特征
- 图像特征
- Harris角点检测
- 亚像素级精度的角点检测
- Shi-Tomasi角点检测
- SIFT(Scale-Invariant Feature Transfrom)
- SURF(Speeded-Up Robust Features)
- FAST算法
- BRIEF(Binary Robust Independent Elementary Features)算法
- ORB (Oriented FAST and Rotated BRIEF)算法
- 特征匹配
- Brute-Force 蛮力匹配
- 对 ORB 描述符进行蛮力匹配
- 对 SIFT 描述符进行蛮力匹配和比值测试
- FLANN 匹配
图像特征
- 特征理解
- 特征检测
- 特征描述
Harris角点检测
- cv2.cornerHarris(img, blockSize, ksize, k, borderType=…)
- img:输入图像,数据类型为float32
- blockSize:角点检测中要考虑的领域大小
- ksize:Sobe求导中使用的窗口大小
- k:Harris角点检测方程中的自由参数,取值参数为 [0.04,0.06]
- borderType:边界类型
import numpy as np
import cv2
from matplotlib import pyplot as plt# img = cv2.imread('./resource/opencv/image/chessboard.png', cv2.IMREAD_COLOR)
img = cv2.imread('./resource/opencv/image/pattern.png', cv2.IMREAD_COLOR)gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)gray = np.float32(gray)# 输入图像必须是float32,最后一个参数在0.04到0.05之间
dst = cv2.cornerHarris(gray, 2, 3, 0.05)
dst = cv2.dilate(dst, None)img[dst>0.01*dst.max()] = [0, 0, 255]cv2.imshow('dst', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
亚像素级精度的角点检测
- cv2.cornerSubPix(img, corners, winSize, zeroZone, criteria)
最大精度的角点检测,首先要找到 Harris角点,然后将角点的重心传给这个函数进行修正。
import numpy as np
import cv2
from matplotlib import pyplot as pltimg = cv2.imread('./resource/opencv/image/subpixel.png', cv2.IMREAD_COLOR)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)gray = np.float32(gray)
dst = cv2.cornerHarris(gray, 2, 3, 0.04)
dst = cv2.dilate(dst, None)
ret, dst = cv2.threshold(dst, 0.01*dst.max(), 255, 0)
dst = np.uint8(dst)ret, labels, stats, centroids = cv2.connectedComponentsWithStats(dst)criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 0.001)corners = cv2.cornerSubPix(gray, np.float32(centroids), (5,5), (-1, -1), criteria)res = np.hstack((centroids, corners))res = np.int0(res)
img[res[:,1],res[:,0]]=[0,0,255]
img[res[:,3],res[:,2]]=[0,255,0]cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Harris 角点用红色像素标出,绿色像素是修正后的角点。
Shi-Tomasi角点检测
- cv2.goodFeatureToTrack()
import numpy as np
import cv2
from matplotlib import pyplot as pltimg = cv2.imread('./resource/opencv/image/shitomasi_block.jpg', cv2.IMREAD_COLOR)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)corners = cv2.goodFeaturesToTrack(gray, 25, 0.01, 10)corners = np.int0(corners)for i in corners:x,y = i.ravel()cv2.circle(img, (x,y), 3, 255, -1)plt.imshow(img)
plt.show()
SIFT(Scale-Invariant Feature Transfrom)
-
SIFT,即尺度不变特征变换(Scale-invariant feature transform,SIFT),是用于图像处理领域的一种描述。这种描述具有尺度不变性,可在图像中检测出关键点,是一种局部特征描述子。
-
cv2.SIFT_create()
- kp = sift.detect(img, None):查找特征点
- kp, des = sift.compute(img, kp):计算特征点
- kp, des = sift.detectAndCompute(img, None) :直接找到特征点并计算描述符
-
cv2.drawKeypoints(img, kp, out_img, flags=cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS):画特征点
- img : 输入图像
- kp:图像特征点
- out_img:输出图像
- flags:
cv2.DRAW_MATCHES_FLAGS_DEFAULT
cv2.DRAW_MATCHES_FLAGS_DRAW_OVER_OUTIMG
cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS
cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS
import numpy as np
import cv2# 读取图片
# img = cv2.imread('./resource/opencv/image/home.jpg')
img = cv2.imread('./resource/opencv/image/AverageMaleFace.jpg')
key_points = img.copy()# 实例化SIFT算法
sift = cv2.SIFT_create()# 得到特征点
kp = sift.detect(img, None)
print(np.array(kp).shape)# 绘制特征点
cv2.drawKeypoints(img, kp, key_points, flags=cv2.DRAW_MATCHES_FLAGS_NOT_DRAW_SINGLE_POINTS)# 图片展示
cv2.imshow("key points", key_points)
cv2.waitKey(0)
cv2.destroyAllWindows()# 保存图片
# cv2.imwrite("key_points.jpg", key_points)# 计算特征
kp, des = sift.compute(img, kp)# 调试输出
print(des.shape)
print(des[0])cv2.imshow('kp', key_points)
cv2.waitKey(0)
cv2.destroyAllWindows()
SURF(Speeded-Up Robust Features)
- 文章前面介绍了使用 SIFT 算法进行关键点检测和描述。但是这种算法的执行速度比较慢,人们需要速度更快的算法。在 2006 年Bay,H.,Tuytelaars,T. 和 Van Gool,L 共同提出了 SURF(加速稳健特征)算法。跟它的名字一样,这是个算法是加速版的 SIFT。
- 与 SIFT 相同 OpenCV 也提供了 SURF 的相关函数。首先我们要初始化一个 SURF 对象,同时设置好可选参数: 64/128 维描述符, Upright/Normal 模式等。所有的细节都已经在文档中解释的很明白了。就像我们在SIFT 中一样,我们可以使用函数 SURF.detect(), SURF.compute() 等来进行关键点搀着和描述。
img = cv2.imread(‘fly.png’, 0)
surf = cv2.SURF(400)
kp, des = surf.detectAndCompute(img, None)
len(kp) # 699
print(surf.hessianThreshold)
surf.hessianThreshold = 50000
kp, des = surf.detectAndCompute(img,None)
print(len(kp)) # 47
不检测关键点的方向
print(surf.upright) #False
surf.upright = True
FAST算法
import numpy as np
import cv2
from matplotlib import pyplot as pltimg = cv2.imread('./resource/opencv/image/fly.jpg', cv2.IMREAD_GRAYSCALE)# fast = cv2.FastFeatureDetector_create(threshold=100, nonmaxSuppression=False, type=cv2.FAST_FEATURE_DETECTOR_TYPE_5_8)
fast = cv2.FastFeatureDetector_create(threshold=400)
kp = fast.detect(img, None)
img2 = cv2.drawKeypoints(img, kp, img.copy(), color=(0, 0, 255), flags=cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)cv2.imshow('fast', img2)
cv2.waitKey(0)
cv2.destroyAllWindows()
BRIEF(Binary Robust Independent Elementary Features)算法
- BRIEF(Binary Robust Independent Elementary Features)
import numpy as np
import cv2
from matplotlib import pyplot as pltimg = cv2.imread('./resource/opencv/image/fly.jpg', cv2.IMREAD_GRAYSCALE)# Initiate STAR detector
star = cv2.FeatureDetector_create("STAR")
# Initiate BRIEF extractor
brief = cv2.DescriptorExtractor_create("BRIEF")
# find the keypoints with STAR
kp = star.detect(img,None)
# compute the descriptors with BRIEF
kp, des = brief.compute(img, kp)
print(brief.getInt('bytes'))
print(des.shape)
ORB (Oriented FAST and Rotated BRIEF)算法
import numpy as np
import cv2
from matplotlib import pyplot as pltimg = cv2.imread('./resource/opencv/image/fly.jpg', cv2.IMREAD_GRAYSCALE)# ORB_create(nfeatures=..., scaleFactor=..., nlevels=..., edgeThreshold=..., firstLevel=..., WTA_K=..., scoreType=..., patchSize=..., fastThreshold=...)
orb = cv2.ORB_create()kp = orb.detect(img, None)kp, des = orb.compute(img, kp)img2 = cv2.drawKeypoints(img, kp, img.copy(), color=(255, 0, 0), flags=0)
plt.imshow(img2)
plt.show()
特征匹配
OpenCV 中的特征匹配
- 蛮力( Brute-Force)匹配
- FLANN 匹配
Brute-Force 蛮力匹配
对 ORB 描述符进行蛮力匹配
import numpy as np
import cv2
from matplotlib import pyplot as pltimg1 = cv2.imread('./resource/opencv/image/box.png', 0)
img2 = cv2.imread('./resource/opencv/image/box_in_scene.png', 0)orb = cv2.ORB_create()kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)bf = cv2.BFMatcher_create(cv2.NORM_HAMMING, crossCheck=True)matches = bf.match(des1, des2)# matches = bf:match(des1; des2) 返回值是一个 DMatch 对象列表。这个
# DMatch 对象具有下列属性:
# • DMatch.distance - 描述符之间的距离。越小越好。
# • DMatch.trainIdx - 目标图像中描述符的索引。
# • DMatch.queryIdx - 查询图像中描述符的索引。
# • DMatch.imgIdx - 目标图像的索引。# 距离排序
matches = sorted(matches, key = lambda x:x.distance)# 画出前30匹配
img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches[:30], None, flags=2)cv2.imshow('img', img3)
cv2.waitKey(0)
cv2.destroyAllWindows()
对 SIFT 描述符进行蛮力匹配和比值测试
现在我们使用 BFMatcher.knnMatch() 来获得 k 对最佳匹配。在本例中我们设置 k = 2,这样我们就可以使用 D.Lowe 文章中的比值测试了。
import numpy as np
import cv2
from matplotlib import pyplot as pltimg1 = cv2.imread('./resource/opencv/image/box.png', 0)
img2 = cv2.imread('./resource/opencv/image/box_in_scene.png', 0)sift = cv2.SIFT_create()
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)bf = cv2.BFMatcher_create()
matches = bf.knnMatch(des1, des2, k=2)good = []
for m,n in matches:if m.distance < 0.75*n.distance:good.append([m])# drawMatchesKnn(img1, keypoints1, img2, keypoints2, matches1to2, outImg, matchColor=..., singlePointColor=..., matchesMask=..., flags: int = ...)
img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, good[:100], None, flags=2)
plt.imshow(img3)
plt.show()
FLANN 匹配
FLANN 是快速最近邻搜索包(Fast_Library_for_Approximate_Nearest_Neighbors)的简称。它是一个对大数据集和高维特征进行最近邻搜索的算法的集合,而且这些算法都已经被优化过了。在面对大数据集时它的效果要好于 BFMatcher。我们来对第二个例子使用 FLANN 匹配看看它的效果。
import numpy as np
import cv2
from matplotlib import pyplot as pltimg1 = cv2.imread('./resource/opencv/image/box.png', 0)
img2 = cv2.imread('./resource/opencv/image/box_in_scene.png', 0)sift = cv2.SIFT_create()
kp1, des1 = sift.detectAndCompute(img1, None)
kp2, des2 = sift.detectAndCompute(img2, None)flann = cv2.FlannBasedMatcher_create()
matches = flann.knnMatch(des1, des2, k=2)matchesMask = [[0,0] for i in range(len(matches))]for i, (m, n) in enumerate(matches):if m.distance < 0.7*n.distance:matchesMask[i] = [1,0]draw_params = dict(matchColor = (0, 255, 0),singlePointColor = (255, 0, 0),matchesMask = matchesMask,flags = 0)img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, matches, None, **draw_params)
plt.imshow(img3)
plt.show()
相关文章:

OpenCV-Python中的图像处理-图像特征
OpenCV-Python中的图像处理-图像特征 图像特征Harris角点检测亚像素级精度的角点检测Shi-Tomasi角点检测SIFT(Scale-Invariant Feature Transfrom)SURF(Speeded-Up Robust Features)FAST算法BRIEF(Binary Robust Independent Elementary Features)算法ORB (Oriented FAST and R…...

Ajax入门+aixos+HTTP协议
一.Ajax入门 概念:AJAX是浏览器与服务器进行数据通信的技术 axios使用: 引入axios.js使用axios函数:传入配置对象,再用.then回调函数接受结果,并做后续处理 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>01.axios使用…...
conda创建虚拟环境
创建虚拟环境是在计算机上设置一个独立的空间,用于安装和运行特定版本的软件和依赖项,以避免与系统其他部分的冲突。 创建虚拟环境: conda create --name myenv python3.8 这将创建一个名为myenv的虚拟环境,并安装Python 3.8版本。…...

Golang服务的请求调度
文章目录 1. 写在前面2. SheddingHandler的实现原理3. 相关方案的对比4. 小结 1. 写在前面 最近在看相关的Go服务的请求调度的时候,发现在gin中默认提供的中间件中,不含有请求调度相关的逻辑中间件,去github查看了一些服务框架,发…...
Jenkins的流水线启动jar后未执行问题处理
现象 在流水线里配置了启动脚本例如,nohup java -jar xxx.jar >nohup.out 2>&1 & 但是在服务器发现服务并未启动,且nohup日志里没输出日志,这样的原因是jenkins在执行完脚本后,就退出了这个进程。 在启动脚本执行jar命令的上一步加入以下…...

智慧工地平台工地人员管理系统 可视化大数据智能云平台源码
智慧工地概述: 智慧工地管理平台是以物联网、移动互联网技术为基础,充分应用大数据、人工智能、移动通讯、云计算等信息技术,利用前端信息采通过人机交互、感知、决策、执行和反馈等,实现对工程项目內人员、车辆、安全、设备、材…...

外包干了2个月测试,技术退步明显...
先说一下自己的情况,大专生,18年通过校招进入湖南某软件公司,干了接近4年的功能测试,今年年初,感觉自己不能够在这样下去了,长时间呆在一个舒适的环境会让一个人堕落!而我已经在一个企业干了四年的功能测试…...
神经网络基础-神经网络补充概念-19-向量化实现的解释
概念 向量化是一种优化技术,通过使用数组操作代替显式的循环,可以大大提高代码的性能和效率。在机器学习和数据分析领域,向量化是一种常见的实践,它允许你在处理大量数据时更快地进行计算。 一般操作 数组操作:向量…...

四层和七层负载均衡的区别
一、四层负载均衡 四层就是ISO参考模型中的第四层。四层负载均衡器也称为四层交换机,它主要时通过分析IP层和TCP/UDP层的流量实现的基于“IP端口”的负载均衡。常见的基于四层的负载均衡器有LVS、F5等。 以常见的TCP应用为例,负载均衡器在接收到第一个来…...

Scala 如何调试隐式转换--隐式转换代码的显示展示
方法1 在需要隐式转换的地方,把需要的参数显示的写出。 略方法2,查看编译代码 在terminal中 利用 scalac -Xprint:typer xxx.scala方法打印添加了隐式值的代码示例。 对于复杂的工程来说,直接跑到terminal执行 scalac -Xprint:typer xxx.…...
Rust交叉编译简述 —— Arm
使用系统:WSL2 —— Kali(Microsoft Store) 命令列表 rustup target list # 当前官方支持的构建目标架构列表 rustup target add aarch64-unknown-linux-gnu # 添加目标架构sudo apt-get install gcc-13-aarch64-linux-gnu gcc-13-aarch64-linux-gnu # 下载目标工具…...

算法与数据结构(二十三)动态规划设计:最长递增子序列
注:此文只在个人总结 labuladong 动态规划框架,仅限于学习交流,版权归原作者所有; 也许有读者看了前文 动态规划详解,学会了动态规划的套路:找到了问题的「状态」,明确了 dp 数组/函数的含义&a…...

相机的位姿在地固坐标系ECEF和ENU坐标系的转换
在地球科学和导航领域,通常使用地心地固坐标系(ECEF,Earth-Centered, Earth-Fixed)和东北天坐标系(ENU,East-North-Up)来描述地球上的位置和姿态。如下图所示: 地心地固坐标ecef和…...

RFID技术助力汽车零配件装配产线,提升效率与准确性
随着科技的不断发展,越来越多的自动化设备被应用到汽车零配件装配产线中。其中,射频识别(Radio Frequency Identification,简称RFID)技术凭借其独特的优势,已经成为了这一领域的重要技术之一。本文将介绍RF…...
应用高分辨率 GAN 对扰动文档图像去扭曲的深度Python实践
1. 引言 随着技术的不断发展,图像处理在各种场景中的应用也变得越来越广泛。高分辨率 GAN (Generative Adversarial Network) 是近年来图像处理领域的热点技术,它能够生成极高分辨率的图像,与此同时,它也可以用于各种修复和增强任…...
【BASH】回顾与知识点梳理(二十六)
【BASH】回顾与知识点梳理 二十六 二十六. 二十一至二十五章知识点总结及练习26.1 总结26.2 模拟26.3 简答题 该系列目录 --> 【BASH】回顾与知识点梳理(目录) 二十六. 二十一至二十五章知识点总结及练习 26.1 总结 Linux 操作系统上面,…...
React下载文件的两种方式
React下载文件的两种方式 - 代码先锋网 不知道有用没用看着挺整齐 没试过 1、GET类型下载 download url > {const eleLink document.createElement(a);eleLink.style.display none;// eleLink.target "_blank"eleLink.href url;// eleLink.href record;d…...

python入门知识:分支结构
前言 嗨喽,大家好呀~这里是爱看美女的茜茜呐 1.内容导图 👇 👇 👇 更多精彩机密、教程,尽在下方,赶紧点击了解吧~ python资料、视频教程、代码、插件安装教程等我都准备好了,直接在文末名片自…...
DNS协议及其工作原理
DNS是域名系统(Domain Name System)的缩写,它是一种用于将域名转换为IP地址的分布式数据库系统。它是因特网的基石,能够使人们通过域名方便地访问互联网,而无需记住复杂的IP地址。 DNS的历史可以追溯到1983年…...
调用被fishhook的原函数
OC类如果通过runtime被hook了,可以通过逆序遍历方法列表的方式调用原方法。 那系统库的C函数被fish hook了该怎么办呢? 原理和OC类异曲同工,即通过系统函数dlopen()获取动态库,以动态库为参数通过系统函数dlsym()即可获取目标系统…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
uniapp中使用aixos 报错
问题: 在uniapp中使用aixos,运行后报如下错误: AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

html-<abbr> 缩写或首字母缩略词
定义与作用 <abbr> 标签用于表示缩写或首字母缩略词,它可以帮助用户更好地理解缩写的含义,尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时,会显示一个提示框。 示例&#x…...

20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
SQL慢可能是触发了ring buffer
简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

在Mathematica中实现Newton-Raphson迭代的收敛时间算法(一般三次多项式)
考察一般的三次多项式,以r为参数: p[z_, r_] : z^3 (r - 1) z - r; roots[r_] : z /. Solve[p[z, r] 0, z]; 此多项式的根为: 尽管看起来这个多项式是特殊的,其实一般的三次多项式都是可以通过线性变换化为这个形式…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement
Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...

Vue3 PC端 UI组件库我更推荐Naive UI
一、Vue3生态现状与UI库选择的重要性 随着Vue3的稳定发布和Composition API的广泛采用,前端开发者面临着UI组件库的重新选择。一个好的UI库不仅能提升开发效率,还能确保项目的长期可维护性。本文将对比三大主流Vue3 UI库(Naive UI、Element …...