рисование ограничительной рамки на больших изображениях

1

Изображение 174551

У меня большое двоичное изображение (4k x 7k pix), из которого я хочу извлечь всю желтую часть в виде одного прямоугольника. Я попробовал бинарную эрозию, чтобы выровнять объекты внутри желтой области. Затем я использовал метод bbox для skimage.regionprops но он не работает достаточно быстро для большого изображения с одним большим bbox. Есть ли у вас предложения?

Теги:
image-processing
bounding-box
scikit-image
image-morphology

2 ответа

1

Поскольку изображение, которое вы предоставили, включает в себя отвлекающие оси, и является неправильным цветом и слишком маленьким, я создал как реалистичную версию, как я мог с ImageMagick, как это в терминале:

convert bbox.png -alpha off -crop 120x215+40+13 -colorspace gray -normalize -threshold 50% -scale 4200x7200\! bbox.png

Изображение 174551

Полноразмерная версия - 4200x7200.

Затем я написал numpy версию -based на bbox следующим

#!/usr/local/bin/python3
import numpy as np
from PIL import Image

def bbox(image):
    """Find bounding box of image"""
    # Project all columns into row same width as image
    proj=np.any(image,axis=0)
    # Find first non-zero value from Left
    L=np.argmax(proj)
    # And right
    R=image.shape[1]-np.argmax(np.flipud(proj))-1
    # Project all rows into column same height as image
    proj=np.any(image,axis=1)
    # Find first non-zero value from Top
    T=np.argmax(proj)
    # And Bottom
    B=image.shape[0]-np.argmax(np.flipud(proj))-1
    return T,L,B,R

image=np.array(Image.open("a.png").convert("L"))
print(bbox(image))

Это работает на 5,3 мс на моем Mac. Просто для удовольствия я нарезал резьбу и выполнил горизонтальную проекцию и вертикальную проекцию на отдельные параллельные потоки, и она достигла 3,6 мс с теми же результатами.

#!/usr/local/bin/python3
import numpy as np
from PIL import Image

import threading
import queue

def DoOneDim(image,axis,q):
    """Find bounding box of image"""
    proj=np.any(image,axis=axis)
    # Find first non-zero value
    A=np.argmax(proj)
    # And and last
    B=image.shape[1-axis]-np.argmax(np.flipud(proj))-1
    q.put({axis:(A,B)})


def bboxTh(image):
    """Threaded version of bbox() that does vertical and horizontal on their own theads"""
    q = queue.Queue()
    Hthread=threading.Thread(target=DoOneDim, args=(image,0,q))
    Vthread=threading.Thread(target=DoOneDim, args=(image,1,q))
    Hthread.start()
    Vthread.start()
    Hthread.join()
    Vthread.join()
    results=dict()
    while not q.empty():
       results.update(q.get())
    return results

image=np.array(Image.open("a.png").convert("L"))
print(bboxTh(image))

Выбранное поле выглядит так:

Изображение 174551

  • 0
    как часть потока +1
0

Поскольку вы ищете одну ограничительную рамку, не используйте regionprops или любую функцию для каждого объекта. Это также делает так, что вам не нужно пытаться сделать один объект из всех желтых точек.

Простейшим решением здесь является прогулка по изображению, и для каждого пикселя определить, достаточно ли он "достаточно желтый" (что бы это ни значило для вашего приложения). Если это так, добавьте пиксельные координаты в расчет выполняемой рамки.

Расчет ограничивающей коробки довольно прост:

top_left = [1e9, 1e9]
bottom_right = [0, 0]
for ...:
   # within your loop over the pixels, [x, y] are the current coordinates
   top_left = [min(top_left[0], x), min(top_left[1], y)];
   bottom_right = [max(bottom_right[0], x), max(bottom_right[1], y)];

Возможно, с помощью skimage можно сделать это без циклов, но я не знаю этого пакета вообще.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню