简体   繁体   中英

Minimize image area while preserving a certain metric

I have a picture and I want to find the crop with the minimal area that at the same time retains a certain percentage of the edge energy.

My take on this was to formulate this as a optimization problem and let scipy's constrained optimizers solve it [code see below]. This apparently is problematic since it is an integer problem (croping takes the integer coordinates of the top-left and down-right corners as parameters). And indeed fmin_cobyla fails to find a solution after some 20s runtime, while fmin_slsqp fails after one iteration with " Singular matrix C in LSQ subproblem (Exit mode 6) ".

Any ideas on how I might tackle this problem otherwise? Is there by chance a library that handles optimization problems on images?


from skimage.filters import sobel
from PIL import Image
from scipy.optimize import fmin_slsqp

def objective(x):
    # minimize the area
    return abs((x[2] - x[0]) * (x[3] - x[1]))

def create_ratio_constr(img):
    def constr(x):
        # 81% of the image energy should be contained
        x = tuple(map(int, x))
        crop = img.crop((x[0], x[1], x[2], x[3]))
        area_ratio = round(sum(list(crop.getdata())) /
                           float(sum(list(img.getdata()))), 2)
        if area_ratio == 0.81:
            return 0.0
        return -1
    return constr

def borders_constr(x):
    x = tuple(map(int, x))
    # 1st point is up and left of 2nd point
    rectangle = x[0] < x[2] and x[1] < x[3]

    # only positive values valid
    positive = x[0] > 0 and x[1] > 0

    if rectangle and positive:
        return 0.0
    return -1

img = Image.open("/some/path.jpg")
# get the edges
edges = Image.fromarray(sobel(img.convert("L")))

ratio_constr = create_ratio_constr(edges)
x = fmin_slsqp(objective,
               (0, 0, edges.size[0]-1, edges.size[1]-1),
               [borders_constr, ratio_constr],
               disp=1)

print x

I would probably ignore the integer requirement for the corners of the cropped area and solve the relaxed problem. Then consider moving the cropped edges in or out to the nearest whole pixel. If it is for aesthetic purposes, the +/- part pixel probably doesn't matter. If it has to be correct, there are only four edges to consider in two places each so should not be a big deal to find the one out of 16 choices which is best.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM