15图像处理之叠加算法和半透明

一设计功能

  通过友善串口助手将198X198像素的十字光标图片转化为198X198的二进制数据后,传送给FPGA后储存到40K的RAM中用VGA来叠加显示,之后再加一个图像的半透明显示。

二设计输入

   (一)verilog实现 关键点:若是十字光标像素为255,则是白色背景(由于8位位宽的rgb全为1表示白色,全为零表示黑色)否则为光标图像。本次设计的模块总共三个,顶层模块,串口接收模块,VGA模块,当然咯还调用了两个IP核,PLL和RAM。图像叠加显示系统框图如下:

module vga_ram(
input wire clk,
input wire clks,
input wire rst_n,
input wire pi_flag,
input wire [7:0] pi_data,
output reg hsync,
output reg vsync,
output reg [7:0] vga_rgb
);

reg [15:0] addrb,addra;
wire [7:0] doutb;

parameter MAX_value = 16'd39203;

reg [8:0]x; //行移动计数器最大439
reg [8:0]y; //场移动计数器最大279

reg dec_x;//行偏移量计数器减一切换标志信号
reg dec_y;//场偏移量计数器减一切换标志信号

reg [9:0]cnt_h;
reg [9:0]cnt_v;

parameter h_max =10'd799;
parameter v_max = 10'd524;

