草庐IT

python - 图像处理:实时FedEx Logo 检测器的算法改进

coder 2023-08-14 原文

我一直在从事涉及徽标检测图像处理的项目。具体来说,目标是为实时FedEx卡车/徽标检测器开发一个自动化系统,该系统可从IP摄像机流中读取帧并发送检测通知。这是运行中的系统的示例,其中已识别的徽标被绿色矩形包围。





对项目的一些限制:

  • 使用原始OpenCV(不使用深度学习,AI或经过训练的神经网络)
  • 图像背景可能很嘈杂
  • 图像的亮度变化很大(早晨,下午,晚上)
  • 联邦 express 卡车/徽标可以具有任何比例,旋转或方向,因为它可以停在人行道上的任何地方
  • 根据一天中的时间,徽标可能会变得模糊或模糊,并具有不同的阴影
  • 在同一帧中可能还有许多其他尺寸或颜色相似的车辆
  • 实时检测(来自IP摄像机的〜25 FPS)
  • IP摄像机处于固定位置,FedEx卡车将始终处于相同方向(切勿向后或上下颠倒)
  • 联邦 express 卡车将始终是“红色”变体,而不是"green" variation

  • 当前实现/算法

    我有两个线程:
  • 线程#1-使用cv2.VideoCapture()从IP摄像机捕获帧并调整帧大小以进行进一步处理。由于cv2.VideoCapture()被阻塞,决定通过减少I / O延迟来在单独的线程中处理抓帧以提高FPS。通过专门用于捕获帧的独立线程,这将允许主处理线程始终具有可用于执行检测的帧。
  • 线程#2-使用颜色阈值和轮廓检测来检测FedEx徽标的主要处理/检测线程。

  • 总体伪算法
    For each frame:
        Find bounding box for purple color of logo
        Find bounding box for red/orange color of logo
        If both bounding boxes are valid/adjacent and contours pass checks:
            Combine bounding boxes
            Draw combined bounding boxes on original frame
            Play sound notification for detected logo
    

    用于徽标检测的颜色阈值

    对于颜色阈值设置,我为紫色和红色定义了HSV(低,高)阈值以检测徽标。
    colors = {
        'purple': ([120,45,45], [150,255,255]),
        'red': ([0,130,0], [15,255,255]) 
    }
    

    为了找到每种颜色的边界框坐标,我遵循以下算法:
  • 模糊框架
  • 侵 eclipse 并用内核扩展帧以消除背景噪声
  • 将帧从BGR转换为HSV颜色格式
  • 使用具有设置的颜色阈值的HSV上下边界在帧上执行遮罩
  • 在蒙版中找到最大轮廓并获得边界坐标

  • 进行遮罩后,获得徽标的这些孤立的紫色(​​左)和红色(右)部分。


    误报检查

    现在,我有了两个遮罩,然后执行检查以确保找到的边界框实际上形成徽标。为此,我使用 cv2.matchShapes() 比较两个轮廓,并返回一个显示相似度的度量。结果越低,匹配度越高。另外,我使用cv2.pointPolygonTest()来查找图像中的点与轮廓之间的最短距离,以进行其他验证。我的误报过程涉及:
  • 检查边界框是否有效
  • 确保两个边界框基于它们的相对接近度相邻

  • 如果边界框通过了邻接和相似性度量标准测试,则边界框将被合并并触发FedEx通知。

    结果




    由于存在许多误报和失败检测,因此该检查算法并不是真正可靠的算法。例如,这些误报被触发。




    尽管此颜色阈值和轮廓检测方法在徽标清晰的基本情况下有效,但在某些方面仍然严重缺乏:
  • 由于必须在每个帧上计算边界框,因此存在延迟问题
  • 偶尔会检测到不存在徽标的情况
  • 亮度和一天中的时间对检测精度有很大影响
  • 当徽标倾斜时,颜色阈值检测有效,但由于检查算法而无法检测到徽标。

  • 谁能帮助我改善算法或提出替代检测策略?由于颜色阈值高度依赖于精确校准,还有其他方法可以执行此检测吗?如果可能的话,我不想使用颜色阈值和多层滤镜,因为它不是很可靠。任何见解或建议,我们将不胜感激!

    最佳答案

    您可能要看一下功能匹配。目标是在两个图像(模板图像和嘈杂的图像)中找到特征并将其匹配。这样,您就可以在嘈杂的图像(相机图像)中找到模板(徽标)。

    本质上,特征是人类会在图像中发现有趣的事物,例如角落或开放空间。我建议使用尺度不变特征变换(SIFT)作为特征检测算法。我建议使用SIFT的原因是,它对于图像的平移,缩放和旋转是不变的,对于照明变化部分不变,并且对于局部几何失真也很稳定。这符合您的规范。

    我使用从OpenCV docs文档中修改的关于SIFT特征检测的代码生成了上述图像:

    import numpy as np
    import cv2
    from matplotlib import pyplot as plt
    
    img = cv2.imread('main.jpg',0)  # target Image
    
    # Create the sift object
    sift = cv2.xfeatures2d.SIFT_create(700)
    
    # Find keypoints and descriptors directly
    kp, des = sift.detectAndCompute(img, None)
    
    # Add the keypoints to the final image
    img2 = cv2.drawKeypoints(img, kp, None, (255, 0, 0), 4)
    
    # Show the image
    plt.imshow(img2)
    plt.show()
    

    在执行此操作时,您会注意到FedEx徽标上有大量功能(上)。

    我要做的下一件事是尝试将视频供稿中的功能与FedEx徽标中的功能进行匹配。我使用FLANN功能匹配器完成了此操作。您可能采用了许多方法(包括蛮力),但是由于您正在处理视频提要,因此这可能是您的最佳选择。以下代码从OpenCV docs的功能匹配中得到启发:
    import numpy as np
    import cv2
    from matplotlib import pyplot as plt
    
    logo = cv2.imread('logo.jpg', 0) # query Image
    img = cv2.imread('main2.jpg',0)  # target Image
    
    
    # Create the sift object
    sift = cv2.xfeatures2d.SIFT_create(700)
    
    # Find keypoints and descriptors directly
    kp1, des1 = sift.detectAndCompute(img, None)
    kp2, des2 = sift.detectAndCompute(logo,None)
    
    # FLANN parameters
    FLANN_INDEX_KDTREE = 1
    index_params = dict(algorithm = FLANN_INDEX_KDTREE, trees = 5)
    search_params = dict(checks=50)   # or pass empty dictionary
    flann = cv2.FlannBasedMatcher(index_params,search_params)
    matches = flann.knnMatch(des1,des2,k=2)
    
    # Need to draw only good matches, so create a mask
    matchesMask = [[0,0] for i in range(len(matches))]
    
    # ratio test as per Lowe's paper
    for i,(m,n) in enumerate(matches):
        if m.distance < 0.7*n.distance:
            matchesMask[i]=[1,0]
    
    # Draw lines
    draw_params = dict(matchColor = (0,255,0),
                       singlePointColor = (255,0,0),
                       matchesMask = matchesMask,
                       flags = 0)
    
    
    # Display the matches
    img3 = cv2.drawMatchesKnn(img,kp1,logo,kp2,matches,None,**draw_params)
    plt.imshow(img3, )
    plt.show()
    

    使用此功能,我可以匹配以下功能,如下所示。您会发现有异常值。但是,大多数功能都可以匹配:



    然后,最后一步将是简单地在此图像周围绘制一个边界框。我将您链接到另一个stack overflow question,它的功能类似于orb检测器。这是使用OpenCV docs获取边界框的另一种方法。

    我希望这有帮助!

    关于python - 图像处理:实时FedEx Logo 检测器的算法改进,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55466089/

    有关python - 图像处理:实时FedEx Logo 检测器的算法改进的更多相关文章

    1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

      关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

    2. ruby - 如何指定 Rack 处理程序 - 2

      Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

    3. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

      我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

    4. ruby-on-rails - 添加回形针新样式不影响旧上传的图像 - 2

      我有带有Logo图像的公司模型has_attached_file:logo我用他们的Logo创建了许多公司。现在,我需要添加新样式has_attached_file:logo,:styles=>{:small=>"30x15>",:medium=>"155x85>"}我是否应该重新上传所有旧数据以重新生成新样式?我不这么认为……或者有什么rake任务可以重新生成样式吗? 最佳答案 参见Thumbnail-Generation.如果rake任务不适合你,你应该能够在控制台中使用一个片段来调用重新处理!关于相关公司

    5. Python 相当于 Perl/Ruby ||= - 2

      这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。

    6. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

      什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

    7. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

      华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

    8. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

      我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

    9. 「Python|Selenium|场景案例」如何定位iframe中的元素? - 2

      本文主要介绍在使用Selenium进行自动化测试或者任务时,对于使用了iframe的页面,如何定位iframe中的元素文章目录场景描述解决方案具体代码场景描述当我们在使用Selenium进行自动化测试的时候,可能会遇到一些界面或者窗体是使用HTML的iframe标签进行承载的。对于iframe中的标签,如果直接查找是无法找到的,会抛出没有找到元素的异常。比如近在咫尺的例子就是,CSDN的登录窗体就是使用的iframe,大家可以尝试通过F12开发者模式查看到的tag_name,class_name,id或者xpath来定位中的页面元素,会抛出NoSuchElementException异常。解决

    10. ruby-on-rails - 在 Ruby (on Rails) 中使用 imgur API 获取图像 - 2

      我正在尝试使用Ruby2.0.0和Rails4.0.0提供的API从imgur中提取图像。我已尝试按照Ruby2.0.0文档中列出的各种方式构建http请求,但均无济于事。代码如下:require'net/http'require'net/https'defimgurheaders={"Authorization"=>"Client-ID"+my_client_id}path="/3/gallery/image/#{img_id}.json"uri=URI("https://api.imgur.com"+path)request,data=Net::HTTP::Get.new(path

    随机推荐