使用 python 和 opencv 计算盒子的尺寸

问题描述 投票:0回答:1

我正在使用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()

使用图片:

Image used

处理后的图像:

Processed image

python opencv machine-learning deep-learning automation
1个回答
0
投票

我已将代码粘贴到此处。如果对您有帮助请告诉我。

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()
© www.soinside.com 2019 - 2024. All rights reserved.