差分图像就是目标场景在连续时间点图像相减所构成的图像,广义的差分图像定义为目标场景在时间点tk和tk+L所成图像的差别。差分图像是由目标场景在相邻时间点的图像相减得到的,从而能够得到目标场景随时间的变换。
差分图像在许多领域得到了广泛的应用,比如:视频压缩,生物医学诊断,天文学,遥感,人脸识别等。
——FPGA开源工作室
一、MATLAB实现
1、主文件 img_diff.m
%-------------------------------------------------------------------------- % 中心差分变换 %-------------------------------------------------------------------------- clc; clear all; RGB = imread('flower.bmp'); %读取图像 Gray = rgb2gray(RGB); Diff = mipcentraldiff(Gray,'dx'); subplot(2,2,1);imshow(RGB); title('原图'); subplot(2,2,3);imshow(Gray);title('灰度图'); subplot(2,2,4);imshow(Diff);title('中心差分变换');
2、子文件 mip1centraldiff.m
%-------------------------------------------------------------------------- % img: input image % direction: 'dx' or 'dy' % dimg: resultant image %-------------------------------------------------------------------------- function dimg = mipcentraldiff(img,direction) img = padarray(img,[1,1],'symmetric','both'); [row,col] = size(img); dimg = zeros(row,col); switch(direction) case'dx', dimg(:,2:col-1)= (img(:,3:col)-img(:,1:col-2))/2; case'dy', dimg(2:row-1,:)= (img(3:row,:)-img(1:row-2,:))/2; otherwise disp('Direction is unknown'); end dimg = dimg(2:end-1,2:end-1);
3、运行结果
在主文件 img_diff.m 中点击运行,得到如下结果:
二、FPGA实现
FPGA中同样采用灰度分量 Y 来实现中心差分变换,对于如何实现灰度分量Y,可以查看前面的博客介绍。我们可以将公式变一下形,如下所示:
Ix = [I(x+2h) - I(x)] / 2h
取 h 的值为1,则公式变成 Ix = [I(x+2) - I(x)] / 2
1、打拍
和前面 FPGA 实现浮雕效果一样,通过打拍实现像素值的延迟,代码如下所示:
//========================================================================== //== 打拍 //========================================================================== always @(posedge clk or negedge rst_n) begin if(!rst_n) begin {Y_de_r2, Y_de_r1 } <= {1'b0,1'b0}; {Y_hsync_r2,Y_hsync_r1} <= {1'b0,1'b0}; {Y_vsync_r2,Y_vsync_r1} <= {1'b0,1'b0}; {Y_data_r2, Y_data_r1 } <= {8'b0,8'b0}; end else begin {Y_de_r2, Y_de_r1 } <= {Y_de_r1, Y_de }; {Y_hsync_r2,Y_hsync_r1} <= {Y_hsync_r1,Y_hsync}; {Y_vsync_r2,Y_vsync_r1} <= {Y_vsync_r1,Y_vsync}; {Y_data_r2, Y_data_r1 } <= {Y_data_r1, Y_data }; end end
2、中心差分变换
对着公式写代码即可,除以 2 的操作我们采用右移 1 位来实现。
//========================================================================== //== 中心差分变换 //========================================================================== always @(posedge clk or negedge rst_n) begin if(!rst_n) begin diff_data <= 8'd0; end else begin diff_data <= (Y_data_r2 - Y_data) >> 1; end end
3、信号同步
这个说了很多遍了,直接将打拍后的信号赋值出去即可。
//========================================================================== //== 信号同步 //========================================================================== assign diff_de = Y_de_r2; assign diff_hsync = Y_hsync_r2; assign diff_vsync = Y_vsync_r2;
三、上板验证
最后在 FPGA 开发板的 TFT 屏中,我们得到如下的实验结果:
从结果可以看出,大体和 MATLAB 中的效果一样,但是有细微的差别,这是因为 (Y_data_r2 - Y_data) 的计算结果可能为负数或奇数,如果要达到完美,公式还得继续改造,这个图像变换比较简单,不想废心思了,有兴趣的同学可以自己尝试看看。
此外也可以将中心差分变换的算法移植到 RGB 三通道,实现彩色输出的中心差分变换。
参考资料:[1] OpenS Lee:FPGA开源工作室(公众号)