数字图像处理(15):图像平移

        (1)图像平移的基本原理:计算每个像素点的移动向量,并将这些像素按照指定的方向和距离进行移动。

        (2)平移向量包括水平和垂直分量,可以表示为(dx,dy),其中dx表示水平方向上的移动距离,dy表示垂直方向上的移动距离。

        (3)经过平移后,新图像中的每个像素点在原图像中都有对应的像素点。图像平移使用软件开发语言实现很容易,但在FGPA中实现需要考虑缓存。

        (4)matlab实现代码:

% 读取图像
% imread函数用于读取图像文件,支持多种格式如BMP、PNG、JPG等
img = imread('1_1920x1080.bmp');

% 获取图像尺寸信息
% size函数返回矩阵的维度,对于彩色图像返回[高度 宽度 通道数]
[rows, cols, channels] = size(img);

% 创建仿射变换矩阵
% 这里创建的是一个2x3的变换矩阵,用于定义图像的变换方式
% [1 0 300;   - 第一行表示x方向的变换:x'= 1*x + 0*y + 300
%  0 1 200]    - 第二行表示y方向的变换:y'= 0*x + 1*y + 200
% 这个矩阵表示将图像向右平移300像素,向下平移200像素
M = single([1, 0, 300; 0, 1, 200]);

