opencv3 目标检测与识别

本文介绍了使用OpenCV3进行目标检测和识别,特别是针对汽车的检测。通过HOGDescriptor和SVM方法尝试检测人,但效果不佳。强调了汽车检测需要大量且多样化的训练数据以确保准确度,并指出负样本的选择对结果影响显著。项目涉及文件包括changefilenames.py、detector.py和sliding_window.py。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目标检测与识别技术

使用Opencv自带的HOGDescriptor函数检测人:利用的是HOG和SVM方法

import cv2
import numpy as np

def is_inside(o, i):
    ox, oy, ow, oh = o
    ix, iy, iw, ih = i
    return ox > ix and oy > iy and ox + ow < ix + iw and oy + oh < iy + ih

def draw_person(image, person):
    x, y, w, h = person
    cv2.rectangle(img, (x, y), (x + w, y + h), (0, 255, 255), 2)

img = cv2.imread("people.jpg")
hog = cv2.HOGDescriptor()
hog.setSVMDetector(cv2.HOGDescriptor_getDefaultPeopleDetector())

found, w = hog.detectMultiScale(img)#, winStride=(8,8),scale=1.05

found_filtered = []
for ri, r in enumerate(found):
    for qi, q in enumerate(found):
        if ri != qi and is_inside(r, q):
            break
    else:
        found_filtered.append(r)

for person in found_filtered:
    draw_person(img, person)

cv2.imshow("people detection", img)  
pic = cv2.resize(img, (400, 400), interpolation=cv2.INTER_CUBIC)
cv2.waitKey(0)
cv2.destroyAllWindows()

实际检测出来的效果并不好,可能是自己太菜了,还不会调


车训练集网址:http://ai.stanford.edu/~jkrause/cars/car_dataset.html


汽车检测

    为了使结果的准确度在可接受范围内,许哟啊一个足够大的数据集,包括训练推向的大小要一样

训练集:


输入:

import cv2
import numpy as np
from os.path import join

datapath = "./TrainCarImages"
def path(cls,i):
    return "%s/%s%d.jpg"  % (datapath,cls,i+1)
  
pos, neg = "pos", "neg"
#print(path(pos,0))
detect = cv2.xfeatures2d.SIFT_create()
extract = cv2.xfeatures2d.SIFT_create()

flann_params = dict(algorithm = 1, trees = 5)
matcher = cv2.FlannBasedMatcher(flann_params, {})

bow_kmeans_trainer = cv2.BOWKMeansTrainer(40)
extract_bow = cv2.BOWImgDescriptorExtractor(extract, matcher)

def extract_sift(fn):
    im = cv2.imread(fn,0)
    return extract.compute(im, detect.detect(im))[1]
  
for i in range(8):
    bow_kmeans_trainer.add(extract_sift(path(pos,i)))
    bow_kmeans_trainer.add(extract_sift(path(neg,i)))
  
voc = bow_kmeans_trainer.cluster()
extract_bow.setVocabulary( voc )

def bow_features(fn):
    im = cv2.imread(fn,0)
    return extract_bow.compute(im, detect.detect(im))

traindata, trainlabels = [],[]

for i in range(20): 
#    print(i)
    traindata.extend(bow_features(path(pos, i)))
    trainlabels.append(1)
    traindata.extend(bow_features(path(neg, i)))
    trainlabels.append(-1)

svm = cv2.ml.SVM_create()
svm.train(np.array(traindata), cv2.ml.ROW_SAMPLE, np.array(trainlabels))

def predict(fn):
    f = bow_features(fn);  
    p = svm.predict(f)
    print (fn, "\t", p[1][0][0])
    return p
  
car, notcar = "car.jpg", "dd.jpg"
car_img = cv2.imread(car)
notcar_img = cv2.imread(notcar)
car_predict = predict(car)
not_car_predict = predict(notcar)

font = cv2.FONT_HERSHEY_SIMPLEX

if (car_predict[1][0][0] == 1.0):
    cv2.putText(car_img,'Car Detected',(10,30), font, 1,(0,255,0),2,cv2.LINE_AA)
    
print('not_car_predict',not_car_predict[1][0][0])
if (not_car_predict[1][0][0] == -1.0):
    cv2.putText(notcar_img,'Car Not Detected',(10,30), font, 1,(0,0, 255),2,cv2.LINE_AA)

