2.使用百度开放图像识别平台搭建物体检测应用

本文介绍 2.使用百度开放图像识别平台搭建一个物体检测应用

使用百度开放图像识别平台搭建物体检测应用

本文由在当地较为英俊的男子金天大神原创,版权所有,欢迎转载,本文首发地址 https://jinfagang.github.io 。但请保留这段版权信息,多谢合作,有任何疑问欢迎通过微信联系我交流:jintianiloveu

众所周知,如果自己从零实现一个物体检测应用步骤是极其复杂的,我们需要构建检测框架比如Faster-RCNN,R-FCN或者yolov2,其次我们还需要相应的标注数据集。整个过程需要不断地训练,测试,即使有开源的实现outside there,但是在我看来很多实现都是a mess。现在我将教大家如何使用百度开放图像识别平台来搭建一个物体检测应用。整个过程绝对不会超过三分钟,并且,整个代码不会超过100行。本文主要分为两部分,一部分教大家具体实现,另外一部分我们会采用自动化的方式来测试一下百度图标识别平台的目标检测速度到底有多快!具体计时方式呢,就是我们发送一张图片到得到最终检测结果所消耗的时间。

物体检测的应用场景

如果说到物体检测有哪些应用场景,那不得不说,现在目前的高精尖科技基本上都需要用到物体检测,比如说百度Apollo平台,自动驾驶里面的行人、车辆检测,比如我们做一个老鼠追踪器,自动跟踪老鼠并预测运动趋势,实现定向抓捕等等,我们来看一下一些具体的使用场景:

自动驾驶视觉

可以说物体检测是自动驾驶的核心了,虽然自动驾驶实现的是本地物体检测,但是其核心都是类似的,就像这样:

尽管这个效果非常酷炫,但要实现它你需要昂贵的GPU,以及可以运行GPU程序的电脑,而使用百度通用物体检测API可以让大家即使在手机上也可以做物体的检测!你甚至可以植入到Android或者是iOS APP中!

浣熊追踪器

很久以前有个澳洲小哥(也许是非洲小哥),做了一个浣熊追踪器,因为浣熊惹人嫌弃啊,他就做了这么一个追踪器,目的是让浣熊出现的时候,捕捉到这个信号,并把图片发给他,这样就能第一时间知道有浣熊光顾了,从而把它赶走。他还进一步做了一个射击装置,当浣熊出现的时候,获取他的位置,用箭去赶走它(浣熊内心OS:我靠,谁打我)。大家可以感受一下澳洲小哥的创意:

21121520824534_.pic_hd

但实际上这里面涉及到的步骤就极其繁琐了,得自己找浣熊的数据集,然后手动给他标注,然后自己写模型去训练它,最后才能预测。但,如果你有了通用物体检测API,只需要短短几分钟时间就自己建造一个浣熊追踪系统!甚至是老鼠,总之通用物体识别里面所有能够识别的物体都可以。接下来我们会用狗狗来示例如何用通用物体检测来做狗狗的位置检测。

家门访客监控

很多极客都想做一个家门访客监控系统,当有人来家的时候,不管家里有没有人,系统都会把出现人的时候拍的照片,发送给我们的手机。听起来非常智能化有没有,但使用百度通用物体检测API三分钟即可搭建一个!可以说是真正的零门槛!而且是跨平台的应用!

相信大家已经迫不及待了接下来我们就开始制作把!

创建通用物体检测APP

大家可以从这里进入百度图像识别平台: http://ai.baidu.com/tech/imagerecognition,创建自己的应用,并获取`api keysecret key`.

百度图像识别平台到底多强大,我截个图来展示一下,强大的模型自定义功能:

1461520304522_.pic_hd

可以创建自己的模型和数据集!

当然我们今天暂时不创建自定义的数据集,我们直接使用百度的图像识别平台来识别我们的小狗

构建物体检测应用

首先,我们需要一张测试图片,在这里我随便找一张。如果大家懒得动手的话,我真心希望你们能用一下这个工具:https://github.com/jinfagang/alfred.git ,用alfred来找一张图片到底多简单?

