簡體   English   中英

使用OpenCV進行矩形檢測/跟蹤

[英]Rectangle detection / tracking using OpenCV

我需要的

我目前正在研究增強現實游戲。 游戲使用的控制器(我在這里談論的是物理輸入設備)是單色的矩形紙張。 我必須檢測相機的捕獲流中該矩形的位置,旋轉和大小。 檢測應在比例上不變,並且在沿X和Y軸的旋轉上不變。

如果用戶將紙張移開或移向相機,則需要縮放比例不變。 我不需要知道矩形的距離,因此比例不變會轉化為尺寸不變。

如果用戶沿矩形的局部X和/或Y軸傾斜矩形,則需要旋轉不變性。 這種旋轉將紙張的形狀從矩形更改為梯形。 在這種情況下,可以使用面向對象的邊界框來測量紙張的尺寸。

我做了什么

開始時有一個校准步驟。 窗口顯示攝像機的提要,用戶必須單擊矩形。 單擊時,將鼠標指向的像素顏色作為參考顏色。 幀被轉換為HSV顏色空間以改善顏色區分。 我有6個滑塊,用於調整每個通道的上限和下限閾值。 這些閾值用於對圖像進行二值化(使用opencv的inRange函數)。
我正在侵蝕和擴張的二值圖像噪聲去除團結nerby塊后(使用的OpenCV的erodedilate功能)。
下一步是在二進制圖像中查找輪廓(使用opencv的findContours函數)。 這些輪廓用於檢測最小的定向矩形(使用opencv的minAreaRect函數)。 最終結果是,我使用面積最大的矩形。

該程序的簡短結論:

  1. 抓框架
  2. 將該幀轉換為HSV
  3. 將其二值化(使用用戶選擇的顏色和滑塊中的閾值)
  4. 應用變形操作(腐蝕和擴張)
  5. 查找輪廓
  6. 獲取每個輪廓的最小定向裝箱
  7. 取最大的那些邊界框作為結果

您可能會注意到,我沒有利用有關紙張實際形狀的知識,只是因為我不知道如何正確使用此信息。

我還考慮過使用opencv的跟蹤算法。 但是有三個原因使我無法使用它們:

  1. 尺度不變性:據我所知,有些算法不支持對象的不同尺度。
  2. 運動預測:某些算法使用運動預測以獲得更好的性能,但是我跟蹤的對象完全是隨機運動的,因此無法預測。
  3. 簡潔性:我只是在尋找圖像中的單色矩形,沒有像汽車或人跟蹤這樣的花哨的東西。

這是一個相對不錯的捕獲(侵蝕和擴張后的二進制圖像) 好

這是一個壞人 壞

問題

一般而言,我如何才能改善檢測效果,尤其是要使其更能抵抗光照變化?

更新資料

是一些原始圖像供測試。

您不能只使用較厚的材料嗎?
是的,我可以而且我已經可以了(不幸的是,目前我無法訪問這些片段)。 但是,問題仍然存在。 即使我使用紙板等材料。 它不像紙一樣容易彎曲,但仍然可以彎曲。

如何獲得矩形的大小,旋轉和位置?
opencv的minAreaRect函數返回RotatedRect對象。 該對象包含我需要的所有數據。

注意
由於矩形是單色的,因此無法區分頂部和底部或左側和右側。 這意味着旋轉始終在[0, 180]范圍內[0, 180]這對我來說是完全可以的。 矩形的兩側之比始終為w:h > 2:1 如果矩形將是正方形,則旋轉范圍將更改為[0, 90] 0,90 [0, 90] ,但是在此可以將其視為無關緊要的。

正如評論中所建議的那樣,我將嘗試直方圖均衡化以減少亮度問題,並介紹一下ORB,SURF和SIFT。

我將更新進度。

我知道自問這個問題已經有一段時間了。 我最近繼續討論該主題並解決了我的問題(盡管不是通過矩形檢測)。