% 执行仿射变换
% affine2d函数用于创建二维仿射变换对象
tform = affine2d(M');  % 注意MATLAB中需要转置变换矩阵
% imwarp函数执行图像变换
% OutputView选项指定输出图像的大小,这里保持与原图相同
res = imwarp(img, tform, 'OutputView', imref2d([rows cols]));

% 保存变换后的图像
% imwrite函数将图像保存到文件
% 第一个参数是图像数据,第二个参数是文件名
imwrite(res, 'result.bmp');

% 显示结果图像
% figure创建新的图形窗口
figure;
% subplot用于创建子图,这里创建1x2的子图布局
subplot(1,2,1);
imshow(img);  % 显示原图
title('原始图像');
subplot(1,2,2);
imshow(res);  % 显示变换后的图像
title('变换后的图像');

        (5)FPGA仿真实现:

module move
(
    input   wire            clk         ,
    input   wire            reset_n     ,
    input   wire    [10:0]  img_width   ,
    input   wire    [10:0]  img_height  ,
    input   wire    [10:0]  img_x_start ,
    input   wire    [10:0]  img_y_start ,
    input   wire    [23:0]  img_data_i  ,
   
    output  wire            wr_ready    ,
    output  reg             valid_o     ,
    output  reg     [23:0]  img_data_o
    
);

reg [11:0]  h_cnt,v_cnt;

always@(posedge clk or negedge reset_n)
    if(!reset_n)
        h_cnt <= 12'd0;
    else if(h_cnt == img_x_start + img_width - 1)
        h_cnt <= 12'd0;
    else 
        h_cnt <= h_cnt + 12'd1;
        
always@(posedge clk or negedge reset_n)
    if(!reset_n) 
        v_cnt <= 12'd0;
    else if((v_cnt == img_y_start + img_height - 1) && (h_cnt == img_x_start + img_width - 1))
        v_cnt <= 12'd0;
    else if(h_cnt == img_x_start + img_width - 1)
        v_cnt <= v_cnt + 12'd1;
    else 
        v_cnt <= v_cnt;
        
assign wr_ready = (h_cnt >= img_x_start) && (v_cnt >= img_y_start);

always@(posedge clk or negedge reset_n)
    if(!reset_n)
        valid_o <= 1'd0;
    else if((h_cnt < img_width) && (v_cnt < img_height))
        valid_o <= 1'd1;
    else 
        valid_o <= 1'd0;
        
always@(posedge clk or negedge reset_n)
    if(!reset_n)
        img_data_o <= 24'd0;
    else if((h_cnt < img_width) && (v_cnt < img_height) && (wr_ready))
        img_data_o <= img_data_i;
    else 
        img_data_o <= 24'd0;

endmodule

        微调读写测试文件后,仿真出来的图像(与matlab仿真结果一致):

        (6)FPGA实现

  • 查看配置进程:report_property -all [get_runs impl_1]
  1. 写入DDR3部分不需要修改,可以沿用,但是读取部分需要修改,首先是结束地址,需要适配新的y轴偏移量
    axi_ddr3_top    axi_ddr3_top_inst
    (
        .ddr3_clk            (clk_320M              ),
        .reset_n             (rst_n                 ),
        .pingpang            (1'd0                  ),
        .ui_clk              (ui_clk                ),
        .ui_rst              (ui_rst                ),
        
        .wr_b_addr           (32'd0                 ),
        .wr_e_addr           (IMG_LENGTH*IMG_WIDE*4 ),
        .wr_clk              (clk                   ),
        .data_wren           (data_wren             ),
        .data_wr             (data_wr               ),
        .wr_rst              (1'd0                  ),
    
        .rd_b_addr           (32'd0                 ),
        .rd_e_addr           (IMG_LENGTH*(IMG_WIDE-Y_OFFSET+1)*4 ),
        .rd_clk              (clk_vga_2             ),
        .data_rden           (lie >= Y_OFFSET       ),
        .data_rd             (data_rd               ),
        .rd_rst              (1'd0                  ),
        .read_enable         (1'd1                  ),
        .rd_data_valid       (),
    
        .ddr3_addr           (ddr3_addr             ),
        .ddr3_ba             (ddr3_ba               ),
        .ddr3_cas_n          (ddr3_cas_n            ),
        .ddr3_ck_n           (ddr3_ck_n             ),
        .ddr3_ck_p           (ddr3_ck_p             ),
        .ddr3_cke            (ddr3_cke              ),
        .ddr3_ras_n          (ddr3_ras_n            ),
        .ddr3_reset_n        (ddr3_reset_n          ),
        .ddr3_we_n           (ddr3_we_n             ),
        .ddr3_dq             (ddr3_dq               ),
        .ddr3_dqs_n          (ddr3_dqs_n            ),
        .ddr3_dqs_p          (ddr3_dqs_p            ),
        .init_calib_complete (init_calib_complete   ),
        .ddr3_cs_n           (ddr3_cs_n             ),
        .ddr3_dm             (ddr3_dm               ),
        .ddr3_odt            (ddr3_odt              )  
    );
  2. 缓存行数据,使用一个24位,深度位2048的双口RAM去存储从DDR3中读出来的数据,然后在VGA模块扫描到对应位置时输出,即可。

    hang_ram_2048  hang_ram_2048_inst 
    (
        .clka       (clk_vga_2                  ), 
        .ena        (1'd1                       ), 
        .wea        (lie >= Y_OFFSET && reading ), 
        .addra      (buf_wr_addr                ), 
        .dina       (line_buffer                ), 
        .clkb       (clk_vga                    ), 
        .enb        (hang >= X_OFFSET           ), 
        .addrb      (buf_rd_addr                ), 
        .doutb      (ram_dout                   )  
    );
    
    always @(posedge clk_vga_2 or negedge init_rst_n) begin
        if(!init_rst_n) begin
            last_data_rd <= 16'd0;
            buf_wr_addr <= 11'd0;
            reading <= 1'b0;
            line_buffer <= 24'd0;
        end
        else begin
            if(lie >= Y_OFFSET) begin
                if(!reading) begin  // 第一次读取
                    last_data_rd <= data_rd;
                    reading <= 1'b1;
                end
                else begin  // 第二次读取
                    line_buffer <= {last_data_rd, data_rd[15:8]};
                    buf_wr_addr <= buf_wr_addr + 11'd1;
                    reading <= 1'b0;
                end
            end
            else begin
                buf_wr_addr <= 11'd0;
                reading <= 1'd0;
            end
        end
    end
    
    // 行缓存读取控制,在这里实现偏移
    always @(posedge clk_vga or negedge init_rst_n) begin
        if(!init_rst_n) 
            buf_rd_addr <= 11'd0;
        else begin
            if(display_valid)
                buf_rd_addr <= buf_rd_addr + 1'd1;
            else 
                buf_rd_addr <= 11'd0;
        end
    end
    
    assign display_valid = (hang >= X_OFFSET)&&(lie >= Y_OFFSET);  
  3. 最终现象如下:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/933651.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JAVA秋招面试题精选-第一天总结

目录 分栏简介&#xff1a; 问题一&#xff1a;订单表每天新增500W条数据&#xff0c;分库分表应该怎么设计&#xff1f; 问题难度以及频率&#xff1a; 问题导向&#xff1a; 满分答案&#xff1a; 举一反三&#xff1a; 问题总结&#xff1a; 问题二&#xff1a;解释…

Rnnoise和SpeexDsp两种降噪方式有什么区别?

在蒙以CourseMaker 7.0软件中&#xff0c;增加了两种降噪模式&#xff0c;一种是Rnnoise&#xff0c;一种是SpeexDsp&#xff0c;这两种降噪模式有什么区别呢&#xff1f; Rnnoise 基于神经网络。当噪声与 rnnoise 的模型训练的噪声匹配时&#xff0c;它的效果非常好。比如说&…

博物馆导览系统方案(一)背景需求分析与核心技术实现

维小帮提供多个场所的室内外导航导览方案&#xff0c;如需获取博物馆导览系统解决方案可前往文章最下方获取&#xff0c;如有项目合作及技术交流欢迎私信我们哦~撒花&#xff01; 一、博物馆导览系统的背景与市场需求 在数字化转型的浪潮中&#xff0c;博物馆作为文化传承和知…

福昕PDF低代码平台

福昕PDF低代码平台简介 福昕PDF 低代码平台是一款创新的工具&#xff0c;旨在简化PDF处理和管理的流程。通过这个平台&#xff0c;用户可以通过简单的拖拽界面上的按钮&#xff0c;轻松完成对Cloud API的调用工作流&#xff0c;而无需编写复杂的代码。这使得即使没有编程经验的…

Linux —— 管理文件

一、Linux的目录结构及用途 /bin&#xff1a;存放最常用的命令&#xff0c;如ls、cat等&#xff0c;所有用户都可以执行的命令。/boot&#xff1a;包含启动Linux系统所需的核心文件&#xff0c;如内核文件和引导加载程序。/dev&#xff1a;设备文件目录&#xff0c;包含系统中的…

NanoLog起步笔记-7-log解压过程初探

nonolog起步笔记-6-log解压过程初探 再看解压过程建立调试工程修改makefile添加新的launch项 注&#xff1a;重新学习nanolog的README.mdPost-Execution Log Decompressor 下面我们尝试了解&#xff0c;解压的过程&#xff0c;是如何得到文件头部的meta信息的。 再看解压过程 …

处理配置System Viewer缺少SFR文件

按照网上的教程&#xff0c;其他的都配好 这里给几个参考 嵌入式开发--Keil MDK仿真时System Viewer不显示寄存器选项_keil system viewer不显示外设寄存器-CSDN博客 keil无法查看外设寄存器&#xff08;生成SFR文件&#xff09;_keil sfr文件-CSDN博客 keil5软件仿真 Logic…

网络安全中大数据和人工智能应用实践

传统的网络安全防护手段主要是通过单点的网络安全设备&#xff0c;随着网络攻击的方式和手段不断的变化&#xff0c;大数据和人工智能技术也在最近十年飞速地发展&#xff0c;网络安全防护也逐渐开始拥抱大数据和人工智能。传统的安全设备和防护手段容易形成数据孤岛&#xff0…

create-react-app react19 搭建项目报错

报错截图 此时运行会报错&#xff1a; 解决方法&#xff1a; 1.根据提示安装依赖法 执行npm i web-vitals然后重新允许 2.删除文件法 在index.js中删除对报错文件的引入&#xff0c;删除报错文件

excel如何让单元格选中时显示提示信息?

现象&#xff1a; 当鼠标放在单元格上&#xff0c;会出现提示信息&#xff1a; 先选中单元格选择上方的【数据】-【数据验证】图标选择【输入信息】勾上【选定单元格时显示输入信息】输入【标题】&#xff0c;如&#xff1a;最上方图中的&#xff1a;姓名&#xff1a;输入【输…

PyCharm+Selenium+Pytest配置小记

1、下载ChromeDriver&#xff1a; Chrome130以后的Driver下载&#xff1a; Chrome for Testing availabilityhttps://googlechromelabs.github.io/chrome-for-testing/ &#xff08;1&#xff09;查看自己Crome浏览器的版本&#xff1a;设置-->关于 Chrome&#xff1b; &…

用最小的代价解决mybatis-plus关于批量保存的性能问题

1.问题说明 问题背景说明&#xff0c;在使用达梦数据库时&#xff0c;mybatis-plus的serviceImpl.saveBatch()方法或者updateBatchById()方法的时候&#xff0c;随着数据量、属性字段的增加&#xff0c;效率越发明显的慢。 serviceImpl.saveBatch(); serviceImpl.updateBatch…

电子商务人工智能指南 4/6 - 内容理解

介绍 81% 的零售业高管表示&#xff0c; AI 至少在其组织中发挥了中等至完全的作用。然而&#xff0c;78% 的受访零售业高管表示&#xff0c;很难跟上不断发展的 AI 格局。 近年来&#xff0c;电子商务团队加快了适应新客户偏好和创造卓越数字购物体验的需求。采用 AI 不再是一…

Helm安装Mysql8主从复制集群

目录 一、Helm安装 二、安装mysql 1、拉取镜像 2、修改配置文件 3、创建mysql-secret 4、安装 一、Helm安装 这里不再赘叙&#xff0c;具体安装请参考官网 Helm | 快速入门指南 二、安装mysql 1、拉取镜像 #添加仓库 helm repo add bitnami https://charts.bitnami.c…

Java并发编程学习之从资本家的角度看多线程和并发性(一)

目录 前言前置知识一、单线程时代二、为什么要有多线程&#xff0c;多线程的优点&#xff1f;三、使用多线程会遇到什么问题&#xff1f;四、多线程和并发编程的关系总结 前言 这篇文章是打开Java多线程和并发编程的大门的开始&#xff0c;如标题《从老板的角度看多线程和并发…

【爬虫】selenium打开浏览器以及页面

本篇探讨如何使用 selenium 打开浏览器 selenium 基础与网页打开 selenium 是一个广泛应用于自动化测试和网页抓取的工具&#xff0c;它能够模拟用户在浏览器中的各种操作。首先&#xff0c;我们需要根据指定的浏览器类型&#xff08;这里以 Chrome 为例&#xff09;打开网页…

【算法练习】162. 寻找峰值

题目链接&#xff1a;162. 寻找峰值 看思路图&#xff1a; class Solution { public:int findPeakElement(vector<int>& nums) {int left 0,right nums.size()-1;while(left<right){int mid left (right-left)/2;if(nums[mid]>nums[mid1]){right mid;}els…

Android SurfaceFlinger layer层级

壁纸作为显示的最底层窗口它是怎么显示的 1. SurfaceFlinger layer层级 锁屏状态dump SurfaceFlinger &#xff0c;adb shell dumpsys SurfaceFlinger Display 0 (active) HWC layers: -----------------------------------------------------------------------------------…

SAP Ariba Approval _Email Approval

Email Approval Example 当用户成为文档审批者时,SAP Ariba会向该用户发送电子邮件通知消息。 在以下情况下,批准人可以收到电子邮件通知: 有人提交或重新提交文件以获得批准 某人撤回文件 系统升级文档 系统即将向主管升级请求 如果多个用户共享一个群组职责,他们则会收到…

vue 封装全局方法及使用

1.找到项目中的utils定义js&#xff0c;这个js存放全局可使用的方法 2.去项目中main.js中引入注册 import publicFun from ./utils/test Vue.prototype.$publicFun publicFun;3.项目使用 ddd(){this.$publicFun.testwen()},