alfred scrap image '小狗'

你就可以在文件夹下看到许多小狗图片了,我们只要一张就可以:

18521520249741_.pic_hd

43751520249803_.pic

我尽量让整个过程变得简洁,所以不拖泥带水。大家拿到测试图片之后,我们就开始编码啦。所有代码都写在obj_det.py 这个文件中。

接下来我们可能需要一些简单的测试:

0. load图片和显示

我们要构建一个基于python的post请求,然后把图片传上去,得到返回的结果。整个过程非常,我们先写一下如何读取图片以及如何把最终结果显示出来吧:

import cv2
img = cv2.imread('小狗/小狗_01.jpg', cv2.COLOR_BGR2RGB)
cv2.imshow('image', img)
cv2.waiteKey(0)

这个就是只是显示了。极其简单。但是接下来就复杂了,我们开始搭建一个 APIDetector的框架。

2. 搭建APIDetector框架

我们知道,之前我们介绍的时候这个api是需要传入一个access_token的,而这个token需要通过apikey和secretkey去获取而且只有30天有效期。因此在这里我直接给大家封装好了,直接传入你们的api keysecret key就可以。这个可以在百度ai平台的控制中心可以看到。

我直接贴上代码:

import os
import requests
import cv2
import base64
import json
from pprint import pprint
class APIDetector(object):
def __init__(self, api_key, secret_key):
self.access_token = self._get_access_token(api_key=api_key, secret_key=secret_key)
self.API_URL = 'https://aip.baidubce.com/rest/2.0/image-classify/v1/object_detect' + '?access_token=' \
+ self.access_token
@staticmethod
def _get_access_token(api_key, secret_key):
api = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials' \
'&client_id={}&client_secret={}'.format(api_key, secret_key)
rp = requests.post(api)
if rp.ok:
rp_json = rp.json()
print(rp_json['access_token'])
return rp_json['access_token']
else:
print('=> Error in get access token!')
def get_result(self, params):
rp = requests.post(self.API_URL, data=params)
if rp.ok:
print('=> Success! got result: ')
rp_json = rp.json()
pprint(rp_json)
return rp_json
else:
print('=> Error! token invalid or network error!')
print(rp.content)
return None
def detect(self, img_path):
f = open(img_path, 'rb')
img_str = base64.b64encode(f.read())
params = {'image': img_str, 'with_face': 1}
rp_json = self.get_result(params)
if __name__ == '__main__':
detector = APIDetector(api_key='', secret_key='')
img = '交通/交通_02.jpg'
detector.detect(img)

看上去挺复杂的,我们先看一下得到的结果吧:

43891520255421_.pic_hd

我们已经看到了正确的检测结果!

首先说明一下,大家运行上面的代码需要将apikey和secretkey改为自己的。也不需要手动去获取accesstoken了。到这里就完了么?

然而并没有,我们还没有把这个检测结果显示出来啊。

3. 可视化检测结果

最后我们可视一下。非常简单,直接贴代码:

def detect(self, img_path):
f = open(img_path, 'rb')
img_str = base64.b64encode(f.read())
params = {'image': img_str, 'with_face': 1}
rp_json = self.get_result(params)
result = rp_json['result']
height = result['height']
left = result['left']
top = result['top']
width = result['width']
origin_img = cv2.imread(img_path, cv2.COLOR_BGR2RGB)
result_img = cv2.rectangle(origin_img, (left, top), (width, height), (255, 255, 0))
return result_img

我们只要简单修改上面的detect 函数即可。二话不多说,检测结果令人惊奇!

43881520254382_.pic_hd

有目共睹的检测结果啊!非常快速的检测到了狗狗的位置。但是并没有完,我们还不知道检测出来的物体是什么类别的。如果大家制作像我之前所说的只是识别门口是否有人,那只需要检测出人的位置即可,不一定需要知道类别。但是如果你想知道这个位置里面的物体是否是狗狗,又或许是其他的什么东西?那我们还需要更进一步的操作、

4. 获取被检测区域的物体类别

