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

2.15 回転画像の動的リアルタイム表示

実験の目的

  1. カメラで画像を取得し、元画像と動的に回転する画像を並べて表示します。

機能要件

回転画像を動的にリアルタイム表示します。

ハードウェアの準備

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

回路接続

ソフトウェア設計

設計フローチャート

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

ソースコードファイル:15_opencv_rotate_img_gif.rar

プログラムコード

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

"""
---------------------------------------------------------------
程序功能: 使用opencv打开USB摄像头,在实时显示的图像中,动态实时显示旋转图像;

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

import cv2
import numpy as np

# ==================== 辅助函数定义 ====================
def rotate_bound(image, angle):
    """
    完整旋转图像(不裁剪),返回包含整个旋转后图像的新图像

    普通旋转会裁剪掉超出边界的部分,这个函数会计算新图像的尺寸,
    确保旋转后的完整图像都在画布内。

    参数:
        image: 输入图像(numpy数组)
        angle: 旋转角度(度数,正值表示逆时针旋转)

    返回:
        旋转后的完整图像(尺寸会自动调整,不会裁剪)
    """
    # 获取原始图像的尺寸
    (h, w) = image.shape[:2]
    # 计算图像中心点坐标(宽度的一半,高度的一半)
    (cX, cY) = (w // 2, h // 2)

    # 获取旋转矩阵
    # cv2.getRotationMatrix2D(center, angle, scale)
    #   center: 旋转中心点
    #   angle: 旋转角度(正值 = 逆时针)
    #   scale: 缩放因子(1.0 表示不缩放)
    # 注意:传入 -angle 是为了让正角度表示逆时针旋转
    M = cv2.getRotationMatrix2D((cX, cY), -angle, 1.0)

    # ========== 计算旋转后图像的新边界尺寸 ==========
    # 从旋转矩阵中提取 cos 和 sin 的绝对值
    # M[0,0] = cosθ, M[0,1] = sinθ
    cos = np.abs(M[0, 0])
    sin = np.abs(M[0, 1])

    # 计算旋转后的新宽度和新高度
    # 公式: new_w = h * |sinθ| + w * |cosθ|
    #      new_h = h * |cosθ| + w * |sinθ|
    new_w = int((h * sin) + (w * cos))
    new_h = int((h * cos) + (w * sin))

    # ========== 调整旋转矩阵的平移部分,使图像居中 ==========
    # 原来旋转矩阵是以原图像中心为中心旋转
    # 现在需要将旋转后的图像平移到新画布的中心位置
    M[0, 2] += (new_w / 2) - cX  # 调整 X 方向平移量
    M[1, 2] += (new_h / 2) - cY  # 调整 Y 方向平移量

    # 执行仿射变换(旋转)
    # cv2.warpAffine(src, M, dsize, flags, borderMode, borderValue)
    #   src: 源图像
    #   M: 变换矩阵
    #   dsize: 输出图像尺寸 (new_w, new_h)
    #   flags: 插值方法(INTER_LINEAR = 线性插值)
    #   borderMode: 边界填充模式(BORDER_CONSTANT = 常数填充)
    #   borderValue: 填充颜色((0,0,0) = 黑色)
    rotated = cv2.warpAffine(
        image, M, (new_w, new_h),
        flags=cv2.INTER_LINEAR,
        borderMode=cv2.BORDER_CONSTANT,
        borderValue=(0, 0, 0)
    )
    return rotated

# ==================== 主程序 ====================
# 打开默认摄像头(设备索引通常是 0)
cap = cv2.VideoCapture(0)

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

print("按 'q' 键退出")

# 初始化旋转角度(0度开始)
angle = 0

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

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

    # ----- 准备原始图像(左半部分)-----
    # 复制原始图像,避免后续操作影响原图
    original = frame.copy()

    # ----- 生成动态旋转图像(右半部分)-----
    # 将当前帧旋转指定角度
    rotated_full = rotate_bound(frame, angle)

    # ========== 统一左右图像的高度(便于拼接) ==========
    # 获取原始图像的高度
    h_orig = original.shape[0]
    # 获取旋转后图像的尺寸
    h_rot, w_rot = rotated_full.shape[:2]

    # 计算缩放比例:将旋转图像缩放到与原始图像相同高度
    scale = h_orig / h_rot
    # 计算缩放后的宽度(按比例缩放,保持宽高比)
    new_w = int(w_rot * scale)

    # 缩放旋转图像
    # cv2.resize(src, dsize, interpolation)
    #   dsize: 目标尺寸 (width, height)
    #   INTER_AREA: 区域插值,适合图像缩小
    rotated_resized = cv2.resize(rotated_full, (new_w, h_orig), 
                                  interpolation=cv2.INTER_AREA)

    # ----- 水平拼接:原始图像 + 旋转图像 -----
    # np.hstack() 将两个图像左右并排拼接
    combined = np.hstack((original, rotated_resized))

    # ----- 显示拼接结果 -----
    cv2.imshow('Original | Rotating', combined)

    # ========== 更新旋转角度(实现动态旋转效果) ==========
    # 角度递增:0 → 1 → 2 → ... → 359 → 0 → 1 → ...
    # % 360 确保角度始终在 0~359 范围内
    angle = (angle + 1) % 360

    # ========== 键盘控制 ==========
    # 等待30毫秒,检测键盘输入
    # 30ms 的延迟同时控制了:
    #   1. 旋转速度(每30ms增加1度,约12秒完成一圈)
    #   2. 帧率(约33 FPS)
    # 如果按下 'q' 键,则退出循环
    if cv2.waitKey(30) & 0xFF == ord('q'):
        break

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

操作手順

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

実験結果

USB カメラを開き、連続的に動的回転する効果を実現します。元画像と回転画像を左右に並べて表示し、回転角度は連続的に増加します(0°→359° を繰り返し)。

参考結果:

お問い合わせ

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