#python #opencv #image-processing
Вопрос:
Я пытаюсь отфильтровать короткие строки из моего хитрого обнаружения краев. Вот что я сейчас использую, а также краткое объяснение:
Я начинаю с того, что беру один канал изображения и запускаю CV2 для обнаружения хитрых краев. После этого я просматриваю каждый пиксель и определяю, есть ли вокруг него белые (Правда, 255). Если это так, я добавляю его в группу истинных пикселей, а затем проверяю каждый пиксель вокруг него (и продолжаю зацикливаться, пока не останется белых/истинных пикселей. Затем я заменяю все пиксели на черный/Ложный, если количество групп меньше заданного порогового значения (в данном случае 100 пикселей).
Хотя это работает (как показано ниже), это ужасно медленно. Мне интересно, есть ли более быстрый и простой способ сделать это.
import cv2
img = cv2.imread("edtest.jpg")
img_r = img.copy()
img_r[:, :, 0] = 0
img_r[:, :, 1] = 0
img_r = cv2.GaussianBlur(img_r, (3, 3), 0)
basic_edge = cv2.Canny(img_r, 240, 250)
culled_edge = basic_edge.copy()
min_threshold = 100
for x in range(len(culled_edge)):
print(x)
for y in range(len(culled_edge[x])):
test_pixels = [(x, y)]
true_pixels = [(x, y)]
while len(test_pixels) != 0:
xorigin = test_pixels[0][0]
yorigin = test_pixels[0][1]
if 0 < xorigin < len(culled_edge) - 1 and 0 < yorigin < len(culled_edge[0]) - 1:
for testx in range(3):
for testy in range(3):
if culled_edge[xorigin-1 testx][yorigin - 1 testy] == 255 and (xorigin-1 testx, yorigin-1 testy) not in true_pixels:
test_pixels.append((xorigin-1 testx, yorigin-1 testy))
true_pixels.append((xorigin-1 testx, yorigin-1 testy))
test_pixels.pop(0)
if 1 < len(true_pixels) < min_threshold:
for i in range(len(true_pixels)):
culled_edge[true_pixels[i][0]][true_pixels[i][1]] = 0
cv2.imshow("basic_edge", basic_edge)
cv2.imshow("culled_edge", culled_edge)
cv2.waitKey(0)
Исходное Изображение:
Точное обнаружение и отфильтрованные (идеальные) результаты:
Комментарии:
1. Вы можете получить контуры своих краев, а затем отфильтровать область контура или периметр. Вы также можете использовать connectedComponentsWithStats() и фильтр по области.
Ответ №1:
Операция, которую вы применяете, называется открытием области. Я не думаю, что в OpenCV есть реализация, но вы можете найти ее либо в scikit-image ( skimage.morphology.area_opening
), либо в DIPlib ( dip.BinaryAreaOpening
).
Например, с помощью DIPlib (раскрытие информации: я автор) вы бы изменили свой код следующим образом:
import diplib as dip
# ...
basic_edge = cv2.Canny(img_r, 240, 250)
min_threshold = 100
culled_edge = dip.BinaryAreaOpening(basic_edge > 0, min_threshold)
Вывод, culled_edge
, теперь является dip.Image
объектом, который совместим с массивами NumPy, и вы должны иметь возможность использовать его как таковой во многих ситуациях. Если есть проблема, то вы можете вернуть ее в массив NumPy с culled_edge = np.array(culled_edge)
помощью .