變化

  • 使用木頭來增強我的控制器(“矩形”),如下所示。
  • 在每個控制器上放置2個ArUco標記。

控制者

怎么運行的

  • 將框架轉換為灰度,
  • 下采樣(以提高檢測過程中的性能),
  • 使用cv::equalizeHist直方圖
  • 使用cv::aruco::detectMarkers查找標記,
  • 關聯標記(如果有多個控制器),
  • 分析標記(位置和旋轉),
  • 計算結果並進行一些糾錯。

事實證明,標記檢測對於照明變化和不同的視角非常強大,這使我可以跳過任何校准步驟。

我在每個控制器上放置了2個標記,以進一步提高檢測的魯棒性。 兩種標記僅需檢測一次(以測量它們之間的相關性)。 之后,每個控制器僅找到一個標記就足夠了,因為可以從先前計算的相關性中推斷出另一個標記。

這是在明亮環境下的檢測結果:

在明亮的環境中檢測

在更黑暗的環境中:

在黑暗環境中檢測

並且隱藏其中一個標記時(藍點表示推斷的標記位置):

檢測缺失的標記

失敗的

我實施的初始形狀檢測效果不佳。 照明變化非常脆弱。 此外,它需要一個初始校准步驟。

在使用形狀檢測方法之后,我嘗試將SIFT和ORB與蠻力和knn匹配器結合使用以提取和定位框架中的特征。 事實證明,單色對象沒有提供太多關鍵點(令人驚訝)。 無論如何,SIFT的性能都很糟糕(540p時約為10 fps)。 我在控制器上畫了一些線和其他形狀,這導致更多的關鍵點出現。 但是,這並沒有帶來巨大的改進。

HSV空間中的H通道是色相,並且對光線變化不敏感。 紅色范圍約為[150,180]。

根據上述信息,我進行以下工作。

  1. 切換到HSV空間,分割H通道,對閾值進行歸一化。
  2. 應用變形操作(打開)
  3. 查找輪廓,並按某些屬性(寬度,高度,面積,比率等)過濾。

PS。 由於網絡原因,我無法提取您在保管箱上載的圖像。 因此,我僅將第二張圖像的右側的 crop作為輸入。

在此處輸入圖片說明

imgname = "src.png"
img = cv2.imread(imgname)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

## Split the H channel in HSV, and get the red range
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h,s,v = cv2.split(hsv)
h[h<150]=0
h[h>180]=0

## normalize, do the open-morp-op
normed = cv2.normalize(h, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8UC1)
kernel = cv2.getStructuringElement(shape=cv2.MORPH_ELLIPSE, ksize=(3,3))
opened = cv2.morphologyEx(normed, cv2.MORPH_OPEN, kernel)
res = np.hstack((h, normed, opened))
cv2.imwrite("tmp1.png", res)

現在,我們得到如下結果(h,歸一化,打開):

在此處輸入圖片說明

然后找到輪廓並對其進行過濾。

contours = cv2.findContours(opened, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
print(len(contours))[-2]

bboxes = []
rboxes = []
cnts = []
dst = img.copy()
for cnt in contours:
    ## Get the stright bounding rect
    bbox = cv2.boundingRect(cnt)
    x,y,w,h = bbox
    if w<30 or h < 30 or w*h < 2000 or w > 500:
        continue

    ## Draw rect
    cv2.rectangle(dst, (x,y), (x+w,y+h), (255,0,0), 1, 16)

    ## Get the rotated rect
    rbox = cv2.minAreaRect(cnt)
    (cx,cy), (w,h), rot_angle = rbox
    print("rot_angle:", rot_angle)  

    ## backup 
    bboxes.append(bbox)
    rboxes.append(rbox)
    cnts.append(cnt)

結果是這樣的:

rot_angle: -2.4540319442749023
rot_angle: -1.8476102352142334

在此處輸入圖片說明

由於源圖像中的藍色矩形標簽,該卡被分為兩個側面。 但是干凈的圖像不會有問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM