Python, OpenCV: classify gender using ORB features and KNN -


task: classify images of human faces female or male. training images labels available, obtain test image webcam.

using: python 2.7, opencv 2.4.4

i using orb extract features grayscale image hope use training k-nearest neighbor classifier. each training image of different person number of keypoints , descriptors each image different. problem i'm not able understand opencv docs knn , orb. i've seen other questions orb, knn , flann didn't much.

what nature of descriptor given orb? how different descriptors obtained brief, surf, sift, etc.?

it seems feature descriptors should of same size each training sample in knn. how make sure descriptors of same size each image? more generally, in format should features presented knn training given data , labels? should data int or float? can char?

the training data can found here.

i using haarcascade_frontalface_alt.xml opencv samples

right knn model given 10 images training see if program passes without errors which, not.

here code:

import cv2 numpy import float32 np.float32  def choosecascade():     # todo: option diferent cascades     # haar classifier frontal face     _cascade = cv2.cascadeclassifier('haarcascade_frontalface_alt.xml')     return _cascade  def croptoobj(cascade,imagefile):     # load 1-channel grayscale image     image = cv2.imread(imagefile,0)      # crop object of interest in image     objregion = cascade.detectmultiscale(image) # todo: if multiple ojbects in image?      x1 = objregion[0,0]     y1 = objregion[0,1]     x1pluswidth = objregion[0,0]+objregion[0,2]     y1plusheight = objregion[0,1]+objregion[0,3]      _objimage = image[y1:y1plusheight,x1:x1pluswidth]      return _objimage  def recognizer(filenames):     # orb contructor     orb = cv2.orb(nfeatures=100)      keypoints = []     descriptors = []       # cascade face detection     haarfacecascade = choosecascade()      # start processing images     imagefile in filenames:         # find faces using haar cascade         faceimage = croptoobj(haarfacecascade,imagefile)          # extract keypoints , description          facekeypoints, facedescriptors = orb.detectandcompute(faceimage, mask = none)          #print facedescriptors.shape         descrow = facedescriptors.shape[0]         desccol = facedescriptors.shape[1]          flatfacedescriptors = facedescriptors.reshape(descrow*desccol).astype(np.float32)          keypoints.append(facekeypoints)         descriptors.append(flatfacedescriptors)      print descriptors      # knn model , training on descriptors     responses = []     name in filenames:         if name.startswith('bf'):             responses.append(0) # female         else:             responses.append(1) # male      knn = cv2.knearest()     knntrainsuccess = knn.train(descriptors,                                 responses,                                 isregression = false) # isregression = false, implies classification      # obtain test face image cam     capture = cv2.videocapture(0)     closecamera = -1     while(closecamera < 0):         _retval, _camimage = capture.retrieve()                # find face in camera image         testfaceimage = haarfacecascade.detectmultiscale(_camimage) # todo: if multiple faces?          # keyponts , descriptors of test face image         testfacekp, testfacedesc = orb.detectandcompute(testfaceimage, mask = none)         testdescrow = testfacedesc.shape[0]         flattestfacedesc = testfacedesc.reshape(1,testdescrow*testdesccol).astype(np.float32)           # args in knn.find_nearest: testdata, neighborhood         returnedvalue, result, neighborresponse, distance = knn.find_nearest(flattestfacedesc,3)           print returnedvalue, result, neighborresponse, distance           # display results         # todo: overlay classification text         cv2.imshow("testimage", _camimage)          closecamera = cv2.waitkey(1)     cv2.destroyallwindows()   if __name__ == '__main__':     filenames = ['bf09nes_gray.jpg',                   'bf11nes_gray.jpg',                   'bf13nes_gray.jpg',                   'bf14nes_gray.jpg',                   'bf18nes_gray.jpg',                   'bm25nes_gray.jpg',                   'bm26nes_gray.jpg',                   'bm29nes_gray.jpg',                   'bm31nes_gray.jpg',                   'bm34nes_gray.jpg']      recognizer(filenames) 

currently getting error @ line knn.train() descriptors not detected numpy array.

also, approach wrong? supposed use other way gender classification? wasn't satisfied fisherface , eigenface example in opencv facerec demo please don't direct me those.

any other appreciated. thanks.

--- edit ---

i've tried few things , come answer.

i still hoping in community can me suggesting idea don't have hardcode things solution. suspect knn.match_nearest() isn't doing need do.

and expected, recognizer not @ accurate , prone giving misclassification due rotation, lighting, etc. suggestions on improving approach appreciated.

the database using training is: karolinska directed emotional faces

i have doubts on effectiveness/workability of described approach. here's approach might want consider. contents of gen folder @ http://www1.datafilehost.com/d/0f263abc. note when data size gets bigger(~10k training samples), size of model may become unacceptable(~100-200mb). need pca/lda etc.

import cv2 import numpy np import os  def feacnt():     mat = np.zeros((400,400,3),dtype=np.uint8)     ret = extr(mat)     return len(ret)  def extr(img):     return sobel(img)  def sobel(img):     gray = cv2.cvtcolor(img,cv2.color_bgr2gray)     klr = [[-1,0,1],[-2,0,2],[-1,0,1]]     kbt = [[1,2,1],[0,0,0],[-1,-2,-1]]     ktb = [[-1,-2,-1],[0,0,0],[1,2,1]]     krl = [[1,0,-1],[2,0,-2],[1,0,-1]]     kd1 = [[0,1,2],[-1,0,1],[-2,-1,0]]     kd2 = [[-2,-1,0],[-1,0,1],[0,1,2]]         kd3 = [[0,-1,-2],[1,0,-1],[2,1,0]]     kd4 = [[2,1,0],[1,0,-1],[0,-1,-2]]     karr = np.asanyarray([         klr,         kbt,         ktb,         krl,         kd1,         kd2,         kd3,         kd4         ])     gray=cv2.resize(gray,(40,40))     res =  np.float32([cv2.resize(cv2.filter2d(gray, -1,k),(15,15)) k in karr])     return res.flatten()   root = 'c:/data/gen'  model='c:/data/models/svm/gen.xml' imgs = [] idx =0 path, subdirs, files in os.walk(root):   name in files:       p =path[len(root):].split('\\')     p.remove('')     lbl = p[0]     fpath = os.path.join(path, name)     imgs.append((fpath,int(lbl)))     idx+=1  samples = np.zeros((len(imgs),feacnt()),dtype = np.float32) labels = np.zeros(len(imgs),dtype = np.float32)  i=0. f,l in imgs:   print   img = cv2.imread(f)   samples[i]=extr(img)   labels[i]=l   i+=1  svm = cv2.svm() svmparams = dict( kernel_type = cv2.svm_poly,                         svm_type = cv2.svm_c_svc,                        degree=3.43,                        gamma=1.5e-4,                        coef0=1e-1,                        ) print 'svm train' svm.train(samples,labels,params=svmparams) svm.save(model) print 'done'  result = np.float32( [(svm.predict(s)) s in samples]) correct=0. total=0.  i,j in zip(result,labels):     total+=1     if i==j:       correct+=1     print '%f'%(correct/total) 

Comments

Popular posts from this blog

java.util.scanner - How to read and add only numbers to array from a text file -

rewrite - Trouble with Wordpress multiple custom querystrings -