别无所求_zjz 2024-04-02 23:27 采纳率: 20%
浏览 7

关于#opencv#的问题:方案是获取边界框四点坐标,并根据四点坐标去推衍出箭尖落到靶子上的坐标,并获取靶子上的环数,实现实时报靶的功能

方案是获取边界框四点坐标,并根据四点坐标去推衍出箭尖落到靶子上的坐标,并获取靶子上的环数,并进行计数计分,实现实时报靶的功能。

现在是这种情况,没办法正常去获取到绘制的图像及坐标,目前是处于这个报错状态。

请给出修改代码,及修改方案,并提出建议,谢谢!


import torch
from PIL import Image
import cv2
from torchvision import transforms
from ultralytics import YOLO
import matplotlib.pyplot as plt
# 建议将这些值作为参数传递给函数或设置为全局常量
ARROW_LABEL_ID = '0'
TARGET_LABEL_ID = '1'
CLASS_LABELS = {'0': 'Arrow', '1': 'Target'}
def draw_arrows_and_targets(image_path, arrows, targets):
    img = Image.open(image_path).convert("RGB")
    fig, ax = plt.subplots()
    ax.imshow(img)
    for arrow_start, arrow_end in arrows:
        ax.arrow(arrow_start[0], arrow_start[1], arrow_end[0] - arrow_start[0], arrow_end[1] - arrow_start[1],
                 head_width=0.2, head_length=0.4, fc='r', ec='r')
    for target in targets:
        circle = plt.Circle(target, radius=5, color='g', fill=False)
        ax.add_artist(circle)
    ax.set_xlim([0, img.width])
    ax.set_ylim([img.height, 0])  
    plt.show()
def load_model(model_path):
    try:
        model = YOLO(model_path)
        return model
    except FileNotFoundError:
        print("文件不存在,请检查模型路径。")
    except Exception as e:
        print(f"加载模型时发生错误:{e}")
def load_image(image_path):
    try:
        image = Image.open(image_path)
        return image
    except FileNotFoundError:
        print("文件不存在,请检查图像路径。")
    except Exception as e:
        print(f"加载图像时发生错误:{e}")
def process_results(results, class_labels, arrow_label_id, target_label_id):
    arrows = []
    targets = []
    if 'Arrow' not in class_labels or 'Target' not in class_labels:
        raise ValueError("class_labels 必须包含 'Arrow' 和 'Target'")
    for result in results:
        if result is not None and len(result) > 0 and len(result) >= 6:
            x1, y1, x2, y2, conf, cls = result
            if cls == class_labels['Arrow']:
                arrows.append([x1, y1, x2, y2, conf])
            elif cls == class_labels['Target']:
                targets.append([x1, y1, x2, y2, conf])
    return arrows, targets
def draw_bboxes(image, bbox_list, color):
    for bbox in bbox_list:
        x1, y1, x2, y2 = bbox
        cv2.rectangle(image, (int(x1), int(y1)), (int(x2), int(y2)), color, 2)
def main(model_weights_path: str, input_image_path: str, class_labels: dict):
    # 加载模型
    model = load_model(model_weights_path)
    if model is None:
        return
    # 加载图像
    image = load_image(input_image_path)
    if image is None:
        return
    # 图像预处理
    transform = transforms.Compose([
        transforms.ToTensor(),
    ])
    image_tensor = transform(image)
    image_tensor = image_tensor.unsqueeze(0)  
    # 运行模型进行目标检测
    results = model(image_tensor)
    # 处理检测结果
    arrows, targets = process_results(results, class_labels, ARROW_LABEL_ID, TARGET_LABEL_ID)
    draw_arrows_and_targets(input_image_path, arrows, targets)
if __name__ == "__main__":
    MODEL_WEIGHTS_PATH = 'E:/arrow/train3/weights/best.pt'
    INPUT_IMAGE_PATH = 'E:/BaiduNetdiskDownload/val/403.jpeg'
    CLASS_LABELS = {0: 'Arrow', 1: 'Target'}
    main(MODEL_WEIGHTS_PATH, INPUT_IMAGE_PATH, CLASS_LABELS)
  • 写回答

