Qt/C++音视频开发-坐标拾取与区域选择

Qt/C++音视频开发-坐标拾取与区域选择

介绍

在音视频开发中,常常需要从视频流或图像中选取特定的矩形区域,这些区域可能用于目标检测、特征提取等多种应用场景。本文将介绍如何使用Qt和C++来实现鼠标点击获取矩形区域,并转换到视频源的真实坐标。

应用使用场景

  • 视频监控:设定监控区域以便触发警报。
  • 图像处理:选择区域进行特征提取或者图像增强。
  • 目标跟踪:在视频流中选定目标初始位置用于后续处理。
  • 交互式工具:允许用户在视频帧上标注感兴趣区域。

以下是各个功能的代码示例实现。为了简洁起见,这里使用了Python和OpenCV库。

1. 视频监控:设定监控区域以便触发警报

import cv2

# 创建视频捕捉对象
cap = cv2.VideoCapture('video.mp4')

def set_monitor_area(event, x, y, flags, param):
    global roi_pts, selecting
    if event == cv2.EVENT_LBUTTONDOWN:
        roi_pts = [(x, y)]
        selecting = True
    elif event == cv2.EVENT_LBUTTONUP:
        roi_pts.append((x, y))
        selecting = False
        cv2.rectangle(frame, roi_pts[0], roi_pts[1], (0, 255, 0), 2)

roi_pts = []
selecting = False

cv2.namedWindow("Frame")
cv2.setMouseCallback("Frame", set_monitor_area)

while True:
    ret, frame = cap.read()
    if not ret:
        break
    
    if len(roi_pts) == 2:
        cv2.rectangle(frame, roi_pts[0], roi_pts[1], (0, 255, 0), 2)
    
    cv2.imshow("Frame", frame)
    
    key = cv2.waitKey(1)
    if key == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

2. 图像处理:选择区域进行特征提取或者图像增强

import cv2

def process_image(img, roi):
    x1, y1, x2, y2 = roi
    roi_img = img[y1:y2, x1:x2]
    enhanced_img = cv2.equalizeHist(cv2.cvtColor(roi_img, cv2.COLOR_BGR2GRAY))
    img[y1:y2, x1:x2] = cv2.cvtColor(enhanced_img, cv2.COLOR_GRAY2BGR)
    return img

roi = (100, 100, 200, 200)
img = cv2.imread('image.jpg')
processed_img = process_image(img, roi)

