def train(self, positive_dir, negative_dir, hnm_dir): model = Model.svc() batch_size = 6000 increment = batch_size // 100 dir_walk_mgr = RecursiveDirectoryWalkerManager() # Get positive samples print('Loading positive samples...') i = batch_size samples = None p_len = 0 while i: if i % increment == 0: sys.stdout.write('.') sys.stdout.flush() f = dir_walk_mgr.get_a_file(directory=positive_dir, filters=['.jpg']) if f is None: print('Not enough positive samples T_T') break img = cv2.imread(os.path.normpath(f.path), 1) # Load as RGB for compatibility if img is None: continue gray = ImageUtilities.preprocess(img, convert_gray=cv2.COLOR_RGB2YCrCb) gray = imresize(gray, HyperParam.window_size) for j in range(3): intensity = 0.3 * j img = ImageUtilities.transform(gray, intensity=intensity) if p_len < 100: cv2.imwrite('./preview/' + str(p_len).zfill(2) + '.jpg', img) hist = self.compute_hog(img) if samples is None: samples = np.zeros((batch_size, ) + hist.shape, dtype=np.float32) samples[p_len, :] = hist p_len += 1 i -= 1 if p_len >= len(samples): break print(samples.shape) positive_samples = np.copy(samples[0:p_len, :]) print('Positive samples loaded:', positive_samples.shape) # Get negative samples print('Loading negative samples...') samples = None n_len = p_len * 10 i = n_len pt = 0 while i: if i % increment == 0: sys.stdout.write('.') sys.stdout.flush() f = dir_walk_mgr.get_a_file(directory=negative_dir, filters=['.jpg']) if f is None: print('Not enough negative samples T_T') break img = cv2.imread(os.path.normpath(f.path), 1) # Load as RGB for compatibility if img is None: continue gray = ImageUtilities.preprocess(img, convert_gray=cv2.COLOR_RGB2YCrCb) gray = imresize(gray, HyperParam.window_size) hist = self.compute_hog(gray) if samples is None: samples = np.zeros((n_len, ) + hist.shape, dtype=np.float32) try: samples[pt, :] = hist.ravel() except: pass pt += 1 i -= 1 print('Negative samples loaded:', samples.shape) samples = np.concatenate([positive_samples, samples]) # Get hard-negative-mining samples for di in range(10): directory = os.path.normpath( os.path.join(hnm_dir, str(di + 1).zfill(4))) if not os.path.isdir(directory): break print('Loading hard-negative-mining samples...', directory) hnm_samples = None t_len = batch_size * 10 i = t_len print('target sample size', i) pt = 0 while i: if i % increment == 0: sys.stdout.write('.') sys.stdout.flush() f = dir_walk_mgr.get_a_file(directory=directory, filters=['.jpg']) if f is None: print('Not enough hard-negative-mining samples T_T') break img = cv2.imread(os.path.normpath(f.path), 1) # Load as RGB for compatibility if img is None: continue gray = ImageUtilities.preprocess( img, convert_gray=cv2.COLOR_RGB2YCrCb) gray = imresize(gray, HyperParam.window_size) hist = self.compute_hog(gray) if hnm_samples is None: hnm_samples = np.zeros((t_len, ) + hist.shape, dtype=np.float32) try: hnm_samples[pt, :] = hist.ravel() except: pass pt += 1 i -= 1 hnm_samples = np.copy(hnm_samples[0:pt, :]) print('HNM samples loaded:', hnm_samples.shape) samples = np.concatenate([samples, hnm_samples]) print('Total samples:', samples.shape) # Convert to numpy array of float32 and create labels labels = np.zeros((samples.shape[0], ), dtype=np.int32) labels[0:p_len] = 1 # Shuffle Samples rand = np.random.RandomState(321) shuffle = rand.permutation(len(samples)) samples = samples[shuffle] labels = labels[shuffle] print(samples.shape) print(labels.shape) print('Training...') # Create SVM classifier model.fit(samples, labels) print(model.best_score_) with open('svm.dat', 'wb') as f: pickle.dump(model, f) '''td = cv2.TrainData.create(InputArray samples, int layout, InputArray responses, InputArray varIdx=noArray(), InputArray sampleIdx=noArray(), InputArray sampleWeights=noArray(), InputArray varType=noArray())
def main(): #pydoc.writedoc("cv2.HOGDescriptor") with open('svm.dat', 'rb') as f: svm = pickle.load(f) pp = 0 nn = 0 tp = 0 tn = 0 fp = 0 fn = 0 cell_size = HyperParam.cell_size window_size = HyperParam.window_size descriptor_shape = (int((window_size[0] - 16) / 8 + 1), int((window_size[1] - 16) / 8 + 1), 2, 2, 9) descriptor_len = int(np.prod(descriptor_shape)) while True: f = DirectoryWalker().get_a_file(directory=ARGS.positive_dir, filters=['.jpg']) if f is None: break source = cv2.imread(f.path, 1) gray = ImageUtilities.preprocess(source, convert_gray=cv2.COLOR_RGB2YCrCb, maxsize=640) gray = imresize(gray, window_size) hog = feature.hog(gray, orientations=9, pixels_per_cell=cell_size, cells_per_block=(2, 2), block_norm='L2-Hys', visualise=False, transform_sqrt=True, feature_vector=True) p = svm.predict(np.reshape(hog, (1, descriptor_len))) pp += 1 if p[0] == 1: # True positive tp += 1 sys.stdout.write('o') else: # False negative fn += 1 sys.stdout.write('x') sys.stdout.flush() while True: f = DirectoryWalker().get_a_file(directory=ARGS.negative_dir, filters=['.jpg']) if f is None: break source = cv2.imread(f.path, 1) gray = ImageUtilities.preprocess(source, convert_gray=cv2.COLOR_RGB2YCrCb, maxsize=640) gray = imresize(gray, window_size) hog = feature.hog(gray, orientations=9, pixels_per_cell=cell_size, cells_per_block=(2, 2), block_norm='L2-Hys', visualise=False, transform_sqrt=True, feature_vector=True) p = svm.predict(np.reshape(hog, (1, descriptor_len))) nn += 1 if p[0] == 0: # True negative tn += 1 sys.stdout.write('.') else: # False positive fp += 1 sys.stdout.write('#') sys.stdout.flush() print() print('total samples:', pp + nn) print('positive samples:', pp) print('negative samples:', nn) print('true positive:', tp) print('true negative:', tn) print('false positive:', fp) print('false negative:', fn) print('correct:', (tp + tn) / (pp + nn)) print('detection rate:', tp / pp) print('error:', (fp + fn) / (pp + nn))
def main(): #pydoc.writedoc("cv2.HOGDescriptor") if ARGS is None: profiling = True debug = False source_dir = '../../data/face/wiki-face/extracted/wiki' else: profiling = False debug = ARGS.debug source_dir = ARGS.source_dir with open('svm.dat', 'rb') as f: svm = pickle.load(f) while True: f = DirectoryWalker().get_a_file(directory=source_dir, filters=['.jpg']) if f is None: print('No more positive sample T_T') break stride = 1 scale = 1.2 cell_size = np.array(HyperParam.cell_size) block_size = np.array(HyperParam.cell_size) * np.array(HyperParam.block_size) #window_size = (96, 64) #descriptor_shape = (11, 7, 2, 2, 9) window_size = np.array(HyperParam.window_size) window_stride = np.array(HyperParam.window_stride) descriptor_shape = tuple(((window_size-block_size)/cell_size + np.array([1, 1])).astype(dtype=np.int)) + tuple(HyperParam.block_size) + (HyperParam.nbins,) descriptor_len = int(np.prod(descriptor_shape)) source = cv2.imread(f.path, 1) src_shape = np.array(source.shape, dtype=np.float32) gray = ImageUtilities.preprocess(source, convert_gray=cv2.COLOR_RGB2YCrCb, maxsize=640) gray = ImageUtilities.cell_resize(gray, cell_size=cell_size*stride) print('source shape', gray.shape) height, width, *rest = gray.shape heat_map = np.zeros(gray.shape, dtype=np.uint8) window_count = 0 positive_count = 0 for i in range(8): if height < window_size[0] or width < window_size[1]: print('sample too small') continue print('pyramid', i, width, height) mrate = [src_shape[0]/height, src_shape[1]/width] #print('mrate', i, mrate) resized = imresize(gray, [height, width]) #src_size = np.array([width, height]) #window_count = np.prod(((src_size - window_size)/cell_size + np.array([1, 1])).astype(dtype=np.int)) #print('windows:', window_count) hog_image = None if debug: hog, hog_image = feature.hog(resized, orientations=HyperParam.nbins, pixels_per_cell=cell_size, cells_per_block=HyperParam.block_size, block_norm='L2-Hys', visualise=True, transform_sqrt=True, feature_vector=False) hog_image = ImageUtilities.gray2rgb((hog_image*255).astype(dtype=np.uint8)) else: hog = feature.hog(resized, orientations=HyperParam.nbins, pixels_per_cell=cell_size, cells_per_block=HyperParam.block_size, block_norm='L2-Hys', visualise=False, transform_sqrt=True, feature_vector=False) if debug: preview = ImageUtilities.gray2rgb(resized) #print(descriptor_shape[:2]) slen = DataUtilities.get_strider_len(matrix=hog, window=descriptor_shape[:2])//(stride*stride) if slen <= 0: continue window_count += slen hoglist = np.zeros((slen,)+(descriptor_len,), dtype=np.float32) poslist = np.zeros((slen, 2), dtype=np.uint16) for index, pos, subarray in DataUtilities.strider(matrix=hog, window=descriptor_shape[:2], stride=stride): #print(index, pos) hoglist[index, :] = np.reshape(subarray, (1, descriptor_len)) poslist[index, :] = pos predictions = svm.predict(hoglist) #print('predictions', predictions.shape) i = 0 for p in predictions: if p==1: pos = poslist[i] p1 = (pos[1]*cell_size[1], pos[0]*cell_size[0]) p2 = (pos[1]*cell_size[1]+window_size[1]-1, pos[0]*cell_size[0]+window_size[0]-1) if debug: cv2.rectangle(preview, p1, p2, (0, 255, 0), 1) positive_count += 1 #yslice = np.array([pos[0]*cell_size[0], pos[0]*cell_size[0]+window_size[0]])*mrate[0].astype(np.uint16) #xslice = np.array([pos[1]*cell_size[1], pos[1]*cell_size[1]+window_size[1]])*mrate[1].astype(np.uint16) #heat_map[yslice[0]:yslice[1], xslice[0]:xslice[1]] += 1 heat_map[p1[1]:p2[1], p1[0]:p2[0]] += 1 #hnm = img[p1[1]:p2[1], p1[0]:p2[0], :] i += 1 if debug: canvas = ViewportManager().open('preview', shape=preview.shape, blocks=(2, 2)) # Process heat_map and get bounding boxes binary = cv2.threshold(heat_map, 0, 255, cv2.THRESH_BINARY)[1] labels = measure.label(binary) #print(labels, blobs_labels) for region in measure.regionprops(labels): #p1 = np.array([region.bbox[0]*mrate[1], region.bbox[1]*mrate[0]]).astype(dtype=np.int) #p2 = np.array([region.bbox[2]*mrate[1], region.bbox[3]*mrate[0]]).astype(dtype=np.int) p1 = np.array([region.bbox[1], region.bbox[0]]).astype(dtype=np.int) p2 = np.array([region.bbox[3], region.bbox[2]]).astype(dtype=np.int) print(region.area*np.prod(mrate), region.bbox, p1, p2) cv2.rectangle(preview, tuple(p1), tuple(p2), (0, 0, 255), 1) labels = imresize(labels, [height, width]) labels = ImageUtilities.gray2rgb(labels) ViewportManager().put('preview', labels, (1,1)) ViewportManager().put('preview', preview, (0,0)) ViewportManager().put('preview', hog_image, (0,1)) resized = imresize(heat_map, [height, width]) resized = ImageUtilities.gray2rgb(resized*32) ViewportManager().put('preview', resized, (1,0)) ViewportManager().update('preview') k = ViewportManager().wait_key() if k in (ViewportManager.KEY_ENTER, ViewportManager.KEY_SPACE): pass elif k in (ViewportManager.KEY_RIGHT,): # Next image break elif k in (ViewportManager.KEY_DOWN,): # Save in hard-negative-mining dataset break elif k in (ViewportManager.KEY_DOWN,): # Save in positive dataset break height = int(height/scale//cell_size[0]*cell_size[0]) width = int(width/scale//cell_size[1]*cell_size[1]) heat_map = imresize(heat_map, [height, width]) # End of a image (pyramid) if width <= 0 or height <= 0: continue print('window_count', positive_count, '/', window_count, (window_count-positive_count)) canvas = ViewportManager().open('preview', shape=source.shape, blocks=(1, 1)) mrate = [src_shape[0]/height, src_shape[1]/width] # Process heat_map and get bounding boxes binary = cv2.threshold(heat_map, 0, 255, cv2.THRESH_BINARY)[1] labels = measure.label(binary) for region in measure.regionprops(labels): p = region.area/(region.bbox[3]-region.bbox[1])/(region.bbox[2]-region.bbox[0]) print('region', region.bbox_area, region.area, region.filled_area, region.solidity) p1 = np.array([region.bbox[1]*mrate[1], region.bbox[0]*mrate[0]]).astype(dtype=np.int) p2 = np.array([region.bbox[3]*mrate[1], region.bbox[2]*mrate[0]]).astype(dtype=np.int) cv2.rectangle(source, tuple(p1), tuple(p2), (0, 255, 0), 1) ViewportManager().put('preview', source, (0, 0)) ViewportManager().update('preview') k = ViewportManager().wait_key() if k in (ViewportManager.KEY_ENTER, ViewportManager.KEY_SPACE): pass if profiling: objgraph.show_refs([svm, heat_map, hoglist], filename='fd-graph.png') snapshot = tracemalloc.take_snapshot() display_top(snapshot) print() break