Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
218 views
in Technique[技术] by (71.8m points)

python - How to calculate the distance between two lines?

I have been trying to calculate the distance between two lines in an image in Python. For example, in the image given below, I want to find the perpendicular distance between the two ends of the yellow block. So far I have been only able to derive the distance between two pixels.

Image of engine

The code I could make was to find the distance between red and blue pixels. I figured I could improve this to make the distance between the two points/lines in this image, but no luck yet.

import numpy as np
from PIL import Image
import math

# Load image and ensure RGB - just in case palettised
im = Image.open("2points.png").convert("RGB")

# Make numpy array from image
npimage = np.array(im)

# Describe what a single red pixel looks like
red = np.array([255,0,0],dtype=np.uint8)

# Find [x,y] coordinates of all red pixels
reds = np.where(np.all((npimage==red),axis=-1))

print(reds)

# Describe what a single blue pixel looks like
blue=np.array([0,0,255],dtype=np.uint8)

# Find [x,y] coordinates of all blue pixels
blues=np.where(np.all((npimage==blue),axis=-1))

print(blues)

dx2 = (blues[0][0]-reds[0][0])**2          # (200-10)^2
dy2 = (blues[1][0]-reds[1][0])**2          # (300-20)^2
distance = math.sqrt(dx2 + dy2)
print(distance)
question from:https://stackoverflow.com/questions/65841870/how-to-calculate-the-distance-between-two-lines

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

While preparing this answer, I realized, that my hint regarding cv2.boxPoints was misleading. Of course, I had cv2.boundingRect on my mind – sorry for that!

Nevertheless, here's the full step-by-step approach:

  1. Use cv2.inRange to mask all yellow pixels. Attention: Your image has JPG artifacts, such that you get a lot of noise in the mask, cf. the output:

Mask

  1. Use cv2.findContours to find all contours in the mask. That'll be over 50, due to the many tiny artifacts.

  2. Use Python's max function on the (list of) found contours using cv2.contourArea as key to get the largest contour.

  3. Finally, use cv2.boundingRect to get the bounding rectangle of the contour. That's a tuple (x, y, widht, height). Just use the last two elements, and you have your desired information.

That'd be my code:

import cv2

# Read image with OpenCV
img = cv2.imread('path/to/your/image.ext')

# Mask yellow color (0, 255, 255) in image; Attention: OpenCV uses BGR ordering
yellow_mask = cv2.inRange(img, (0, 255, 255), (0, 255, 255))

# Find contours in yellow mask w.r.t the OpenCV version
cnts = cv2.findContours(yellow_mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]

# Get the largest contour
cnt = max(cnts, key=cv2.contourArea)

# Get width and height from bounding rectangle of largest contour
(x, y, w, h) = cv2.boundingRect(cnt)
print('Width:', w, '| Height:', h)

The output

Width: 518 | Height: 320

seems reasonable.

----------------------------------------
System information
----------------------------------------
Platform:      Windows-10-10.0.16299-SP0
Python:        3.8.5
OpenCV:        4.5.1
----------------------------------------

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...