cv2.imshow('BOW + SVM Success', car_img)
cv2.imshow('BOW + SVM Failure', notcar_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

输出:

    在实际验证过程中发现,是否识别为Car Not Detected与负样本有很大关系,如果目标样本与负样本区别很大的话,很可能会被识别为正样本。

    造成的原因可能是负样本的单一性,以及训练集数量过少等



汽车检测:

项目结构:


changefilesname.py

import cv2
import numpy as np
from car_detector.detector import car_detector, bow_features
from car_detector.pyramid import pyramid
from car_detector.non_maximum import non_max_suppression_fast as nms
from car_detector.sliding_window import sliding_window
import urllib.request

def in_range(number, test, thresh=0.2):
    return abs(number - test) < thresh

test_image = "testcar.jpg"
#img_path = "testcars.jpg"

#urllib.urlretrieve(test_image, img_path)
#urllib.request.urlretrieve(test_image, img_path)

svm, extractor = car_detector()
detect = cv2.xfeatures2d.SIFT_create()

w, h = 100, 40
img = cv2.imread(test_image)
#img = cv2.imread(test_image)

rectangles = []
counter = 1
scaleFactor = 1.25
scale = 1
font = cv2.FONT_HERSHEY_PLAIN

for resized in pyramid(img, scaleFactor):  
  scale = float(img.shape[1]) / float(resized.shape[1])
  for (x, y, roi) in sliding_window(resized, 20, (100, 40)):
    
    if roi.shape[1] != w or roi.shape[0] != h:
      continue

    try:
      bf = bow_features(roi, extractor, detect)
      _, result = svm.predict(bf)
      a, res = svm.predict(bf, flags=cv2.ml.STAT_MODEL_RAW_OUTPUT | cv2.ml.STAT_MODEL_UPDATE_MODEL)
      print ("Class: %d, Score: %f, a: %s" % (result[0][0], res[0][0], res))
      score = res[0][0]
      if result[0][0] == 1:
        if score < -1.0:
          rx, ry, rx2, ry2 = int(x * scale), int(y * scale), int((x+w) * scale), int((y+h) * scale)
          rectangles.append([rx, ry, rx2, ry2, abs(score)])
    except:
      pass

    counter += 1 

windows = np.array(rectangles)
boxes = nms(windows, 0.25)


for (x, y, x2, y2, score) in boxes:
  print (x, y, x2, y2, score)
  cv2.rectangle(img, (int(x),int(y)),(int(x2), int(y2)),(0, 255, 0), 1)
  cv2.putText(img, "%f" % score, (int(x),int(y)), font, 1, (0, 255, 0))

cv2.imshow("img", img)
cv2.waitKey(0)

detector.py

import cv2
import numpy as np

datapath = "./TrainCarImages"

SAMPLES = 20

def path(cls,i):
    return "%s/%s%d.jpg"  % (datapath,cls,i+1)

def get_flann_matcher():
    flann_params = dict(algorithm = 1, trees = 5)
    return cv2.FlannBasedMatcher(flann_params, {})

def get_bow_extractor(extract, match):
    return cv2.BOWImgDescriptorExtractor(extract, match)

def get_extract_detect():
    return cv2.xfeatures2d.SIFT_create(), cv2.xfeatures2d.SIFT_create()

def extract_sift(fn, extractor, detector):
    im = cv2.imread(fn,0)
    return extractor.compute(im, detector.detect(im))[1]
    
def bow_features(img, extractor_bow, detector):
    return extractor_bow.compute(img, detector.detect(img))

def car_detector():
    pos, neg = "pos", "neg"
    detect, extract = get_extract_detect()
    matcher = get_flann_matcher()
    #extract_bow = get_bow_extractor(extract, matcher)
    print ("building BOWKMeansTrainer...")
    bow_kmeans_trainer = cv2.BOWKMeansTrainer(12)
    extract_bow = cv2.BOWImgDescriptorExtractor(extract, matcher)
    
    print ("adding features to trainer")
    for i in range(SAMPLES):
        print (i)
        print('path(pos,i):',path(pos,i))
        bow_kmeans_trainer.add(extract_sift(path(pos,i), extract, detect))
        #bow_kmeans_trainer.add(extract_sift(path(neg,i), extract, detect))
    
      
    vocabulary = bow_kmeans_trainer.cluster()
    extract_bow.setVocabulary(vocabulary)
    
    traindata, trainlabels = [],[]
    print ("adding to train data")
    for i in range(SAMPLES):
        print (i)
        traindata.extend(bow_features(cv2.imread(path(pos, i), 0), extract_bow, detect))
        trainlabels.append(1)
        traindata.extend(bow_features(cv2.imread(path(neg, i), 0), extract_bow, detect))
        trainlabels.append(-1)
    
    svm = cv2.ml.SVM_create()
    svm.setType(cv2.ml.SVM_C_SVC)
    svm.setGamma(1)
    svm.setC(35)
    svm.setKernel(cv2.ml.SVM_RBF)
    
    svm.train(np.array(traindata), cv2.ml.ROW_SAMPLE, np.array(trainlabels))
    return svm, extract_bow
pyramid.py
import cv2

def resize(img, scaleFactor):
    return cv2.resize(img, (int(img.shape[1] * (1 / scaleFactor)), int(img.shape[0] * (1 / scaleFactor))), interpolation=cv2.INTER_AREA)

def pyramid(image, scale=1.5, minSize=(200, 80)):
    yield image
    
    while True:
        image = resize(image, scale)
        if image.shape[0] < minSize[1] or image.shape[1] < minSize[0]:
            break
        
        yield image
non_maximum.py
# import the necessary packages
import numpy as np

# Malisiewicz et al.
# Python port by Adrian Rosebrock
def non_max_suppression_fast(boxes, overlapThresh):
  # if there are no boxes, return an empty list
  if len(boxes) == 0:
    return []

  # if the bounding boxes integers, convert them to floats --
  # this is important since we'll be doing a bunch of divisions
  if boxes.dtype.kind == "i":
    boxes = boxes.astype("float")

  # initialize the list of picked indexes 
  pick = []

  # grab the coordinates of the bounding boxes
  x1 = boxes[:,0]
  y1 = boxes[:,1]
  x2 = boxes[:,2]
  y2 = boxes[:,3]
  scores = boxes[:,4]
  # compute the area of the bounding boxes and sort the bounding
  # boxes by the score/probability of the bounding box
  area = (x2 - x1 + 1) * (y2 - y1 + 1)
  idxs = np.argsort(scores)[::-1]

  # keep looping while some indexes still remain in the indexes
  # list
  while len(idxs) > 0:
    # grab the last index in the indexes list and add the
    # index value to the list of picked indexes
    last = len(idxs) - 1
    i = idxs[last]
    pick.append(i)

    # find the largest (x, y) coordinates for the start of
    # the bounding box and the smallest (x, y) coordinates
    # for the end of the bounding box
    xx1 = np.maximum(x1[i], x1[idxs[:last]])
    yy1 = np.maximum(y1[i], y1[idxs[:last]])
    xx2 = np.minimum(x2[i], x2[idxs[:last]])
    yy2 = np.minimum(y2[i], y2[idxs[:last]])

    # compute the width and height of the bounding box
    w = np.maximum(0, xx2 - xx1 + 1)
    h = np.maximum(0, yy2 - yy1 + 1)

    # compute the ratio of overlap
    overlap = (w * h) / area[idxs[:last]]

    # delete all indexes from the index list that have
    idxs = np.delete(idxs, np.concatenate(([last],
      np.where(overlap > overlapThresh)[0])))

  # return only the bounding boxes that were picked using the
  # integer data type
  return boxes[pick].astype("int")

sliding_window.py

def sliding_window(image, step, window_size):
    for y in range(0, image.shape[0], step):
        for x in range(0, image.shape[1], step):
            yield (x, y, image[y:y + window_size[1], x:x + window_size[0]])

输出:

OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
Class: -1, Score: 1.113939, a: [[ 1.11393857]]
Class: -1, Score: 2.090496, a: [[ 2.09049606]]
Class: -1, Score: 2.090496, a: [[ 2.09049606]]
Class: -1, Score: 2.090496, a: [[ 2.09049606]]
Class: -1, Score: 2.963510, a: [[ 2.96351004]]
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols == var_count && samples.type() == 5) in cv::ml::SVMImpl::predict, file C:\projects\opencv-python\opencv\modules\ml\src\svm.cpp, line 2005
OpenCV(3.4.1) Error: Assertion failed (samples.cols &#
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值