예제 #1
0
def select_region(img, mask, color=None):
    """
    Given a color mask and image and a given color,
    create an alpha channel on the given image, exposing only the regions
    associated with the color mask matching the given color.
    If the color is not provided, choose one of the available colors in the mask.
    Return the RGBA image and the color.
    :param img:
    :param mask:
    :return:
    @type img: image_wrap.ImageWrapper
    @type mask: image_wrap.ImageWrapper
    """
    rgba = img.convert('RGBA').to_array()
    mask = mask.to_array()
    channel = np.zeros((mask.shape[0], mask.shape[1])).astype('uint8')
    if color is None or color == 'None':
        colors = np.unique(
            np.vstack(mask).view([('', mask.dtype)] *
                                 np.prod(np.vstack(mask).shape[1])))
        colors = [color for color in colors.tolist()]
        colors.remove((0, 0, 0))
        color = colors[np.random.randint(0, len(colors) - 1)]

    channel[np.all(mask == [color[0], color[1], color[2]], axis=2)] = 255
    (contours, _) = cv2api.findContours(channel.copy(), cv2.RETR_LIST,
                                        cv2.CHAIN_APPROX_SIMPLE)
    for cnt in contours:
        if len(cnt) > 3:
            channel = np.zeros((mask.shape[0], mask.shape[1])).astype('uint8')
            cv2.fillConvexPoly(channel, cnt, 255)
            break
    rgba[:, :, 3] = channel
    return image_wrap.ImageWrapper(rgba), color
예제 #2
0
def minimum_bounding_ellipse(image):
    """
    :param image:
    :return:  (x, y, MA, ma, angle, area, contour)
    @rtype : (int,int,int,int,float, float,np.array)
    """
    (contours, _) = cv2api.findContours(image.copy(), cv2.RETR_LIST,
                                        cv2.CHAIN_APPROX_SIMPLE)
    selected = []
    for cnt in contours:
        try:
            bounded_info = minimum_bounding_ellipse_of_points(cnt)
            if bounded_info is not None:
                selected.append(bounded_info)
        except:
            continue
    if len(selected) == 0:
        return None
    selected = sorted(selected, key=lambda cnt: cnt[5], reverse=True)
    return selected[0] if len(selected) > 0 else None
예제 #3
0
def minimum_bounding_box(image):
    # (contours, _) = cv2.findContours(image.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
    contours, hierarchy = cv2api.findContours(image.copy(), cv2.RETR_LIST,
                                              cv2.CHAIN_APPROX_SIMPLE)
    selected = []
    for cnt in contours:
        try:
            M = cv2.moments(cnt)
            x = int(M['m10'] / M['m00'])
            y = int(M['m01'] / M['m00'])
            x1, y1, w, h = cv2.boundingRect(cnt)
            w = w - 1
            h = h - 1
            selected.append((w, h, w * h, x, y))
        except:
            continue

    selected = sorted(selected, key=lambda cnt: cnt[2], reverse=True)

    if len(selected) == 0:
        x, y, w, h = tool_set.widthandheight(image)
        selected = [(w, h, w * h, x + w / 2, y + h / 2)]
    return selected[0]
예제 #4
0
def performPaste(img, img_to_paste, approach, segment_algorithm):

    mask_of_image_to_paste = img_to_paste.to_mask().to_array()
    out2 = None
    if approach == 'texture':
        denoise_img = denoise_tv_bregman(np.asarray(img), weight=0.4)
        denoise_img = (denoise_img * 255).astype('uint8')
        gray = cv2.cvtColor(denoise_img, cv2.COLOR_BGR2GRAY)
        gray = cv2.equalizeHist(gray)
        mask_of_image_to_paste_ellipse = minimum_bounding_ellipse(
            mask_of_image_to_paste)
        if mask_of_image_to_paste_ellipse is not None:
            img_to_paste = img_to_paste.apply_mask_rgba(mask_of_image_to_paste)
            dims = (math.ceil(denoise_img.shape[0] / 500.0) * 500.0,
                    math.ceil(denoise_img.shape[1] / 500.0) * 500.0)
            sigma = max(1.0, math.log10(dims[0] * dims[1] / 10000.0) - 0.5)
            min_size = max(100.0, math.ceil(sigma * 10.0) * 10)
            while out2 is None and sigma < 5:
                if segment_algorithm == 'slic':
                    masksize = float(sum(sum(mask_of_image_to_paste)) / 255)
                    imgsize = float(img.size[0] * img.size[1])
                    labels1 = segmentation.slic(
                        gray,
                        compactness=5,
                        n_segments=min(500,
                                       int(imgsize / (sigma * 2 * masksize))))
                else:
                    labels1 = segmentation.felzenszwalb(gray,
                                                        scale=min_size,
                                                        sigma=sigma,
                                                        min_size=int(min_size))

                # Compute the Region Adjacency Graph using mean colors.

                #
                # Given an image and its initial segmentation, this method constructs the corresponding  RAG.
                # Each node represents a set of pixels  within image with the same label in labels.
                # The weight between two adjacent regions represents how similar or dissimilar two
                # regions are depending on the mode parameter.

                cutThresh = 0.00000001
                labelset = np.unique(labels1)
                sizeOfLabelSet = len(labelset)
                increment = 0.0000005
                while increment < 0.01 and (len(labels1) > 100000
                                            or sizeOfLabelSet > 1000):
                    g = graph.rag_mean_color(denoise_img,
                                             labels1,
                                             mode='similarity')
                    labels1 = graph.cut_threshold(labels1, g, cutThresh)
                    labelset = np.unique(labels1)
                    # too slow of a change
                    if sizeOfLabelSet - len(labelset) < 5:
                        increment *= 10
                    sizeOfLabelSet = len(labelset)
                    cutThresh += increment
                labelset = np.unique(labels1)
                for label in labelset:
                    if label == 0:
                        continue
                    mask = np.zeros(labels1.shape)
                    mask[labels1 == label] = 255
                    mask = mask.astype('uint8')
                    ret, thresh = cv2.threshold(mask, 127, 255, 0)
                    (contours,
                     _) = cv2api.findContours(thresh, cv2.RETR_LIST,
                                              cv2.CHAIN_APPROX_SIMPLE)
                    areas = [(cnt, cv2.contourArea(cnt)) for cnt in contours
                             if cv2.moments(cnt)['m00'] > 2.0]
                    contours = sorted(areas,
                                      key=lambda cnt: cnt[1],
                                      reverse=True)
                    contours = contours[0:min(20, len(contours))]
                    if len(contours) > 0:
                        for contour in contours:
                            try:
                                placement_ellipse = minimum_bounding_ellipse_of_points(
                                    contour[0])
                                if placement_ellipse is not None:
                                    transform_matrix = build_transform_matrix(
                                        placement_ellipse,
                                        mask_of_image_to_paste_ellipse)
                                    if transform_matrix is None:
                                        continue
                                    transformed_image = transform_image(
                                        img_to_paste.to_array(),
                                        transform_matrix)
                                else:
                                    transformed_image = img_to_paste.to_array()
                                out2 = tool_set.place_in_image(
                                    ImageWrapper(transformed_image).to_mask().
                                    to_array(), transformed_image,
                                    np.asarray(img), (placement_ellipse[0],
                                                      placement_ellipse[1]))
                                if out2 is not None:
                                    break
                            except Exception as e:
                                continue
                    if out2 is not None:
                        break
                sigma += 0.5

    if out2 is None:
        transform_matrix, out2 = pasteAnywhere(img, img_to_paste.to_array(),
                                               mask_of_image_to_paste,
                                               approach == 'simple')
    return transform_matrix, out2
