使用OpenCV Python检测对象

时间:2016-12-13 12:43:17

标签: python opencv image-processing

OpenCV真的很新。我正在阅读一些教程和文档,以便制作我的第一个小脚本。

我有一张图片,我想detect objects这张照片:路灯,垃圾桶......

我的图片如下:

enter image description here

我写了这个剧本:

import cv2

img_filt = cv2.medianBlur(cv2.imread('ville.jpg',0), 5)
img_th = cv2.adaptiveThreshold(img_filt,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)
img_filt, contours, hierarchy = cv2.findContours(img_th, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

display = cv2.imshow("Objects",img_filt)
wait_time = cv2.waitKey(0)

但是如何用矩形显示图片结果?

非常感谢你!

2 个答案:

答案 0 :(得分:2)

我猜对象检测,我个人使用并向所有人推荐,是使用SIFT(Scale-Invariant Feature Transform)或SURF算法,但请注意,这些算法现已获得专利,不再包含在OpenCV 3中,仍然可以在openCV2中使用,作为替代方案,我更喜欢使用ORB,这是SIFT / SURF的开源实现。

使用SIFT描述符和比率测试进行强力匹配

这里我们使用BFMatcher.knnMatch()来获得最佳匹配。在这个例子中,我们将采用k = 2,以便我们可以在他的论文中应用D.Lowe解释的比率测试。

import numpy as np
import cv2
from matplotlib import pyplot as plt

img1 = cv2.imread('box.png',0)          # queryImage
img2 = cv2.imread('box_in_scene.png',0) # trainImage

# Initiate SIFT detector
sift = cv2.SIFT()

# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)

# BFMatcher with default params
bf = cv2.BFMatcher()
matches = bf.knnMatch(des1,des2, k=2)

# Apply ratio test
good = []
for m,n in matches:
    if m.distance < 0.75*n.distance:
        good.append([m])

# cv2.drawMatchesKnn expects list of lists as matches.
img3 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,good,flags=2)

plt.imshow(img3),plt.show()

An sample output for above code would be

继续使用基于FLANN的匹配器

  

FLANN代表近似最近邻居的快速图书馆。它   包含一组针对快速最近的算法优化的算法   邻居搜索大型数据集和高维特征。   对于大型数据集,它比BFMatcher更快。我们会看到   基于FLANN的匹配器的第二个例子。

     

对于基于FLANN的匹配器,我们需要传递两个词典   指定要使用的算法,其相关参数等   一个是IndexParams。对于各种算法,信息是   传递在FLANN文档中解释。作为总结,对于像这样的算法   SIFT,SURF等。

使用带有SIFT的FLANN的示例代码:

import numpy as np
import cv2
from matplotlib import pyplot as plt

img1 = cv2.imread('box.png',0)          # queryImage
img2 = cv2.imread('box_in_scene.png',0) # trainImage

# Initiate SIFT detector
sift = cv2.SIFT()

# find the keypoints and descriptors with SIFT
kp1, des1 = sift.detectAndCompute(img1,None)
kp2, des2 = sift.detectAndCompute(img2,None)

# FLANN parameters
FLANN_INDEX_KDTREE = 0
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 xrange(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_params = dict(matchColor = (0,255,0),
                   singlePointColor = (255,0,0),
                   matchesMask = matchesMask,
                   flags = 0)

img3 = cv2.drawMatchesKnn(img1,kp1,img2,kp2,matches,None,**draw_params)



plt.imshow(img3,),plt.show()

请参阅以下结果:

enter image description here

但我推荐的是,与ORB描述符的强力匹配

  

在此示例中,我将ORB与Bruteforce matcher一起使用,此代码捕获   来自摄像机的实时帧,并计算关键点,描述符   从输入框架中将其与存储的查询图像进行比较   做同样的事情,并返回匹配的关键点长度,   同样可以应用于使用SIFT算法代替的上述代码   ORB。

import numpy as np
import cv2
from imutils.video import WebcamVideoStream
from imutils.video import FPS

MIN_MATCH_COUNT = 10

img1 = cv2.imread('input_query.jpg', 0)


orb = cv2.ORB()
kp1, des1 = orb.detectAndCompute(img1, None)

webcam = WebcamVideoStream(src=0).start()
fps = FPS().start()

while True:
    img2 = webcam.read()
    key = cv2.waitKey(10)
    cv2.imshow('',img2)
    if key == 1048603:
        break
    kp2, des2 = orb.detectAndCompute(img2, None)

    bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)

    matches = bf.match(des1, des2)
    matches = sorted(matches, key=lambda x: x.distance)  # compute the descriptors with ORB

    if not len(matches) > MIN_MATCH_COUNT:
        print "Not enough matches are found - %d/%d" % (len(matches), MIN_MATCH_COUNT)
        matchesMask = None

    #simg2 = cv2.polylines(img2,[np.int32(dst)],True,255,3, cv2.LINE_AA)

    print len(matches)
    #img3 = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None, flags=2)

    fps.update()

fps.stop()
  

更多描述性视频教程可在此处找到,   https://www.youtube.com/watch?v=ZW3nrP2OyLQ还有一件好事   它的开源:   https://gitlab.com/josemariasoladuran/object-recognition-opencv-python.git

答案 1 :(得分:0)

我发布了代码作为答案,但它只显示过滤器检索到的轮廓。如果您的图像是B&amp; W并且不是超级复杂,那么这种类型的过滤器有利于轮廓检索。否则我认为你在寻找的是物体周围的边界框。这需要比一些过滤器更多。

我还添加了matplotlib显示,因为这是你最初要求的,但是你可以这样做不是很有用。

import cv2
import matplotlib.pyplot as plt

img_orig = cv2.imread('ville.jpg',0)
img_filt = cv2.medianBlur(img_orig, 5)
img_th = cv2.adaptiveThreshold(img_filt,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,11,2)
contours, hierarchy = cv2.findContours(img_th, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)

plt.imshow(img_orig)

cv2.drawContours(img_orig,contours,-1,(128,255,0),1)
display = cv2.imshow("Objects",img_orig)
wait_time = cv2.waitKey(0)
cv2.destroyAllWindows()

其他有用的链接: http://docs.opencv.org/3.1.0/dd/d49/tutorial_py_contour_features.html http://docs.opencv.org/3.1.0/dd/d49/tutorial_py_contour_features.html

稍后编辑一些有用的文献,可以帮助您开始进行高级对象检测,您可以在此处找到:http://www.cs.utoronto.ca/~fidler/teaching/2015/CSC2523.html

注意:这更多地涉及有意义的物体检测,而不仅仅是检测描述形状的简单轮廓。