class ColorThreshold(Filter): """Apply a binary threshold on the three channels of the images Each channel have a minimum and a maximum value. Everything within this threshold is white (255, 255, 255) Everything else is black (0, 0, 0)""" def __init__(self): Filter.__init__(self) self.blue = Param("Blue", 20, min_v=1, max_v=256, thres_h=256) self.green = Param("Green", 20, min_v=1, max_v=256, thres_h=256) self.red = Param("Red", 20, min_v=1, max_v=256, thres_h=256) self._barray = None self._garray = None self._rarray = None self.configure() def configure(self): min_v, max_v = self.blue.get() self._barray = np.array([1.0 * (min_v <= x <= max_v) for x in range(0, 256)], dtype=np.float32) min_v, max_v = self.green.get() self._garray = np.array([1.0 * (min_v <= x <= max_v) for x in range(0, 256)], dtype=np.float32) min_v, max_v = self.red.get() self._rarray = np.array([1.0 * (min_v <= x <= max_v) for x in range(0, 256)], dtype=np.float32) def execute(self, image): image[:, :, 0] = image[:, :, 1] = image[:, :, 2] = ( 255 * self._barray[image[:, :, 0]] * self._garray[image[:, :, 1]] * self._rarray[image[:, :, 2]]) return image
class Morphology(Filter): def __init__(self): Filter.__init__(self) self.kernel_width = Param("Kernel Width", 3, min_v=1, max_v=256) self.kernel_height = Param("Kernel Height", 3, min_v=1, max_v=256) self.anchor_x = Param("Anchor X", -1) self.anchor_y = Param("Anchor Y", -1) self.iterations = Param("Iteration,", 1, min_v=1) self.configure() def configure(self): self._kernel = cv2.getStructuringElement( cv2.MORPH_RECT, (self.kernel_width.get(), self.kernel_height.get()), (self.anchor_x.get(), self.anchor_y.get())) def execute(self, image): morph = cv2.cvtColor(image, cv.CV_BGR2GRAY) cv2.morphologyEx(morph, cv2.MORPH_CLOSE, self._kernel, dst=morph, iterations=self.iterations.get()) cv2.merge((morph, morph, morph), image) return image
class Morphology(Filter): def __init__(self): Filter.__init__(self) self.kernel_width = Param("Kernel Width", 3, min_v=1, max_v=256) self.kernel_height = Param("Kernel Height", 3, min_v=1, max_v=256) self.anchor_x = Param("Anchor X", -1) self.anchor_y = Param("Anchor Y", -1) self.iterations = Param("Iteration,", 1, min_v=1) self.configure() def configure(self): self._kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (self.kernel_width.get(), self.kernel_height.get()), (self.anchor_x.get(), self.anchor_y.get())) def execute(self, image): morph = cv2.cvtColor(image, cv.CV_BGR2GRAY) cv2.morphologyEx( morph, cv2.MORPH_CLOSE, self._kernel, dst=morph, iterations=self.iterations.get()) cv2.merge((morph, morph, morph), image) return image
class ParticleFilter(Filter): """Remove small particles from the image. The image is first converted to grayscale and is then eroded and the remaining blobs are filtered according to the area of the blobs.""" def __init__(self): Filter.__init__(self) self.kernel_height = Param("Kernel Height", 10, min_v=1, max_v=256) self.kernel_width = Param("Kernel Width", 10, min_v=1, max_v=256) self.area_min = Param("Area Min", 3200, min_v=1) self.configure() def configure(self): self._kernel = cv2.getStructuringElement( cv2.MORPH_CROSS, (self.kernel_width.get(), self.kernel_height.get())) def execute(self, image): cv2.erode(image, self._kernel, image) gray = cv2.split(image)[0] contours, _ = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) image = np.zeros(image.shape, np.uint8) for contour in contours: area = np.abs(cv2.contourArea(contour)) if area > self.area_min.get(): cv2.drawContours(image, [contour], -1, (255, 255, 255), thickness=-1) return image
class LineOrientation(Filter): """Port of the old line detection code""" def __init__(self): Filter.__init__(self) self.area_min = Param("Area Min", 300, min_v=1, max_v=100000) self.area_max = Param("Area Max", 35000, min_v=1, max_v=100000) self._kernel = cv2.getStructuringElement( cv2.MORPH_RECT, (3, 3), (0, 0)) def execute(self, image): image_threshold = cv2.split(image)[0] image_morphology = cv2.morphologyEx( image_threshold, cv2.MORPH_CLOSE, self._kernel, iterations=1) contours, _ = cv2.findContours( image_morphology, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) lines = self.find_lines(contours, image) self.draw_lines(lines, image) return image def draw_lines(self, lines, image): msg = "LineOrientation: x1=%s x2=%s y1=%s y2=%s \n" for l, t in lines: vx, vy, x, y = l point1 = (x - t * vx, y - t * vy) point2 = (x + t * vx, y + t * vy) to_send = msg % (int(point1[0][0]), int(point1[1][0]), int(point2[0][0]), int(point2[1][0])) self.notify_output_observers(to_send) cv2.line(image, point1, point2, (0, 0, 255), 3, -1) cv2.circle(image, (x, y), 5, (0, 255, 0), -1) self.notify_output_observers("LineOrientation: \n") def find_lines(self, contours, image): lines = [] for contour in contours: approx = cv2.approxPolyDP(contour, 0, False) area = np.abs(cv2.contourArea(contour)) if self.area_min.get() < area < self.area_max.get(): line_values = cv2.fitLine(approx, cv.CV_DIST_L2, 0, 0.01, 0.01) rect = cv2.boundingRect(approx) t = math.sqrt((rect[2] ** 2 + rect[3] ** 2) / 2.0) lines.append((line_values, t)) cv2.drawContours(image, contour, -1, (255, 255, 0)) return lines
class BilateralFilter(Filter): """Applies the bilateral filter to an image.""" def __init__(self): Filter.__init__(self) self.diameter = Param("Diameter", 10, min_v=0, max_v=255) self.sigma_color = Param("Sigma Color", 0, min_v=0, max_v=255) self.sigma_space = Param("Sigma Space", 0, min_v=0, max_v=255) def execute(self, image): return cv2.bilateralFilter(image, self.diameter.get(), self.sigma_color.get(), self.sigma_space.get())
class Blur(Filter): """Smoothes an image using the normalized box filter""" def __init__(self): Filter.__init__(self) self.kernel_width = Param("width", 3, min_v=1, max_v=10) self.kernel_height = Param("height", 3, min_v=1, max_v=10) def execute(self, image): cv2.blur(image, (self.kernel_width.get(), self.kernel_height.get()), image) return image
class LineOrientation(Filter): """Port of the old line detection code""" def __init__(self): Filter.__init__(self) self.area_min = Param("Area Min", 300, min_v=1, max_v=100000) self.area_max = Param("Area Max", 35000, min_v=1, max_v=100000) self._kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3), (0, 0)) def execute(self, image): image_threshold = cv2.split(image)[0] image_morphology = cv2.morphologyEx(image_threshold, cv2.MORPH_CLOSE, self._kernel, iterations=1) contours, _ = cv2.findContours(image_morphology, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) lines = self.find_lines(contours, image) self.draw_lines(lines, image) return image def draw_lines(self, lines, image): msg = "LineOrientation: x1=%s x2=%s y1=%s y2=%s \n" for l, t in lines: vx, vy, x, y = l point1 = (x - t * vx, y - t * vy) point2 = (x + t * vx, y + t * vy) to_send = msg % (int(point1[0][0]), int( point1[1][0]), int(point2[0][0]), int(point2[1][0])) self.notify_output_observers(to_send) cv2.line(image, point1, point2, (0, 0, 255), 3, -1) cv2.circle(image, (x, y), 5, (0, 255, 0), -1) self.notify_output_observers("LineOrientation: \n") def find_lines(self, contours, image): lines = [] for contour in contours: approx = cv2.approxPolyDP(contour, 0, False) area = np.abs(cv2.contourArea(contour)) if self.area_min.get() < area < self.area_max.get(): line_values = cv2.fitLine(approx, cv.CV_DIST_L2, 0, 0.01, 0.01) rect = cv2.boundingRect(approx) t = math.sqrt((rect[2]**2 + rect[3]**2) / 2.0) lines.append((line_values, t)) cv2.drawContours(image, contour, -1, (255, 255, 0)) return lines
class Blur(Filter): """Smoothes an image using the normalized box filter""" def __init__(self): Filter.__init__(self) self.kernel_width = Param("width", 3, min_v=1, max_v=10) self.kernel_height = Param("height", 3, min_v=1, max_v=10) self.kernel_height.set_description("kernel's height") self.kernel_width.set_description("kernel's width") def execute(self, image): cv2.blur(image, (self.kernel_width.get(), self.kernel_height.get()), image) return image
class Rotate(Filter): """Draw a black rectangle on top of the image""" def __init__(self): Filter.__init__(self) self.enable = Param('enable', True) self.angle = Param('angle', 0, max_v=3, min_v=0) def execute(self, image): angle = self.angle.get() * 90 if self.enable.get(): return scipy.ndimage.interpolation.rotate(image, angle) return image
class Perspective(Filter): """Wrap perspective""" def __init__(self): Filter.__init__(self) self.topleftx = Param("Top Left X", 0, min_v=0, max_v=640) self.toplefty = Param("Top Left TY", 0, min_v=0, max_v=480) self.bottomleftx = Param("Bottom Left X", 100, min_v=0, max_v=640) self.bottomlefty = Param("Bottom Left Y", 480, min_v=0, max_v=480) self.toprightx = Param("Top Right X", 640, min_v=0, max_v=640) self.toprighty = Param("Top Right Y", 0, min_v=0, max_v=480) self.bottomrightx = Param("Bottom Right X", 540, min_v=0, max_v=640) self.bottomrighty = Param("Bottom Right Y", 480, min_v=0, max_v=480) self.mmat = None self.configure() def configure(self): c1 = np.array([[self.topleftx.get(), self.toplefty.get()], [self.bottomleftx.get(), self.bottomlefty.get()], [self.toprightx.get(), self.toprighty.get()], [self.bottomrightx.get(), self.bottomrighty.get()]], np.float32) c2 = np.array([[0, 0], [0, 480], [640, 0], [640, 480]], np.float32) self.mmat = cv2.getPerspectiveTransform(c2, c1) def execute(self, image): cv2.warpPerspective(image, self.mmat, (640, 480), image) return image
class Perspective(Filter): """Wrap perspective""" def __init__(self): Filter.__init__(self) self.topleftx = Param("Top Left X", 0, min_v=0, max_v=640) self.toplefty = Param("Top Left TY", 0, min_v=0, max_v=480) self.bottomleftx = Param("Bottom Left X", 100, min_v=0, max_v=640) self.bottomlefty = Param("Bottom Left Y", 480, min_v=0, max_v=480) self.toprightx = Param("Top Right X", 640, min_v=0, max_v=640) self.toprighty = Param("Top Right Y", 0, min_v=0, max_v=480) self.bottomrightx = Param("Bottom Right X", 540, min_v=0, max_v=640) self.bottomrighty = Param("Bottom Right Y", 480, min_v=0, max_v=480) self.mmat = None self.configure() def configure(self): c1 = np.array( [[self.topleftx.get(), self.toplefty.get()], [self.bottomleftx.get(), self.bottomlefty.get()], [self.toprightx.get(), self.toprighty.get()], [self.bottomrightx.get(), self.bottomrighty.get()]], np.float32) c2 = np.array([[0, 0], [0, 480], [640, 0], [640, 480]], np.float32) self.mmat = cv2.getPerspectiveTransform(c2, c1) def execute(self, image): cv2.warpPerspective(image, self.mmat, (640, 480), image) return image
class Canny(Filter): """Apply a canny filter to the image""" def __init__(self): Filter.__init__(self) self.threshold1 = Param("Threshold1", 10, min_v=0, max_v=255) self.threshold2 = Param("Threshold2", 100, min_v=0, max_v=255) def execute(self, image): gray = cv2.cvtColor(image, cv.CV_BGR2GRAY) cv2.Canny(gray, self.threshold1.get(), self.threshold2.get(), gray) cv2.merge((gray, gray, gray), image) return image
class ExePy1(Filter): """ Python Example Test #1 Convert BGR color to another color. """ def __init__(self): Filter.__init__(self) self.convert_color = Param("Convert choice", 1, min_v=0, max_v=4) desc = "0 = original\n1 = BGR TO YUV\n2 = BGR TO HSV\n3 = BGR TO RGB\n\ 4 = BGR TO GRAY" self.convert_color.set_description(desc) def execute(self, image): convert_color = self.convert_color.get() if convert_color == 1: image = cv2.cvtColor(image, cv2.COLOR_BGR2YUV) elif convert_color == 2: image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV) elif convert_color == 3: image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) elif convert_color == 4: image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) return image
class RemoveObstacle(Filter): """Remove obstacles from an image""" def __init__(self): Filter.__init__(self) self.threshold = Param("Threshold", 12, min_v=0, max_v=255) #self.vertical_blur = Param("Vertical Blur", 18, min_v=0, max_v=255) #self.horizontal_blur = Param("Horizontal Blur", 3, min_v=0, max_v=255) def execute(self, image): # copy = cv2.cvtColor(image, cv.CV_BGR2HSV) copy = cv2.blur(image, (3, 3)) h, _, _ = cv2.split(copy) h[h > self.threshold.get()] = 0 contours, _ = cv2.findContours( h, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) for contour in contours: x, y, w, h = cv2.boundingRect(contour) miny = y - h if miny < 0: miny = 0 maxy = y + h if maxy > image.shape[0]: maxy = image.shape[0] minx = x if minx < 0: minx = 0 maxx = x + w if maxx > image.shape[1]: maxx = image.shape[1] image[miny:maxy, minx:maxx] = 0 return image
class GaussianBlur(Filter): """Smoothes an image using a Gaussian filter""" def __init__(self): Filter.__init__(self) self.kernel_height = Param("Kernel Height", 3, min_v=1, max_v=256) self.kernel_width = Param("Kernel Width", 3, min_v=1, max_v=256) self.sigma_x = Param("Sigma X", 3, min_v=1, max_v=256) self.sigma_y = Param("Sigma Y", 3, min_v=1, max_v=256) def execute(self, image): cv2.GaussianBlur(image, (self.kernel_height.get(), self.kernel_width.get()), sigmaX=self.sigma_x.get(), sigmaY=self.sigma_y.get(), dst=image) return image
class RemoveObstacle(Filter): """Remove obstacles from an image""" def __init__(self): Filter.__init__(self) self.threshold = Param("Threshold", 12, min_v=0, max_v=255) # self.vertical_blur = Param("Vertical Blur", 18, min_v=0, max_v=255) # self.horizontal_blur = Param("Horizontal Blur", 3, min_v=0, # max_v=255) def execute(self, image): # copy = cv2.cvtColor(image, cv.CV_BGR2HSV) copy = cv2.blur(image, (3, 3)) h, _, _ = cv2.split(copy) h[h > self.threshold.get()] = 0 contours, _ = cv2.findContours(h, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) for contour in contours: x, y, w, h = cv2.boundingRect(contour) miny = y - h if miny < 0: miny = 0 maxy = y + h if maxy > image.shape[0]: maxy = image.shape[0] minx = x if minx < 0: minx = 0 maxx = x + w if maxx > image.shape[1]: maxx = image.shape[1] image[miny:maxy, minx:maxx] = 0 return image
class Rectangle(Filter): """Draw a black rectangle on top of the image""" def __init__(self): Filter.__init__(self) self.x1 = Param('x1', 0, max_v=65535, min_v=0) self.y1 = Param('y1', 0, max_v=65535, min_v=0) self.x2 = Param('x2', 100, max_v=65535, min_v=0) self.y2 = Param('y2', 100, max_v=65535, min_v=0) def execute(self, image): cv2.rectangle(image, (self.x1.get(), self.y1.get()), (self.x2.get(), self.y2.get()), (0, 0, 0), cv2.cv.CV_FILLED) return image
class RemoveGrass(Filter): """Remove grass from an image""" def __init__(self): Filter.__init__(self) self.threshold = Param("Threshold", 100, min_v=0, max_v=255) self.technique = Param("Technique", 0, min_v=0, max_v=2) def remove_green_from_blue(self, image): blue, green, red = cv2.split(image) new_blue = blue - green / 2 black = blue < new_blue new_blue[black] = 0 threshold = new_blue < self.threshold.get() blue[threshold] = 0 green[threshold] = 0 red[threshold] = 0 cv2.merge((blue, green, red), image) return image def add_green_to_blue(self, image): blue, green, red = cv2.split(image) new_color = green + blue white = ((new_color < green) & (new_color < blue)) new_color[white] = 255 threshold = new_color > self.threshold.get() blue[threshold] = 0 green[threshold] = 0 red[threshold] = 0 cv2.merge((blue, green, red), image) return image def enhance_grass(self, image): blue, green, _ = cv2.split(image) image[:, :, 0] = np.subtract(blue, green / 2) return image def execute(self, image): if self.technique.get() == 0: return self.add_green_to_blue(image) elif self.technique.get() == 1: return self.remove_green_from_blue(image) elif self.technique.get() == 2: return self.enhance_grass(image)
class FaceDetection(Filter): """Detect faces and eyes""" def __init__(self): Filter.__init__(self) self.nb_face = 1 # linux path path_frontal_face = os.path.join('/', 'usr', 'share', 'opencv', 'haarcascades', 'haarcascade_frontalface_alt.xml') self.face_detect_name = os.path.join( 'data', 'facedetect', path_frontal_face) self.face_cascade = cv2.CascadeClassifier() self.face_cascade.load(self.face_detect_name) self.notify_filter = Param("notify", False) def execute(self, image): gray = cv2.cvtColor(image, cv.CV_BGR2GRAY) cv2.equalizeHist(gray, gray) faces = self.face_cascade.detectMultiScale(gray, 1.1, 2, 0 | cv.CV_HAAR_SCALE_IMAGE, (30, 30)) for face in faces: self.draw_rectangle(image, face, (0, 0, 255)) return image def draw_rectangle(self, image, coord, color): x, y, w, h = coord miny = y if miny < 0: miny = 0 max_y = y + h if max_y > image.shape[0]: max_y = image.shape[0] minx = x if minx < 0: minx = 0 max_x = x + w if max_x > image.shape[1]: max_x = image.shape[1] cv2.rectangle(image, (minx, miny), (max_x, max_y), color, 3) c_x = (max_x - minx) / 2 + minx c_y = (max_y - miny) / 2 + miny if self.notify_filter.get(): self.notify_output_observers("facedetect%d : x=%d, y=%d" % (self.nb_face, c_x, c_y)) self.nb_face += 1 return image[miny:max_y, minx:max_x]
class ColorLevel(Filter): """Determine the value in % a color will have. 0% = Nothing 50% = Half the original value. 100% = Original Example: With 50% Blue and the following pixel (100, 100, 100) give (50, 100, 100)""" def __init__(self): Filter.__init__(self) self.red = Param("red", 100, min_v=0, max_v=255) self.green = Param("green", 100, min_v=0, max_v=255) self.blue = Param("blue", 100, min_v=0, max_v=255) def execute(self, image): if self.red != 100: image[:, :, 2] *= self.red.get() / 100 if self.green != 100: image[:, :, 1] *= self.green.get() / 100 if self.blue != 100: image[:, :, 0] *= self.blue.get() / 100 return image
class SectionFilter(Filter): def __init__(self): Filter.__init__(self) self.kernel_erode_height = Param("Kernel Erode Height", 3, min_v=1, max_v=255) self.kernel_erode_width = Param("Kernel Dilate Width", 3, min_v=1, max_v=255) self.kernel_dilate_height = Param("Kernel Erode Height", 5, min_v=1, max_v=255) self.kernel_dilate_width = Param("Kernel Dilate Width", 5, min_v=1, max_v=255) self.sections = Param("Sections", 5, min_v=1, max_v=10) self.min_area = Param("Minimum Area", 1000, min_v=1, max_v=65535) self.configure() def configure(self): self.kerode = cv2.getStructuringElement( cv2.MORPH_CROSS, (self.kernel_erode_width.get(), self.kernel_erode_height.get())) self.kdilate = cv2.getStructuringElement( cv2.MORPH_CROSS, (iself.kernel_dilate_width.get(), self.kernel_dilate_height.get())) def execute(self, image): image = cv2.erode(image, self.kerode) rows = image.shape[0] section_size = rows / self.sections.get() for i in xrange(0, self.sections.get()): start = (section_size) * i end = (section_size) * (i + 1) if end > rows: end = rows section = image[start:end] gray = cv2.split(section)[0] contours, _ = cv2.findContours(gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) section = np.zeros(section.shape, np.uint8) for contour in contours: area = np.abs(cv2.contourArea(contour)) if area > self.min_area.get(): cv2.drawContours(section, [cv2.convexHull(contour)], -1, (255, 255, 255), thickness=-1) image[start:end] = section image = cv2.dilate(image, self.kdilate) return image
class Rotate(Filter): """ Rotate picture """ def __init__(self): Filter.__init__(self) self.angle = Param('angle', 0, max_v=3, min_v=0) def execute(self, image): angle = self.angle.get() * 90 if self.enable.get(): return scipy.ndimage.interpolation.rotate(image, angle) return image
class TestSeagoat(Filter): def __init__(self): Filter.__init__(self) self.param_str = Param("param_str", "") def configure(self): # This is called when param is modify pass def execute(self, image): self.notify_output_observers(self.param_str.get()) return image
class ParticleFilter(Filter): """Remove small particles from the image. The image is first converted to grayscale and is then eroded and the remaining blobs are filtered according to the area of the blobs.""" def __init__(self): Filter.__init__(self) self.kernel_height = Param("Kernel Height", 10, min_v=1, max_v=256) self.kernel_width = Param("Kernel Width", 10, min_v=1, max_v=256) self.area_min = Param("Area Min", 3200, min_v=1) self.configure() def configure(self): self._kernel = cv2.getStructuringElement( cv2.MORPH_CROSS, (self.kernel_width.get(), self.kernel_height.get())) def execute(self, image): cv2.erode(image, self._kernel, image) gray = cv2.split(image)[0] contours, _ = cv2.findContours( gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) image = np.zeros(image.shape, np.uint8) for contour in contours: area = np.abs(cv2.contourArea(contour)) if area > self.area_min.get(): cv2.drawContours(image, [contour], - 1, (255, 255, 255), thickness=-1) return image
class SectionFilter(Filter): """""" def __init__(self): Filter.__init__(self) self.kernel_erode_height = Param("Kernel Erode Height", 3, min_v=1, max_v=255) self.kernel_erode_width = Param("Kernel Dilate Width", 3, min_v=1, max_v=255) self.kernel_dilate_height = Param("Kernel Erode Height", 5, min_v=1, max_v=255) self.kernel_dilate_width = Param("Kernel Dilate Width", 5, min_v=1, max_v=255) self.sections = Param("Sections", 5, min_v=1, max_v=10) self.min_area = Param("Minimum Area", 1000, min_v=1, max_v=65535) self.configure() def configure(self): self.kerode = cv2.getStructuringElement( cv2.MORPH_CROSS, (self.kernel_erode_width.get(), self.kernel_erode_height.get())) self.kdilate = cv2.getStructuringElement( cv2.MORPH_CROSS, (iself.kernel_dilate_width.get(), self.kernel_dilate_height.get())) def execute(self, image): image = cv2.erode(image, self.kerode) rows = image.shape[0] section_size = rows / self.sections.get() for i in xrange(0, self.sections.get()): start = (section_size) * i end = (section_size) * (i + 1) if end > rows: end = rows section = image[start : end] gray = cv2.split(section)[0] contours, _ = cv2.findContours( gray, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) section = np.zeros(section.shape, np.uint8) for contour in contours: area = np.abs(cv2.contourArea(contour)) if area > self.min_area.get(): cv2.drawContours(section, [cv2.convexHull(contour)], - 1, (255, 255, 255), thickness= -1) image[start: end] = section image = cv2.dilate(image, self.kdilate) return image
class Psychedelic(Filter): """Acid trip""" def __init__(self): Filter.__init__(self) self._images = [] self.nb_images = Param("Nb Images", 10, min_v=1, max_v=99) def execute(self, image): self._images.append(image) while len(self._images) >= self.nb_images.get(): del self._images[0] try: for img in self._images: image = np.add(image, img) except: pass return image
class HoughTransform(Filter): """Apply a Canny filter to the image then finds lines in a binary image using the standard Hough transform""" def __init__(self): Filter.__init__(self) self.canny1 = Param("Canny1", 50, min_v=1, max_v=256) self.canny2 = Param("Canny2", 200, min_v=1, max_v=256) self.rho = Param("Rho", 1, min_v=1, max_v=256) self.theta = Param("Theta", 180, min_v=0, max_v=360) self.threshold = Param("Threshold", 100, min_v=1, max_v=256) self.line_size = Param("Line Size", 1000, min_v=1, max_v=2000) def execute(self, image): edges = cv2.Canny(image, self.canny1.get(), self.canny2.get()) lines = cv2.HoughLines( edges, self.rho.get(), cv.CV_PI / self.theta.get(), self.threshold.get()) if lines is None: return image rho = lines[:, :, 0] theta = lines[:, :, 1] a = np.cos(theta) b = np.sin(theta) x0 = a * rho y0 = b * rho size = lines.shape[1] pt1x = np.round(x0 + self.line_size.get() * -b).astype(np.int) pt1y = np.round(y0 + self.line_size.get() * a).astype(np.int) pt2x = np.round(x0 - self.line_size.get() * -b).astype(np.int) pt2y = np.round(y0 - self.line_size.get() * a).astype(np.int) for i in xrange(size): cv2.line(image, (pt1x.item(i), pt1y.item(i)), (pt2x.item(i), pt2y.item(i)), (0, 0, 255), 3, -1) return image
class PygameCam(MediaStreaming): """Return images from the webcam.""" def __init__(self, config): # Go into configuration/template_media for more information self.config = Configuration() self.own_config = config super(PygameCam, self).__init__() self.media_name = config.name self.run = True self.video = None self.thread_image = None pygame.init() pygame.camera.init() self._create_params() self.deserialize(self.config.read_media(self.get_name())) self.cam = None self._is_opened = True self.image = None def _create_params(self): default_resolution_name = "800x600" self.dct_resolution = { default_resolution_name: (800, 600), "320x240": (320, 240), "640x480": (640, 480), "1024x768": (1024, 768), "1280x960": (1280, 960), "1280x1024": (1280, 1024) } self.param_resolution = Param("resolution", default_resolution_name, lst_value=self.dct_resolution.keys()) self.param_resolution.add_notify(self.reload) default_fps_name = "30" self.dct_fps = {default_fps_name: 30, "15": 15, "7.5": 7.5} self.param_fps = Param("fps", default_fps_name, lst_value=self.dct_fps.keys()) self.param_fps.add_notify(self.reload) def open(self): try: shape = self.dct_resolution[self.param_resolution.get()] fps = self.dct_fps[self.param_fps.get()] self.video = pygame.camera.Camera(self.own_config.path, shape) self.video.start() self.thread_image = True thread.start_new_thread(self.update_image, ()) except BaseException as e: log.printerror_stacktrace( logger, "Open camera %s: %s" % (self.get_name(), e)) return False # call open when video is ready return MediaStreaming.open(self) def update_image(self): while self.thread_image: image_surface = self.video.get_image() image = pygame.surfarray.pixels3d(image_surface) image = np.rot90(image, 3) copy_image = np.zeros(image.shape, np.float32) copy_image = cv2.cvtColor(image, cv2.cv.CV_BGR2RGB, copy_image) self.image = copy_image def next(self): return self.image def close(self): MediaStreaming.close(self) self.thread_image = False # TODO add semaphore? self.video.stop() self._is_opened = False return True
class ImageGenerator(MediaStreaming): """Return a generate image.""" def __init__(self, config): # Go into configuration/template_media for more information self.config = Configuration() self.own_config = config super(ImageGenerator, self).__init__() self.media_name = config.name self.run = True self._is_opened = True self._create_params() self.deserialize(self.config.read_media(self.get_name())) def _create_params(self): default_width = 800 self.param_width = Param("width", default_width, min_v=1, max_v=1200) self.param_width.add_group("Resolution") self.param_width.set_description("Change width resolution.") default_height = 600 self.param_height = Param("height", default_height, min_v=1, max_v=1200) self.param_height.add_group("Resolution") self.param_height.set_description("Change height resolution.") default_fps = 30 self.param_fps = Param("fps", default_fps, min_v=1, max_v=100) self.param_fps.set_description("Change frame per second.") self.param_color_r = Param("color_r", 0, min_v=0, max_v=255) self.param_color_r.add_group("Color") self.param_color_r.set_description("Change red color.") self.param_color_g = Param("color_g", 0, min_v=0, max_v=255) self.param_color_g.add_group("Color") self.param_color_g.set_description("Change green color.") self.param_color_b = Param("color_b", 0, min_v=0, max_v=255) self.param_color_b.add_group("Color") self.param_color_b.set_description("Change blue color.") self.param_auto_color = Param("auto-change-color", False) self.param_auto_color.set_description( "Change the color automatically.") self.param_auto_color.add_group("Color") self.param_random_green = Param("pooling_green_random", False) self.param_random_green.set_description( "Active pooling update of green color with random value.") self.param_random_green.add_notify(self._active_green_pooling) self.param_random_green.add_group("Color") self.param_transpose_r_color = Param("Transpose red color", None) self.param_transpose_r_color.set_description( "Copy the red color on others color.") self.param_transpose_r_color.add_notify(self._transpose_red_color) self.param_transpose_r_color.add_group("Color") self.param_freeze = Param("freeze", False) self.param_freeze.set_description("Freeze the stream.") def next(self): if self.param_freeze.get(): return width = self.param_width.get() height = self.param_height.get() color_r = self.param_color_r.get() color_g = self.param_color_g.get() color_b = self.param_color_b.get() if self.param_auto_color.get(): color_r += 1 if color_r > 255: color_r = 0 color_g += 2 if color_g > 255: color_g = 0 color_b += 3 if color_b > 255: color_b = 0 self.param_color_r.set(color_r) self.param_color_r.set_lock(True) self.param_color_g.set(color_g) self.param_color_g.set_lock(True) self.param_color_b.set(color_b) self.param_color_b.set_lock(True) else: self.param_color_r.set_lock(False) self.param_color_g.set_lock(False) self.param_color_b.set_lock(False) image = np.zeros((height, width, 3), dtype=np.uint8) image[:, :, 0] += color_b image[:, :, 1] += color_g image[:, :, 2] += color_r return image def _transpose_red_color(self, param): color_r = self.param_color_r.get() self.param_color_g.set(color_r) self.param_color_b.set(color_r) def _active_green_pooling(self, param): if param.get(): self.param_color_g.start_pooling(self._pool_random_green) else: self.param_color_g.stop_pooling() def _pool_random_green(self, param): return randrange(255)
class PygameCam(MediaStreaming): """Return images from the webcam.""" def __init__(self, config): # Go into configuration/template_media for more information self.config = Configuration() self.own_config = config super(PygameCam, self).__init__() self.media_name = config.name self.run = True self.video = None self.thread_image = None pygame.init() pygame.camera.init() self._create_params() self.deserialize(self.config.read_media(self.get_name())) self.cam = None self._is_opened = True self.image = None def _create_params(self): default_resolution_name = "800x600" self.dct_resolution = {default_resolution_name: (800, 600), "320x240": (320, 240), "640x480": (640, 480), "1024x768": (1024, 768), "1280x960": (1280, 960), "1280x1024": (1280, 1024)} self.param_resolution = Param( "resolution", default_resolution_name, lst_value=self.dct_resolution.keys()) self.param_resolution.add_notify(self.reload) default_fps_name = "30" self.dct_fps = {default_fps_name: 30, "15": 15, "7.5": 7.5} self.param_fps = Param("fps", default_fps_name, lst_value=self.dct_fps.keys()) self.param_fps.add_notify(self.reload) def open(self): try: shape = self.dct_resolution[ self.param_resolution.get()] fps = self.dct_fps[self.param_fps.get()] self.video = pygame.camera.Camera(self.own_config.path, shape) self.video.start() self.thread_image = True thread.start_new_thread(self.update_image, ()) except BaseException as e: log.printerror_stacktrace( logger, "Open camera %s: %s" % (self.get_name(), e)) return False # call open when video is ready return MediaStreaming.open(self) def update_image(self): while self.thread_image: image_surface = self.video.get_image() image = pygame.surfarray.pixels3d(image_surface) image = np.rot90(image, 3) copy_image = np.zeros(image.shape, np.float32) copy_image = cv2.cvtColor(image, cv2.cv.CV_BGR2RGB, copy_image) self.image = copy_image def next(self): return self.image def close(self): MediaStreaming.close(self) self.thread_image = False # TODO add semaphore? self.video.stop() self._is_opened = False return True
class FaceDetection(Filter): """Detect faces and eyes""" def __init__(self): Filter.__init__(self) self.nb_face = 1 eye_xml = 'haarcascade_eye_tree_eyeglasses.xml' self.eye_detect_name = os.path.join('/', 'usr', 'share', 'opencv', 'haarcascades', eye_xml) self.face_detect_nam = os.path.join('/', 'usr', 'share', 'opencv', 'haarcascades', 'haarcascade_frontalface_alt.xml') self.eye_cascade = cv2.CascadeClassifier() self.face_cascade = cv2.CascadeClassifier() self.eye_cascade.load(self.eye_detect_name) self.face_cascade.load(self.face_detect_name) self.show_rectangle = Param("show_rectangle", True) # To share parameter between filter, create it with : self.add_shared_param(Param("width", 3, min_v=1, max_v=10)) # On the execution, use it like this : # param = self.get_shared_params("width") def configure(self): # This is called when param is modify pass def execute(self, image): gray = cv2.cvtColor(image, cv.CV_BGR2GRAY) cv2.equalizeHist(gray, gray) faces = self.face_cascade.detectMultiScale(gray, 1.1, 2, 0 | cv.CV_HAAR_SCALE_IMAGE, (30, 30) ) for face in faces: faceimg = self.draw_rectangle(image, face, (0, 0, 255)) self.nb_face = 1 return image def draw_rectangle(self, image, coord, color): x, y, w, h = coord miny = y if miny < 0: miny = 0 maxy = y + h if maxy > image.shape[0]: maxy = image.shape[0] minx = x if minx < 0: minx = 0 maxx = x + w if maxx > image.shape[1]: maxx = image.shape[1] if self.show_rectangle.get(): cv2.rectangle(image, (minx, miny), (maxx, maxy), color, 3) c_x = (maxx - minx) / 2 + minx c_y = (maxy - miny) / 2 + miny self.notify_output_observers( "facedetect%d : x=%d, y=%d" % (self.nb_face, c_x, c_y)) self.nb_face += 1 return image[miny:maxy, minx:maxx]
class Filter(PoolParam): def __init__(self, name=None): super(Filter, self).__init__() self._output_observers = list() self.original_image = None self.name = name self.dct_global_param = {} self.dct_media_param = {} self.execution_name = None self._publisher = None self._publish_key = None # add generic param self._active_param = Param("_active_filter", True) self._active_param.set_description("Enable filter in filterchain.") self._active_param.add_group("Generic") def serialize(self, is_config=False, is_info=False): if is_info: return {"name": self.name, "doc": self.__doc__} lst_param = super(Filter, self).serialize(is_config=is_config) return { "filter_name": self.__class__.__name__, "lst_param": lst_param } def deserialize(self, value): return super(Filter, self).deserialize(value.get("lst_param")) def get_name(self): return self.name def get_code_name(self): key = "-" if key in self.name: return self.name[:self.name.rfind("-")] return self.name def set_name(self, name): self.name = name def get_is_active(self): return bool(self._active_param.get()) def destroy(self): # edit me # It's called just before to be destroyed pass def configure(self): # edit me pass def execute(self, image): # edit me return image def set_global_params(self, dct_global_param): # complete the list and point on it for key, param in self.dct_global_param.items(): if key in dct_global_param: log.print_function( logger.error, "Duplicate key on dct_global_param : %s", key) continue dct_global_param[key] = param self.dct_global_param = dct_global_param self.set_global_params_cpp(self.dct_global_param) def set_global_params_cpp(self, dct_global_param): pass def set_media_param(self, dct_media_param): self.dct_media_param = dct_media_param def set_execution_name(self, execution_name): self.execution_name = execution_name def get_media_param(self, param_name): return self.dct_media_param.get(param_name, None) def set_original_image(self, image): self.original_image = image def get_original_image(self): return self.original_image def notify_output_observers(self, data): for obs in self._output_observers: obs(data) def get_list_output_observer(self): return self._output_observers def add_output_observer(self, observer): self._output_observers.append(observer) def remove_output_observer(self, observer): self._output_observers.remove(observer) def set_publisher(self, publisher): self._publisher = publisher # create publisher key execution_name = self.execution_name filter_name = self.name key = keys.create_unique_exec_filter_name(execution_name, filter_name) self._publish_key = key self._publisher.register(key) # create callback publisher self._cb_publish = self._get_cb_publisher() def _add_notification_param(self, param): # send from publisher if not self._publisher: return data = { "execution": self.execution_name, "filter": self.name, "param": param.serialize() } json_data = json.dumps(data) self._publisher.publish(keys.get_key_filter_param(), json_data) def _get_cb_publisher(self): if not self._publisher: return return self._publisher.get_callback_publish(self._publish_key) def get_media(self, name): from resource import Resource resource = Resource() return resource.get_media(name)
class Filter(PoolParam): def __init__(self, name=None): super(Filter, self).__init__() self._output_observers = list() self.original_image = None self.name = name self.dct_global_param = {} self.dct_media_param = {} self.execution_name = None self._publisher = None self._publish_key = None # add generic param self._active_param = Param("_active_filter", True) self._active_param.set_description("Enable filter in filterchain.") self._active_param.add_group("Generic") def serialize(self, is_config=False, is_info=False): if is_info: return {"name": self.name, "doc": self.__doc__} lst_param = super(Filter, self).serialize(is_config=is_config) return {"filter_name": self.__class__.__name__, "lst_param": lst_param} def deserialize(self, value): return super(Filter, self).deserialize(value.get("lst_param")) def get_name(self): return self.name def get_code_name(self): key = "-" if key in self.name: return self.name[:self.name.rfind("-")] return self.name def set_name(self, name): self.name = name def get_is_active(self): return bool(self._active_param.get()) def destroy(self): # edit me # It's called just before to be destroyed pass def configure(self): # edit me pass def execute(self, image): # edit me return image def set_global_params(self, dct_global_param): # complete the list and point on it for key, param in self.dct_global_param.items(): if key in dct_global_param: log.print_function(logger.error, "Duplicate key on dct_global_param : %s", key) continue dct_global_param[key] = param self.dct_global_param = dct_global_param self.set_global_params_cpp(self.dct_global_param) def set_global_params_cpp(self, dct_global_param): pass def set_media_param(self, dct_media_param): self.dct_media_param = dct_media_param def set_execution_name(self, execution_name): self.execution_name = execution_name def get_media_param(self, param_name): return self.dct_media_param.get(param_name, None) def set_original_image(self, image): self.original_image = image def get_original_image(self): return self.original_image def notify_output_observers(self, data): for obs in self._output_observers: obs(data) def get_list_output_observer(self): return self._output_observers def add_output_observer(self, observer): self._output_observers.append(observer) def remove_output_observer(self, observer): self._output_observers.remove(observer) def set_publisher(self, publisher): self._publisher = publisher # create publisher key execution_name = self.execution_name filter_name = self.name key = keys.create_unique_exec_filter_name(execution_name, filter_name) self._publish_key = key self._publisher.register(key) # create callback publisher self._cb_publish = self._get_cb_publisher() def _add_notification_param(self, param): # send from publisher if not self._publisher: return data = { "execution": self.execution_name, "filter": self.name, "param": param.serialize() } json_data = json.dumps(data) self._publisher.publish(keys.get_key_filter_param(), json_data) def _get_cb_publisher(self): if not self._publisher: return return self._publisher.get_callback_publish(self._publish_key) def get_media(self, name): from resource import Resource resource = Resource() return resource.get_media(name)
class FaceDetection(Filter): """Detect faces and eyes""" def __init__(self): Filter.__init__(self) self.nb_face = 1 eye_xml = 'haarcascade_eye_tree_eyeglasses.xml' self.eye_detect_name = os.path.join('/', 'usr', 'share', 'opencv', 'haarcascades', eye_xml) self.face_detect_nam = os.path.join('/', 'usr', 'share', 'opencv', 'haarcascades', 'haarcascade_frontalface_alt.xml') self.eye_cascade = cv2.CascadeClassifier() self.face_cascade = cv2.CascadeClassifier() self.eye_cascade.load(self.eye_detect_name) self.face_cascade.load(self.face_detect_name) self.show_rectangle = Param("show_rectangle", True) # To share parameter between filter, create it with : self.add_shared_param(Param("width", 3, min_v=1, max_v=10)) # On the execution, use it like this : # param = self.get_shared_params("width") def configure(self): # This is called when param is modify pass def execute(self, image): gray = cv2.cvtColor(image, cv.CV_BGR2GRAY) cv2.equalizeHist(gray, gray) faces = self.face_cascade.detectMultiScale(gray, 1.1, 2, 0 | cv.CV_HAAR_SCALE_IMAGE, (30, 30)) for face in faces: faceimg = self.draw_rectangle(image, face, (0, 0, 255)) self.nb_face = 1 return image def draw_rectangle(self, image, coord, color): x, y, w, h = coord miny = y if miny < 0: miny = 0 maxy = y + h if maxy > image.shape[0]: maxy = image.shape[0] minx = x if minx < 0: minx = 0 maxx = x + w if maxx > image.shape[1]: maxx = image.shape[1] if self.show_rectangle.get(): cv2.rectangle(image, (minx, miny), (maxx, maxy), color, 3) c_x = (maxx - minx) / 2 + minx c_y = (maxy - miny) / 2 + miny self.notify_output_observers("facedetect%d : x=%d, y=%d" % (self.nb_face, c_x, c_y)) self.nb_face += 1 return image[miny:maxy, minx:maxx]
class Webcam(MediaStreaming): """Return images from the webcam.""" def __init__(self, config): # Go into configuration/template_media for more information self.config = Configuration() self.own_config = config super(Webcam, self).__init__() self.media_name = config.name self.run = True self.video = None video = cv2.VideoCapture(config.no) if video.isOpened(): self._is_opened = True video.release() self._create_params() self.deserialize(self.config.read_media(self.get_name())) def _create_params(self): self.dct_params = {} default_resolution_name = "800x600" self.dct_resolution = {default_resolution_name: (800, 600), "320x240": (320, 240), "640x480": (640, 480), "1024x768": (1024, 768), "1280x960": (1280, 960), "1280x1024": (1280, 1024)} self.param_resolution = Param( "resolution", default_resolution_name, lst_value=self.dct_resolution.keys()) self.param_resolution.add_notify(self.reload) default_fps_name = "30" self.dct_fps = {default_fps_name: 30, "15": 15, "7.5": 7.5} self.param_fps = Param("fps", default_fps_name, lst_value=self.dct_fps.keys()) self.param_fps.add_notify(self.reload) def open(self): try: shape = self.dct_resolution[self.param_resolution.get()] fps = self.dct_fps[self.param_fps.get()] # TODO check argument video capture self.video = cv2.VideoCapture(self.own_config.no) self.video.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, shape[0]) self.video.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, shape[1]) self.video.set(cv2.cv.CV_CAP_PROP_FPS, fps) except BaseException as e: log.printerror_stacktrace( logger, "Open camera %s: %s" % (self.get_name(), e)) return False # call open when video is ready return MediaStreaming.open(self) def next(self): run, image = self.video.read() if not run: raise StopIteration return image def close(self): MediaStreaming.close(self) if self.video: self.video.release() self._is_opened = False return True
class Webcam(MediaStreaming): """Return images from the webcam.""" def __init__(self, config): # Go into configuration/template_media for more information self.config = Configuration() self.own_config = config super(Webcam, self).__init__() self.media_name = config.name self.run = True self.video = None video = cv2.VideoCapture(config.no) if video.isOpened(): self._is_opened = True video.release() self._create_params() self.deserialize(self.config.read_media(self.get_name())) def _create_params(self): self.dct_params = {} default_resolution_name = "800x600" self.dct_resolution = { default_resolution_name: (800, 600), "320x240": (320, 240), "640x480": (640, 480), "1024x768": (1024, 768), "1280x960": (1280, 960), "1280x1024": (1280, 1024) } self.param_resolution = Param("resolution", default_resolution_name, lst_value=self.dct_resolution.keys()) self.param_resolution.add_notify(self.reload) default_fps_name = "30" self.dct_fps = {default_fps_name: 30, "15": 15, "7.5": 7.5} self.param_fps = Param("fps", default_fps_name, lst_value=self.dct_fps.keys()) self.param_fps.add_notify(self.reload) def open(self): try: shape = self.dct_resolution[self.param_resolution.get()] fps = self.dct_fps[self.param_fps.get()] # TODO check argument video capture self.video = cv2.VideoCapture(self.own_config.no) self.video.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, shape[0]) self.video.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, shape[1]) self.video.set(cv2.cv.CV_CAP_PROP_FPS, fps) except BaseException as e: log.printerror_stacktrace( logger, "Open camera %s: %s" % (self.get_name(), e)) return False # call open when video is ready return MediaStreaming.open(self) def next(self): run, image = self.video.read() if not run: raise StopIteration return image def close(self): MediaStreaming.close(self) if self.video: self.video.release() self._is_opened = False return True
class IPC(MediaStreaming): """ Return image from IPC socket with ZeroMQ This media is a subscriber of ZeroMQ """ key_ipc_name = "ipc name" def __init__(self, config): # Go into configuration/template_media for more information super(IPC, self).__init__() self.config = Configuration() self.own_config = config self.media_name = config.name if config.device: self.device_name = config.device else: self.device_name = "/tmp/seagoatvision_media.ipc" self._is_opened = True self.run = True self.video = None self.context = zmq.Context() self.subscriber = None self.message = None self._create_params() self.deserialize(self.config.read_media(self.get_name())) def _create_params(self): default_ipc_name = "ipc://%s" % self.device_name self.param_ipc_name = Param(self.key_ipc_name, default_ipc_name) self.param_ipc_name.add_notify(self.reload) def open(self): self.subscriber = self.context.socket(zmq.SUB) self.subscriber.setsockopt(zmq.SUBSCRIBE, b'') device_name = self.param_ipc_name.get() logger.info("Open media device %s" % device_name) self.subscriber.connect(device_name) thread.start_new_thread(self.fill_message, tuple()) # call open when video is ready return MediaStreaming.open(self) def next(self): if not self.subscriber or not self.message: return image = None message = self.message[:] self.message = None lst_pixel = list(bytearray(message)) # the first 2 bytes is width of image len_message = len(lst_pixel) - 2 if len_message: width = (lst_pixel[0] << 8) + lst_pixel[1] if not width: return image = np.array(lst_pixel[2:]) # check if missing pixel and replace by zero diff = len_message % width if diff: image += [0] * (width - diff) image = image.reshape((-1, width)) shape = image.shape if len(shape) < 3 or 3 > shape[2]: # convert in 3 depth, bgr picture image_float = np.array(image, dtype=np.float32) vis2 = cv2.cvtColor(image_float, cv2.COLOR_GRAY2BGR) image = np.array(vis2, dtype=np.uint8) return image def close(self): MediaStreaming.close(self) # TODO need to debug, closing socket create errors and \ # context.term freeze # self.subscriber.close() # self.context.term() self.subscriber = None return True def fill_message(self): try: while self.subscriber: self.message = self.subscriber.recv() except zmq.ContextTerminated: pass finally: self.message = None
class ExePy2(Filter): """ Python Example Test #2 Example filter to test params. Show rectangle on each detected face. """ def __init__(self): Filter.__init__(self) self.dct_color_choose = {"red": (0, 0, 255), "green": (0, 255, 0), "blue": (255, 0, 0)} self.color_rect = self.dct_color_choose["red"] self.i_text_size = 1.0 # add params self.show_output = Param("enable_output", True) self.show_output.set_description("Enable to show rectangle.") self.color_rectangle = Param("color_rectangle", "red", lst_value=self.dct_color_choose.keys()) self.color_rectangle.set_description( "Change the RGB color of the rectangle.") self.color_rectangle.add_group("rectangle") self.show_rectangle = Param("show_rectangle", True) self.show_rectangle.set_description( "Colorize a rectangle around the face.") self.show_rectangle.add_group("rectangle") self.border_rec_size = Param("border_rec_size", 3, min_v=1, max_v=9) self.border_rec_size.set_description( "Change the border size of the rectangle.") self.border_rec_size.add_group("rectangle") self.show_text = Param("enable_text", True) self.show_text.set_description("Show text upper the rectangle.") self.show_text.add_group("message") self.text_face = Param("text_face", "") self.text_face.set_description("The text to write on the rectangle.") self.text_face.add_group("message") self.text_size = Param("text_size", self.i_text_size, min_v=0.1, max_v=4.9) self.text_size.set_description("Change the text size.") self.text_size.add_group("message") self.nb_face = 1 # linux path path_frontal_face = os.path.join('/', 'usr', 'share', 'opencv', 'haarcascades', 'haarcascade_frontalface_alt.xml') self.face_detect_name = os.path.join('data', 'facedetect', path_frontal_face) self.face_cascade = cv2.CascadeClassifier() self.face_cascade.load(self.face_detect_name) def configure(self): self.color_rect = self.dct_color_choose[self.color_rectangle.get()] self.i_text_size = self.text_size.get() def execute(self, image): gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) cv2.equalizeHist(gray, gray) faces = self.face_cascade.detectMultiScale(gray, 1.1, 2, 0 | cv.CV_HAAR_SCALE_IMAGE, (30, 30)) for face in faces: self.draw_rectangle(image, face, self.color_rect, self.i_text_size) self.nb_face = 1 return image def draw_rectangle(self, image, coord, color, txt_size): x, y, w, h = coord min_y = y if min_y < 0: min_y = 0 min_face_y = min_y - 10 if min_face_y < 0: min_face_y = 0 max_y = y + h if max_y > image.shape[0]: max_y = image.shape[0] min_x = x if min_x < 0: min_x = 0 max_x = x + w if max_x > image.shape[1]: max_x = image.shape[1] if self.show_rectangle.get(): cv2.rectangle(image, (min_x, min_y), (max_x, max_y), color, thickness=self.border_rec_size.get()) if self.show_text.get(): text = "%s.%s" % (self.nb_face, self.text_face.get()) cv2.putText(image, text, (min_x, min_face_y), cv2.FONT_HERSHEY_SCRIPT_SIMPLEX, txt_size, color) # note: >> 2 == / 2 c_x = (max_x - min_x) >> 2 + min_x c_y = (max_y - min_y) >> 2 + min_y if self.show_output.get(): self.notify_output_observers( "face detect no %d : x=%d, y=%d" % (self.nb_face, c_x, c_y)) self.nb_face += 1
class HDR(Filter): """High-dynamic-range_imaging with python PIL - works with files""" def __init__(self): Filter.__init__(self) self.case = 'test' self.resize = False self.strength = Param("strength", 0.0, min_v=0.0, max_v=3.0) self.naturalness = Param("naturalness", 10, min_v=0, max_v=10) # self.sub_lum = Param("sub_lum", 100, min_v=0, max_v=255) # self.shift_x = Param("shift_x", 0, min_v=-800, max_v=800) # self.shift_y = Param("shift_y", 0, min_v=-600, max_v=600) self.show_image = Param("show_images", 1, min_v=1, max_v=10) self.limit_image = Param("limit_image", 4, min_v=1, max_v=10) self.debug_show = Param( "show_debug", "show_normal", lst_value=[ "show_normal", "show_sat", "show_con"]) self.show_hdr = Param("show_hdr", False) self.index = 0 self.images = [] self.imgs = [] self.first_time = True def execute(self, image): show_hdr = self.show_hdr.get() limit_image = self.limit_image.get() len_image = len(self.images) if len_image == limit_image: self.images[self.index - 1] = image self.index += 1 if self.index > limit_image: self.index = 1 elif len_image < limit_image: self.images.append(image) self.index += 1 else: self.images.pop() if self.index > limit_image: self.index = limit_image len_image = len(self.images) show_no = self.show_image.get() show_no = len_image if show_no > len_image else show_no if not show_hdr: return self.images[show_no - 1] nature = self.naturalness.get() if nature: nature /= 10.0 return self.get_hdr(self.images, strength=self.strength.get(), naturalness=nature) """ SOURCE: https://sites.google.com/site/bpowah/hdrandpythonpil a collection of images to merge into HDR blend an arbitrary number of photos into a single HDR image or several images with various combinations of HDR parameters it is assumed that project folders contain all the images you want to merge case = folder name cur_dir = folder where the project folders are located images are auto-sorted by degree of exposure (image brightness) """ def get_masks(self, imgs, cur_str): """ create a set of masks from a list of images (one mask for every adjacent pair of images """ masks = [] mask_ct = len(imgs) - 1 imgs = [self.bal(img.convert(mode='L'), cur_str) for img in imgs] for i in range(mask_ct): blend_fraction = .5 # 1. - (float(i)+.5)/float(mask_ct) m = Image.blend(imgs[i], imgs[i + 1], blend_fraction) masks.append(m) return masks def bal(self, im, cur_str): """ adjust the balance of the mask (re-distribute the histogram so that there are more extreme blacks and whites) like increasing the contrast, but without clipping and maintains overall average image brightness """ h = im.histogram() ln = range(len(h)) up = [sum(h[0: i]) for i in ln] lo = [sum(h[i:-1]) for i in ln] ct = sum(h) st = int(cur_str * 255.) lut = [i + st * up[i] * lo[i] * (up[i] - lo[i]) / ct ** 3 for i in ln] for i in ln: if lut[i] < 1: lut[i] = 1 if lut[i] > 255: lut[i] = 255 return im.point(lut) def merge(self, imgs, cur_str): """ combine a set images into a smaller set by combinding all adjacent images """ masks = self.get_masks(imgs, cur_str) imx = lambda i: Image.composite(imgs[i], imgs[i + 1], masks[i]) return [imx(i) for i in range(len(masks))] def merge_all(self, imgs, cur_str): """ iteratively merge a set of images until only one remains """ while len(imgs) > 1: imgs = self.merge(imgs, cur_str) return imgs[0] def get_hdr(self, images, strength=0.0, naturalness=1.0): """ process the hdr image(s) strength - a float that defines how strong the hdr effect should be - a value of zero will combine images by using a greyscale image average - a value greater than zero will use higher contrast versions of those greyscale images - suggest you a value between 0.0 and 2.0 naturalness - values between zero and one - zero will be a very high-contrast image - 1.0 will be a very flat image - 0.7 to 0.9 tend to give the best results """ imgs = copy([Image.fromarray(img) for img in images]) sat_img = self.merge_all(imgs, strength) if self.debug_show.get_pos_list() == 1: return np.array(sat_img) imgs.reverse() con_img = self.merge_all(imgs, strength) if self.debug_show.get_pos_list() == 2: return np.array(con_img) """ combines a saturated image with a contrast image and puts them in a dictionary of completed images """ images = Image.blend(con_img, sat_img, naturalness) images = np.array(images) return images