예제 #5
0
def transform(img, source, target, **kwargs):
    op = kwargs['op'] if 'op' in kwargs else 'felzenszwalb'
    denoise_img = denoise_tv_bregman(numpy.asarray(img), weight=0.4)
    denoise_img = (denoise_img * 255).astype('uint8')
    gray = cv2.cvtColor(denoise_img, cv2.COLOR_BGR2GRAY)
    gray = cv2.equalizeHist(gray)

    imgsize = denoise_img.shape[0] * denoise_img.shape[1]
    max_area = imgsize / 100

    dims = (math.ceil(denoise_img.shape[0] / 500.0) * 500.0,
            math.ceil(denoise_img.shape[1] / 500.0) * 500.0)
    sigma = max(0.75, math.log10(dims[0] * dims[1] / 10000.0) - 0.5)
    min_size = max(0.05 * denoise_img.shape[0] * denoise_img.shape[1],
                   math.ceil(sigma * 10.0) * 10)

    if op == 'felzenszwalb':
        segment_labels = felzenszwalb(gray,
                                      scale=min_size,
                                      sigma=sigma,
                                      min_size=int(min_size))
        unique_labels, label_counts = numpy.unique(segment_labels,
                                                   return_counts=True)
    else:
        numsegments = max(16, int(imgsize * 0.000025))
        segment_labels = slic(img, compactness=5, n_segments=numsegments)
        unique_labels, label_counts = numpy.unique(segment_labels,
                                                   return_counts=True)

    cnts = []
    for label in unique_labels:
        mask = numpy.zeros(gray.shape, dtype="uint8")
        mask[segment_labels == label] = 255
        cnts.extend(
            cv2api.findContours(mask.copy(), cv2.RETR_EXTERNAL,
                                cv2.CHAIN_APPROX_SIMPLE)[-2])

    areas = [(cnt, cv2.contourArea(cnt)) for cnt in cnts]
    areas = [area for area in areas if area[1] > 4.0 and area[1] <= max_area]
    cnts = sorted(areas, key=lambda cnt: cnt[1], reverse=True)
    cnts = [cnt for cnt in cnts]
    # top 15 largest
    cnts = cnts[0:min(15, len(cnts))]
    if len(cnts) == 0:
        cnt = build_box_contour(denoise_img.shape)
    else:
        cnt = random.choice(cnts)[0]
    mask = numpy.zeros((denoise_img.shape[0], denoise_img.shape[1]),
                       numpy.uint8)
    cv2.fillPoly(mask, pts=[cnt], color=255)
    if 'alpha' not in kwargs or kwargs['alpha'] == 'yes':
        rgba = numpy.asarray(img.convert('RGBA'))
        rgba = numpy.copy(rgba)
        rgba[mask != 255] = 0
        ImageWrapper(rgba).save(target)
    else:
        ImageWrapper(mask.astype('uint8')).save(target)

    shape = mask.shape
    x, y, w, h = cv2.boundingRect(cnt)
    trial_boxes = [[0, 0, x, shape[0] - h], [0, 0, shape[1] - w, y],
                   [x + w, 0, shape[1] - w, shape[0] - h],
                   [0, y + h, shape[1] - w, shape[0] - h]]

    boxes = [box for box in trial_boxes \
             if (box[2] - box[0]) > 0 and (box[3] - box[1]) > 0]

    if len(boxes) == 0:
        box = [1, 1, shape[1] - w, shape[0] - h]
    else:
        box = choice(boxes)

    new_position_x = randint(box[0], box[2])
    new_position_y = randint(box[1], box[3])
    return {'paste_x': new_position_x, 'paste_y': new_position_y}, None