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常見邊緣檢測的算法的實驗結果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM