跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
编程语言算法

FPGA 任意角度图像旋转实现原理与代码设计

综述由AI生成在 FPGA 中实现任意角度图像旋转的原理与代码设计。通过 CORDIC 算法获取正余弦值,利用旋转公式计算新坐标。文章详细阐述了旋转后图像尺寸计算、有效位置设定、四级流水线设计及仿真结果。最终实现了基于中心坐标系的图像旋转映射,支持任意角度和方向。

BigDataPan发布于 2026/4/6更新于 2026/5/2125 浏览

概述

本文介绍在 FPGA 中实现任意角度图像旋转的原理与代码设计。通过 CORDIC 算法获取正余弦数值,结合旋转公式计算新坐标,完成图像映射。

文章配图

图像旋转代码设计思路

2.1 旋转后的图像尺寸

图像旋转后像素位置发生变化,总像素面积不变但显示范围改变。为完整显示旋转后的图像,需以原始图像对角线长度作为旋转后图像的显示范围。

利用勾股定理计算对角线值,确定旋转后图像尺寸 Pixel_X 和 Pixel_Y:

reg [12:0] row_size ; reg [12:0] col_size ; 
assign Pixel_X = row_size ; assign Pixel_Y = col_size ; 
wire [31:0] cosout_abs = (cosout[31]) ? -cosout : cosout; 
wire [31:0] sinout_abs = (sinout[31]) ? -sinout : sinout; 
always @(posedge clk_i, negedge rstn_i) begin 
    if (!rstn_i) begin 
        row_size <= 'd0 ; col_size <= 'd0 ; 
    end else begin 
        // h --> row
        // w --> col
        row_size <= (ROW*cosout_abs + COL*sinout_abs) >>14 ; // h 
        col_size <= (COL*cosout_abs + ROW*sinout_abs) >>14 ; // w 
    end 
end 

2.2 旋转后图像的有效位置

有效位置可自由设定,此处设定为屏幕中心位置。具体设计如下:

以屏幕中点位置为旋转后图像的中点位置,根据流水线级数调整偏移量以确保对齐。

//parameter define 
localparam H_SYNC = 11'd41 , //行同步 
H_BACK = 11'd2 , //行时序后沿 
H_LEFT = 11'd0 , //行时序左边框 
H_VALID = 11'd480 , //行有效数据 
H_RIGHT = 11'd0 , //行时序右边框 
H_FRONT = 11'd2 , //行时序前沿 
H_TOTAL = 11'd525 ; //行扫描周期 
localparam V_SYNC = 11'd10 , //场同步 
V_BACK = 11'd2 , //场时序后沿 
V_TOP = 11'd0 , //场时序左边框 
V_VALID = 11'd272 , //场有效数据 
V_BOTTOM = 11'd0 , //场时序右边框 
V_FRONT = 11'd2 , //场时序前沿 
V_TOTAL = 11'd286 ; //场扫描周期 
//cnt_h:行扫描计数器 
//cnt_v:场扫描计数器 
//data_req:数据请求信号 
wire data_req = (((cnt_h >= (((H_VALID - Pixel_X)>>1) + H_SYNC + H_BACK - 'd5)) && (cnt_h < (((H_VALID - Pixel_X)>>1) + Pixel_X + H_SYNC + H_BACK - 'd5))) &&((cnt_v >= ((V_VALID - Pixel_Y)>>1) + V_SYNC + V_BACK - 'd5) && ((cnt_v < (((V_VALID - Pixel_Y)>>1) + Pixel_Y + V_SYNC + V_BACK - 'd5))))); 

2.3 第一级流水线

在图像有效信号有效时进行行场计数。

always @(posedge clk_i, negedge rstn_i) begin 
    if (!rstn_i) r_rotate_valid <= 1'b0 ; 
    else r_rotate_valid <= data_req ; 
end 
always @(posedge clk_i, negedge rstn_i) begin 
    if (!rstn_i) r_rotate_end <= 'd0 ; 
    else if (r_rotate_valid && (vcnt == row_abs - 1) && (hcnt == col_abs - 2)) r_rotate_end <= 'd1 ; 
    else r_rotate_end <= 'd0 ; 
