Как измерить ширину объекта, учитывая, что расстояние от камеры (откалибровано) до моего объекта фиксировано? - PullRequest
0 голосов
/ 27 февраля 2019

Простите меня, потому что я совершенно новичок в кодировании.Для начала, я использую библиотеку привязок Python к OpenCV для целей этого проекта.

Моя камера откалибрована для отображения искажения типа «рыбий глаз».Я получил следующие значения для K и D, матрицы внутренней камеры и матрицы искажений соответственно:

K = [[438.76709 0.00000 338.13894]
[0.00000 440.79169 246.80081]
[0.00000 0.00000 1.00000]]

D = [-0.098034379506 0.054022224927 -0.046172648829 -0.009039512970]

Focal length: 2.8mm
Field of view: 145 degrees (from manual)

Когда я искажаю изображение и отображаю его, я получаю изображение с черными пикселями в областях, которые были растянутыслишком далеко (ожидается).Однако это не мешает вычислению ширины объекта, так как объект не большой, и заполняет 20% изображения.

Я буду размещать объект 10 см от объектива камеры..Исходя из того, что я прочитал о модели камеры с точечным отверстием, мне потребуются внешние параметры, управляющие преобразованием 3D в 2D.Однако я не уверен, как мне его получить.

Предполагая, что у меня есть пиксельные координаты 2 точек (каждая по краям, между которыми я хотел бы измерить расстояние), как мне найтиреальное расстояние между этими двумя точками с использованием этих производных матриц?

Кроме того, если мой прямоугольный объект не параллелен главной оси камеры, существует ли алгоритм для вычисления ширины даже при таких условиях?

Ответы [ 2 ]

0 голосов
/ 16 апреля 2019

Учитывая, что расстояние между вашей камерой и объектом фиксировано, вы можете сначала найти расстояние пикселей между найденными углами , а затем преобразовать его в миллиметр для вашегоШирина объекта с использованием отношения пикселов на миллиметр / масштабного коэффициента.

Используемый алгоритм - определение угла Харриса определение угла Харриса

Захват кадра с находящимся в нем объектом

cap = cv2.VideoCapture(0)
while(True):
#Capture frame-by-frame
ret, frame = cap.read()
cv2.imshow('LIVE FRAME!', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
    break
#Save it to some location
cv2.imwrite('Your location', frame)

Откалибруйте соотношение пикселей на миллиметр, используя сначала эталонный объект.

 #Read Image
image = cv2.imread('Location of your previously saved frame with the object in it.')
object_width = input(int("Enter the width of your object: ")
object_height = input(int("Enter the height of your object: ")


#Find Corners
def find_centroids(dst):
    ret, dst = cv2.threshold(dst, 0.01 * dst.max(), 255, 0)
    dst = np.uint8(dst)

    # find centroids
    ret, labels, stats, centroids = cv2.connectedComponentsWithStats(dst)
    # define the criteria to stop and refine the corners
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 100, 
                0.001)
    corners = cv2.cornerSubPix(gray,np.float32(centroids[1:]),(5,5), 
              (-1,-1),criteria)
    return corners

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = np.float32(gray)
dst = cv2.cornerHarris(gray, 5, 3, 0.04)
dst = cv2.dilate(dst, None)

# Get coordinates of the corners.
corners = find_centroids(dst)



for i in range(0, len(corners)):
    print("Pixels found for this object are:",corners[i])
    image[dst>0.1*dst.max()] = [0,0,255]
    cv2.circle(image, (int(corners[i,0]), int(corners[i,1])), 7, (0,255,0), 2)

for corner in corners:
    image[int(corner[1]), int(corner[0])] = [0, 0, 255]


a = len(corners)
print("Number of corners found:",a)

#List to store pixel difference.
distance_pixel = []

#List to store mm distance.
distance_mm = []


    P1 = corners[0]
    P2 = corners[1]
    P3 = corners[2]
    P4 = corners[3]

    P1P2 = cv2.norm(P2-P1)
    P1P3 = cv2.norm(P3-P1)
    P2P4 = cv2.norm(P4-P2)
    P3P4 = cv2.norm(P4-P3)

    pixelsPerMetric_width1 = P1P2 / object_width
    pixelsPerMetric_width2 = P3P4 / object_width
    pixelsPerMetric_height1 = P1P3 / object_height
    pixelsPerMetric_height2 = P2P4 / object_height



    #Average of PixelsPerMetric
    pixelsPerMetric_avg = pixelsPerMetric_width1 + pixelsPerMetric_width2 + pixelsPerMetric_height1 + pixelsPerMetric_height2 

    pixelsPerMetric = pixelsPerMetric_avg / 4
    print(pixelsPerMetric)
    P1P2_mm = P1P2 / pixelsPerMetric
    P1P3_mm = P1P3 / pixelsPerMetric
    P2P4_mm = P2P4 / pixelsPerMetric
    P3P4_mm = P3P4 / pixelsPerMetric

    distance_mm.append(P1P2_mm)
    distance_mm.append(P1P3_mm)
    distance_mm.append(P2P4_mm)
    distance_mm.append(P3P4_mm)

    distance_pixel.append(P1P2)
    distance_pixel.append(P1P3)
    distance_pixel.append(P2P4)
    distance_pixel.append(P3P4)

Напечатайте расстояние в пикселях и мм, т.е. ваши ширина и высота

print(distance_pixel)
print(distance_mm)

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

0 голосов
/ 28 февраля 2019

Я бы использовал похожие треугольники, чтобы определить, что ширина изображения пропорциональна ширине объекта с масштабным коэффициентом (distance of camera to object)/(focal length), который в вашем случае равен 100/2.8.Это было бы в предположении, что объект находится в центре изображения (то есть непосредственно перед камерой).

...