收尾结束--致敬一直坚持的我们

今天下午中国机器人及人工智能大赛(服务机器人赛项)比赛结束了,就效果而言,我们的机器人能够成功的进行所有流程以及操作,尽管速度上可能并不是很快,但是此范围的问题已经属于机器人硬件的问题了(我们又不能拆机器人改轮子!),所以说,在我们的可能范围之内,我们已经做到了极致,虽然可能幸运女神并不眷顾我们,但是我们也算是尽到自己的最大努力去认真的做,认真的负责,认真的努力,最后认认真真的坚持了,说的遗憾也是有的,可能一个过程永远不会是完美吧。

收尾结束--致敬一直坚持的我们_第1张图片 '大蓝'  机器人

大约是在去年的寒假前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的问题:

收尾结束--致敬一直坚持的我们_第2张图片 python2.7 opencv相关问题

 具体解决方法是通过python的os操作,删除cv2.so这个文件,然后就可以没有冲突的运行这个检测程序了,如果你觉得删除文件不放心(duck不必),因为经过测试,这个文件会重新生成,所以可以在防止冲突的时候直接删除,很是玄学(是我不懂,大佬可以在评论区交流),然后在conda运行的时候,也是需要在他的bash文件进行修改的,具体目的就是让conda能够顺利启动,要不然可能会报没有source这个错误(时间太长,已经记不清当时怎么改的了555),就先不贴了,解决这个问题后就能顺利开始运行人脸检测了,效果嘎嘎好,哦对,你还需要搭好paddle的环境,在conda中安装paddle,我相信这不会是问题,采用paddlehub,去飞浆官网直接搜索用就可,教程也很是不错,预训练模型贼好用(轻量+准确),在此宣传一波飞浆yyds!

收尾结束--致敬一直坚持的我们_第3张图片 开天眼

  人脸检测在此优化完成,如何协调到你的机器人程序中,大家自行调试吧。

  接下来就是抓取的问题,一开始对于物品的抓取不是很准确,怎么调整都是出问题,且不能识别两个平面进行不同高度的抓取,于是最后决定采用深度学习来进行物品识别,并通过物品识别框计算平面位置,通过深度摄像头估算相关距离来进行抓取,好吧,再来一波paddle,这次是采用的paddleclas,飞桨图像识别套件PaddleClas是飞桨为工业界和学术界所准备的一个图像识别任务的工具集,助力使用者训练出更好的视觉模型和应用落地。模型自行去寻找吧,这边采用了轻量级的识别与检测模型,在预训练模型的基础上,对可能用到的商品进行了训练,训练完后的模型进行推理预测,而其最大的一个优势就是,对于新的未经训练过的商品,无需重新训练,在导入其图片以及构建索引库之后可以直接进行识别,准确率在百分之六七十左右,划重点!!!无需重新训练!!!

模型文件
ps:此为官方直接下载的预训练模型,自己的推理模型需要自行训练

 在此就只贴一下预测的代码吧,对于其一些以来文件自行去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博客-领域博主

你可能感兴趣的:(笔记,人工智能,paddlepaddle,opencv,计算机视觉)