You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Python+OpenCV检测视频中指定电锯并绘制外接矩形框

问题分析
  • 仅使用了第一张参考图像的特征,其余3张参考图像未参与匹配,有效特征量不足,误匹配概率高
  • 匹配对筛选逻辑过于简单,直接取前10个匹配结果,未过滤误匹配点,大量错误匹配点直接导致框选位置漂移
  • 直接对匹配点取最大最小坐标画框,未考虑目标在视频中存在的旋转、缩放、视角变化,框选范围完全不符合实际目标位置
优化方案
  • 4张参考图像全部参与特征匹配,每帧选择匹配有效点数量最多的参考图像结果计算目标位置
  • 先用KNN匹配加距离阈值筛选粗筛匹配对,再通过RANSAC算法计算单应性矩阵,进一步过滤误匹配点
  • 基于单应性矩阵将参考图像的四个角点透视变换到当前帧,再根据变换后的点计算外接矩形,适配目标的旋转、缩放、视角变化
修正后代码
import numpy as np
import cv2
import matplotlib.pyplot as plt # 如不需要show_img函数可删除

def show_img(img, bw=False):
    fig = plt.figure(figsize=(13,13))
    ax = fig.gca()
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
    ax.imshow(img, cmap='Greys_r' if bw else None)
    plt.show()

# 读取所有参考图并预处理
ref_imgs = []
ref_grays = []
ref_kps = []
ref_des = []
ref_paths = ["saw1.jpg", "saw2.jpg", "saw3.jpg", "saw4.jpg"]
for path in ref_paths:
    img = cv2.imread(path)
    ref_imgs.append(img)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    ref_grays.append(gray)

# 初始化ORB
orb = cv2.ORB_create(nfeatures=2000)
for gray in ref_grays:
    kp, des = orb.detectAndCompute(gray, None)
    ref_kps.append(kp)
    ref_des.append(des)

# 初始化匹配器
matcher = cv2.BFMatcher(cv2.NORM_HAMMING)

cap = cv2.VideoCapture('sawmovie.mp4')

while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        break
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
    frame_kp, frame_des = orb.detectAndCompute(frame_gray, None)
    
    best_h = None
    max_good = 0
    # 遍历所有参考图找匹配效果最好的
    for i in range(4):
        if ref_des[i] is None or frame_des is None:
            continue
        # KNN匹配
        matches = matcher.knnMatch(ref_des[i], frame_des, k=2)
        # 距离阈值筛选
        good = []
        for m, n in matches:
            if m.distance < 0.75 * n.distance:
                good.append(m)
        # 有效匹配点数量足够才计算单应性
        if len(good) > 10 and len(good) > max_good:
            max_good = len(good)
            src_pts = np.float32([ref_kps[i][m.queryIdx].pt for m in good]).reshape(-1,1,2)
            dst_pts = np.float32([frame_kp[m.trainIdx].pt for m in good]).reshape(-1,1,2)
            # RANSAC过滤误匹配
            H, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)
            if H is not None:
                best_h = H
                best_ref_idx = i
    
    # 找到有效单应性矩阵则画框
    if best_h is not None:
        h, w = ref_grays[best_ref_idx].shape
        # 参考图四个角点
        ref_corners = np.float32([[0,0], [0,h-1], [w-1,h-1], [w-1,0]]).reshape(-1,1,2)
        # 变换到当前帧
        frame_corners = cv2.perspectiveTransform(ref_corners, best_h)
        # 计算外接矩形
        x,y,w,h = cv2.boundingRect(frame_corners)
        # 画框
        cv2.rectangle(frame, (x,y), (x+w, y+h), (255,0,0), 2)
    
    cv2.imshow('Frame', frame)
    if cv2.waitKey(25) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()
运行说明
  • 请将代码中参考图路径、视频路径替换为本地实际路径
  • 可根据实际匹配效果调整ORB的nfeatures参数、KNN匹配的距离阈值、RANSAC的重投影误差阈值参数
  • 如果目标在视频中运动速度较快,可降低waitKey的等待时长提升帧率

内容的提问来源于stack exchange,提问作者LordKroak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.22 02:12:16