2.14 さまざまな角度での画像の回転
実験の目的
-
画像を取得し、さまざまな角度で回転させた画像を表示します。
-
回転変換を応用できるようになります。
機能要件
さまざまな角度で画像を回転させ、結果を表示します。
ハードウェアの準備
| No. | 名称 | 数量 | 備考 |
|---|---|---|---|
| 1 | RDK X5 | 1 | 組み込みメインボード(32GB メモリーカード付き)。上位機(PC 側)システムとして動作します。 |
| 2 | カードリーダー | 1 | システムイメージの書き込みに使用します。 |
| 3 | USB カメラ | 1 | 画像を取得します。 |
| 4 | 電源ケーブル | 1 | 電源供給用です。 |
| 5 | LAN ケーブル | 1 | ネットワーク接続用です。 |
回路接続

ソフトウェア設計
設計フローチャート

ソースコードのダウンロード
ソースコードファイル:14_opencv_rotate_img.rar
プログラムコード
完全なプロジェクトコードは(ソースコードファイル)をクリックしてダウンロードしてください。
"""
---------------------------------------------------------------
程序功能: 使用opencv打开USB摄像头,在实时显示的图像中,按照30,60,90,120度旋转图像
---------------------------------------------------------------
"""
import cv2
import numpy as np
import math
# ==================== 辅助函数定义 ====================
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
def resize_half(img):
"""
将图像缩小为原来的一半(宽高各 ÷ 2)
使用 INTER_AREA 插值方法,适合图像缩小,能减少锯齿和波纹
参数:
img: 输入图像
返回:
缩小为一半尺寸的图像
"""
h, w = img.shape[:2]
# cv2.resize(src, dsize, interpolation)
# dsize: 目标尺寸 (width, height)
# INTER_AREA: 区域插值,适合图像缩小
return cv2.resize(img, (w // 2, h // 2), interpolation=cv2.INTER_AREA)
# ==================== 初始化摄像头 ====================
# 打开默认摄像头(设备索引通常是 0)
cap = cv2.VideoCapture(0)
# 检查摄像头是否成功打开
if not cap.isOpened():
print("错误:无法打开摄像头")
exit()
print("按 'q' 键退出")
# ==================== 主循环:实时采集并旋转 ====================
while True:
# 从摄像头读取一帧图像
ret, frame = cap.read()
# 检查是否成功读取到图像
if not ret:
print("错误:无法获取帧")
break
# ==================== 生成不同角度的旋转图像 ====================
# 对每一帧图像分别旋转 30°、60°、90°、180°
# 先完整旋转(不裁剪),再缩小为原来的一半(便于拼接显示)
img30 = resize_half(rotate_bound(frame, 30)) # 旋转30度后缩小
img60 = resize_half(rotate_bound(frame, 60)) # 旋转60度后缩小
img90 = resize_half(rotate_bound(frame, 90)) # 旋转90度后缩小
img180 = resize_half(rotate_bound(frame, 180)) # 旋转180度后缩小
# ==================== 统一所有图片的尺寸 ====================
# 由于旋转角度不同,旋转后的图像尺寸可能略有差异
# 以 img30 的尺寸为基准,将其它图片缩放至相同尺寸
target_h, target_w = img30.shape[:2] # 获取基准尺寸
img60 = cv2.resize(img60, (target_w, target_h))
img90 = cv2.resize(img90, (target_w, target_h))
img180 = cv2.resize(img180, (target_w, target_h))
# ==================== 拼接图像(2x2网格) ====================
# 水平拼接第一行:30° 和 60° 并排
# np.hstack() 将多个数组水平堆叠(左右拼接)
top_row = np.hstack((img30, img60))
# 水平拼接第二行:90° 和 180° 并排
bottom_row = np.hstack((img90, img180))
# 垂直拼接两行:上下堆叠,形成2x2网格
# np.vstack() 将多个数组垂直堆叠(上下拼接)
combined = np.vstack((top_row, bottom_row))
# ==================== 显示结果 ====================
# 显示原始图像
cv2.imshow("raw_img", frame)
# 显示2x2网格的旋转效果图
cv2.imshow('Full Rotated Views (30/60/90/180)', combined)
# ==================== 键盘控制 ====================
# 等待1毫秒,检测键盘输入
# 如果按下 'q' 键,则退出循环
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# ==================== 资源释放 ====================
cap.release() # 释放摄像头设备
cv2.destroyAllWindows() # 关闭所有OpenCV创建的窗口
操作手順
- ターミナルを開き、Python プログラムのディレクトリに移動してプログラムを実行します。以下のコマンドを入力してください。
python 14_opencv_rotate_img.py
実験結果
USB カメラを開き、リアルタイム映像をそれぞれ 30°、60°、90°、180° 回転させ、2×2 のグリッドで比較表示します。
参考結果:

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