cv2.imshow('Processed Image', processed_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

3. 目标跟踪:在视频流中选定目标初始位置用于后续处理

import cv2

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

ret, frame = cap.read()
bbox = cv2.selectROI(frame, False)

tracker = cv2.TrackerKCF_create()
tracker.init(frame, bbox)

while True:
    ret, frame = cap.read()
    if not ret:
        break
    
    success, box = tracker.update(frame)
    if success:
        p1 = (int(box[0]), int(box[1]))
        p2 = (int(box[0] + box[2]), int(box[1] + box[3]))
        cv2.rectangle(frame, p1, p2, (0, 255, 0), 2)
    
    cv2.imshow("Tracking", frame)
    
    key = cv2.waitKey(1)
    if key == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()

4. 交互式工具:允许用户在视频帧上标注感兴趣区域

import cv2

drawing = False
ix, iy = -1, -1

def draw_rectangle(event, x, y, flags, param):
    global ix, iy, drawing, img

    if event == cv2.EVENT_LBUTTONDOWN:
        drawing = True
        ix, iy = x, y

    elif event == cv2.EVENT_MOUSEMOVE:
        if drawing:
            img_copy = img.copy()
            cv2.rectangle(img_copy, (ix, iy), (x, y), (0, 255, 0), 2)
            cv2.imshow('Image', img_copy)

    elif event == cv2.EVENT_LBUTTONUP:
        drawing = False
        cv2.rectangle(img, (ix, iy), (x, y), (0, 255, 0), 2)
        cv2.imshow('Image', img)

img = cv2.imread('image.jpg')
cv2.namedWindow('Image')
cv2.setMouseCallback('Image', draw_rectangle)

while True:
    cv2.imshow('Image', img)
    if cv2.waitKey(20) & 0xFF == 27:  # ESC key to exit
        break

cv2.destroyAllWindows()

这些代码示例展示了如何使用OpenCV实现各种与视频监控、图像处理、目标跟踪和交互式工具相关的功能。可以根据需要进行调整和扩展。

原理解释

通过鼠标点击和拖动事件,可以捕获用户在窗口上的操作,从而确定一个矩形区域。该区域可以映射回视频源中的实际坐标,实现对视频内容的精准定位。

算法原理

  1. 鼠标事件捕捉

    • 按下(Press)事件:记录起始点。
    • 移动(Move)事件:实时更新终点并绘制矩形。
    • 松开(Release)事件:确定最终的矩形区域。
  2. 坐标转换

    • 将窗口坐标转换为视频源坐标。这需要考虑窗口大小与视频源分辨率的比例关系。

算法流程图

继续拖动
松开鼠标
按下鼠标
记录起始点
拖动鼠标
实时更新终点和绘制矩形
确定矩形区域
转换为视频源坐标

算法原理解释

  1. 初始化捕捉状态:监听鼠标事件,准备开始捕捉。
  2. 捕捉起始点:当鼠标按下时,记录起始点坐标。
  3. 绘制矩形框:随着鼠标移动,动态绘制矩形框,以提供即时反馈。
  4. 捕捉终点:当鼠标释放时,记录终点坐标。
  5. 坐标转换:将窗口坐标系下的矩形区域转换为视频源坐标系下的矩形区域。

实际应用代码示例

主程序代码

#include <QApplication>
#include <QWidget>
#include <QMouseEvent>
#include <QPainter>

class RectPicker : public QWidget {
    
    
    Q_OBJECT

public:
    RectPicker(QWidget *parent = nullptr) : QWidget(parent), isSelecting(false) {
    
    }

protected:
    void mousePressEvent(QMouseEvent *event) override {
    
    
        if (event->button() == Qt::LeftButton) {
    
    
            startPoint = event->pos();
            isSelecting = true;
        }
    }

    void mouseMoveEvent(QMouseEvent *event) override {
    
    
        if (isSelecting) {
    
    
            endPoint = event->pos();
            update();
        }
    }

    void mouseReleaseEvent(QMouseEvent *event) override {
    
    
        if (isSelecting && event->button() == Qt::LeftButton) {
    
    
            endPoint = event->pos();
            isSelecting = false;
            update();
            // 这里可以添加代码,将窗口坐标转换为视频源坐标
        }
    }

    void paintEvent(QPaintEvent *event) override {
    
    
        Q_UNUSED(event);
        QPainter painter(this);
        if (isSelecting) {
    
    
            QRect rect(startPoint, endPoint);
            painter.setPen(Qt::DashLine);
            painter.drawRect(rect);
        }
    }

private:
    bool isSelecting;
    QPoint startPoint;
    QPoint endPoint;
};

测试代码

int main(int argc, char *argv[]) {
    
    
    QApplication app(argc, argv);
    RectPicker window;
    window.resize(800, 600);
    window.show();
    return app.exec();
}

坐标转换示例

void convertToVideoSourceCoordinates(QRect &rect, QSize widgetSize, QSize videoSize) {
    
    
    double xRatio = static_cast<double>(videoSize.width()) / widgetSize.width();
    double yRatio = static_cast<double>(videoSize.height()) / widgetSize.height();

    rect.setX(static_cast<int>(rect.x() * xRatio));
    rect.setY(static_cast<int>(rect.y() * yRatio));
    rect.setWidth(static_cast<int>(rect.width() * xRatio));
    rect.setHeight(static_cast<int>(rect.height() * yRatio));
}

部署场景

  • 桌面应用程序:可以直接打包成可执行文件,在具有Qt运行环境的系统上运行。
  • 嵌入式设备:例如,部署在智能摄像头系统中,用于实时视频分析。

材料链接

总结

在音视频开发中,通过Qt和C++实现坐标拾取与矩形区域选定是常见需求。本文详细介绍了算法原理、流程以及具体实现方法,并提供了完整示例代码。

未来展望

未来可以结合更多高级功能,例如:

  • 动态缩放和旋转矩形区域。
  • 集成图像处理算法,对选定区域进行实时分析。
  • 使用机器学习模型对选定区域进行分类或识别,提高自动化程度。

猜你喜欢

转载自blog.csdn.net/feng1790291543/article/details/142167571