def _calc_video_frame_safe_boundary(self, frame_shape): frame_width, frame_height = frame_shape # Video frame boundary minus the frame edge buffer. video_frame_safe_boundary = Rectangle( (0 + self.frame_edge, 0 + self.frame_edge), (frame_width - self.frame_edge, frame_height - self.frame_edge), ) return video_frame_safe_boundary
def __init__(self, frame_count, frame_shape=None, VERBOSE=False, DEBUG=False): """ Initialize droplet labeler for a video frame. """ self._labels = OrderedDict() self.frame = frame_count self._VERBOSE = VERBOSE self._DEBUG = DEBUG self.frame_edge = 5 self._video_frame_safe_boundary = self._calc_video_frame_safe_boundary( frame_shape) self.video_frame_boundary = Rectangle((0, 0), frame_shape)
def __init__( self, x, y, width = WIDTH, height = HEIGHT ): """ Constructor. @param x: X-coordinate of the top left corner of the object. @param y: Y-coordinate of the top left corner of the object. @param width: Width of the object. @param height: Height of the object. """ Piece.__init__( self ); self.__x = x; self.__y = y; self.__width = width; self.__height = height; # Create a rectangle. self.__rectangle = Rectangle( top = self.__y, left = self.__x, bottom = self.__y + self.__height, right = self.__x + self.__width );
class PieceRectangular( Piece ): """ PieceRectangular """ WIDTH = 30; HEIGHT = 30; def __init__( self, x, y, width = WIDTH, height = HEIGHT ): """ Constructor. @param x: X-coordinate of the top left corner of the object. @param y: Y-coordinate of the top left corner of the object. @param width: Width of the object. @param height: Height of the object. """ Piece.__init__( self ); self.__x = x; self.__y = y; self.__width = width; self.__height = height; # Create a rectangle. self.__rectangle = Rectangle( top = self.__y, left = self.__x, bottom = self.__y + self.__height, right = self.__x + self.__width ); @staticmethod def fromCenter( x, y, width = WIDTH, height = HEIGHT ): """ Returns a rectangular object from the center coordinates instead of the top left coordinates. @param x: X-coordinate of the center of the object. @param y: Y-coordinate of the center corner of the object. @param width: Width of the object. @param height: Height of the object. """ topLeftX = x - width / 2; topLeftY = y - height / 2; return PieceRectangular( topLeftX, topLeftY, width, height ); def get( self ): """ Returns the rectangle which describes the object. @return: The rectangle which describes the object. """ return self.__rectangle; def x( self ): """ Returns the x-coordinate of the object. @return: The x-coordinate of the object. """ return self.__x; def y( self ): """ Returns the y-coordinate of the object. @return: The y-coordinate of the object. """ return self.__y; def width( self ): """ Returns the width of the object. @return: The width of the object. """ return self.__width; def height( self ): """ Returns the height of the object. @return: The height of the object. """ return self.__height; def doesIntersectsWithRectangle( self, rectangle ): """ Returns true if the object intersects with another rectangle. @param rectangle: The rectangle to check the intersection with. @return: True if the object intersects with the rectangle, false if not. """ return self.__rectangle.doesIntersects( rectangle ); def __str__( self ): return '({x}, {y}) w={width},h={height}'.format( x = self.__x, y = self.__y, width = self.__width, height = self.__height );
def _calc_center(self): self.center = Rectangle(self.text_bounding_box[0].upper_left, self.text_bounding_box[2].lower_right).center
def _calc_points(self): # Text sizes. This is painful, as convincing opencv to do pixel-accurate text # is icky. Breaking this into smaller pieces would be good, but going to PIL # or Cairo/qahirah text would be better. # (This is evolving - I added a Rectangle class to help understand overlaps # between labels, and I'll back into using it here.) # initial id text_string = str(self.initial_id) ( ( self._text_data["width"]["initial_id"], self._text_data["height"]["initial_id"], ), self._text_data["baseline"]["initial_id"], ) = cv2.getTextSize(text_string, cv2.FONT_HERSHEY_PLAIN, 1, 1) self._text_data["height"][ "initial_id"] += 1 # fudge, as opencv reports height as one pixel less than it is self._text_data["baseline"][ "initial_id"] -= 1 # fudge, baseline seems consistently 1 px big # id text_string = str(self.id) ( (self._text_data["width"]["id"], self._text_data["height"]["id"]), self._text_data["baseline"]["id"], ) = cv2.getTextSize(text_string, cv2.FONT_HERSHEY_PLAIN, 2, 1) self._text_data["height"]["id"] += 1 self._text_data["baseline"][ "id"] -= 1 # fudge, baseline seems consistently 1 px big # area in pixels as "Npx" text_string = "{}px".format(self.area) ( (self._text_data["width"]["area"], self._text_data["height"]["area"]), self._text_data["baseline"]["area"], ) = cv2.getTextSize(text_string, cv2.FONT_HERSHEY_PLAIN, 1, 1) self._text_data["height"]["area"] += 1 self._text_data["baseline"][ "area"] -= 1 # fudge, baseline seems consistently 1 px big [self._text_box_width] = max([self._text_data["width"][x]] for x in self._text_data["width"]) self._text_box_height = (self._text_data["height"]["id"] + self.leading + self._text_data["baseline"]["area"] + self.leading + self._text_data["height"]["area"]) if self.initial_id != self.id: self._text_box_height += self._text_data["height"]["initial_id"] + 1 # Bounding box corner points. # These are the corner points on drawn contour bounding box, plus a stand-off # distance, and from which the label bounding boxes can be drawn. ((x1, y1), (x2, y2)) = self._contour_bounding_box_corners # 0th point is upper left, and then clockwise from there through 1, 2, and 3 self._corner_points[0] = (x1 - self.stand_off, y1 - self.stand_off) self._corner_points[1] = (x2 + self.stand_off, y1 - self.stand_off) self._corner_points[2] = (x2 + self.stand_off, y2 + self.stand_off) self._corner_points[3] = (x1 - self.stand_off, y2 + self.stand_off) # And the actual label text area bounding boxes. self.text_bounding_box[0] = Rectangle( ( self._corner_points[0][0] - self._text_box_width, self._corner_points[0][1] - self._text_box_height, ), self._corner_points[0], ) self.text_bounding_box[1] = Rectangle( ( self._corner_points[1][0], self._corner_points[1][1] - self._text_box_height, ), ( self._corner_points[1][0] + self._text_box_width, self._corner_points[1][1], ), ) self.text_bounding_box[2] = Rectangle( self._corner_points[2], ( self._corner_points[2][0] + self._text_box_width, self._corner_points[2][1] + self._text_box_height, ), ) self.text_bounding_box[3] = Rectangle( ( self._corner_points[3][0] - self._text_box_width, self._corner_points[3][1], ), ( self._corner_points[3][0], self._corner_points[3][1] + self._text_box_height, ), )