今天下午中国机器人及人工智能大赛(服务机器人赛项)比赛结束了,就效果而言,我们的机器人能够成功的进行所有流程以及操作,尽管速度上可能并不是很快,但是此范围的问题已经属于机器人硬件的问题了(我们又不能拆机器人改轮子!),所以说,在我们的可能范围之内,我们已经做到了极致,虽然可能幸运女神并不眷顾我们,但是我们也算是尽到自己的最大努力去认真的做,认真的负责,认真的努力,最后认认真真的坚持了,说的遗憾也是有的,可能一个过程永远不会是完美吧。
大约是在去年的寒假前2个月,我们接手了师哥们去年的‘大蓝’机器人,来备战2021年的机器人大赛,可是由于疫情的原因,一直延期到今天下午才正式比完,我是负责‘大蓝’的‘双眼’,我的大佬队友是负责ROS方面的调试,在刚接手它的时候,它并不算是‘成年’,实属‘青年’的懵懂状态,从抓取的调整到人脸检测的改变,它也算是逐渐的成熟,对于ROS方面我就不进行多余的叙述了,在文末会将两位大佬的博客贴出来,毕竟我对于ROS方面的问题涉猎还是比较少,然后在一开始的时候,我就是被分工到做他的人脸检测那一部分的优化。
总的来说,opencv的级联分类器的效果的确不是很好,并且会受到光线等条件的限制,而机器人当中又是将人脸检测与3D点云结合在一起来进行的识别,在综合考虑之下,打算直接采用多加一个摄像头(简单粗暴,解决根本性问题),于是直接拿走了我的工业摄像头(我的小摄),在小蓝的头部加上一个“开!天!眼!”,嗨嘿,通过百度飞浆Paddlehub来进行人脸检测,效果显著,遮挡一半的脸都可以完美检测到,(缺点就是:实在太准,有时候会将路人的脸检测上),在此贴上人脸检测的代码:
from signal import SIGINT
#删除cv.so
'''
import sys
sys.path.remove('/opt/ros/kinetic/lib/python2.7/dist-packages')
'''
from cv2 import LSD_REFINE_STD, createTonemapReinhard, data
from numpy.lib.function_base import vectorize
import paddlehub as hub
import cv2
from PIL import Image
from paddlehub import module
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FOURCC, cv2.VideoWriter_fourcc('M', 'J', 'P', 'G'))
cap.set(cv2.CAP_PROP_FPS, 60)
cap.set(3, 240)
cap.set(4, 240)
center=0
flag = 0
flag2=1
r = 0
def receive(x):
if x<160 and x>140:
flag = 1
print("center")
if __name__ == '__main__':
while cap.isOpened():
ok,frames = cap.read()
if not ok:
break
face_detector = hub.Module(name="pyramidbox_lite_mobile")
result = face_detector.face_detection(images=[frames],visualization=False)
if result[0]['data'] != []:
for face in result[0]['data']:
# 将Dict形式的key-value对转换成变量形式
locals().update(face)
left = face["left"]
top = face["top"]
right = face["right"]
bottom = face["bottom"]
center = (right-left)/2+left
r=cv2.rectangle(frames, tuple([left,top]), tuple([right,bottom]), (255, 0, 0), 3)
#print(r)
if r is not None:
r = frames
cv2.imshow("cnm2",r)
#receive(center)
key = cv2.waitKey(1)
if key == 27: #ESC键
break
if center<160 and center>140:
#flag = 1
print("center")
if key == 27: #ESC键
cv2.destroyAllWindows()
cap.release()
break
#cap.release()
else:
cv2.imshow("cnm3",frames)
key = cv2.waitKey(1)
if key == 27: #ESC键
break
cap.release()
在此人脸检测的运行当中还有一个大的问题,就是ROS的opencv与miniconda环境当中的python3的opencv的冲突问题,(天坑!!!!),在这个问题上调试了很久,期间还将系统搞崩过一次,最后采用的古月居当中的一个方法:conda和ros环境共存方法 (qq.com)https://mp.weixin.qq.com/s/sbal2Hjkn0qOTSPKdsO_Vg
尽管此方法还算比较成功,但是在搭建完之后还是会出现一个有关python2.7的问题:
python2.7 opencv相关问题具体解决方法是通过python的os操作,删除cv2.so这个文件,然后就可以没有冲突的运行这个检测程序了,如果你觉得删除文件不放心(duck不必),因为经过测试,这个文件会重新生成,所以可以在防止冲突的时候直接删除,很是玄学(是我不懂,大佬可以在评论区交流),然后在conda运行的时候,也是需要在他的bash文件进行修改的,具体目的就是让conda能够顺利启动,要不然可能会报没有source这个错误(时间太长,已经记不清当时怎么改的了555),就先不贴了,解决这个问题后就能顺利开始运行人脸检测了,效果嘎嘎好,哦对,你还需要搭好paddle的环境,在conda中安装paddle,我相信这不会是问题,采用paddlehub,去飞浆官网直接搜索用就可,教程也很是不错,预训练模型贼好用(轻量+准确),在此宣传一波飞浆yyds!
人脸检测在此优化完成,如何协调到你的机器人程序中,大家自行调试吧。
接下来就是抓取的问题,一开始对于物品的抓取不是很准确,怎么调整都是出问题,且不能识别两个平面进行不同高度的抓取,于是最后决定采用深度学习来进行物品识别,并通过物品识别框计算平面位置,通过深度摄像头估算相关距离来进行抓取,好吧,再来一波paddle,这次是采用的paddleclas,飞桨图像识别套件PaddleClas是飞桨为工业界和学术界所准备的一个图像识别任务的工具集,助力使用者训练出更好的视觉模型和应用落地。模型自行去寻找吧,这边采用了轻量级的识别与检测模型,在预训练模型的基础上,对可能用到的商品进行了训练,训练完后的模型进行推理预测,而其最大的一个优势就是,对于新的未经训练过的商品,无需重新训练,在导入其图片以及构建索引库之后可以直接进行识别,准确率在百分之六七十左右,划重点!!!无需重新训练!!!
在此就只贴一下预测的代码吧,对于其一些以来文件自行去paddleclas了解吧!
# Copyright (c) 2021 PaddlePaddle Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
from re import I
import sys
from cv2 import IMWRITE_PNG_STRATEGY_FILTERED
__dir__ = os.path.dirname(os.path.abspath(__file__))
sys.path.append(os.path.abspath(os.path.join(__dir__, '../')))
import copy
import cv2
import numpy as np
import faiss
import pickle
from python.predict_rec import RecPredictor
from python.predict_det import DetPredictor
from utils import logger
from utils import config
from utils.get_image_list import get_image_list
from utils.draw_bbox import draw_bbox_results
class SystemPredictor(object):
def __init__(self, config):
self.config = config
self.rec_predictor = RecPredictor(config)
self.det_predictor = DetPredictor(config)
assert 'IndexProcess' in config.keys(), "Index config not found ... "
self.return_k = self.config['IndexProcess']['return_k']
index_dir = self.config["IndexProcess"]["index_dir"]
assert os.path.exists(os.path.join(
index_dir, "vector.index")), "vector.index not found ..."
assert os.path.exists(os.path.join(
index_dir, "id_map.pkl")), "id_map.pkl not found ... "
if config['IndexProcess'].get("dist_type") == "hamming":
self.Searcher = faiss.read_index_binary(
os.path.join(index_dir, "vector.index"))
else:
self.Searcher = faiss.read_index(
os.path.join(index_dir, "vector.index"))
with open(os.path.join(index_dir, "id_map.pkl"), "rb") as fd:
self.id_map = pickle.load(fd)
def append_self(self, results, shape):
results.append({
"class_id": 0,
"score": 1.0,
"bbox":
np.array([0, 0, shape[1], shape[0]]), # xmin, ymin, xmax, ymax
"label_name": "foreground",
})
return results
def nms_to_rec_results(self, results, thresh=0.1):
filtered_results = []
x1 = np.array([r["bbox"][0] for r in results]).astype("float32")
y1 = np.array([r["bbox"][1] for r in results]).astype("float32")
x2 = np.array([r["bbox"][2] for r in results]).astype("float32")
y2 = np.array([r["bbox"][3] for r in results]).astype("float32")
scores = np.array([r["rec_scores"] for r in results])
areas = (x2 - x1 + 1) * (y2 - y1 + 1)
order = scores.argsort()[::-1]
while order.size > 0:
i = order[0]
xx1 = np.maximum(x1[i], x1[order[1:]])
yy1 = np.maximum(y1[i], y1[order[1:]])
xx2 = np.minimum(x2[i], x2[order[1:]])
yy2 = np.minimum(y2[i], y2[order[1:]])
w = np.maximum(0.0, xx2 - xx1 + 1)
h = np.maximum(0.0, yy2 - yy1 + 1)
inter = w * h
ovr = inter / (areas[i] + areas[order[1:]] - inter)
inds = np.where(ovr <= thresh)[0]
order = order[inds + 1]
filtered_results.append(results[i])
return filtered_results
def predict(self, img):
output = []
# st1: get all detection results
results = self.det_predictor.predict(img)
# st2: add the whole image for recognition to improve recall
results = self.append_self(results, img.shape)
# st3: recognition process, use score_thres to ensure accuracy
for result in results:
preds = {}
xmin, ymin, xmax, ymax = result["bbox"].astype("int")
crop_img = img[ymin:ymax, xmin:xmax, :].copy()
rec_results = self.rec_predictor.predict(crop_img)
preds["bbox"] = [xmin, ymin, xmax, ymax]
scores, docs = self.Searcher.search(rec_results, self.return_k)
# just top-1 result will be returned for the final
if self.config["IndexProcess"]["dist_type"] == "hamming":
if scores[0][0] <= self.config["IndexProcess"][
"hamming_radius"]:
preds["rec_docs"] = self.id_map[docs[0][0]].split()[1]
preds["rec_scores"] = scores[0][0]
output.append(preds)
else:
if scores[0][0] >= self.config["IndexProcess"]["score_thres"]:
preds["rec_docs"] = self.id_map[docs[0][0]].split()[1]
preds["rec_scores"] = scores[0][0]
output.append(preds)
# st5: nms to the final results to avoid fetching duplicate results
output = self.nms_to_rec_results(
output, self.config["Global"]["rec_nms_thresold"])
return output
def main(config):
system_predictor = SystemPredictor(config)
#image_list = get_image_list(config["Global"]["infer_imgs"])
#cap = cv2.VideoCapture(0, cv2.CAP_DSHOW)
cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 640)
while True:
ret, frame = cap.read()
#image_list = get_image_list(frame)
assert config["Global"]["batch_size"] == 1
img = frame[:,:,::-1]
#img = frame
output = system_predictor.predict(img)
for item in output:
#print(item['bbox'][0])
fuckx = (item['bbox'][0] + item['bbox'][2])/2
fucky = (item['bbox'][1] + item['bbox'][3])/2
print(fuckx)
print(fucky)
print(output)
img1 = draw_bbox_results(img,output,frame)
cv2.imshow("window1",img1)
#print(output)
if cv2.waitKey(1)&0xFF == ord("q"):
break
cap.release()
cv2.destroyAllWindows()
#return
# for idx, image_file in enumerate(image_list):
# img = cv2.imread(image_file)[:, :, ::-1]
# output = system_predictor.predict(img)
# draw_bbox_results(img, output, image_file)
# print(output)
# return
if __name__ == "__main__":
args = config.parse_args()
config = config.get_config(args.config, overrides=args.override, show=True)
main(config)
此方案还是比较好用的,可以应对比赛的“突发状况”,划重点!比赛往往会在比赛前一天公布物品名单,所以说没有数据集是很难受的,所以无需训练就可以进行识别并且又比opencv的模板匹配准确好几倍可以友好的解决这一问题。最后因为时间的问题,未能采用此方案,本来打算将深度摄像头的2d图像提取出来进行物品检测,其他直接套用,但是后来发现并没想象的那么简单,但是!!队友成功将机械臂的抓取解决了!!(队除我佬 手动滑稽)解决之后效果很是不错,也能够成功解决不同高度抓取的问题,尽管可能也比较局限吧,但是效果还是真的哇塞!对于其抓取的相关问题,不知道队友大佬会不会写博客分享(可能不会)。
最后在此结束了,但是还有一点吧,对于问题需要针对性的高鲁棒性解决!
(15条消息) while_Shi:的博客_CSDN博客-领域博主
(15条消息) 一个127的博客_CSDN博客-领域博主