用Python实现OpenCV特征提取与图像检索 | Demo
参加「CTA 核心技术及应用峰会」,请扫码报名
↑↑↑
作者|Andrey Nikishaev
翻译 | 张蔚敏
审校 | reason_W
来源 | Python大本营(id:pythonnews)
“拍立淘”“一键识花”“街景匹配”……不知道大家在使用这些神奇的功能的时候,有没有好奇过它们背后的技术原理?其实这些技术都离不开最基本的图像检索技术。本篇文章我们就将对这一技术的原理进行介绍,并通过一个简单的Python脚本来实现一个最基本的图像检索demo。
图像特征
首先我们需要明白图像特征是什么以及它的使用方法。
图像特征是一种简单的图像模式,基于这种模式我们可以描述我们在图像上所看到的内容。例如,在一张跟猫有关的图片中,猫咪的眼睛就可以作为这幅图像的特征。特征在(包括但不限于)计算机视觉中的主要作用是将视觉信息转换为向量空间表示。这种向量空间表示让我们可以利用数学运算对其进行处理,例如通过计算寻找相似向量(这可以用来寻找相似图像或图像中的相似目标)。
如何从图像中获取特征?
从图像中获取特征的方法有两种,第一种是通过提取图像描述符实现(白盒算法);第二种通过基于神经网络的方法实现(黑盒算法)。本文主要介绍第一种方法。
特征提取的算法有很多,最常用的有:SURF、ORB、SIFT、BRIEF等。这些算法大多是基于图像梯度的。为了简化安装需求,本教程使用的是KAZE描述符,因为其他描述符在python的基础OpenCV库中没有提供。
下面是特征提取器的实现代码:
import cv2
import numpy as np
import scipy
from scipy.misc import imread
import cPickle as pickle
import random
import os
import matplotlib.pyplot as plt
# Feature extractor
# 特征提取器
def extract_features(image_path, vector_size=32):
image = imread(image_path, mode="RGB")
try:
# Using KAZE, cause SIFT, ORB and other was moved to additional module
# which is adding addtional pain during install
#此处为了简化安装步骤,使用KAZE,因为SIFT/ORB以及其他特征算子需要安
#装额外的模块
alg = cv2.KAZE_create()
# Finding image keypoints
#寻找图像关键点
kps = alg.detect(image)
# Getting first 32 of them.
#计算前32个
# Number of keypoints is varies depend on image size and color pallet
#关键点的数量取决于图像大小以及彩色调色板
# Sorting them based on keypoint response value(bigger is better)
#根据关键点的返回值进行排序(越大越好)
kps = sorted(kps, key=lambda x: -x.response)[:vector_size]
# computing descriptors vector
#计算描述符向量
kps, dsc = alg.compute(image, kps)
# Flatten all of them in one big vector - our feature vector
# 将其放在一个大的向量中,作为我们的特征向量
dsc = dsc.flatten()
# Making descriptor of same size
# 使描述符的大小一致
# Descriptor vector size is 64
#描述符向量的大小为64
needed_size = (vector_size * 64)
if dsc.size < needed_size:
# if we have less the 32 descriptors then just adding zeros
# at the end of our feature vector
#如果少于32个描述符,则在特征向量后面补零
dsc = np.concatenate([dsc, np.zeros(needed_size - dsc.size)])
except cv2.error as e:
print 'Error: ', e
return None
return dsc
def batch_extractor(images_path, pickled_db_path="features.pck"):
files = [os.path.join(images_path, p) for p in sorted(os.listdir(images_path))]
result = {}
for f in files:
print 'Extracting features from image %s' % f
name = f.split('/')[-1].lower()
result[name] = extract_features(f)
# saving all our feature vectors in pickled file
# 将特征向量存于pickled 文件
with open(pickled_db_path, 'w') as fp:
pickle.dump(result, fp)
OpenCV中的大多数特征提取算法的python接口都相同,所以如果你想要使用SIFT特征,只需要用SIFT_create替换KAZE_create就行。
首先,程序会用extract_features检测图像上的关键点(局部模式的中心点)。因为关键点数量随图像的不同有所不同,因此我们需要添加一些规则,以确保所得到的特征向量大小始终相同(这是因为在计算时,我们无法对维度不同的向量进行比较,所以必须保证相同的大小)。
然后是根据关键点构建向量描述符,每个描述符的大小为64,我们有32个这样的描述符,所以我们的特征向量是2048维。
batch_extractor是在所有的图像中批量运行特征提取器,并将特征向量保存在pickled文件中以供后续使用。
现在我们来建立类Matcher,它会将待搜索图像和数据库中的图像进行匹配。
class Matcher(object):
def __init__(self, pickled_db_path="features.pck"):
with open(pickled_db_path) as fp:
self.data = pickle.load(fp)
self.names = []
self.matrix = []
for k, v in self.data.iteritems():
self.names.append(k)
self.matrix.append(v)
self.matrix = np.array(self.matrix)
self.names = np.array(self.names)
def cos_cdist(self, vector):
# getting cosine distance between search image and images database
#计算待搜索图像与数据库图像的余弦距离
v = vector.reshape(1, -1)
return scipy.spatial.distance.cdist(self.matrix, v, 'cosine').reshape(-1)
def match(self, image_path, topn=5):
features = extract_features(image_path)
img_distances = self.cos_cdist(features)
# getting top 5 records
# 获得前5个记录
nearest_ids = np.argsort(img_distances)[:topn].tolist()
nearest_img_paths = self.names[nearest_ids].tolist()
return nearest_img_paths, img_distances[nearest_ids].tolist()
这里要加载前一步得到的特征向量,并从它们中创建一个大矩阵,然后计算待搜索图像的特征向量和特征向量数据库之间的余弦距离,然后输出最近的前N个结果。
当然,这仅仅是一个demo,在实际计算中,还可以用一些算法来快速计算数百万图像间的余弦距离。你可以使用简单且运行速度相当快的Annoy Index(在1M图像中搜索约需2ms)。
现在把它们放在一起运行一下:
def show_img(path):
img = imread(path, mode="RGB")
plt.imshow(img)
plt.show()
def run():
images_path = 'resources/images/'
files = [os.path.join(images_path, p) for p in sorted(os.listdir(images_path))]
# getting 3 random images
# 随机获取3张图
sample = random.sample(files, 3)
batch_extractor(images_path)
ma = Matcher('features.pck')
for s in sample:
print 'Query image =========================================='
show_img(s)
names, match = ma.match(s, topn=3)
print 'Result images ========================================'
for i in range(3):
# we got cosine distance, less cosine distance between vectors
# more they similar, thus we subtruct it from 1 to get match value
#我们得到了余弦距离,向量之间的余弦距离越小表示它们越相似,因此我们从1中减去它以得到匹配值
print 'Match %s' % (1-match[i])
show_img(os.path.join(images_path, names[i]))
run()
大家可以在我的 github上下载源码,或者在Google Colab上运行(Google Colab是一种提供GPU在线计算的免费服务):
https://colab.research.google.com/drive/1BwdSConGugBlGzPLLkXHTz2ahkdzEhQ9
总结
在运行上述代码的过程中,你可能会发现搜索到的相似图像并不总能达到我们想象中的那种相似程度。这是因为我们所用的这种算法是上下文无关(context-unaware)的,所以该算法在寻找相同(即使是被修改过的)图像方面表现更好,而不是在相似图像方面。如果是要寻找上下文相关的相似图像,那就要使用卷积神经网络了,我的下一篇文章会对这方面的知识进行详细介绍。
原文链接:
https://towardsdatascience.com/feature-extraction-and-similar-image-search-with-opencv-for-newbies-3c59796bf774
(本文为AI科技大本营转载文章,转载请联系原作者。)
◆
精彩推荐
◆
5月25-27日,由中国IT社区CSDN与数字经济人才发展中心联合主办的第一届CTA核心技术及应用峰会将在杭州国际博览中心隆重召开。首届CTA核心技术及应用峰会将围绕人工智能,邀请技术领航者,与开发者共同探讨机器学习和知识图谱的前沿研究及应用。
同时,我们推出会议双日开发者盲定票,仅售299元(原票价1099元),限量30张。请扫描下方二维码,或添加小助手微信1731967109,备注【CTA】,了解大会详情以及票务问题。
推荐阅读:
开什么玩笑?股票价格如何经得起AI的推敲?| 技术头条
深入卷积神经网络背后的数学原理 | 技术头条
用Python实现OpenCV特征提取与图像检索demo
Python基础入门——简介和环境配置,超实用!
云计算之基,一文带你速懂虚拟化KVM和XEN
Erlang 之父去世,他留给程序员两点忠告
程序员逆袭为美国最佳 CEO,他说因为爱情
用一枚比特币环游世界? 他是不是疯了...
程序员如何向女友解释:为啥软件都要装C盘?
❤点击“阅读原文”,直接参与大会报名。
相关文章:

