Numpy: обрезать интересующий объект путем удаления черных осей X и Y - PullRequest
1 голос
/ 18 октября 2019

Проблема: у меня есть несколько изображений (в виде цифры), которые имеют черный фон. Посередине у меня есть объект, который меня интересует. Я бы хотел обрезать интересующий объект в виде кучи.

Допустим, у нас есть изображение, которое выглядит примерно так:

a generated image for demo and testing

Мне нужна функция crop_region_of_interest, которая обнаруживает и удаляет любые оси X и Y, если вся ось черная или [0,0,0], вЧтобы получить это:

enter image description here

Некоторые коды, используемые в этой демонстрации:

# just a function to add colors to generate test image
def add_color(img, pixel_x, pixel_y, rgb):
    img[pixel_x][pixel_y][0] = rgb[0]
    img[pixel_x][pixel_y][1] = rgb[1]
    img[pixel_x][pixel_y][2] = rgb[2]

def generate_fake_image_for_stackoverflow():
    # a black background image
    base_img = np.zeros((16,16,3), dtype=int)

    # lets add some colors, these are the region we want
    for x in range(4,10):
        for y in range(6,12):
            if(x==y):
                continue
            if(x+y<12):
                continue
            if(x+y>16):
                continue
            add_color(base_img, x,y, [255,60,90])

    return base_img

# a hardcoded cropped to generate expected result 
def crop_region_of_interest(img):
    # crop first axis
    cropped = img[4:10]

    # transpose to second axis, so can crop
    cropped = cropped.transpose((1,0,2))
    cropped = cropped[6:12]

    # transpose back
    cropped = cropped.transpose((1,0,2))
    cropped = cropped.transpose((1,0,2))
    cropped = cropped.transpose((1,0,2))

    return cropped

img = generate_fake_image_for_stackoverflow() # to generate a test image
plt.imshow(img)
plt.show()

cropped = crop_region_of_interest(img) # a hardcoded cropped to generate expected result, this to be replaced 
plt.imshow(cropped)
plt.show()

Ответы [ 3 ]

1 голос
/ 18 октября 2019

Я подумал еще об этом, следуя предложению @ Divakar по поводу комментариев. Процесс довольно сложный, поэтому я реорганизовал его в очень короткие функции, чтобы дать всем полезное имя.

def bounds(values):
    # create a slice object representing the range from lowest to highest
    # index value. Add 1 on the high side because of how ranges work
    return slice(min(values), max(values) + 1)

def crop_bounds(mask, axis):
    # find the indexes along this axis where any of the pixels are
    # non-black, then convert those indexes into a bounds slice.
    return bounds(np.where(mask.any(axis)))

def trim(img):
    # True where pixels are non-black.
    mask = np.any(img != 0, axis = 2)
    # Get the crop bounds for each axis, and slice with them.
    return img[crop_bounds(mask, 0)][crop_bounds(mask, 1)]

(Объекты Slice являются встроенным Python, поддерживаемымNumpy. Они в основном представляют значения, используемые в операции среза; x[slice(a,b)] эквивалентно x[a:b].)

0 голосов
/ 20 октября 2019

просто небольшое редактирование решения, предоставленного [https://codereview.stackexchange.com/questions/132914/crop-black-border-of-image-using-numpy]

def crop_image(img,tol=0):
    # img is 2D or 3D image data
    # tol  is tolerance
    mask = img>tol
    if img.ndim==3:
        mask = mask.all(2)
    m,n = mask.shape
    mask0,mask1 = mask.any(0),mask.any(1)
    col_start,col_end = mask0.argmax(),n-mask0[::-1].argmax()
    row_start,row_end = mask1.argmax(),m-mask1[::-1].argmax()
    return img[row_start:row_end,col_start:col_end]

Спасибо @jamal и @ divakar

0 голосов
/ 18 октября 2019

Используйте следующую функцию:

def crop_image(img):
    x_dim = len(img)
    y_dim = len(img[0])

    vertical_bounds = []
    horizontal_bounds = []

    for index_x, line in enumerate(img):
        for index_y, value in enumerate(line):

            if value[0]+value[1]+value[2] != 0:
                vertical_bounds.append(index_x)
                horizontal_bounds.append(index_y)

    cropped = img[min(vertical_bounds):max(vertical_bounds)+1]

    cropped = cropped.transpose((1,0,2))    
    cropped = cropped[min(horizontal_bounds):max(horizontal_bounds)+1]

    cropped = cropped.transpose((1,0,2))
    cropped = cropped.transpose((1,0,2))
    cropped = cropped.transpose((1,0,2))
    return cropped
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...