end 
always @(posedge clk_i, negedge rstn_i) begin 
    if (!rstn_i) hcnt <= 'd0 ; 
    else if (r_rotate_valid && (r_rotate_end || (hcnt == col_abs - 1))) hcnt <= 'd0 ; 
    else if (r_rotate_valid) hcnt <= hcnt + 'd1 ; 
end 
always @(posedge clk_i, negedge rstn_i) begin 
    if (!rstn_i) vcnt <= 'd0 ; 
    else if (r_rotate_valid && r_rotate_end) vcnt <= 'd0 ; 
    else if (r_rotate_valid && (hcnt == col_abs - 1)) vcnt <= vcnt + 'd1 ; 
end 

2.4 第二级流水

开始计算图像旋转公式。以中心点为起始坐标,相当于坐标系 (0,0) 点,四个象限的所有坐标点均可表示。按照公式组合,最终右移 14 位。

文章配图

reg signed [12:0] x_cos ; reg signed [12:0] y_sin ; reg signed [12:0] y_cos ; reg signed [12:0] x_sin ; 
assign row_abs = row_size; assign col_abs = col_size; 
// 得到旋转后图片的中点 
assign row1 = row_abs >> 1 ; assign col1 = col_abs >> 1 ; 
always @(posedge clk_i, negedge rstn_i) begin 
    if (!rstn_i) x_cos <= 'd0 ; 
    else if(r_rotate_valid_1d) x_cos <= ((hcnt - col1 ) * cosout) >>>14; 
    else x_cos <= x_cos ; 
end 
always @(posedge clk_i, negedge rstn_i) begin 
    if (!rstn_i) y_sin <= 'd0 ; 
    else if(r_rotate_valid_1d) y_sin <= ((vcnt-row1 ) * sinout) >>>14; 
    else y_sin <= y_sin ; 
end 
always @(posedge clk_i, negedge rstn_i) begin 
    if (!rstn_i) y_cos <= 'd0 ; 
    else if(r_rotate_valid_1d) y_cos <= ((vcnt - row1 ) * cosout) >>>14; 
    else y_cos <= y_cos ; 
end 
always @(posedge clk_i, negedge rstn_i) begin 
    if (!rstn_i) x_sin <= 'd0 ; 
    else if(r_rotate_valid_1d) x_sin <= ((hcnt - col1 ) * sinout) >>>14; 
    else x_sin <= x_sin ; 
end 

2.5 第三级流水

按照公式排列组合得出旋转后图像映射到原始图像的坐标位置。流程包括:原始屏幕坐标转换到中心坐标系 -> 应用旋转公式 -> 旋转后的中心坐标 -> 转换回屏幕坐标系。

always @(posedge clk_i, negedge rstn_i) begin 
    if (!rstn_i) r_rotate_valid_2d <= 'd0 ; 
    else r_rotate_valid_2d <= r_rotate_valid_1d ; 