【ffmpeg】编译时报错:error: undefined reference to `av...
1、问题描述 昨天使用ffmpeg库编译demo一切正常,今天再次链接ffmpeg库时报了一堆错误: error: undefined reference to `av_frame_alloc() error: undefined reference to `avio_close(AVIOContext*) error: undefined reference to `avcodec_find_encoder(AVCodecID) erro…

Spring Initializr 构建Spring Boot/Cloud工程
2019独角兽企业重金招聘Python工程师标准>>> 在之前的所有Spring Boot和Spring Cloud相关博文中,都会涉及Spring Boot工程的创建。而创建的方式多种多样,我们可以通过Maven来手工构建或是通过脚手架等方式快速搭建,也可以通过《Sp…

linux下用phpize给PHP动态添加扩展
使用php的常见问题是:编译php时忘记添加某扩展,后来想添加扩展,但是因为安装php后又装了一些东西如PEAR等,不想删除目录重装,别说,php还真有这样的功能。 我没有在手册中看到。 如我想增加bcmath支持&…

“996 是福利,007 才是常态”?!千万程序员怒怼每日优鲜!
呔!热度不是你想蹭,想蹭就能蹭……作者 | 仲培艺封图 | CSDN 付费下载自东方IC出品 | 程序人生(ID:coder_life)App Store 评分一日之间从 4.5 断崖直降至 1.5,每日优鲜这是怎么了?究其原因——大…
亚太信息安全领袖成就表彰计划:阿里成中国互联网公司唯一代表
近日,全球最大的信息安全非营利会员组织(ISC)公布了第十二届年度亚太区信息安全领袖成就(亚太区ISLA)表彰计划的获奖者,共有17名人员获得此项殊荣。据悉,(ISC)将于2018年7月9日在香港举行的庆典活动中表彰这17名获奖者…