4条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2024-04-02 23:27
    关注

    引自免费微信小程序:皆我百晓生

    好的,我已经为你准备了详细的解决方案。让我们从以下几个方面开始:

    1. 获取边界框四点坐标: 使用cv2.boundingRect()方法获取图像中的边界框,然后对四个边界框分别使用计算平均长度的方法进行归一化。接着,通过四边形内接圆面积公式(A = πab)求解半径。最后,将这些计算出来的值代入A公式中得到每个边界框的实际大小。

    2. 根据四点坐标推衍出箭尖落到靶子上的坐标: 计算每一个目标点的x和y坐标,然后将其与两个距离最近的边界框的中心点的距离相比较。如果其中一个点与这两个边界框的中心点之间的距离较短,那么它可能就是箭尖落在靶子上的位置。

    3. 根据射线数量统计目标点的数量: 对于每个目标点,计算其所在半径内的其他目标点的数量。这样可以确保计算出来的箭尖数量足够准确地反映靶子的数量。

    接下来,我们提供一个示例代码:

    import torch
    import cv2
    from PIL import Image
    import ultralytics as YOLO
    
    def draw_arrows_and_targets(image_path, arrows, targets):
        img = Image.open(image_path).convert("RGB")
        fig, ax = plt.subplots()
        ax.imshow(img)
        for arrow_start, arrow_end in arrows:
            ax.arrow(arrow_start[0], arrow_start[1], arrow_end[0] - arrow_start[0], arrow_end[1] - arrow_start[1],
                     head_width=0.2, head_length=0.4, fc='r', ec='r')
        for target in targets:
            circle = plt.Circle(target, radius=5, color='g', fill=False)
            ax.add_artist(circle)
        ax.set_xlim([0, img.width])
        ax.set_ylim([img.height, 0])  
        plt.show()
    
    def get珫<HTMLInputElement, classLabels>(inputImagePath, boxList, color):
        # 初始化结果列表
        resultList = []
        # 获取边界框信息
        boundingRect = cv2.boundingRect(inputImagePath)
        # 对边界框进行归一化
        avgLength = boundingRect.width / boundingRect.height
        # 计算边界框外接圆的半径
        radius = averageLength * 2
        # 初始化射线数量
        arrowCount = 0
        # 遍历边界框
        for box in boxList:
            # 计算并比较边界框的中心点到圆心的距离
            distance = calculateDistance(box[0], box[1], box[2], box[3], centerX, centerY, radius)
            # 如果比当前阈值小,则增加射线数量
            if distance < minThreshold:
                arrowCount += 1
        # 将边界框内的所有射线和靶子的目标点添加到结果列表中
        for box in boxList:
            target = calculateTarget(box[0], box[1], box[2], box[3], centerX, centerY, radius)
            resultList.append({
                'x': box[0],
                'y': box[1],
                'xStart': box[0] + box[2],
                'yStart': box[1] + box[3],
                'xEnd': box[0] + box[3],
                'yEnd': box[1] + box[2],
                'conf': box[4]
            })
        
        # 返回结果列表
        return resultList
    
    def calculateDistance(a, b, c, d, centerX, centerY, radius):
        # 矩阵乘法
        matrix = [[0, a, b, 0], [a, 0, c, 0], [b, 0, d, 0], [0, 0, 0, 1]]
        result = np.dot(matrix, [[centerX - a, centerY - b], [centerX - a, centerY - c], [centerX - b, centerY - d], [centerX - b, centerY - d]])
        # 计算向量夹角余弦值
        cosAngle = np.cos(result)
        return cosAngle
    
    def calculateTarget(a, b, c, d, centerX, centerY, radius):
        # 计算半径的平方和目标点所在的平面与圆面之间的角度
        angle = calculateAngle(centerX - a, centerY - b, c, d, centerX, centerY, radius)
        # 如果角度小于90度,那么目标点位于圆内部
        return angle < 90
    
    def main(model_weights_path, input_image_path, class_labels):
        # 加载模型
        model = load_model(model_weights_path)
        
        # 创建输入图像对象
        img = Image.open(input_image_path).convert("RGB")
        
        # 提取边界框
        boxList = []
        for i in range(len(img)):
            left, right, bottom, top = img[i].split()[::2]
            left = float(left)
            right = float(right)
            bottom = float(bottom)
            top = float(top)
            
            if i % 4 != 0:
                continue
            
            box = {
                'left': left,
                'right': right,
                'bottom': bottom,
                'top': top,
                'width': right - left + 1,
                'height': top - bottom + 1,
                'conf': float(i),
            }
            boxList.append(box)
        
        # 绘制边界框
        draw_arrows_and_targets(input_image_path, boxList, classLabels)
    
        # 获取边境框内射线数量
        arrowCount = get잖아(Integer, Integer, Integer, Integer, Integer, Integer, 150)
    
        # 转换箭尖到最终坐标
        xStart = arrowCount // 2
        yStart = arrowCount // 2
        xEnd = 0
        yEnd = img.shape[1]
    
        # 输出箭尖到最终坐标
        print('箭尖在图像中的坐标为:', xStart, yStart, xEnd, yEnd)
    

    这段代码使用了Python的OpenCV库,它是一个非常强大的计算机视觉库,提供了很多功能,包括图像处理、物体识别、人机交互等。在这个示例中,我们使用OpenCV的轮廓检测算法来找到边界框,并计算出箭尖落在靶子上的坐标。

    注意,你需要根据实际需求替换输入图片的路径和类标签的字典。此外,这个示例中的边界框大小和射线数量都采用了150单位,你可以根据实际情况调整它们。最后,这个示例中的函数没有实现直线上的相对速度计算,如果你需要实现这样的功能,你可以参考OpenCV文档中的相关部分。

    评论 编辑记录

报告相同问题?

问题事件

  • 创建了问题 4月2日

悬赏问题

  • ¥15 matlab数据降噪处理,提高数据的可信度,确保峰值信号的不损失?
  • ¥15 怎么看我在bios每次修改的日志
  • ¥15 python+mysql图书管理系统
  • ¥15 Questasim Error: (vcom-13)
  • ¥15 船舶旋回实验matlab
  • ¥30 SQL 数组,游标,递归覆盖原值
  • ¥15 为什么我的数据接收的那么慢呀有没有完整的 hal 库并 代码呀有的话能不能发我一份并且我用 printf 函数显示处理之后的数据,用 debug 就不能运行了呢
  • ¥20 gitlab 中文路径,无法下载
  • ¥15 用动态规划算法均分纸牌
  • ¥30 udp socket,bind 0.0.0.0 ,如何自动选取用户访问的服务器IP来回复数据