def test_doesnt_get_smaller_than_focal_point(self): "Test that the cropbox doesn't get any smaller than the focal point" self.assertEqual( crop_to_point((640, 480), (10, 10), FocalPoint(x=320, y=240, width=100, height=100)), CropBox(270, 190, 370, 290), )
def detect_faces(self): if opencv_available: cascade_filename = os.path.join( os.path.dirname(__file__), 'face_detection', 'haarcascade_frontalface_alt2.xml') cascade = cv.Load(cascade_filename) image = self.opencv_grey_image() cv.EqualizeHist(image, image) min_size = (40, 40) haar_scale = 1.1 min_neighbors = 3 haar_flags = 0 faces = cv.HaarDetectObjects(image, cascade, cv.CreateMemStorage(0), haar_scale, min_neighbors, haar_flags, min_size) if faces: return [ FocalPoint.from_square(face[0][0], face[0][1], face[0][2], face[0][3]) for face in faces ] return []
def test_keeps_composition(self): "Test that the cropbox tries to keep the composition of the original image as much as it can" self.assertEqual( crop_to_point((300, 300), (150, 150), FocalPoint(x=100, y=200)), CropBox( 50, 100, 200, 250), # Focal point is 1/3 across and 2/3 down in the crop box )
def test_keeps_focal_point_in_view_bottom_left(self): """ Even though it tries to keep the composition of the image, it shouldn't let that get in the way of keeping the entire subject in view """ self.assertEqual( crop_to_point((300, 300), (150, 150), FocalPoint(x=100, y=200, width=150, height=150)), CropBox(25, 125, 175, 275), )
def focal_point(self): if self.focal_point_x is not None and \ self.focal_point_y is not None and \ self.focal_point_width is not None and \ self.focal_point_height is not None: return FocalPoint( self.focal_point_x, self.focal_point_y, width=self.focal_point_width, height=self.focal_point_height, )
def detect_features(self): if opencv_available: image = self.opencv_grey_image() rows = self.image_size[0] cols = self.image_size[1] eig_image = cv.CreateMat(rows, cols, cv.CV_32FC1) temp_image = cv.CreateMat(rows, cols, cv.CV_32FC1) points = cv.GoodFeaturesToTrack(image, eig_image, temp_image, 20, 0.04, 1.0, useHarris=False) if points: return [FocalPoint(x, y, 1) for x, y in points] return []
def detect_faces(self): if opencv_available: cascade_filename = os.path.join(os.path.dirname(__file__), 'face_detection', 'haarcascade_frontalface_alt2.xml') cascade = cv.Load(cascade_filename) image = self.opencv_grey_image() cv.EqualizeHist(image, image) min_size = (40, 40) haar_scale = 1.1 min_neighbors = 3 haar_flags = 0 faces = cv.HaarDetectObjects( image, cascade, cv.CreateMemStorage(0), haar_scale, min_neighbors, haar_flags, min_size ) if faces: return [FocalPoint.from_square(face[0][0], face[0][1], face[0][2], face[0][3]) for face in faces] return []
def test_doesnt_exit_bottom_right(self): "Test that the cropbox doesn't exit the image at the bottom right" self.assertEqual( crop_to_point((640, 480), (100, 100), FocalPoint(x=640, y=480)), CropBox(540, 380, 640, 480), )
def test_doesnt_exit_top_left(self): "Test that the cropbox doesn't exit the image at the top left" self.assertEqual( crop_to_point((640, 480), (100, 100), FocalPoint(x=0, y=0)), CropBox(0, 0, 100, 100), )
def test_basic(self): "Test basic cropping in the centre of the image" self.assertEqual( crop_to_point((640, 480), (100, 100), FocalPoint(x=320, y=240)), CropBox(270, 190, 370, 290), )
def crop_to_point(image_size, crop_size, focal_point): (original_width, original_height) = image_size (crop_width, crop_height) = crop_size if not focal_point: focal_point = FocalPoint(original_width / 2, original_height / 2) # Make sure that the crop size is no smaller than the focal point crop_width = max(crop_width, focal_point.width) crop_height = max(crop_height, focal_point.height) # Make sure final dimensions do not exceed original dimensions final_width = min(original_width, crop_width) final_height = min(original_height, crop_height) # Get UV for focal point focal_point_u = focal_point.x / original_width focal_point_v = focal_point.y / original_height # Get crop box left = focal_point.x - focal_point_u * final_width top = focal_point.y - focal_point_v * final_height right = focal_point.x - focal_point_u * final_width + final_width bottom = focal_point.y - focal_point_v * final_height + final_height # Make sure the entire focal point is in the crop box focal_point_left = focal_point.x - focal_point.width / 2 focal_point_top = focal_point.y - focal_point.height / 2 focal_point_right = focal_point.x + focal_point.width / 2 focal_point_bottom = focal_point.y + focal_point.height / 2 if left > focal_point_left: right -= left - focal_point_left left = focal_point_left if top > focal_point_top: bottom -= top - focal_point_top top = focal_point_top if right < focal_point_right: left += focal_point_right - right right = focal_point_right if bottom < focal_point_bottom: top += focal_point_bottom - bottom bottom = focal_point_bottom # Don't allow the crop box to go over the image boundary if left < 0: right -= left left = 0 if top < 0: bottom -= top top = 0 if right > original_width: left -= right - original_width right = original_width if bottom > original_height: top -= bottom - original_height bottom = original_height return CropBox(left, top, right, bottom)