У меня есть изображение в градациях серого с черным фоном и некоторые нечерные объекты на нем, например:
Теперь я хочу найти минимальную (прямоугольную) ограничивающую рамку для каждого объекта. Я могу предоставить отправную точку внутри каждого объекта, если это поможет.
Поскольку нет никаких причудливых порогов или чего-то еще, я бы хотел избежать чего-то вроде Canny для поиска контуров. Если пиксель не равен 0, он находится в капле.
Независимо от того, что вы используете, вам все равно придется перебирать все пиксели. хотя Bitmap.GetPixel(x,y)
в основном используется, но он очень медленный. но если вы заблокируете биты в памяти и зациклите массив байтов, это будет в сотни раз быстрее.
пожалуйста, взгляните на этот документ для блокировки битов изображения в памяти.
Реализация цикла самостоятельно не будет проблемой, я также знаком с битовой блокировкой. Я просто подумал, что такую простую задачу, вероятно, можно решить с помощью некоторых существующих библиотечных функций, вместо того, чтобы самому изобретать велосипед. Что также библиотека, скорее всего, будет перебирать все пиксели, да, понятно. Но все же, зачем заново изобретать велосипед.
Я не уверен, существует ли такая библиотека или нет. Но если вы начали изобретать колесо, оно у вас уже есть.
Или я бы все еще отлаживал какой-то странный пограничный случай. Версия @Carlos Melus отлично работает, поэтому для этого есть библиотечная функция. И дело не в том, что я провел время в ожидании ответа, рисуя что-то, а в это время я сделал кое-что еще. Так что в целом это было самое быстрое и чистое решение.
Чтобы нарисовать прямоугольники вокруг всего, что не является полностью черным на вашем изображении, вы можете сделать следующее:
imagefile = '/path/to/your/image'
img = cv2.imread(imagefile)
# Convert you image to grayscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# Threshold the image to extract only objects that are not black
# You need to use a one channel image, that's why the slice to get the first layer
tv, thresh = cv2.threshold(gray[:,:,0], 1, 255, cv2.THRESH_BINARY)
# Get the contours from your thresholded image
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]
# Create a copy of the original image to display the output rectangles
output = img.copy()
# Loop through your contours calculating the bounding rectangles and plotting them
for c in contours:
x, y, w, h = cv2.boundingRect(c)
cv2.rectangle(output, (x,y), (x+w, y+h), (0, 0, 255), 2)
# Display the output image
plt.imshow(cv2.cvtColor(output, cv2.COLOR_BGR2RGB))
Ищите алгоритмы трассировки краев. Если вы не знаете, сколько пятен, начните с чтения горизонтальных и вертикальных линий на изображении в поисках пятен. Как только вы найдете его, найдите край и обведите его. Затем продолжайте искать кляксы, удаляя те, которые вы уже нашли. Чем больше правил для больших двоичных объектов вы знаете (минимальный размер, количество больших двоичных объектов и т. д.), тем быстрее это будет работать. Я только что перечитал, у вас есть отправная точка в блоге. Посмотрите вниз оттуда, чтобы найти край, затем идите.