HumansXドキュメントセンター 公式サイトへ ↗

2.13 マウス操作による対象画像のクロップ

実験の目的

  1. マウスで選択した 2 つの座標点が形成する矩形をクロップ領域とし、その領域の画像を表示します。

  2. マウスイベントに応答して処理できるようになります。

機能要件

マウス操作で対象画像をクロップします。

ハードウェアの準備

No. 名称 数量 備考
1 RDK X5 1 組み込みメインボード(32GB メモリーカード付き)。上位機(PC 側)システムとして動作します。
2 カードリーダー 1 システムイメージの書き込みに使用します。
3 USB カメラ 1 画像を取得します。
4 電源ケーブル 1 電源供給用です。
5 LAN ケーブル 1 ネットワーク接続用です。

回路接続

ソフトウェア設計

設計フローチャート

ソースコードのダウンロード

ソースコードファイル:13_opencv_cut_img_mouse.rar

プログラムコード

完全なプロジェクトコードは(ソースコードファイル)をクリックしてダウンロードしてください。

"""
---------------------------------------------------------------
程序功能: 使用opencv打开USB摄像头,在实时显示的图像中,点击鼠标的任意两个位置,显示出裁剪区域图像(按下键盘的r键,重置裁剪区域)

---------------------------------------------------------------
"""

import cv2

# ==================== 全局变量 ====================
# 存储鼠标点击的两个点坐标
points = []
# 存储裁剪后的图像(保留备用,虽然当前未大量使用)
cropped = None
# 裁剪窗口名称常量
CROP_WINDOW_NAME = 'Cropped Region'

# ==================== 安全销毁窗口函数 ====================
def safe_destroy_window(window_name):
    """
    安全销毁OpenCV窗口(如果窗口存在则销毁,不存在则忽略错误)

    参数:
        window_name: 要销毁的窗口名称
    """
    try:
        # 检查窗口是否存在(getWindowProperty返回-1表示窗口不存在)
        if cv2.getWindowProperty(window_name, cv2.WND_PROP_VISIBLE) >= 0:
            cv2.destroyWindow(window_name)
    except cv2.error:
        # 如果窗口不存在,忽略错误
        pass

# ==================== 鼠标回调函数 ====================
def mouse_callback(event, x, y, flags, param):
    """
    鼠标事件回调函数

    参数:
        event: 鼠标事件类型(如左键按下、右键按下、移动等)
        x, y: 鼠标在窗口中的坐标(像素)
        flags: 事件标志(如Ctrl、Shift等按键状态)
        param: 用户传递的额外参数
    """
    global points  # 声明使用全局变量 points

    # 检测鼠标左键按下事件
    if event == cv2.EVENT_LBUTTONDOWN:
        # 将点击坐标添加到 points 列表
        points.append((x, y))

        # 如果 points 中存储的点超过2个
        if len(points) > 2:
            # 只保留最近的两个点(即最后两个)
            # 这样每次点击新点,会自动丢弃最早的点
            points = points[-2:]

# ==================== 初始化摄像头 ====================
# 打开默认摄像头(设备索引通常是 0)
cap = cv2.VideoCapture(0)

# 检查摄像头是否成功打开
if not cap.isOpened():
    print("错误:无法打开摄像头")
    exit()

# ==================== 创建窗口并绑定鼠标回调 ====================
# 创建名为 'Camera Feed' 的窗口
window_name = 'Camera Feed'
cv2.namedWindow(window_name)

# 将鼠标回调函数绑定到窗口
# 当在 'Camera Feed' 窗口中进行鼠标操作时,会自动调用 mouse_callback
cv2.setMouseCallback(window_name, mouse_callback)

# ==================== 程序使用提示 ====================
print("左键点击两个点以选择矩形区域")
print("按 'r' 重置选区,按 'q' 退出")

# ==================== 主循环:实时采集并处理 ====================
while True:
    # 从摄像头读取一帧图像
    ret, frame = cap.read()

    # 检查是否成功读取到图像
    if not ret:
        print("错误:无法获取帧")
        break

    # 创建原始图像的副本用于显示(避免在原图上直接修改)
    display_frame = frame.copy()

    # ==================== 处理裁剪区域 ====================
    # 如果已经选择了两个点(形成矩形区域)
    if len(points) == 2:
        # 获取两个点的坐标
        x1, y1 = points[0]  # 第一个点的 (x, y)
        x2, y2 = points[1]  # 第二个点的 (x, y)

        # 确定矩形的左上角和右下角坐标
        # 因为用户可能从右下往左上拖拽,需要取最小/最大值
        x_min, x_max = min(x1, x2), max(x1, x2)  # 左边界和右边界
        y_min, y_max = min(y1, y2), max(y1, y2)  # 上边界和下边界

        # 在显示图像上绘制选区矩形框(绿色,线宽2像素)
        # 这样可以直观地看到裁剪区域的位置
        cv2.rectangle(display_frame, (x_min, y_min), (x_max, y_max), (0, 255, 0), 2)

        # 检查矩形是否有效(宽度和高度都大于0)
        if x_max > x_min and y_max > y_min:
            # 从原始图像中裁剪出选中区域
            # 注意:使用 frame(原图)而不是 display_frame(带框的副本)
            cropped = frame[y_min:y_max, x_min:x_max]
            # 在新窗口中显示裁剪后的图像
            cv2.imshow(CROP_WINDOW_NAME, cropped)
        else:
            # 如果矩形无效(宽度或高度为0),则安全关闭裁剪窗口
            safe_destroy_window(CROP_WINDOW_NAME)
    else:
        # 如果未选择两个点(0个或1个点),安全关闭裁剪窗口
        safe_destroy_window(CROP_WINDOW_NAME)

    # ==================== 显示主画面 ====================
    # 显示带有矩形框(如果有)的摄像头画面
    cv2.imshow(window_name, display_frame)

    # ==================== 键盘控制 ====================
    key = cv2.waitKey(1) & 0xFF  # 获取按键(等待1毫秒)

    if key == ord('q'):  # 按 'q' 键退出程序
        break
    elif key == ord('r'):  # 按 'r' 键重置选区
        points = []  # 清空点的列表,清除选区
        safe_destroy_window(CROP_WINDOW_NAME)  # 安全关闭裁剪窗口

# ==================== 资源释放 ====================
cap.release()  # 释放摄像头设备
cv2.destroyAllWindows()  # 关闭所有OpenCV创建的窗口

操作手順

  1. ターミナルを開き、Python プログラムのディレクトリに移動してプログラムを実行します。以下のコマンドを入力してください。
python 13_opencv_cut_img_mouse.py

実験結果

USB カメラを開き、マウスで任意の 2 点をクリックして矩形のクロップ領域を選択すると、クロップ結果がリアルタイムで表示されます。選択範囲のリセットにも対応しています。

参考結果:

お問い合わせ

資料のダウンロード・技術サポートについては、HumansX株式会社までお問い合わせください。