本来该部分应该是后面讲解的内容,但为了进一步让大家完善我们的物体检测应用。在这里我们继续深化它。我们将使用百度图片平台的识别API来识别被检测区域的物体类别!

其实整个实现也非常简单。我们只需要再新建一个类去做类别的识别:

import os
import requests
import cv2
import base64
import json
from pprint import pprint
import time
class AnimalRecognizer(object):
def __init__(self, api_key, secret_key):
self.access_token = self._get_access_token(api_key=api_key, secret_key=secret_key)
self.API_URL = 'https://aip.baidubce.com/rest/2.0/image-classify/v1/animal' + '?access_token=' \
+ self.access_token
@staticmethod
def _get_access_token(api_key, secret_key):
api = 'https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials' \
'&client_id={}&client_secret={}'.format(api_key, secret_key)
rp = requests.post(api)
if rp.ok:
rp_json = rp.json()
print(rp_json['access_token'])
return rp_json['access_token']
else:
print('=> Error in get access token!')
def get_result(self, params):
rp = requests.post(self.API_URL, data=params)
if rp.ok:
print('=> Success! got result: ')
rp_json = rp.json()
pprint(rp_json)
return rp_json
else:
print('=> Error! token invalid or network error!')
print(rp.content)
return None
def detect(self, img_path):
f = open(img_path, 'rb')
img_str = base64.b64encode(f.read())
params = {'image': img_str, 'with_face': 1}
tic = time.clock()
rp_json = self.get_result(params)
toc = time.clock()
print('=> Cost time: ', toc - tic)
result = rp_json['result']
print(result)

因为我们识别的是狗狗,所以为了得到更加精确地识别结果,我们将使用动物的识别API,如果你要识别猫,或者马,其实也是一样的。我们最后来看一下识别的结果:

3921521164594_.pic_hd

OK!我们已经拥有了一个物体检测的应用了!而且这个应用时跨平台的,Android, iOS,树莓派,甚至Arduino你都可以做出一个物体检测应用来!这里说到Arduino大家可以自行脑补了,这可是硬件里面最简单的,但是你可能只需要一块esp8266来访问API就可以让Arduino获取人工智能的能力!

好了,我们还有最后一件事情没有做,很多人肯定想知道这个平台的检测速度怎么样?接下来我们来做一个评测。

百度图像识别平台速度评测

这个部分非常简单,我们需要在detect方法中加入一个即时的函数。方便我们测算整个过程到底消耗多少时间。对于我们来说,我们关心的是从图片上传过去的那么一刹那,到百度服务器处理完给出结果,再给我们返回一个api的result所花费的所有时间。因此我们在detect方法里面加上这么两句:

def detect(self, img_path):
f = open(img_path, 'rb')
img_str = base64.b64encode(f.read())
params = {'image': img_str, 'with_face': 1}
tic = time.clock()
rp_json = self.get_result(params)
toc = time.clock()
print('=> Cost time: ', toc - tic)
result = rp_json['result']
height = result['height']
left = result['left']
top = result['top']
width = result['width']
origin_img = cv2.imread(img_path, cv2.COLOR_BGR2RGB)
result_img = cv2.rectangle(origin_img, (left, top), (width, height), (0, 255, 0))
return result_img

也就是我们用tic toc的方式来计时。最终返回的结果是:

24.f440b722ecb57b84b8cbbaa337201cb6.2592000.1522846593.282335-10883291
=> Success! got result:
{'log_id': 3720916064315782272,
'result': {'height': 332, 'left': 30, 'top': 48, 'width': 216}}
=> Cost time: 0.025509000000000004
2018-03-05 20:56:36.112 Python[91255:5031018] ApplePersistenceIgnoreState: Existing state will not be touched. New state will be written to (null)

只用了0.02s!!!!这是一个什么概念??相当于是连续视频检测时候50帧的速度。这个基本上你用来做视频实时处理也不是问题了。。不过问题是这个api调用有次数限制。不管怎么样,我们再一次见证了百度的强大,图像识别处理api大为点赞!!