Как измерить центральный угол с помощью пакета Python cv2 - PullRequest
0 голосов
/ 04 мая 2020

Наша команда создала систему видения с камерой, микроскопом и перестраиваемым объективом, чтобы смотреть на внутреннюю поверхность конуса.

Визуально говоря, камера снимает 12 изображений для одного конуса с каждым изображением охватывая 30 градусов.

Теперь мы собрали много образцов изображений и хотим убедиться, что каждый «веер» (как показано ниже) имеет минимум 30 градусов.

Есть ли способ в Python, с cv2 или другими упаковками, чтобы измерить этот центральный угол. Спасибо.

enter image description here

Ответы [ 2 ]

2 голосов
/ 05 мая 2020

Вот один из способов сделать это в Python / OpenCV.

  • Считать изображение
  • Преобразовать в серый
  • Порог
  • Использовать морфологию открыть и закрыть, чтобы сгладить и заполнить границу
  • Применить выделение края Кенни
  • Разделить изображение на верхний край и нижний край путем зачерчивания противоположной стороны к каждому краю
  • Подгонка линий к верхнему и нижнему краям
  • Вычисление угла каждого ребра
  • Вычисление разницы между двумя углами
  • Нарисуйте линии на входе
  • Сохранить результаты

Ввод:

enter image description here

import cv2
import numpy as np
import math

# read image
img = cv2.imread('cone_shape.jpg')

# convert to grayscale
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# threshold
thresh = cv2.threshold(gray,11,255,cv2.THRESH_BINARY)[1]

# apply open then close to smooth boundary
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (13,13))
morph = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
kernel = np.ones((33,33), np.uint8)
morph = cv2.morphologyEx(morph, cv2.MORPH_CLOSE, kernel)

# apply canny edge detection
edges = cv2.Canny(morph, 150, 200)
hh, ww = edges.shape
hh2 = hh // 2

# split edge image in half vertically and blacken opposite half
top_edge = edges.copy()
top_edge[hh2:hh, 0:ww] = 0
bottom_edge = edges.copy()
bottom_edge[0:hh2, 0:ww] = 0

# get coordinates of white pixels in top and bottom
# note: need to transpose y,x in numpy to x,y for opencv
top_white_pts = np.argwhere(top_edge.transpose()==255)
bottom_white_pts = np.argwhere(bottom_edge.transpose()==255)

# fit lines to white pixels
# (x,y) is point on line, (vx,vy) is unit vector along line
(vx1,vy1,x1,y1) = cv2.fitLine(top_white_pts, cv2.DIST_L2, 0, 0.01, 0.01)
(vx2,vy2,x2,y2) = cv2.fitLine(bottom_white_pts, cv2.DIST_L2, 0, 0.01, 0.01)

# compute angle for vectors vx,vy
top_angle = (180/math.pi)*math.atan(vy1/vx1)
bottom_angle = (180/math.pi)*math.atan(vy2/vx2)
print(top_angle, bottom_angle)

# cone angle is the difference
cone_angle = math.fabs(top_angle - bottom_angle)
print(cone_angle)

# draw lines on input
lines = img.copy()
p1x1 = int(x1-1000*vx1)
p1y1 = int(y1-1000*vy1)
p1x2 = int(x1+1000*vx1)
p1y2 = int(y1+1000*vy1)
cv2.line(lines, (p1x1,p1y1), (p1x2,p1y2), (0, 0, 255), 1)
p2x1 = int(x2-1000*vx2)
p2y1 = int(y2-1000*vy2)
p2x2 = int(x2+1000*vx2)
p2y2 = int(y2+1000*vy2)
cv2.line(lines, (p2x1,p2y1), (p2x2,p2y2), (0, 0, 255), 1)

# save resulting images
cv2.imwrite('cone_shape_thresh.jpg',thresh)
cv2.imwrite('cone_shape_morph.jpg',morph)
cv2.imwrite('cone_shape_edges.jpg',edges)
cv2.imwrite('cone_shape_lines.jpg',lines)

# show thresh and result    
cv2.imshow("thresh", thresh)
cv2.imshow("morph", morph)
cv2.imshow("edges", edges)
cv2.imshow("top edge", top_edge)
cv2.imshow("bottom edge", bottom_edge)
cv2.imshow("lines", lines)
cv2.waitKey(0)
cv2.destroyAllWindows()


С пороговым изображением:

enter image description here

Морфология обработанного изображения:

enter image description here

Край изображения:

enter image description here

Линии на входе:

enter image description here

Угол конуса (в градусах):

42,03975696357633

1 голос
/ 04 мая 2020

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

Существует три подхода, которые могут работать.

1.)

Основная идея c состоит в том, чтобы как-то получить две линии и измерить угол между ними.

  • Определить пороговое значение для определения внешней черной области (вне центральный угол) и установите все значения под ним на ноль.

  • Это также установит некоторые размытые полосы внутри центрального угла на ноль, поэтому мы должны попытаться «залечить» их , Это делается с помощью Морфологические преобразования . Вы можете прочитать о них здесь и здесь .

  • Вы можете попробовать операцию Закрытие , но я не не знаю, исправляет ли это полосы. Обычно это исправляет точки или царапины. Этот ответ , кажется, указывает на то, что он должен работать на линиях.

  • Возможно, в этот момент снова примените размытие по Гауссу и к пороговому значению снова. Затем попробуйте использовать некоторые края или линии обнаружения.

Это в основном попытка и ошибка, вы должны увидеть, что работает.

2.)

  • Еще одна вещь, которая может сработать, это попытаться использовать ar c - enter code here как царапины, возможно, даже укрепить их и использовать Hough Circle Transform . Я думаю, что он также обнаруживает дуги.

  • Просто попробуйте и посмотрите, что возвращает функция. В лучшем случае есть несколько кругов / дуг, которые вы можете использовать для оценки центрального угла.

  • Есть несколько подходов к ar c обнаружение здесь StackOverflow или здесь .

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

  • Этот вопрос может быть полезным.

3.)

  • Применение краевого фильтра, например, Canny skimage.feature.canny

  • Попробуйте несколько сигм и опубликуйте изображения в своем вопросе, затем мы можем подумать, как продолжить.

  • Что может сработать, так это вычислить выпуклую оболочку вокруг всех точек, которые являются частью края. Затем получите две линии, которые образуют центральный угол из выпуклой оболочки.

...