我正在使用Python绘制盒子照片的轮廓,并使用opencv在盒子的轮廓上画线,我想做的是计算,如附图所示。 绘制另一个不同颜色的轮廓并标记顶点(tl、tr、br、bl)。 我想做的是计算宽度(BL + BR)、高度(BL,TL)和长度(TL,TR)。 但这样做时,它会采用其他参考来计算不同的尺寸。
我正在尝试计算盒子的大小,尝试获取宽度、高度和长度。
import cv2
import numpy as np
from scipy.spatial import distance as dist
def tup(point):
return (int(point[0]), int(point[1]))
# Function to order points in the correct order
def order_points(pts):
rect = np.zeros((4, 2), dtype="float32")
s = pts.sum(axis=1)
rect[0] = pts[np.argmin(s)]
rect[2] = pts[np.argmax(s)]
diff = np.diff(pts, axis=1)
rect[1] = pts[np.argmin(diff)]
rect[3] = pts[np.argmax(diff)]
return rect
# Load image
img = cv2.imread("boxing.jpg")
# Reduce size to fit on screen
scale = 0.2
h, w = img.shape[:2]
h = int(scale * h)
w = int(scale * w)
img = cv2.resize(img, (w, h))
copy = np.copy(img)
# Convert to hsv
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(hsv)
# Make mask
mask = cv2.inRange(s, 30, 255)
# Dilate and erode to get rid of small holes
kernel = np.ones((5, 5), np.uint8)
mask = cv2.dilate(mask, kernel, iterations=1)
mask = cv2.erode(mask, kernel, iterations=1)
# Find contours
contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contour = max(contours, key=cv2.contourArea) # Use the largest contour
# Approximate the contour to a polygon
epsilon = 0.02 * cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, epsilon, True)
# Draw contour
cv2.drawContours(img, [approx], -1, (0, 0, 200), 2)
# Calculate box dimensions
if len(approx) == 6:
pts = approx.reshape(6, 2)
# Order the points
rect = order_points(pts[:4])
# Calculate the dimensions
(tl, tr, br, bl) = rect
widthA = dist.euclidean(br, bl)
widthB = dist.euclidean(tr, tl)
heightA = dist.euclidean(tr, br)
heightB = dist.euclidean(tl, bl)
maxWidth = max(int(widthA), int(widthB))
maxHeight = max(int(heightA), int(heightB))
print(f"Width: {maxWidth}px")
print(f"Height: {maxHeight}px")
# Draw the points and lines with labels
colors = [(0, 255, 0), (0, 255, 255), (255, 0, 255), (255, 255, 0)]
labels = ["TL", "TR", "BR", "BL"]
for i, point in enumerate(rect):
cv2.circle(img, tup(point), 5, colors[i], -1)
cv2.putText(img, labels[i], tup(point), cv2.FONT_HERSHEY_SIMPLEX, 0.5, colors[i], 2)
cv2.line(img, tup(tl), tup(tr), (0, 255, 0), 2)
cv2.line(img, tup(tr), tup(br), (0, 255, 0), 2)
cv2.line(img, tup(br), tup(bl), (0, 255, 0), 2)
cv2.line(img, tup(bl), tup(tl), (0, 255, 0), 2)
# Show
cv2.imshow("Image", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
使用图片:
处理后的图像:
我已将代码粘贴到此处。如果对您有帮助请告诉我。
import cv2
import numpy as np
from scipy.spatial import distance as dist
def tup(point):
return (int(point[0]), int(point[1]))
def order_points(pts):
rect = np.zeros((4, 2), dtype="float32")
s = pts.sum(axis=1)
rect[0] = pts[np.argmin(s)]
rect[2] = pts[np.argmax(s)]
diff = np.diff(pts, axis=1)
rect[1] = pts[np.argmin(diff)]
rect[3] = pts[np.argmax(diff)]
return rect
image_path = 'Image used path'
img = cv2.imread(image_path)
scale = 0.2
h, w = img.shape[:2]
h = int(scale * h)
w = int(scale * w)
img = cv2.resize(img, (w, h))
copy = np.copy(img)
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
h, s, v = cv2.split(hsv)
mask = cv2.inRange(s, 30, 255)
kernel = np.ones((5, 5), np.uint8)
mask = cv2.dilate(mask, kernel, iterations=1)
mask = cv2.erode(mask, kernel, iterations=1)
contours, _ = cv2.findContours(mask, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
contour = max(contours, key=cv2.contourArea)
epsilon = 0.02 * cv2.arcLength(contour, True)
approx = cv2.approxPolyDP(contour, epsilon, True)
cv2.drawContours(img, [approx], -1, (0, 0, 200), 2)
if len(approx) >= 4:
pts = approx.reshape(len(approx), 2)
rect = order_points(pts[:4])
(tl, tr, br, bl) = rect
width = dist.euclidean(br, bl)
height = dist.euclidean(bl, tl)
length = dist.euclidean(tl, tr)
print(f"Width (BL to BR): {width}px")
print(f"Height (BL to TL): {height}px")
print(f"Length (TL to TR): {length}px")
colors = [(0, 255, 0), (0, 255, 255), (255, 0, 255), (255, 255, 0)]
labels = ["TL", "TR", "BR", "BL"]
for i, point in enumerate(rect):
cv2.circle(img, tup(point), 5, colors[i], -1)
cv2.putText(img, labels[i], tup(point), cv2.FONT_HERSHEY_SIMPLEX, 0.5, colors[i], 2)
cv2.line(img, tup(tl), tup(tr), (0, 255, 0), 2)
cv2.line(img, tup(tr), tup(br), (0, 255, 0), 2)
cv2.line(img, tup(br), tup(bl), (0, 255, 0), 2)
cv2.line(img, tup(bl), tup(tl), (0, 255, 0), 2)
cv2.imshow("Process Image", img)
cv2.waitKey(0)
cv2.destroyAllWindows()