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

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

综述由AI生成基于 FPGA 的任意角度图像旋转实现方案,利用 Cordic 算法获取正余弦值进行坐标变换。设计了包含尺寸计算、有效区域判定、多级流水线的处理逻辑,将旋转后坐标映射至原始图像 ROM 地址。仿真验证支持任意角度旋转,适用于 LCD 显示场景。

月光旅人发布于 2026/4/10更新于 2026/5/2111 浏览

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

概述

基于 Cordic 算法获取正余弦数值后,即可进行旋转公式的计算。图像旋转的本质是实现坐标变换公式,通过多级流水线处理完成像素映射。

文章配图

图像旋转代码设计思路

1. 旋转后的图像尺寸

图像旋转后像素位置发生变化,总像素面积不变但显示范围改变。为确保完整显示,需计算对角线尺寸作为新图像的显示范围。

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;
        col_size <= (COL * cosout_abs + ROW * sinout_abs) >> 14;
    end
end

2. 旋转后图像的有效位置

有效位置可自由设定,此处以屏幕中心为旋转后图像的中点。采用通用 LCD 时序参数(如 480*272)进行对齐。

// 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)))));

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 <= 1'b1;
    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

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

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

6. 第四级流水线

判断 hcnt_rotate 和 vcnt_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
            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°、228° 等任意角度逆时针或顺时针旋转,功能正常。

文章配图

文章配图

文章配图

文章配图

文章配图

文章配图

总结

该方案实现了任意角度图像旋转,时序逻辑清晰,适用于 LCD 显示场景。核心在于利用 Cordic 算法生成三角函数值,并通过多级流水线完成坐标映射与数据读取。

目录

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

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

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

更多推荐文章

查看全部
  • Gitee 代码上传全流程:从初始化到推送实战
  • IntelliJ IDEA 中修改 Git 远程仓库地址
  • 基于 ROS 的黑线循迹与激光跟随双模态视觉导航系统实战
  • 从“写代码”到“说需求”:2026年AI辅助工具与大模型完全使用指南
  • 智能量化交易系统 QuantCell:从数据收集到策略执行全流程自动化
  • Qwen3Guard-Gen-WEB 实战测评:真实业务场景下的安全审核表现
  • 全面掌握LIBERO开源机器人学习框架:从入门到实践
  • Java 核心面试题及答案汇总
  • 构建 AI 逆向 MCP:使用 MCP 辅助 JS 逆向分析
  • VNCTF 2026 Web 部分题目解题思路
  • Python Selenium 自动化测试实战:从入门到企业级应用
  • llama-cpp-python 完整安装与配置指南
  • 视觉语言模型(VLM)综述:训练、评估与扩展指南
  • Java 全栈面试题及答案汇总
  • AI 大模型开发必备书籍推荐:从入门到实战
  • IDM 激活脚本技术原理与使用注意事项
  • C++ 继承机制核心详解
  • 位运算实战:位图与异或消消乐高频算法题解析
  • Flutter 在 OpenHarmony 中使用 nanoid 替代 UUID 生成唯一标识
  • 二叉树递归遍历与剪枝算法详解

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如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