[英]Image Processing: Algorithm Improvement for Real-Time FedEx Logo Detector
我一直致力於一個涉及圖像處理的徽標檢測項目。 具體而言,目標是為實時FedEx卡車/徽標檢測器開發自動化系統,該檢測器從IP攝像機流中讀取幀並在檢測時發送通知。 以下是綠色矩形中包含識別徽標的系統示例。
對項目的一些限制:
當前的實現/算法
我有兩個主題:
cv2.VideoCapture()
從IP攝像機捕獲幀並調整幀大小以進行進一步處理。 決定在單獨的線程中處理抓取幀,以通過減少因cv2.VideoCapture()
阻塞而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的原因是它對於圖像平移,縮放和旋轉是不變的,對於光照變化是部分不變的並且對局部幾何失真是魯棒的。 這符合您的規格。
我使用從SIFT特征檢測的OpenCV docs文檔修改的代碼生成了上面的圖像:
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徽標上方(上圖)。
我接下來要做的是嘗試將視頻Feed中的功能與FedEx徽標中的功能相匹配。 我是使用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()
使用這個我能夠獲得以下匹配的以下功能。 你會注意到有異常值。 但是大多數功能都匹配:
最后一步是簡單地在該圖像周圍繪制一個邊界框。 我將鏈接到另一個堆棧溢出問題 ,它使用orb檢測器執行類似的操作。 這是使用OpenCV文檔獲取邊界框的另一種方法。
我希望這有幫助!
您可以幫助探測器預處理圖像,然后您不需要那么多的訓練圖像。
首先,我們減少桶形失真。
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)
然后我們轉換圖像的方式就像攝像機正對着FedEx卡車一樣。 這就是卡車停在路邊的地方,聯邦快遞的標志將具有幾乎相同的尺寸和方向。
# 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]))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.