Stokry

Posted on

# How to calculate the distance between the objects in the image with Python

Today I want to show you how to calculate the distance between the objects in the image. We will write an awesome algorithm that you can modify and extend to your needs.

This is our test image:

First, we need to import the necessary packages:

``````from scipy.spatial import distance as dist
from imutils import perspective
from imutils import contours
import numpy as np
import argparse
import imutils
import cv2
``````

Then we construct the argument parse and parse the arguments

``````def midpoint(ptA, ptB):
return ((ptA[0] + ptB[0]) * 0.5, (ptA[1] + ptB[1]) * 0.5)
``````

after that we load the image, convert it to grayscale:

``````image = cv2.imread('images/test.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray, (7, 7), 0)
``````

then we perform edge detection and close gaps in between object edges:

``````edged = cv2.Canny(gray, 50, 100)
edged = cv2.dilate(edged, None, iterations=1)
edged = cv2.erode(edged, None, iterations=1)
``````

find contours in the edge map

``````cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)
``````

then initialize the distance colors and reference object:

``````(cnts, _) = contours.sort_contours(cnts)
colors = ((0, 0, 255), (240, 0, 159), (0, 165, 255), (255, 255, 0),
(255, 0, 255))
refObj = None
``````

then we loop over the contours individually:

``````for c in cnts:
if cv2.contourArea(c) < 100:
continue
box = cv2.minAreaRect(c)
box = cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box)
box = np.array(box, dtype="int")
box = perspective.order_points(box)
cX = np.average(box[:, 0])
cY = np.average(box[:, 1])
if refObj is None:
(tl, tr, br, bl) = box
(tlblX, tlblY) = midpoint(tl, bl)
(trbrX, trbrY) = midpoint(tr, br)
D = dist.euclidean((tlblX, tlblY), (trbrX, trbrY))
refObj = (box, (cX, cY), D / 70)
continue
orig = image.copy()
cv2.drawContours(orig, [box.astype("int")], -1, (0, 255, 0), 2)
cv2.drawContours(orig, [refObj[0].astype("int")], -1, (0, 255, 0), 2)
refCoords = np.vstack([refObj[0], refObj[1]])
objCoords = np.vstack([box, (cX, cY)])
``````

then we loop over the original points:

``````for ((xA, yA), (xB, yB), color) in zip(refCoords, objCoords, colors):
cv2.circle(orig, (int(xA), int(yA)), 5, color, -1)
cv2.circle(orig, (int(xB), int(yB)), 5, color, -1)
cv2.line(orig, (int(xA), int(yA)), (int(xB), int(yB)),
color, 2)
D = dist.euclidean((xA, yA), (xB, yB)) / refObj[2]
(mX, mY) = midpoint((xA, yA), (xB, yB))
cv2.putText(orig, "{:.1f}in".format(D), (int(mX), int(mY - 10)),
cv2.FONT_HERSHEY_SIMPLEX, 0.55, color, 2)
cv2.imshow("Image", orig)
cv2.waitKey(0)
cv2.destroyAllWindows()
``````

This is our final result:

Thank you all.

victori polly

hi, how can i calculate the object size (width, length, x, y)

Stokry • Edited

`cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)

for c in cnts:
if cv2.contourArea(c) < 100:
continue

``````rect = cv2.minAreaRect(c)
box = cv2.boxPoints(rect)
box = np.array(box, dtype="int")
box = perspective.order_points(box)

width = dist.euclidean(box[0], box[1])
height = dist.euclidean(box[1], box[2])

if refObj is not None:
width = width / refObj[2]
height = height / refObj[2]

cv2.drawContours(image, [box.astype("int")], -1, (0, 255, 0), 2)

cv2.putText(image, "{:.1f}in".format(width), (int(box[0][0]), int(box[0][1])),
cv2.FONT_HERSHEY_SIMPLEX, 0.55, (255, 255, 255), 2)
cv2.putText(image, "{:.1f}in".format(height), (int(box[2][0]), int(box[2][1])),
cv2.FONT_HERSHEY_SIMPLEX, 0.55, (255, 255, 255), 2)
``````

cv2.imshow("Image", image)
cv2.waitKey(0)
cv2.destroyAllWindows()`

Remember to replace "images/test.jpg" with the actual path of your image and adjust the contour area threshold and other parameters as needed for your specific use case. You need to test this out, this is just quick example

Samuel Saldaña

Hi, how calculate the object and its distances... i'm using this code and the results not are according with the reality (inches).

samuelsaldanav@gmail.com

Thanks.