图像处理:实时联邦快递标识检测的算法改进

7 浏览
0 Comments

图像处理:实时联邦快递标识检测的算法改进

我一直在做一个涉及图像处理的Logo检测项目。具体来说,目标是开发一个实时快递物流的自动化系统,该系统从IP相机流中读取画面并在检测到物流车和Logo时发送通知。以下是系统的一些操作实例,其中包含了在绿色矩形框内识别出来的Logo。

\"原始图像\"

\"Fedex

该项目的一些限制:

  • 仅使用原生的OpenCV(无深度学习、AI或经过训练的神经网络)
  • 图像背景可能会噪声干扰
  • 图像亮度可能会有很大变化(清晨、下午、晚上)
  • 快递物流车/Logo可以具有任何比例、旋转或方向,因为它可能停在人行道的任何地方
  • Logo可能会有不同的阴影和模糊程度,具体取决于时间的变化
  • 在同一帧中可能会有许多其他具有相似大小或颜色的车辆
  • 实时检测(IP相机的帧率为25 FPS)
  • IP相机处于固定位置,快递物流车将始终处于相同的方向位置(永远不会倒置或倒立)
  • 快递车将始终是“红色”版本,而不是“绿色”版本

当前实现/算法

我有两个线程:

  • 线程 #1 - 使用 cv2.VideoCapture()捕获IP相机的帧并调整帧大小以便进一步处理。决定在单独的线程中处理抓取帧以通过减少I / O延迟来提高FPS,因为 cv2.VideoCapture()是阻塞式的。通过为捕获帧专门分配独立的线程,这将允许主处理线程始终有一个可用的帧来执行检测。
  • 线程#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]) 
}

要查找每种颜色的边界框坐标,我遵循以下算法:

  • 对帧进行模糊处理
  • 使用核对帧进行腐蚀和膨胀以去除背景噪声
  • 将帧从BGR转换为HSV颜色格式
  • 使用设置的颜色阈值在帧上执行掩码
  • 在蒙版中查找最大轮廓并获取边界坐标

执行掩码后,我获得了标志的这些分离的紫色(左侧)和红色(右侧)部分。

虚假阳性检查

现在我有了这两个掩码,我执行检查以确保找到的边界框实际上形成一个标志。为此,我使用cv2.matchShapes()进行比较并返回显示相似性的度量标准。结果越低,匹配度越高。此外,我还使用cv2.pointPolygonTest(),这会找到图像中的点与轮廓之间的最短距离以进行额外的验证。我的虚假阳性处理过程包括:

  • 检查边框是否有效
  • 根据它们的相对距离确保两个边界框是相邻的

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

结果

\"enter

\"enter

这个检查算法并不是非常稳健,因为有很多误报和未检测到的情况。例如,这些误报被触发了。

\"enter

\"enter

虽然这种颜色阈值和轮廓检测方法在标志清晰的基本案例中起作用,但在一些领域严重不足:

  • 每一帧都要计算边界框,存在延迟问题
  • 有时会误检测,当标志不在场时
  • 亮度和时间对检测精度有很大影响
  • 当徽标处于倾斜角度时,颜色阈值检测起作用,但由于检查算法而无法检测到徽标。

是否有人能帮助我改进我的算法或建议替代检测策略?是否有其他方法可以执行这种检测,因为颜色阈值高度依赖于精确的校准?如果可能,我希望摆脱颜色阈值和多层过滤器,因为它不太稳健。任何见解或建议都将不胜感激!

admin 更改状态以发布 2023年5月21日
0
0 Comments

你可以通过对图像进行预处理来帮助探测器,这样就不需要那么多的训练图像了。

enter image description here

首先我们减少桶形畸变。

import cv2
img = cv2.imread('fedex.jpg')
margin = 150
# add border as the undistorted image is going to be larger
img = cv2.copyMakeBorder(
                 img, 
                 margin, 
                 margin, 
                 margin, 
                 margin, 
                 cv2.BORDER_CONSTANT, 
                 0)
import numpy as np
width  = img.shape[1]
height = img.shape[0]
distCoeff = np.zeros((4,1), np.float64)
k1 = -4.5e-5;
k2 = 0.0;
p1 = 0.0;
p2 = 0.0;
distCoeff[0,0] = k1;
distCoeff[1,0] = k2;
distCoeff[2,0] = p1;
distCoeff[3,0] = p2;
cam = np.eye(3, dtype=np.float32)
cam[0,2] = width/2.0  # define center x
cam[1,2] = height/2.0 # define center y
cam[0,0] = 12.        # define focal length x
cam[1,1] = 12.        # define focal length y
dst = cv2.undistort(img, cam, distCoeff)

enter image description here

然后我们以一种方式转换图像,就像摄像机正对着联邦快递卡车一样。也就是说,无论卡车停放在路缘的哪个位置,联邦快递标志的大小和方向几乎相同。

# use four points for homography estimation, coordinated taken from undistorted image
# 1. top-left corner of F
# 2. bottom-left corner of F
# 3. top-right of E
# 4. bottom-right of E
pts_src = np.array([[1083, 235], [1069, 343], [1238, 301],[1201, 454]])
pts_dst = np.array([[1069, 235],[1069, 320],[1201, 235],[1201, 320]])
h, status = cv2.findHomography(pts_src, pts_dst)
im_out = cv2.warpPerspective(dst, h, (dst.shape[1], dst.shape[0]))

0
0 Comments

您可能想要查看特征匹配。目标是在两个图像(一个模板图像和一个嘈杂图像)中查找特征并将其匹配。这将允许您在嘈杂图像(相机图像)中找到模板(logo)。

特征本质上是人类在图像中感到有趣的事物,例如角落或开放的空间。我建议使用尺度不变特征变换(SIFT)作为特征检测算法。我建议使用SIFT的原因是它不受图像平移、缩放和旋转的影响,对光照变化部分具有不变性并且对局部几何畸变具有强大的鲁棒性。这符合您的规格要求。

特征检测示例

我使用修改自OpenCV文档关于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()

当您进行此操作时,您将注意到大量的特征落在联邦快递的标志上(上面的图像)。

接下来我尝试将视频源中的特征与联邦快递标志的特征匹配。我使用了FLANN特征匹配器来实现这一点。您可以选择许多方法(包括暴力方法),但由于您正在使用视频源,这可能是您最好的选择。下面的代码受到OpenCV文档关于特征匹配的启示:

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()

使用这种方法,我成功将下面看到的特征匹配。您会注意到有离群值。但大多数特征匹配:

标志匹配

最后一步就是在图像周围简单地绘制边界框。我会链接您到另一个stackoverflow问题,它使用ORB探测器进行类似操作。这是通过OpenCV文档的另一种方法获得边界框。

希望这有所帮助!

0