2011-10-24 70 views
6

另一圖像I有一個包含一個對象,如以下圖像中的耳環的樣本圖像:檢測是否從一個圖像中的對象與OpenCV的

http://imgur.com/luj2Z

我然後有一個大的候選圖像設置爲我需要確定哪一個最有可能包含對象,如:

http://imgur.com/yBWgc

所以我需要產生分數爲每個圖像,其中最高分數對應於最有可能包含目標對象的圖像。現在,在這種情況下,我可以使用以下條件/限制:

1)我可以在不同角度獲得多個樣本圖像。

2)樣本圖像可能與候選圖像處於不同的分辨率,角度和距離。

3)有很多候選圖像(> 10,000),所以它必須相當快。

4)我願意犧牲一些速度的精度,所以如果這意味着我們必須搜索前100名而不是前10名,這很好,可以手動完成。

5)我可以手動操作樣本圖像,例如概述我想檢測的對象;由於候選圖像太多,無法手動操作。

6)我在OpenCV或計算機視覺方面根本沒有真正的背景,所以我從頭開始。

我最初的想法是首先在樣本圖像中圍繞對象繪製粗略輪廓。然後,我可以識別候選圖像中的物體角落和角落。我可以分析每個角落周圍的像素,看看它們是否相似,然後按照每個角落最大相似性分數的總和排名。我也不確定如何量化相似的像素。我想他們的RGB值的歐幾里得距離?

問題就在於它忽略了對象的中心。在上面的例子中,如果耳環的角落都在金框附近,那麼它就不會考慮耳環內的紅色,綠色和藍色寶石。我想我可以通過查看所有角落對並通過對它們之間沿線的一些點進行採樣來確定相似度來改善此情況。

所以,我有幾個問題:

A)請問這種思路的意義,一般還是有我丟失的東西? B)我應該調查哪些來自OpenCV的特定算法?我知道有多個角點檢測算法,但我只需要一個,如果差異都在邊緣優化,那麼我用最快的速度就可以了。

C)使用算法有助於我理解的任何示例代碼?

我的語言選項是Python或C#。

回答

4

查看SURF功能,它們是openCV的一部分。這裏的想法是,你有一個算法來找到兩個圖像中的「興趣點」。您還有一個算法來計算每個興趣點周圍圖像塊的描述符。通常這個描述符捕獲補丁中邊緣方向的分佈。然後你嘗試找到點對應,我。即對於圖像A中的每個興趣點嘗試在圖像B中找到相應的興趣點。這通過比較描述符並尋找最接近的匹配來完成。然後,如果您有一組通過某種幾何變換相關的對應關係,則會發現一個對象。

當然,這是一個非常高層次的解釋。魔鬼在細節中,對於那些你應該閱讀一些文件。從David Lowe開始Distinctive image features from scale-invariant keypoints,然後閱讀SURF上的論文。

另外,還要考慮這個問題,移動至Signal and Image Processing Stack Exchange

0

至於說,像SIFT和SURF算法包含的特徵點,這是不變的一些扭曲和描述符,其目的是穩健的模型特徵點的環境。

後者越來越多地用於圖像分類和識別中,通常稱爲「包字」或「視覺詞」方法。

以最簡單的形式,可以從所有圖像中的所有描述符中收集所有數據並對它們進行聚類,例如使用k-means。然後每個原始圖像都有描述符,這些描述符對多個聚類有貢獻。這些聚類的質心,即視覺詞,可以用作圖像的新描述符。然後這些可以在具有倒排文件設計的體系結構中使用。

該方法允許軟匹配和一定量的概括,例如用飛機檢索所有圖像。

  • VLfeat website包含,旁邊有一個良好的SIFT庫,這種方法的一個很好的演示,加州理工學院的101數據集進行分類。

  • Caltech本身提供Matlab/C++軟件和相關出版物。

  • 也是一個良好的開端是LEAR

5

工作倖運的是,來自OpenCV的那種傢伙只是做對於你。檢查您的示例文件夾「opencv \ samples \ cpp \ matching_to_many_images.cpp」。編譯並嘗試使用默認圖像。

該算法可以很容易地適應,使其更快或更精確。

主要是,物體識別算法分爲兩部分:關鍵點檢測&描述和對象匹配。對於他們來說,都有很多算法/變體,你可以直接進入OpenCV。

檢測/描述可以通過:SIFT/SURF/ORB/GFTT/STAR/FAST等完成。

匹配你有:蠻力,漢明等。(有些方法是特定針對給定的檢測算法)

提示來啓動:

  • 作物您的原始圖像,因此感興趣的對象涵蓋儘可能多的圖像區域。將其用作培訓。

  • SIFT是最準確和最懶惰的描述符。 FAST是精確度和準確度的完美結合。 GFTT比較老,相當不可靠。 ORB新增加到OPENCV中,速度和準確度都非常有希望。

  • 結果取決於其他圖像中物體的姿勢。如果它被調整大小,旋轉,擠壓,部分覆蓋等,請嘗試SIFT。如果它是一個簡單的任務(即它出現在幾乎相同的大小/旋轉等等,大多數描述符會很好地處理)
  • ORB可能還沒有在OpenCV版本中。嘗試從openCV幹線下載最新版本並編譯它https://code.ros.org/svn/opencv/trunk

因此,您可以通過反覆試驗找到最適合您的組合。

有關每個實施的詳細信息,您應該閱讀原始論文/教程。谷歌學者是一個好開始

2

如果有人來到未來,這是一個小樣本與openCV做這個。它基於opencv sample,但是(在我看來),這有點更清楚,所以我也包括它。

