├── README.md ├── detector.py ├── gather_annotations.py ├── selectors ├── __init__.py └── box_selector.py ├── test.py └── train.py /README.md: -------------------------------------------------------------------------------- 1 | #Object-Detector 2 | This project is created to support the blog [post](http://hackevolve.com/create-your-own-object-detector/). It uses HOG+SVM framework for performing Object Detection. 3 | 4 | ###Usage: 5 | 6 | ####Gather annotations from images... 7 | ![](https://i0.wp.com/hackevolve.com/wp-content/uploads/2017/02/Screenshot-from-2017-02-05-22-08-08.png) 8 | 9 | ####Train Object Detector 10 | ![](https://i0.wp.com/hackevolve.com/wp-content/uploads/2017/02/Screenshot-from-2017-02-05-22-00-48.png?resize=768%2C432) 11 | 12 | ####Performing Object Detection 13 | ![](https://i2.wp.com/hackevolve.com/wp-content/uploads/2017/02/Screenshot-from-2017-02-05-22-02-53.png?resize=768%2C432) -------------------------------------------------------------------------------- /detector.py: -------------------------------------------------------------------------------- 1 | import dlib 2 | import cv2 3 | 4 | 5 | class ObjectDetector(object): 6 | def __init__(self,options=None,loadPath=None): 7 | #create detector options 8 | self.options = options 9 | if self.options is None: 10 | self.options = dlib.simple_object_detector_training_options() 11 | 12 | #load the trained detector (for testing) 13 | if loadPath is not None: 14 | self._detector = dlib.simple_object_detector(loadPath) 15 | 16 | def _prepare_annotations(self,annotations): 17 | annots = [] 18 | for (x,y,xb,yb) in annotations: 19 | annots.append([dlib.rectangle(left=long(x),top=long(y),right=long(xb),bottom=long(yb))]) 20 | return annots 21 | 22 | def _prepare_images(self,imagePaths): 23 | images = [] 24 | for imPath in imagePaths: 25 | image = cv2.imread(imPath) 26 | image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB) 27 | images.append(image) 28 | return images 29 | 30 | def fit(self, imagePaths, annotations, visualize=False, savePath=None): 31 | annotations = self._prepare_annotations(annotations) 32 | images = self._prepare_images(imagePaths) 33 | self._detector = dlib.train_simple_object_detector(images, annotations, self.options) 34 | 35 | #visualize HOG 36 | if visualize: 37 | win = dlib.image_window() 38 | win.set_image(self._detector) 39 | dlib.hit_enter_to_continue() 40 | 41 | #save detector to disk 42 | if savePath is not None: 43 | self._detector.save(savePath) 44 | 45 | return self 46 | 47 | def predict(self,image): 48 | boxes = self._detector(image) 49 | preds = [] 50 | for box in boxes: 51 | (x,y,xb,yb) = [box.left(),box.top(),box.right(),box.bottom()] 52 | preds.append((x,y,xb,yb)) 53 | return preds 54 | 55 | def detect(self,image,annotate=None): 56 | image = cv2.cvtColor(image,cv2.COLOR_BGR2RGB) 57 | preds = self.predict(image) 58 | for (x,y,xb,yb) in preds: 59 | image = cv2.cvtColor(image,cv2.COLOR_RGB2BGR) 60 | 61 | #draw and annotate on image 62 | cv2.rectangle(image,(x,y),(xb,yb),(0,0,255),2) 63 | if annotate is not None and type(annotate)==str: 64 | cv2.putText(image,annotate,(x+5,y-5),cv2.FONT_HERSHEY_SIMPLEX,1.0,(128,255,0),2) 65 | cv2.imshow("Detected",image) 66 | cv2.waitKey(0) 67 | -------------------------------------------------------------------------------- /gather_annotations.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import cv2 3 | import argparse 4 | from imutils.paths import list_images 5 | from selectors import BoxSelector 6 | 7 | #parse arguments 8 | ap = argparse.ArgumentParser() 9 | ap.add_argument("-d","--dataset",required=True,help="path to images dataset...") 10 | ap.add_argument("-a","--annotations",required=True,help="path to save annotations...") 11 | ap.add_argument("-i","--images",required=True,help="path to save images") 12 | args = vars(ap.parse_args()) 13 | 14 | #annotations and image paths 15 | annotations = [] 16 | imPaths = [] 17 | 18 | #loop through each image and collect annotations 19 | for imagePath in list_images(args["dataset"]): 20 | 21 | #load image and create a BoxSelector instance 22 | image = cv2.imread(imagePath) 23 | bs = BoxSelector(image,"Image") 24 | cv2.imshow("Image",image) 25 | cv2.waitKey(0) 26 | 27 | #order the points suitable for the Object detector 28 | pt1,pt2 = bs.roiPts 29 | (x,y,xb,yb) = [pt1[0],pt1[1],pt2[0],pt2[1]] 30 | annotations.append([int(x),int(y),int(xb),int(yb)]) 31 | imPaths.append(imagePath) 32 | 33 | #save annotations and image paths to disk 34 | annotations = np.array(annotations) 35 | imPaths = np.array(imPaths,dtype="unicode") 36 | np.save(args["annotations"],annotations) 37 | np.save(args["images"],imPaths) 38 | -------------------------------------------------------------------------------- /selectors/__init__.py: -------------------------------------------------------------------------------- 1 | from box_selector import BoxSelector -------------------------------------------------------------------------------- /selectors/box_selector.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import cv2 3 | 4 | class BoxSelector(object): 5 | def __init__(self, image, window_name,color=(0,0,255)): 6 | #store image and an original copy 7 | self.image = image 8 | self.orig = image.copy() 9 | 10 | #capture start and end point co-ordinates 11 | self.start = None 12 | self.end = None 13 | 14 | #flag to indicate tracking 15 | self.track = False 16 | self.color = color 17 | self.window_name = window_name 18 | 19 | #hook callback to the named window 20 | cv2.namedWindow(self.window_name) 21 | cv2.setMouseCallback(self.window_name,self.mouseCallBack) 22 | 23 | def mouseCallBack(self, event, x, y, flags, params): 24 | #start tracking if left-button-clicked down 25 | if event==cv2.EVENT_LBUTTONDOWN: 26 | self.start = (x,y) 27 | self.track = True 28 | 29 | #capture/end tracking while mouse-move or left-button-click released 30 | elif self.track and (event==cv2.EVENT_MOUSEMOVE or event==cv2.EVENT_LBUTTONUP): 31 | self.end = (x,y) 32 | if not self.start==self.end: 33 | self.image = self.orig.copy() 34 | #draw rectangle on the image 35 | cv2.rectangle(self.image, self.start, self.end, self.color, 2) 36 | if event==cv2.EVENT_LBUTTONUP: 37 | self.track=False 38 | 39 | #in case of clicked accidently, reset tracking 40 | else: 41 | self.image = self.orig.copy() 42 | self.start = None 43 | self.track = False 44 | cv2.imshow(self.window_name,self.image) 45 | 46 | @property 47 | def roiPts(self): 48 | if self.start and self.end: 49 | pts = np.array([self.start,self.end]) 50 | s = np.sum(pts,axis=1) 51 | (x,y) = pts[np.argmin(s)] 52 | (xb,yb) = pts[np.argmax(s)] 53 | return [(x,y),(xb,yb)] 54 | else: 55 | return [] 56 | 57 | 58 | -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | from detector import ObjectDetector 2 | import numpy as np 3 | import cv2 4 | import argparse 5 | 6 | ap = argparse.ArgumentParser() 7 | ap.add_argument("-d","--detector",required=True,help="path to trained detector to load...") 8 | ap.add_argument("-i","--image",required=True,help="path to an image for object detection...") 9 | ap.add_argument("-a","--annotate",default=None,help="text to annotate...") 10 | args = vars(ap.parse_args()) 11 | 12 | detector = ObjectDetector(loadPath=args["detector"]) 13 | 14 | imagePath = args["image"] 15 | image = cv2.imread(imagePath) 16 | detector.detect(image,annotate=args["annotate"]) 17 | -------------------------------------------------------------------------------- /train.py: -------------------------------------------------------------------------------- 1 | from detector import ObjectDetector 2 | import numpy as np 3 | import argparse 4 | 5 | ap = argparse.ArgumentParser() 6 | ap.add_argument("-a","--annotations",required=True,help="path to saved annotations...") 7 | ap.add_argument("-i","--images",required=True,help="path to saved image paths...") 8 | ap.add_argument("-d","--detector",default=None,help="path to save the trained detector...") 9 | args = vars(ap.parse_args()) 10 | 11 | print "[INFO] loading annotations and images" 12 | annots = np.load(args["annotations"]) 13 | imagePaths = np.load(args["images"]) 14 | 15 | detector = ObjectDetector() 16 | print "[INFO] creating & saving object detector" 17 | 18 | detector.fit(imagePaths,annots,visualize=True,savePath=args["detector"]) 19 | --------------------------------------------------------------------------------