2.15 回転画像の動的リアルタイム表示
実験の目的
- カメラで画像を取得し、元画像と動的に回転する画像を並べて表示します。
機能要件
回転画像を動的にリアルタイム表示します。
ハードウェアの準備
| 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创建的窗口
操作手順
- ターミナルを開き、Python プログラムのディレクトリに移動してプログラムを実行します。以下のコマンドを入力してください。
python 15_opencv_rotate_img_gif.py
実験結果
USB カメラを開き、連続的に動的回転する効果を実現します。元画像と回転画像を左右に並べて表示し、回転角度は連続的に増加します(0°→359° を繰り返し)。
参考結果:
お問い合わせ
資料のダウンロード・技術サポートについては、HumansX株式会社までお問い合わせください。
ドキュメント