測試了OpenCV的2.4.4

#!/usr/bin/env python 

''' 
Uses SURF to match two images. 
    Finds common features between two images and draws them 

Based on the sample code from opencv: 
    samples/python2/find_obj.py 

USAGE 
    find_obj.py <image1> <image2> 
''' 

import sys 

import numpy 
import cv2 


############################################################################### 
# Image Matching 
############################################################################### 

def match_images(img1, img2, img1_features=None, img2_features=None): 
    """Given two images, returns the matches""" 
    detector = cv2.SURF(3200) 
    matcher = cv2.BFMatcher(cv2.NORM_L2) 

    if img1_features is None: 
     kp1, desc1 = detector.detectAndCompute(img1, None) 
    else: 
     kp1, desc1 = img1_features 

    if img2_features is None: 
     kp2, desc2 = detector.detectAndCompute(img2, None) 
    else: 
     kp2, desc2 = img2_features 

    #print 'img1 - %d features, img2 - %d features' % (len(kp1), len(kp2)) 

    raw_matches = matcher.knnMatch(desc1, trainDescriptors=desc2, k=2) 
    kp_pairs = filter_matches(kp1, kp2, raw_matches) 
    return kp_pairs 


def filter_matches(kp1, kp2, matches, ratio=0.75): 
    """Filters features that are common to both images""" 
    mkp1, mkp2 = [], [] 
    for m in matches: 
     if len(m) == 2 and m[0].distance < m[1].distance * ratio: 
      m = m[0] 
      mkp1.append(kp1[m.queryIdx]) 
      mkp2.append(kp2[m.trainIdx]) 
    kp_pairs = zip(mkp1, mkp2) 
    return kp_pairs 


############################################################################### 
# Match Diplaying 
############################################################################### 

def draw_matches(window_name, kp_pairs, img1, img2): 
    """Draws the matches""" 
    mkp1, mkp2 = zip(*kp_pairs) 

    H = None 
    status = None 

    if len(kp_pairs) >= 4: 
     p1 = numpy.float32([kp.pt for kp in mkp1]) 
     p2 = numpy.float32([kp.pt for kp in mkp2]) 
     H, status = cv2.findHomography(p1, p2, cv2.RANSAC, 5.0) 

    if len(kp_pairs): 
     explore_match(window_name, img1, img2, kp_pairs, status, H) 


def explore_match(win, img1, img2, kp_pairs, status=None, H=None): 
    """Draws lines between the matched features""" 
    h1, w1 = img1.shape[:2] 
    h2, w2 = img2.shape[:2] 
    vis = numpy.zeros((max(h1, h2), w1 + w2), numpy.uint8) 
    vis[:h1, :w1] = img1 
    vis[:h2, w1:w1 + w2] = img2 
    vis = cv2.cvtColor(vis, cv2.COLOR_GRAY2BGR) 

    if H is not None: 
     corners = numpy.float32([[0, 0], [w1, 0], [w1, h1], [0, h1]]) 
     reshaped = cv2.perspectiveTransform(corners.reshape(1, -1, 2), H) 
     reshaped = reshaped.reshape(-1, 2) 
     corners = numpy.int32(reshaped + (w1, 0)) 
     cv2.polylines(vis, [corners], True, (255, 255, 255)) 

    if status is None: 
     status = numpy.ones(len(kp_pairs), numpy.bool_) 
    p1 = numpy.int32([kpp[0].pt for kpp in kp_pairs]) 
    p2 = numpy.int32([kpp[1].pt for kpp in kp_pairs]) + (w1, 0) 

    green = (0, 255, 0) 
    red = (0, 0, 255) 
    for (x1, y1), (x2, y2), inlier in zip(p1, p2, status): 
     if inlier: 
      col = green 
      cv2.circle(vis, (x1, y1), 2, col, -1) 
      cv2.circle(vis, (x2, y2), 2, col, -1) 
     else: 
      col = red 
      r = 2 
      thickness = 3 
      cv2.line(vis, (x1 - r, y1 - r), (x1 + r, y1 + r), col, thickness) 
      cv2.line(vis, (x1 - r, y1 + r), (x1 + r, y1 - r), col, thickness) 
      cv2.line(vis, (x2 - r, y2 - r), (x2 + r, y2 + r), col, thickness) 
      cv2.line(vis, (x2 - r, y2 + r), (x2 + r, y2 - r), col, thickness) 
    vis0 = vis.copy() 
    for (x1, y1), (x2, y2), inlier in zip(p1, p2, status): 
     if inlier: 
      cv2.line(vis, (x1, y1), (x2, y2), green) 

    cv2.imshow(win, vis) 

############################################################################### 
# Test Main 
############################################################################### 

if __name__ == '__main__': 
    if len(sys.argv) < 3: 
     print "No filenames specified" 
     print "USAGE: find_obj.py <image1> <image2>" 
     sys.exit(1) 

    fn1 = sys.argv[1] 
    fn2 = sys.argv[2] 

    img1 = cv2.imread(fn1, 0) 
    img2 = cv2.imread(fn2, 0) 

    if img1 is None: 
     print 'Failed to load fn1:', fn1 
     sys.exit(1) 

    if img2 is None: 
     print 'Failed to load fn2:', fn2 
     sys.exit(1) 

    kp_pairs = match_images(img1, img2) 

    if kp_pairs: 
     draw_matches('find_obj', kp_pairs, img1, img2) 
    else: 
     print "No matches found" 

    cv2.waitKey() 
    cv2.destroyAllWindows() 
+1

謝謝,這個我指出了正確的方向。欣賞它。 –