Mask-R CNN从初学者到专业人士


一旦我需要分析来自图像和输出的信息以了解对象的类型,对象的类型以及分析帧的集合,就需要给出对象的标识符以及在帧中花费的时间,有必要确定对象的移动方式以及哪些摄像机可以进入视野。 让我们从头两个开始,下一部分将讨论总体人员分析。


好吧,我们将更详细地描述我们的任务:


  • 修复人员和汽车-在图像中选择它们并使用必要的字段生成相应的类实例。
  • 确定汽车的编号(如果它落入特定摄像机的框架中)
  • 将当前框架与前一个框架进行比较,以确保对象相等,以便我们找出

好吧,我想,然后捡起一条厚实的蛇蟒蛇。 决定结合其简单性和现代性来使用Mask R-Cnn神经网络。 另外,当然,我们将使用OpenCV进行图像处理。


环境设定


我们将使用Windows 10,因为您最有可能使用它。
据了解,您已经拥有64位Python。 如果没有,那么您可以例如从此处下载软件包


套件安装


git clone https://github.com/matterport/Mask_RCNN cd Mask_RCNN pip3 install -r requirements.txt python3 setup.py install 

如果由于某种原因无法从源代码进行编译,则有一个来自pip的版本:


 pip3 install mrcnn --user 

该软件包当然带有所有依赖项


阶段1.创建一个简单的识别器。


我们将进行必要的进口


 import os import cv2 import mrcnn.config import mrcnn from mrcnn.model import MaskRCNN 

神经网络需要使用覆盖字段创建配置


 class MaskRCNNConfig(mrcnn.config.Config): NAME = "coco_pretrained_model_config" GPU_COUNT = 1 IMAGES_PER_GPU = 1 DETECTION_MIN_CONFIDENCE = 0.8 #     NUM_CLASSES = 81 

用比例尺指示文件的位置。 在此示例中,它将位于此文件的文件夹中。 如果不是,则将下载。


 import mrcnn.utils DATASET_FILE = "mask_rcnn_coco.h5" if not os.path.exists(DATASET_FILE): mrcnn.utils.download_trained_weights(DATASET_FILE) 

让我们使用上面的设置创建模型


 model = MaskRCNN(mode="inference", model_dir="logs", config=MaskRCNNConfig()) model.load_weights(DATASET_FILE, by_name=True) 

也许我们将开始处理当前目录中images目录中的所有图像。


 IMAGE_DIR = os.path.join(os.getcwd(), "images") for filename in os.listdir(IMAGE_DIR): image = cv2.imread(os.path.join(IMAGE_DIR, filename)) rgb_image = image[:, :, ::-1] detections = model.detect([rgb_image], verbose=1)[0] 

我们在检测中会看到什么?


  print(detections) 

例如,类似的内容:


 {'rois': array([[ 303, 649, 542, 1176],[ 405, 2, 701, 319]]), 'class_ids': array([3, 3]), 'scores': array([0.99896, 0.99770015], dtype=float32), 'masks': array()} 

在这种情况下,找到了2个对象。
rois左下角和右上角的坐标数组
class_ids是找到的对象的数字标识符,而我们需要知道1是一个人,3是一辆汽车,8是卡车。
scores -只要模型对解决方案有信心,就可以通过配置中的DETECTION_MIN_CONFIDENCE出该参数,从而消除所有不合适的选项。
masks对象的轮廓。 数据用于绘制对象蒙版。 因为 它们非常庞大,并且不打算供人类理解;在本文中,我不会引用它们。


好的,我们可以在这里停下来,但是我们想看看指导使用神经网络的图像,通常选择精美的物体发出?


调用函数mrcnn.visualize.display_instances会更简单,但是我们不会这样做,我们将编写自己的函数。


该函数将拍摄图像,并从第一步开始从字典中获取主要参数。


 def visualize_detections(image, masks, boxes, class_ids, scores): import numpy as np bgr_image = image[:, :, ::-1] CLASS_NAMES = ['BG',"person", "bicycle", "car", "motorcycle", "bus", "truck"] COLORS = mrcnn.visualize.random_colors(len(CLASS_NAMES)) for i in range(boxes.shape[0]): y1, x1, y2, x2 = boxes[i] classID = class_ids[i] label = CLASS_NAMES[classID] font = cv2.FONT_HERSHEY_DUPLEX color = [int(c) for c in np.array(COLORS[classID]) * 255] text = "{}: {:.3f}".format(label, scores[i]) size = 0.8 width = 2 cv2.rectangle(bgr_image, (x1, y1), (x2, y2), color, width) cv2.putText(bgr_image, text, (x1, y1-20), font, size, color, width) 


源图像


尽管此神经网络的主要优点之一是解决了实例分割的问题-获取对象的轮廓,但我们尚未使用它,我们将对其进行分析。


要实现蒙版,在为找到的每个对象绘制矩形之前,添加几行。


 mask = masks[:, :, i] #   image = mrcnn.visualize.apply_mask(image, mask, color, alpha=0.6) #   

结果:


白色口罩版


第二阶段。 最初的成功。 识别汽车数量。