//行计数器
always@(posedge clk or negedge rst_n)
if(!rst_n)
cnt_h<=10'd0;
else if(cnt_h==h_max)
cnt_h<=10'd0;
else
cnt_h<=cnt_h+1'b1;
//场计数器
always@(posedge clk or negedge rst_n)
if(!rst_n)
cnt_v<=10'd0;
else if(cnt_v==v_max & cnt_h==h_max)
cnt_v<=10'd0;
else if(cnt_h==h_max)
cnt_v<=cnt_v+1'b1;
//hsync 行同步信号
always@(posedge clk or negedge rst_n)
if(!rst_n)
hsync<=1'b1;
else if(cnt_h==10'd95)
hsync<=1'b0;
else if(cnt_h==h_max)
hsync<=1'b1;

//vsync场同步信号
always@(posedge clk or negedge rst_n)
if(!rst_n)
vsync<=1'b1;
else if(cnt_v=='d1 & cnt_h==h_max)
vsync<=1'b0;
else if(cnt_v==v_max & cnt_h==h_max)
vsync<=1'b1;


parameter T100MS = 23'd2_599_999;
//div counter
reg [22:0]div_cnt;
always@(posedge clk or negedge rst_n)begin
if(rst_n==0)
div_cnt<=23'd0;
else if(div_cnt==T100MS)
div_cnt<=23'd0;
else
div_cnt<=div_cnt+1'b1;
end

//the flag of one_s_flag
reg one_s_flag;
always@(posedge clk or negedge rst_n)begin
if(rst_n==0)
one_s_flag<=1'b0;
else if(div_cnt==(T100MS-1))begin
one_s_flag<=1'b1;
end
else begin
one_s_flag<=1'b0;
end
end
always@(posedge clk or negedge rst_n)
if(!rst_n)begin
x<=9'd0;
dec_x<=1'b0;
end
else begin
case(dec_x)
0:begin
if(x==9'd439)begin
x<=x;
dec_x<=1'b1;
end
else if(one_s_flag) begin
x<=x+1'b1;
dec_x<=1'b0;
end
end
1:begin
if(x==9'd0)begin
x<=x;
dec_x<=1'b0;
end
else if(one_s_flag) begin
x<=x-1'b1;
dec_x<=1'b1;
end
end
default: ;
endcase
end


always@(posedge clk or negedge rst_n)
if(!rst_n)begin
y<=9'd0;
dec_y<=1'b0;
end
else begin
case(dec_y)
0:begin
if(y==9'd279)begin
y<=y;
dec_y<=1'b1;
end
else if(one_s_flag)begin
y<=y+1'b1;
dec_y<=1'b0;
end
end
1:begin
if(y==9'd0)begin
y<=y;
dec_y<=1'b0;
end
else if(one_s_flag)begin
y<=y-1'b1;
dec_y<=1'b1;
end
end
default: ;
endcase
end


// //下面代码为实现半透明效果
// //即RGB的像素和光标线的像素加起来各显示%50
// always@(posedge clk or negedge rst_n)
// if(!rst_n)
// vga_rgb<=8'b0;
// else if(cnt_h>10'd144+x &cnt_h<=10'd341+x & cnt_v>10'd35+y & cnt_v<=10'd232+y)begin
// if(cnt_v>10'd35 & cnt_v<=10'd194 &doutb=='d255)begin
// vga_rgb<=(8'b111_000_00+doutb)>>1;

// end
// else if( cnt_v>10'd194 & cnt_v<=10'd354 &doutb=='d255)
// vga_rgb<=(8'b000_111_00+doutb)>>1;
// else if( cnt_v>10'd354 & cnt_v<=10'd514&doutb=='d255)
// vga_rgb<=(8'b000_000_11+doutb)>>1;
// else
// vga_rgb<=doutb;
// end

// else if(cnt_h>10'd144 &cnt_h<=10'd783 & cnt_v>10'd35 & cnt_v<=10'd194)
// vga_rgb<=8'b111_000_00;
// else if(cnt_h>10'd144 &cnt_h<=10'd783 & cnt_v>10'd194 & cnt_v<=10'd354)
// vga_rgb<=8'b000_111_00;
// else if(cnt_h>10'd144 &cnt_h<=10'd783 & cnt_v>10'd354 & cnt_v<=10'd514)
// vga_rgb<=8'b000_000_11;
// else
// vga_rgb<=8'b0;
//下面注释为十字光标叠加算法
//叠加算法的核心对于光标的背景像素处理为RGB像素,否则就显示光标线的像素
always@(posedge clk or negedge rst_n)
if(!rst_n)
vga_rgb<=8'b0;
else if(cnt_h>10'd144+x &cnt_h<=10'd341+x & cnt_v>10'd35+y & cnt_v<=10'd232+y)begin
if(cnt_v>10'd35 & cnt_v<=10'd194 &doutb=='d255)begin
vga_rgb<=8'b111_000_00;

end
else if( cnt_v>10'd194 & cnt_v<=10'd354 &doutb=='d255)
vga_rgb<=8'b000_111_00;
else if( cnt_v>10'd354 & cnt_v<=10'd514&doutb=='d255)
vga_rgb<=8'b000_000_11;
else
vga_rgb<=doutb;
end

else if(cnt_h>10'd144 &cnt_h<=10'd783 & cnt_v>10'd35 & cnt_v<=10'd194)
vga_rgb<=8'b111_000_00;
else if(cnt_h>10'd144 &cnt_h<=10'd783 & cnt_v>10'd194 & cnt_v<=10'd354)
vga_rgb<=8'b000_111_00;
else if(cnt_h>10'd144 &cnt_h<=10'd783 & cnt_v>10'd354 & cnt_v<=10'd514)
vga_rgb<=8'b000_000_11;
else
vga_rgb<=8'b0;

//cnt_h >=143+x读出地址相对于读出的数据提前一个像素点
always @(posedge clk or negedge rst_n) begin
if (rst_n == 1'b0) begin
// reset
addrb <= 'd0;
end
else if(cnt_h >=143+x && cnt_h <=340+x && cnt_v >=35+y && cnt_v <=232+y && addrb=='d39203)begin
addrb <= 'd0;
end
else if (cnt_h >=143+x && cnt_h <=340+x && cnt_v >=35+y && cnt_v <=232+y) begin
addrb <= addrb + 1'b1;
end
end

always @(posedge clks or negedge rst_n) begin
if (rst_n == 1'b0) begin
// reset
addra <= 'd0;
end
else if (pi_flag == 1'b1 && addra == 'd39203) begin
addra <= 'd0;
end
else if (pi_flag == 1'b1) begin
addra <= addra + 1'b1;
end
end


RAM40K ram_inst(
.clka(clks),
.wea(pi_flag),
.addra(addra),
.dina(pi_data),
.clkb(clk),
.addrb(addrb),
.doutb(doutb)
);
endmodule

    (二)MATLAB处理代码

作用:将图片转换198X198的数据矩阵,然后用串口助手发送给FPGA。

clc;
clear all;
imrgb24=imread('pkq.jpg','jpg');%读取十字光标文件
R=bitshift(imrgb24(1:198,1:198,1),-5);%读取R的高3位
G=bitshift(imrgb24(1:198,1:198,1),-5);%读取G的高3位
B=bitshift(imrgb24(1:198,1:198,1),-6);%读取B的高2位
rgb8=bitshift(R,5)+bitshift(G,2)+B;%拼接{R[2:0],G[2:0],B[1:0]}
fid=fopen('rgb8.txt','w+');%打开文件
fprintf(fid,'%02x ',rgb8');%将字符打印到txt文档中

(三)MATLAB常见边缘检测的算法

clc
clear
clear all
close all
%%%对图像做均值滤波处理
img = imread('pkq.jpg');
figure(1)
subplot(1,2,1),imshow(img),title('原始图像')
%%%将彩色图像转灰度图像
img_gray = rgb2gray(img);
subplot(1,2,2),imshow(img_gray),title('RGB-GRAY灰度图像')
BW1=edge(img_gray,'sobel'); %用Sobel算子进行边缘检测
BW2=edge(img_gray,'roberts');%用Roberts算子进行边缘检测
BW3=edge(img_gray,'prewitt'); %用Prewitt算子进行边缘检测
BW4=edge(img_gray,'log'); %用Log算子进行边缘检测
BW5=edge(img_gray,'canny'); %用Canny算子进行边缘检测
figure(2)
subplot(2,3,1),imshow(img_gray),title('原始图像')
subplot(2,3,2),imshow(BW1),title('Sobel算子图像')
subplot(2,3,3),imshow(BW2),title('Roberts算子图像')
subplot(2,3,4),imshow(BW3),title('Prewitt算子图像')
subplot(2,3,5),imshow(BW4),title('Log算子图像')
%%
%
% PREFORMATTED
% TEXT
%
subplot(2,3,6),imshow(BW5),title('Canny算子图像')

figure(3);
Sobel_Img = img_gray;
Sobel_Threshold = 30; %用Sobel算子设置边缘检测的阈值
[ROW,COL] = size(Sobel_Img); %用 sizel抓取灰度图像行和列的最大值
for r = 2:ROW-1
for c = 2:COL-1
%%%根据公式计算Sobel算子的横向和纵向算子
Sobel_x = img_gray(r-1,c+1) + 2*img_gray(r,c+1) + img_gray(r+1,c+1) - img_gray(r-1,c-1) - 2*img_gray(r,c-1) - img_gray(r+1,c-1);
Sobel_y = img_gray(r-1,c-1) + 2*img_gray(r-1,c) + img_gray(r-1,c+1) - img_gray(r+1,c-1) - 2*img_gray(r+1,c) - img_gray(r+1,c+1);
Sobel_Num = abs(Sobel_x) + abs(Sobel_y);
%Sobel_Num = sqrt(Sobel_x^2 + Sobel_y^2);
if(Sobel_Num > Sobel_Threshold)
Sobel_Img(r,c)=0;
else
Sobel_Img(r,c)=255;
end
end
end
imshow(Sobel_Img);

wq = 1;

三工程成果展示:

十字光标的叠加显示如下图:

皮卡丘半透明实验显示如下图:

MATLAB常见边缘检测的算法的实验结果:

原文地址:https://www.cnblogs.com/Xwangzi66/p/12975762.html