end 
always @(posedge clk_i, negedge rstn_i) begin 
    if (!rstn_i) hcnt_rotate <= 'd0 ; 
    else if(r_rotate_valid_2d==1'b1) hcnt_rotate <= x_cos - y_sin + (COL>>1 ) ; 
    else hcnt_rotate <= 'd0 ; 
end 
always @(posedge clk_i, negedge rstn_i) begin 
    if (!rstn_i) vcnt_rotate <= 'd0 ; 
    else if(r_rotate_valid_2d==1'b1) vcnt_rotate <= y_cos + x_sin + (ROW>>1) ; 
    else vcnt_rotate <= 'd0 ; 
end

2.6 第四级流水线

  • hcnt_rotate 在 0 到 COL-1 之间(在原图像列范围内)
  • vcnt_rotate 在 0 到 ROW-1 之间(在原图像行范围内)
  • 已读取的像素数小于图像总像素数(ROW*COL)
  • 每行有 COL 个像素,所以第 vcnt_rotate 行的起始地址是 COL*vcnt_rotate
  • 再加上该行内的列偏移 hcnt_rotate

data_cnt 计数器用于限制读取的像素总数不超过原图像的总像素数,防止地址溢出或重复读取。使用 ROM IP 核存放预先处理好的图像数据,生成地址和使能信号读取。ROM 读出数据延迟一个时钟,第五级流水用于对齐。

always @(posedge clk_i, negedge rstn_i) begin 
    if (!rstn_i) r_rotate_valid_3d <= 'd0 ; 
    else r_rotate_valid_3d <= r_rotate_valid_2d ; 
end 
always @(posedge clk_i, negedge rstn_i) begin 
    if (!rstn_i) begin rden <= 'd0 ; addra <= 'd0 ; end 
    else if(r_rotate_valid_3d==1'b1) begin 
        if((hcnt_rotate>='d0)&&(hcnt_rotate<COL)&&(vcnt_rotate>='d0)&&(vcnt_rotate<ROW)&&data_cnt<ROW*COL) begin 
            // start_dly3 
            rden <= 1'b1 ; addra<= COL*vcnt_rotate + hcnt_rotate ; 
        end else begin rden <= 1'b0 ; addra<= 'd0 ; end 
    end else begin rden <= 'd0 ; addra <= 'd0 ; end 
end 
always @(posedge clk_i, negedge rstn_i) begin 
    if (!rstn_i) data_cnt <= 'd0 ; 
    else if (data_cnt == ROW*COL - 1) data_cnt <= 'd0 ; 
    else if (r_rotate_valid_3d && (hcnt_rotate>='d0)&&(hcnt_rotate<COL)&&(vcnt_rotate>='d0)&&(vcnt_rotate<ROW)) data_cnt <= data_cnt + 'd1 ; 
end 
img_mem_gen img_mem_gen_inst ( .address ( addra ), .clock ( clk_i ), .rden ( rden ), .q ( rom_data ) );

仿真结果

30°旋转

文章配图

图片横着看,逆时针旋转 30°。

文章配图

-30°

文章配图

文章配图

228°

文章配图

文章配图

仿真验证支持任意角度、任意方向的旋转。

总结

该设计方案实现了基于 FPGA 的任意角度图像旋转功能。通过多级流水线优化时序,利用 CORDIC 算法辅助坐标变换,成功将旋转逻辑集成至显示驱动流程中。目前功能正常,时序架构符合预期,可作为相关项目的参考实现。

目录

  1. 概述
  2. 图像旋转代码设计思路
  3. 2.1 旋转后的图像尺寸
  4. 2.2 旋转后图像的有效位置
  5. 2.3 第一级流水线
  6. 2.4 第二级流水
  7. 2.5 第三级流水
  8. 2.6 第四级流水线
  9. 仿真结果
  10. 总结
  • 💰 8折买阿里云服务器限时8折了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 🤖 一键搭建Deepseek满血版了解详情
  • 一键打造专属AI 智能体了解详情
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Git 配置与使用详解
  • C++ 高阶数据结构:平衡二叉树(AVLTree)
  • PID 算法原理、实现与应用实战
  • Trae AI 编程提高工作效率技巧
  • Linux 常用命令汇总
  • 企业级新能源充电系统管理架构设计与实现
  • Python 列表 insert 方法:在指定位置插入元素
  • Stable Diffusion XL 1.0 实战:灵感画廊的创意应用案例
  • 基于 Python-Django 的台球厅管理收费系统
  • AI Agent 架构:基础组成模块深度解析
  • AI 提示词写作指南:精准表达与场景应用
  • 无人机路径规划技术:A*算法与 GPS 定位实现
  • Copilot的Plan模式到底好在哪?
  • Docker 拉取镜像失败报错 403 Forbidden 解决方案
  • 精选 GitHub 上 7 款热门 Claude Skills 开源工具
  • OpenClaw 启动后 Web 控制面板返回 Not Found 错误排查
  • 面向前端开发者的 Claude Code / Codex / OpenClaw 共享插件实践
  • BettaFish 多智能体系统 Docker 部署指南
  • C++ 多态的概念、实现与原理详解
  • Python 驱动浏览器自动化:Playwright 与 AI 集成实战

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online