为了识别,我们需要在附近有一个清晰的车架,因此决定只从检查站拍摄车架,然后将它们与相似度进行比较(下一章将对此进行详细介绍)。 但是,这种方法会带来太多的不准确性,因为 机器在视觉上可能非常相似,而我的算法仍无法避免这种情况。


决定使用来自乌克兰制造商nomeroff-net的现成库(非广告)。 因为 几乎所有的代码都可以在该模型的示例中找到,然后我将不给出完整的描述。


我只能说此功能可以从原始图像开始,也可以将识别出的机器切出框架并传递给该功能。


 import sys import matplotlib.image as mpimg import os sys.path.append(cfg.NOMEROFF_NET_DIR) from NomeroffNet import filters, RectDetector, TextDetector, OptionsDetector, Detector, textPostprocessing nnet = Detector(cfg.MASK_RCNN_DIR, cfg.MASK_RCNN_LOG_DIR) nnet.loadModel("latest") rectDetector = RectDetector() optionsDetector = OptionsDetector() optionsDetector.load("latest") textDetector = TextDetector.get_static_module("ru")() textDetector.load("latest") def detectCarNumber(imgPath: str) -> str: img = mpimg.imread(imgPath) NP = nnet.detect([img]) cvImgMasks = filters.cv_img_mask(NP) arrPoints = rectDetector.detect(cvImgMasks) zones = rectDetector.get_cv_zonesBGR(img, arrPoints) regionIds, stateIds, _c = optionsDetector.predict(zones) regionNames = optionsDetector.getRegionLabels(regionIds) # find text with postprocessing by standart textArr = textDetector.predict(zones) textArr = textPostprocessing(textArr, regionNames) return textArr 

输出的textArr将表示一个字符串数组,其中包含在框架中找到的机器数,例如:
["293163"][""][] -如果找不到匹配的数字。


第三阶段。 通过相似性识别对象。


现在,我们需要了解如何修复一次对象,以了解下一帧中的对象。 在此阶段,我们将假设我们只有一个摄像头,并且仅区分其中的不同帧。


为此,您需要找出我们如何比较两个对象。


为此,我将提出一个筛选算法。 我们保留它不是OpenCV主体部分的保留,因此我们需要另外交付contrib模块。 不幸的是,该算法已申请专利,并且在商业程序中的使用受到限制。 但是我们专注于研究活动,对吗?


 pip3 install opencv-contrib-python --user 

~~重载运算符== ~~我们编写了一个函数,该函数以矩阵形式获取2个比较对象。 例如,我们在调用函数cv2.open(path)后得到它们


我们将编写算法的实现。


 def compareImages(img1, img2) -> bool: sift = cv2.xfeatures2d.SIFT_create() 

使用SIFT查找关键点和描述符。 也许我不会为这些功能提供帮助,因为您总是可以在交互式外壳程序中将其作为help(somefunc)来调用


  kp1, des1 = sift.detectAndCompute(img1, None) kp2, des2 = sift.detectAndCompute(img2, None) 

设置我们的算法。


  FLANN_INDEX_KDTREE = 0 indexParams = dict(algorithm=FLANN_INDEX_KDTREE, trees=5) searchParams = dict(checks=50) flann = cv2.FlannBasedMatcher(indexParams, searchParams) 

现在运行它。


  matches = flann.knnMatch(des1, des2, k=2) 

计算图像之间的相似度。


  matchesCount = 0 for m, n in matches: if m.distance < cfg.cencitivity*n.distance: matchesCount += 1 return matchesCount > cfg.MIN_MATCH_COUNT 

现在,尝试使用它
为此,在检测到对象后,我们需要将其从原始图像中剪切下来


我写不出比保存它慢的内存更好的东西,然后从那里读取。


  def extractObjects(objects, binaryImage, outputImageDirectory, filename=None): for item in objects: y1, x1, y2, x2 = item.coordinates #       cropped = binaryImage[y1:y2, x1:x2] beforePoint, afterPoint = filename.split(".") outputDirPath = os.path.join(os.path.split(outputImageDirectory)[0], "objectsOn" + beforePoint) if not os.path.exists(outputDirPath): os.mkdir(outputDirPath) coordinates = str(item).replace(" ", ",") pathToObjectImage = "{}{}.jpg".format(item.type, coordinates) cv2.imwrite(os.path.join(outputDirPath, str(pathToObjectImage)), cropped) 

现在我们在<outputImageDirectory>/objectsOn<imageFilename>拥有对象


现在,如果我们至少有2个这样的目录,则可以比较其中的对象。 运行之前编写的函数


 if compareImages(previousObjects, currentObjects): print(“  !”) 

或者,我们可以执行其他操作,例如使用相同的标识符标记这些对象。


当然,像所有神经网络一样,这一网络有时会给出错误的结果。


通常,我们已经完成了开始时设置的3个任务,因此我们将四舍五入。 我怀疑本文是否引起了至少编写了一个解决图像识别/图像分割问题程序的人的注意,但是我希望我能帮助至少一个新手开发人员。


该项目的完整源代码可以在这里找到。

Source: https://habr.com/ru/post/zh-CN483018/


All Articles