【C++】clipp 一个命令行参数解析器
1、简介 clipp是一个使用方便、功能强大的命令行解析器,源码只有一个头文件《clipp.h》 github地址:https://github.com/muellan/clipp 2、使用 只演示最简单的例子,更复杂的参见源码中《README.md》。 例如需要如下命令行参数 用法&…

Oracle 聚合函数(Aggregate Functions)说明
Oracle Aggregate Functions用过很多,官网的说明如下:Aggregate Functionshttp://docs.oracle.com/cd/E11882_01/server.112/e26088/functions003.htm#SQLRF20035Aggregatefunctions return a single result row based on groups of rows, rather than o…

【OpenCV】正确创建用于保存YUV420P格式的cv::Mat
1、问题描述 cv::Mat保存RGB24或BRG24格式时,传入宽、高和格式类型CV_8UC3就行了;今天在创建cv::Mat用来保存YUV420P时,有点懵圈了,因为类型是CV_8UC1,直接传宽和高,只能保存Y分量。因此需要宽或者高乘以一…

特斯拉全新自动驾驶芯片最强?英伟达回怼,投资者用脚投票
整理 | 一一出品 | AI科技大本营(ID:rgznai100)马斯克前脚刚说完自家发布的自动驾驶计算机是全球最强,后脚就被英伟达怼了。在刚刚结束的自动驾驶投资者日上,特斯拉发布了全自动驾驶(FSD)计算机(…

2012年我的十大工程9——形象工程
形象对于每一个人来说都很重要,人以群分,物以类聚!说的就是这个道理,不同的人接触不同的社会,不同的级别接触不同的层面。还记得我【千日计划】项目中怎么说的吗?第七项:改良自己的外貌形象。老…

【MySQL】ubuntu16.04安装mysql,然后源码编译Qt5.12.4版本的libqsqlmysql.so
一、Ubuntu16.04.5 安装 MySQL 1、使用apt命令安装 sudo apt install mysql-server安装过程会提示,推荐设置MySQL的root用户密码(注意:这里root不是指ubuntu系统的root) While not mandatory, it is highly recommended that you set a password for the MySQL administr…

A* 算法之父、人工智能先驱Nils Nilsson逝世 | 缅怀
整理 | 琥珀出品 | AI科技大本营(id:rgznai100)2019 年 4 月 23 日,人工智能学科创始研究者之一、斯坦福大学计算机科学系 Kumagai 教授 Nils J. Nilsson 逝世,享年 86 岁。Nils J. Nilsson(1933 年 2 月 6…

类执行方法的过程与运行时
大家都知道,调用一个未声明方法大多数情况下会崩溃,崩溃信息就是unrecognized selector sent to instance;是的,的确大多数情况下是这样的,但是有了运行时就不一定了,这就是我今天的主题——“安全类”(哈哈…

NandFlash系列之一:NorFlash与NandFlash对比
NandFlash系列之一:NorFlash与NandFlash对比作者:刘洪涛,华清远见嵌入式学院高级讲师。FLASH存储器又称闪存,主要有两种:NorFlash和NandFlash,下面我们从多个角度来对比介绍一下。在实际开发中,…

机器学习萌新必备的三种优化算法 | 选型指南
作者 | Nasir Hemed编译 | Rachel出品 | AI科技大本营(id:rgznai100)【导读】在本文中,作者对常用的三种机器学习优化算法(牛顿法、梯度下降法、最速下降法)进行了介绍和比较,并结合算法的数学原…

【MySQL】缩略语PK NN UQ BIN UN ZF AI G、基本操作语句
一、缩略语 PK:primary key 主键 NN:not null 非空 UQ:unique 唯一索引 BIN:binary 二进制数据 UN:unsigned 无符号整数(非负数) ZF:zero fill 填充0 例如字段内容是1 int(4), 则内…

C#(WPF)去除事件中注册的事件处理方法!
在WPF中,移除一个事件中已经注册的处理方法,看似简单,实际还是很痛苦的一件事情。因为C#的灵活性,定义事件的方法也是多种多样。我自己定义了一个事件: public event EventHandler TestEvent; 当我想注销这个事件上注册…

memcached图形界面的监控
wget http://livebookmark.net/memcachephp/memcachephp.zip 前提是已经安装了php和memcached 图形界面的监控是通过memcache.php来实现的, 1.把该php程序拷贝到nginx的html根目录 [rootcacti srv]# cd /usr/local/nginx/html 2. 更改相应的连接IP和端口…

薅百度GPU羊毛!PaddlePaddle大升级,比Google更懂中文,打响AI开发者争夺战
记者 | 阿司匹林出品 | AI科技大本营(ID: rgznai100)深度学习已经推动人工智能进入工业大生产阶段,而深度学习框架则是智能时代的操作系统。在4月23日下午的Wave Summit深度学习开发者峰会上,百度高级副总裁王海峰开场就为深度学习…

vue中axios如何实现token验证
title: vue中axios如何实现token验证 date: 2018-02-08 17:50:07 tags: [axios,vue] 继上篇实现Auth认证之后,然后每个跳转页面都会在后端验证token的存在 然后那天晚上通过模仿Auth发送请求,发送成功(上篇末尾的方式) 但是今天再继续写,发现每个页面请求都要发送token验证 就比…

【视频】视频方面大神博客总结
1、雷霄骅博客 [总结]视音频编解码技术零基础学习方法:雷神对音视频技术的总结,包括:视频播放器原理、流媒体协议、封装格式、视频编码、音频编码、网络视音频平台对比。首先对雷神的顶礼膜拜,学完这篇博客,就算跨入音…

IHttpHandler 在SharePoint中的应用
1. 一个文件名为VCChartHandler.ashx,其文件代码为: <% WebHandler Language"C#" Class"VCSharePoint.BL.VCHandler,VCSharePoint, Version1.0.0.0, Cultureneutral, PublicKeyToken0134fd28ed40d3b2"%>2. 另一个类为VCHandler.cs的文件…

普通人也能用AI拍出3D大片?这位清华博士后这么做
从《阿凡达》到《流浪地球》,从好莱坞科幻 3D 电影之最到中国科幻 3D 电影之最,从 2009 年到 2019 年,近十年的岁月,见证了中国 3D 影视制作的快速成长和繁盛,也刺激着赵天奇探索人工智能与影视制作结合应用的信心。影…

[asp.net core]SignalR一个例子
摘要 在一个后台管理的页面想实时监控一些操作的数据,想到用signalR。 一个例子 asp.net coresignalR 使用Nuget安装包:Microsoft.AspNetCore.SignalR 在StartUp中启用signalR // This method gets called by the runtime. Use this method to add serv…

【FFmpeg】截至ffmpeg4.2不推荐(Deprecate)继续使用的接口,以及代替它的接口汇总
1、问题描述 使用ffmpeg库写程序,编译时,经常报警告“xxx is deprecated” 查看源码时,该接口或结构体字段被标记attribute_deprecated,表示它已经过时,不推荐使用。 如: attribute_deprecated void avcodec_register(AVCodec *codec);attribute_deprecated void avcod…

Asp.net开发过程中,我们会遇到很多Exception
在Asp.net开发过程中,我们会遇到很多Exception,不处理这些Exception的话会出现很难看的页面。还有一些我们未预料到的Exception,当发生Exception时,我们也必须进行记录具体位置,以便我们修正错误。asp.net异常处理的位…

【经验】对一个合格C++高级工程师(音视频方向)的要求
1、C高级工程师 经过查看招聘网站上对“C高级工程师”这个职位的招聘要求,只总结了技术、能力要求,不涉及工作年限、学历 具体要求如下: 精通C面向对象程序设计; 熟悉设计模式; 敏捷开发经验; 扎实数据结…

马云:腾讯不是阿里要打败的对手,是同为社会创造价值的伴侣
整理 | 琥珀出品 | AI科技大本营(ID:rgznai100)近日,在甘肃敦煌举办的 2019 年中国绿公司年会上,阿里巴巴创始人、董事局主席马云谈及企业间的竞争时,提到了与腾讯的关系。他表示,没有腾讯,阿里…

Win10 | Mac 在server上统一办公
一个非常实际的问题,通常我们主要有三个工作的地点:1,server,用于大型数据的分析和处理;2,办公室的电脑,正式办公;3.自己的电脑,偶尔加班。 不同的工作平台之间很难同步&…

JDK5.0新特性系列---目录
JDK5.0新特性系列---目录 JDK5.0新特性系列---1.自动装箱和拆箱 JDK5.0新特性系列---2.新的for循环 JDK5.0新特性系列---3.枚举类型 JDK5.0新特性系列---4.静态导入 JDK5.0新特性系列---5.可变长参数Varargs JDK5.0新特性系列---6.格式化输出 JDK5.0新特性系列---7.使用Proce…