我一直在从事涉及徽标检测图像处理的项目。具体来说,目标是为实时FedEx卡车/徽标检测器开发一个自动化系统,该系统可从IP摄像机流中读取帧并发送检测通知。这是运行中的系统的示例,其中已识别的徽标被绿色矩形包围。
对项目的一些限制:
当前实现/算法
我有两个线程:
cv2.VideoCapture()
从IP摄像机捕获帧并调整帧大小以进行进一步处理。由于cv2.VideoCapture()
被阻塞,决定通过减少I / O延迟来在单独的线程中处理抓帧以提高FPS。通过专门用于捕获帧的独立线程,这将允许主处理线程始终具有可用于执行检测的帧。 总体伪算法
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])
}
为了找到每种颜色的边界框坐标,我遵循以下算法:
进行遮罩后,获得徽标的这些孤立的紫色(左)和红色(右)部分。
误报检查
现在,我有了两个遮罩,然后执行检查以确保找到的边界框实际上形成徽标。为此,我使用
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/