├── 1.RTL ├── src │ ├── VIP_RGB888_YCbCr444.v │ ├── calculate_A.v │ ├── dark_channel.v │ ├── fifo_ram.v │ ├── haze_removal_cal.v │ ├── haze_removal_top.v │ ├── matrix_generate_3x3.v │ ├── one_column_ram.v │ ├── search_block_min.v │ ├── sort3.v │ ├── src_min.v │ ├── time_alignment.v │ ├── tx_get.v │ └── ycbcr2rgb.v └── tb │ ├── haze_removal_tb.sv │ ├── sim_cmos_tb.sv │ └── video_to_pic.sv ├── 2.C++_Model └── Haze Removal Verification │ ├── Haze Removal Verification.cpp │ └── function.h ├── 3.Matlab_Model └── enhance_y.m ├── 4.Vivado_Project ├── haze_removal.xpr └── haze_removal_tb_behav.wcfg ├── 5.QuestaSim └── readme.md ├── 6.Pic ├── combine.png ├── duck.bmp ├── forest.bmp ├── outcom.bmp └── reademe_pic │ └── KaiMingHe.png └── readme.md /1.RTL/src/VIP_RGB888_YCbCr444.v: -------------------------------------------------------------------------------- 1 | module VIP_RGB888_YCbCr444 2 | ( 3 | //global clock 4 | input clk, //cmos video pixel clock 5 | input rst_n, //global reset 6 | 7 | //Image data prepred to be processd 8 | input pre_frame_vsync, //Prepared Image data vsync valid signal 9 | input pre_frame_href, //Prepared Image data href vaild signal 10 | input pre_frame_clken, //Prepared Image data output/capture enable clock 11 | input [7:0] pre_img_red, //Prepared Image red data to be processed 12 | input [7:0] pre_img_green, //Prepared Image green data to be processed 13 | input [7:0] pre_img_blue, //Prepared Image blue data to be processed 14 | 15 | //Image data has been processd 16 | output post_frame_vsync, //Processed Image data vsync valid signal 17 | output post_frame_href, //Processed Image data href vaild signal 18 | output post_frame_clken, //Processed Image data output/capture enable clock 19 | output [7:0] post_img_Y, //Processed Image brightness output 20 | output [7:0] post_img_Cb, //Processed Image blue shading output 21 | output [7:0] post_img_Cr //Processed Image red shading output 22 | ); 23 | 24 | //-------------------------------------------- 25 | /********************************************* 26 | //Refer to page 5 27 | Y = (77 *R + 150*G + 29 *B)>>8 28 | Cb = (-43*R - 85 *G + 128*B)>>8 + 128 29 | Cr = (131*R - 110*G - 21 *B)>>8 + 128 30 | Cr0(i, j) = 0.511*R(i, j) - 0.428*G(i, j) - 0.083*B(i, j) + 128; 31 | ---> 32 | Y = (77 *R + 150*G + 29 *B)>>8 33 | Cb = (-43*R - 85 *G + 128*B + 32768)>>8 34 | Cr = (128*R - 107*G - 21 *B + 32768)>>8 35 | **********************************************/ 36 | //Step 1 37 | reg [15:0] img_red_r0, img_red_r1, img_red_r2; 38 | reg [15:0] img_green_r0, img_green_r1, img_green_r2; 39 | reg [15:0] img_blue_r0, img_blue_r1, img_blue_r2; 40 | always@(posedge clk or negedge rst_n) 41 | begin 42 | if(!rst_n) 43 | begin 44 | img_red_r0 <= 0; 45 | img_red_r1 <= 0; 46 | img_red_r2 <= 0; 47 | img_green_r0 <= 0; 48 | img_green_r1 <= 0; 49 | img_green_r2 <= 0; 50 | img_blue_r0 <= 0; 51 | img_blue_r1 <= 0; 52 | img_blue_r2 <= 0; 53 | end 54 | else 55 | begin 56 | img_red_r0 <= pre_img_red * 8'd77; 57 | img_red_r1 <= pre_img_red * 8'd43; 58 | img_red_r2 <= pre_img_red * 8'd131; 59 | img_green_r0 <= pre_img_green * 8'd150; 60 | img_green_r1 <= pre_img_green * 8'd85; 61 | img_green_r2 <= pre_img_green * 8'd110; 62 | img_blue_r0 <= pre_img_blue * 8'd29; 63 | img_blue_r1 <= pre_img_blue * 8'd128; 64 | img_blue_r2 <= pre_img_blue * 8'd21; 65 | end 66 | end 67 | 68 | //-------------------------------------------------- 69 | //Step 2 70 | reg [15:0] img_Y_r0; 71 | reg [15:0] img_Cb_r0; 72 | reg [15:0] img_Cr_r0; 73 | always@(posedge clk or negedge rst_n) 74 | begin 75 | if(!rst_n) 76 | begin 77 | img_Y_r0 <= 0; 78 | img_Cb_r0 <= 0; 79 | img_Cr_r0 <= 0; 80 | end 81 | else 82 | begin 83 | img_Y_r0 <= img_red_r0 + img_green_r0 + img_blue_r0; 84 | img_Cb_r0 <= img_blue_r1 - img_red_r1 - img_green_r1 + 16'd32768; 85 | img_Cr_r0 <= img_red_r2 - img_green_r2 - img_blue_r2 + 16'd32768; 86 | end 87 | end 88 | 89 | //-------------------------------------------------- 90 | //Step 3 91 | reg [7:0] img_Y_r1; 92 | reg [7:0] img_Cb_r1; 93 | reg [7:0] img_Cr_r1; 94 | always@(posedge clk or negedge rst_n) 95 | begin 96 | if(!rst_n) 97 | begin 98 | img_Y_r1 <= 0; 99 | img_Cb_r1 <= 0; 100 | img_Cr_r1 <= 0; 101 | end 102 | else 103 | begin 104 | img_Y_r1 <= img_Y_r0[15:8]; 105 | img_Cb_r1 <= img_Cb_r0[15:8]; 106 | img_Cr_r1 <= img_Cr_r0[15:8]; 107 | end 108 | end 109 | 110 | 111 | 112 | //------------------------------------------ 113 | //lag 3 clocks signal sync 114 | reg [2:0] pre_frame_vsync_r; 115 | reg [2:0] pre_frame_href_r; 116 | reg [2:0] pre_frame_clken_r; 117 | always@(posedge clk or negedge rst_n) 118 | begin 119 | if(!rst_n) 120 | begin 121 | pre_frame_vsync_r <= 0; 122 | pre_frame_href_r <= 0; 123 | pre_frame_clken_r <= 0; 124 | end 125 | else 126 | begin 127 | pre_frame_vsync_r <= {pre_frame_vsync_r[1:0], pre_frame_vsync }; 128 | pre_frame_href_r <= {pre_frame_href_r[1:0], pre_frame_href }; 129 | pre_frame_clken_r <= {pre_frame_clken_r[1:0], pre_frame_clken }; 130 | end 131 | end 132 | assign post_frame_vsync = pre_frame_vsync_r[2]; 133 | assign post_frame_href = pre_frame_href_r[2]; 134 | assign post_frame_clken = pre_frame_clken_r[2]; 135 | assign post_img_Y = img_Y_r1 ; 136 | assign post_img_Cb = img_Cb_r1; 137 | assign post_img_Cr = img_Cr_r1; 138 | 139 | endmodule 140 | -------------------------------------------------------------------------------- /1.RTL/src/calculate_A.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOUDIU/Hardware-Implementation-of-the-Dark-Channel-Prior-Haze-Removal-Algorithm/558adccb7800acd472b9b20145cb2aa874f601fd/1.RTL/src/calculate_A.v -------------------------------------------------------------------------------- /1.RTL/src/dark_channel.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOUDIU/Hardware-Implementation-of-the-Dark-Channel-Prior-Haze-Removal-Algorithm/558adccb7800acd472b9b20145cb2aa874f601fd/1.RTL/src/dark_channel.v -------------------------------------------------------------------------------- /1.RTL/src/fifo_ram.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOUDIU/Hardware-Implementation-of-the-Dark-Channel-Prior-Haze-Removal-Algorithm/558adccb7800acd472b9b20145cb2aa874f601fd/1.RTL/src/fifo_ram.v -------------------------------------------------------------------------------- /1.RTL/src/haze_removal_cal.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOUDIU/Hardware-Implementation-of-the-Dark-Channel-Prior-Haze-Removal-Algorithm/558adccb7800acd472b9b20145cb2aa874f601fd/1.RTL/src/haze_removal_cal.v -------------------------------------------------------------------------------- /1.RTL/src/haze_removal_top.v: -------------------------------------------------------------------------------- 1 | module haze_removal_top#( 2 | parameter Y_ENHANCE_ENABLE = 1 , 3 | parameter PIC_WIDTH = 640 4 | )( 5 | input clk , 6 | input rst_n , 7 | //Image data prepred to be processd 8 | input pre_frame_vsync , 9 | input pre_frame_href , 10 | input pre_frame_clken , 11 | input [23:0] pre_img , 12 | //Image data has been processd 13 | output post_frame_vsync , 14 | output post_frame_href , 15 | output post_frame_clken , 16 | output [23:0] post_img 17 | ); 18 | 19 | wire dark_channel_frame_vsync ; 20 | wire dark_channel_frame_href ; 21 | wire dark_channel_frame_clken ; 22 | wire [7 : 0] dark_channel_img ; 23 | 24 | wire src_cal_A_frame_vsync ; 25 | wire src_cal_A_frame_href ; 26 | wire src_cal_A_frame_clken ; 27 | wire [7 : 0] src_cal_A_result ; 28 | wire src_cal_A_valid ; 29 | 30 | wire src_tx_frame_vsync ; 31 | wire src_tx_frame_href ; 32 | wire src_tx_frame_clken ; 33 | wire [7 : 0] src_tx_img ; 34 | 35 | wire cal_src_frame_vsync ; 36 | wire cal_src_frame_href ; 37 | wire cal_src_frame_clken ; 38 | wire [23 : 0] cal_img ; 39 | wire cal_tx_frame_vsync ; 40 | wire cal_tx_frame_href ; 41 | wire cal_tx_frame_clken ; 42 | wire [7 : 0] cal_tx_img ; 43 | wire [7 : 0] cal_A ; 44 | 45 | dark_channel#( 46 | .PIC_WIDTH (PIC_WIDTH ) 47 | )u_dark_channel( 48 | .clk (clk ), 49 | .rst_n (rst_n ), 50 | //Image data prepred to be processd 51 | .pre_frame_vsync (pre_frame_vsync ), 52 | .pre_frame_href (pre_frame_href ), 53 | .pre_frame_clken (pre_frame_clken ), 54 | .pre_img (pre_img ), 55 | //Image data has been processd 56 | .post_frame_vsync (dark_channel_frame_vsync ), 57 | .post_frame_href (dark_channel_frame_href ), 58 | .post_frame_clken (dark_channel_frame_clken ), 59 | .post_img (dark_channel_img ) 60 | ); 61 | 62 | calculate_A u_calculate_A( 63 | .clk (clk ), 64 | .rst_n (rst_n ), 65 | //Image data prepred to be processd 66 | .pre_frame_vsync (pre_frame_vsync ), 67 | .pre_frame_href (pre_frame_href ), 68 | .pre_frame_clken (pre_frame_clken ), 69 | .pre_img (pre_img ), 70 | //Image data has been processd 71 | .post_frame_vsync (src_cal_A_frame_vsync ), 72 | .post_frame_href (src_cal_A_frame_href ), 73 | .post_frame_clken (src_cal_A_frame_clken ), 74 | .post_result (src_cal_A_result ), 75 | .post_done (src_cal_A_valid ) 76 | ); 77 | 78 | tx_get u_tx_get( 79 | .clk (clk ), 80 | .rst_n (rst_n ), 81 | //Image data prepred to be processd 82 | .pre_frame_vsync (dark_channel_frame_vsync ), 83 | .pre_frame_href (dark_channel_frame_href ), 84 | .pre_frame_clken (dark_channel_frame_clken ), 85 | .pre_img (dark_channel_img ), 86 | .A_value (src_cal_A_result ), 87 | //Image data has been processd 88 | .post_frame_vsync (src_tx_frame_vsync ), 89 | .post_frame_href (src_tx_frame_href ), 90 | .post_frame_clken (src_tx_frame_clken ), 91 | .post_img (src_tx_img ) 92 | ); 93 | 94 | time_alignment u_time_alignment( 95 | .clk (clk ), 96 | .rst_n (rst_n ), 97 | //Image data prepred to be processd 98 | .pre_src_frame_vsync (pre_frame_vsync ), 99 | .pre_src_frame_href (pre_frame_href ), 100 | .pre_src_frame_clken (pre_frame_clken ), 101 | .pre_img (pre_img ), 102 | 103 | .pre_tx_frame_vsync (src_tx_frame_vsync ), 104 | .pre_tx_frame_href (src_tx_frame_href ), 105 | .pre_tx_frame_clken (src_tx_frame_clken ), 106 | .pre_tx_img (src_tx_img ), 107 | 108 | .pre_A (src_cal_A_result ), 109 | //Image data has been processd 110 | .post_src_frame_vsync (cal_src_frame_vsync ), 111 | .post_src_frame_href (cal_src_frame_href ), 112 | .post_src_frame_clken (cal_src_frame_clken ), 113 | .post_img (cal_img ), 114 | 115 | .post_tx_frame_vsync (cal_tx_frame_vsync ), 116 | .post_tx_frame_href (cal_tx_frame_href ), 117 | .post_tx_frame_clken (cal_tx_frame_clken ), 118 | .post_tx_img (cal_tx_img ), 119 | 120 | .post_A (cal_A ) 121 | ); 122 | 123 | generate 124 | if(Y_ENHANCE_ENABLE == 0) begin 125 | haze_removal_cal u_haze_removal_cal( 126 | .clk (clk ), 127 | .rst_n (rst_n ), 128 | 129 | .pre_src_frame_vsync (cal_src_frame_vsync ), 130 | .pre_src_frame_href (cal_src_frame_href ), 131 | .pre_src_frame_clken (cal_src_frame_clken ), 132 | .pre_img (cal_img ), 133 | 134 | .pre_tx_frame_vsync (cal_tx_frame_vsync ), 135 | .pre_tx_frame_href (cal_tx_frame_href ), 136 | .pre_tx_frame_clken (cal_tx_frame_clken ), 137 | .pre_tx_img (cal_tx_img ), 138 | 139 | .pre_A (cal_A ), 140 | 141 | .post_frame_vsync (post_frame_vsync ), 142 | .post_frame_href (post_frame_href ), 143 | .post_frame_clken (post_frame_clken ), 144 | .post_img (post_img ) 145 | ); 146 | end 147 | else begin 148 | 149 | 150 | wire haze_removal_vsync ; 151 | wire haze_removal_hsync ; 152 | wire haze_removal_de ; 153 | wire [23 : 0] haze_removal_data ; 154 | wire tem_YCbCr_vsync ; 155 | wire tem_YCbCr_hsync ; 156 | wire tem_YCbCr_de ; 157 | wire [07 : 0] tem_Y_data ; 158 | wire [07 : 0] tem_Cb_data ; 159 | wire [07 : 0] tem_Cr_data ; 160 | 161 | haze_removal_cal u_haze_removal_cal( 162 | .clk (clk ), 163 | .rst_n (rst_n ), 164 | 165 | .pre_src_frame_vsync (cal_src_frame_vsync ), 166 | .pre_src_frame_href (cal_src_frame_href ), 167 | .pre_src_frame_clken (cal_src_frame_clken ), 168 | .pre_img (cal_img ), 169 | 170 | .pre_tx_frame_vsync (cal_tx_frame_vsync ), 171 | .pre_tx_frame_href (cal_tx_frame_href ), 172 | .pre_tx_frame_clken (cal_tx_frame_clken ), 173 | .pre_tx_img (cal_tx_img ), 174 | 175 | .pre_A (cal_A ), 176 | 177 | .post_frame_vsync (haze_removal_vsync ), 178 | .post_frame_href (haze_removal_hsync ), 179 | .post_frame_clken (haze_removal_de ), 180 | .post_img (haze_removal_data ) 181 | ); 182 | 183 | VIP_RGB888_YCbCr444 u_rgb_ycncr_haze( 184 | //global clock 185 | .clk (clk ), 186 | .rst_n (rst_n ), 187 | 188 | //Image data prepred to be processd 189 | .pre_frame_vsync (haze_removal_vsync ), 190 | .pre_frame_href (haze_removal_hsync ), 191 | .pre_frame_clken (haze_removal_de ), 192 | .pre_img_red (haze_removal_data[16+:8] ), 193 | .pre_img_green (haze_removal_data[ 8+:8] ), 194 | .pre_img_blue (haze_removal_data[ 0+:8] ), 195 | 196 | //Image data has been processd 197 | .post_frame_vsync (tem_YCbCr_vsync ), 198 | .post_frame_href (tem_YCbCr_hsync ), 199 | .post_frame_clken (tem_YCbCr_de ), 200 | .post_img_Y (tem_Y_data ), 201 | .post_img_Cb (tem_Cb_data ), 202 | .post_img_Cr (tem_Cr_data ) 203 | ); 204 | 205 | YCbCr2RGB u_ycbcr_to_rgb( 206 | .i_sys_clk (clk ), 207 | 208 | .i_vs (tem_YCbCr_vsync ), 209 | .i_hs (tem_YCbCr_hsync ), 210 | .i_convert_en (tem_YCbCr_de ), 211 | .i_y_data (tem_Y_data + 30 ), 212 | .i_cr_data (tem_Cb_data ), 213 | .i_cb_data (tem_Cr_data ), 214 | 215 | .o_vs (post_frame_vsync ), 216 | .o_hs (post_frame_href ), 217 | .o_convert_en (post_frame_clken ), 218 | .o_red (post_img[ 0+:8] ), 219 | .o_green (post_img[ 8+:8] ), 220 | .o_blue (post_img[16+:8] ) 221 | ); 222 | end 223 | endgenerate 224 | 225 | 226 | endmodule 227 | -------------------------------------------------------------------------------- /1.RTL/src/matrix_generate_3x3.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOUDIU/Hardware-Implementation-of-the-Dark-Channel-Prior-Haze-Removal-Algorithm/558adccb7800acd472b9b20145cb2aa874f601fd/1.RTL/src/matrix_generate_3x3.v -------------------------------------------------------------------------------- /1.RTL/src/one_column_ram.v: -------------------------------------------------------------------------------- 1 | module one_column_ram#( 2 | parameter DATA_WIDTH = 8, 3 | parameter DATA_DEPTH = 640 4 | )( 5 | input clock, 6 | input clken, 7 | input [DATA_WIDTH - 1 : 0] shiftin, 8 | 9 | output [DATA_WIDTH - 1 : 0] taps0x, 10 | output [DATA_WIDTH - 1 : 0] taps1x, 11 | output [DATA_WIDTH - 1 : 0] taps2x 12 | ); 13 | 14 | //***************************************************** 15 | //** main code 16 | //***************************************************** 17 | wire [DATA_WIDTH - 1 : 0] fifo_rd_data0; 18 | reg [DATA_WIDTH - 1 : 0] fifo_rd_data0_d1; 19 | wire [DATA_WIDTH - 1 : 0] fifo_rd_data1; 20 | reg clken_d1; 21 | reg clken_d2; 22 | reg [DATA_WIDTH - 1 : 0] shiftin_d1; 23 | reg [DATA_WIDTH - 1 : 0] shiftin_d2; 24 | 25 | always@(posedge clock)begin 26 | clken_d1 <= clken; 27 | clken_d2 <= clken_d1; 28 | shiftin_d1 <= shiftin; 29 | shiftin_d2 <= shiftin_d1; 30 | fifo_rd_data0_d1 <= fifo_rd_data0; 31 | end 32 | 33 | fifo_ram#( 34 | .DATA_WIDTH(DATA_WIDTH), 35 | .DATA_DEPTH(DATA_DEPTH) 36 | ) 37 | u_fifo_ram0( 38 | .clk (clock), 39 | //write port 40 | .wr_en (clken_d2), 41 | .wr_data (shiftin_d2), 42 | .wr_full (), 43 | //read port 44 | .rd_en (clken), 45 | .rd_data (fifo_rd_data0), 46 | .rd_empty () 47 | ); 48 | 49 | fifo_ram#( 50 | .DATA_WIDTH(DATA_WIDTH), 51 | .DATA_DEPTH(DATA_DEPTH) 52 | ) 53 | u_fifo_ram1( 54 | .clk (clock), 55 | //write port 56 | .wr_en (clken_d2), 57 | .wr_data (fifo_rd_data0_d1), 58 | .wr_full (), 59 | //read port 60 | .rd_en (clken), 61 | .rd_data (fifo_rd_data1), 62 | .rd_empty () 63 | ); 64 | 65 | assign taps0x = shiftin_d1; 66 | assign taps1x = fifo_rd_data0; 67 | assign taps2x = fifo_rd_data1; 68 | 69 | endmodule -------------------------------------------------------------------------------- /1.RTL/src/search_block_min.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOUDIU/Hardware-Implementation-of-the-Dark-Channel-Prior-Haze-Removal-Algorithm/558adccb7800acd472b9b20145cb2aa874f601fd/1.RTL/src/search_block_min.v -------------------------------------------------------------------------------- /1.RTL/src/sort3.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOUDIU/Hardware-Implementation-of-the-Dark-Channel-Prior-Haze-Removal-Algorithm/558adccb7800acd472b9b20145cb2aa874f601fd/1.RTL/src/sort3.v -------------------------------------------------------------------------------- /1.RTL/src/src_min.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOUDIU/Hardware-Implementation-of-the-Dark-Channel-Prior-Haze-Removal-Algorithm/558adccb7800acd472b9b20145cb2aa874f601fd/1.RTL/src/src_min.v -------------------------------------------------------------------------------- /1.RTL/src/time_alignment.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOUDIU/Hardware-Implementation-of-the-Dark-Channel-Prior-Haze-Removal-Algorithm/558adccb7800acd472b9b20145cb2aa874f601fd/1.RTL/src/time_alignment.v -------------------------------------------------------------------------------- /1.RTL/src/tx_get.v: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOUDIU/Hardware-Implementation-of-the-Dark-Channel-Prior-Haze-Removal-Algorithm/558adccb7800acd472b9b20145cb2aa874f601fd/1.RTL/src/tx_get.v -------------------------------------------------------------------------------- /1.RTL/src/ycbcr2rgb.v: -------------------------------------------------------------------------------- 1 | 2 | `timescale 1ns/1ps 3 | module YCbCr2RGB 4 | ( 5 | input i_sys_clk , 6 | 7 | input i_vs , 8 | input i_hs , 9 | input i_convert_en , 10 | input [7:0] i_y_data , 11 | input [7:0] i_cr_data , 12 | input [7:0] i_cb_data , 13 | 14 | 15 | output o_vs , 16 | output o_hs , 17 | output o_convert_en , 18 | output reg [7:0] o_red , 19 | output reg [7:0] o_green , 20 | output reg [7:0] o_blue 21 | ); 22 | 23 | reg i_vs_d1; 24 | reg i_vs_d2; 25 | reg i_vs_d3; 26 | 27 | 28 | reg i_hs_d1; 29 | reg i_hs_d2; 30 | reg i_hs_d3; 31 | 32 | 33 | reg i_convert_en_d1; 34 | reg i_convert_en_d2; 35 | reg i_convert_en_d3; 36 | 37 | always@(posedge i_sys_clk)begin 38 | 39 | i_vs_d1 <= i_vs; 40 | i_vs_d2 <= i_vs_d1; 41 | i_vs_d3 <= i_vs_d2; 42 | 43 | i_hs_d1 <= i_hs; 44 | i_hs_d2 <= i_hs_d1; 45 | i_hs_d3 <= i_hs_d2; 46 | 47 | i_convert_en_d1 <= i_convert_en; 48 | i_convert_en_d2 <= i_convert_en_d1; 49 | i_convert_en_d3 <= i_convert_en_d2; 50 | end 51 | 52 | assign o_vs = i_vs_d3; 53 | assign o_hs = i_hs_d3; 54 | assign o_convert_en = i_convert_en_d3; 55 | 56 | reg [7:0] r_y_data ; 57 | reg [7:0] r_cb_data ; 58 | reg [7:0] r_cr_data ; 59 | reg [32:0] r_r_ypart ; 60 | reg [32:0] r_r_crpart ; 61 | reg [32:0] r_g_ypart ; 62 | reg [32:0] r_g_crpart ; 63 | reg [32:0] r_g_cbpart ; 64 | reg [32:0] r_b_ypart ; 65 | reg [32:0] r_b_cbpart ; 66 | reg [32:0] r_r_sum ; 67 | reg [32:0] r_g_sum ; 68 | reg [32:0] r_b_sum ; 69 | 70 | always@(posedge i_sys_clk) 71 | begin 72 | if(i_convert_en) 73 | begin 74 | r_y_data <= i_y_data; 75 | r_cr_data <= i_cr_data; 76 | r_cb_data <= i_cb_data; 77 | end 78 | end 79 | /******************************************************************************\ 80 | RGB(i, j,1) =Y1(i,j)+1.371*(Cr0(i,j)-128); 81 | \******************************************************************************/ 82 | always@(posedge i_sys_clk) 83 | begin 84 | if(i_convert_en) 85 | begin 86 | r_r_crpart <= 10'd380 * i_cr_data; //0.594*1024 = 610 87 | r_r_sum <= ((r_y_data + r_cr_data)<<10) + r_r_crpart - 179700; 88 | end 89 | end 90 | /******************************************************************************\ 91 | RGB(i, j,2) =Y1(i,j)-0.689*(Cr0(i,j)-128)-0.336*(Cb0(i,j)-128); 92 | \******************************************************************************/ 93 | always@(posedge i_sys_clk) 94 | begin 95 | if(i_convert_en) 96 | begin 97 | r_g_crpart <= 10'd706 * i_cr_data; 98 | r_g_cbpart <= 10'd344 * i_cb_data; 99 | r_g_sum <= (r_y_data << 10) - r_g_crpart - r_g_cbpart + 134349; 100 | end 101 | end 102 | /******************************************************************************\ 103 | RGB(i, j,3) =Y1(i,j)+1.732*(Cb0(i,j)-128); 104 | \******************************************************************************/ 105 | always@(posedge i_sys_clk) 106 | begin 107 | if(i_convert_en) 108 | begin 109 | r_b_cbpart <= 10'd750 * i_cb_data; 110 | r_b_sum <= (r_y_data << 10) + (r_cb_data << 10) + r_b_cbpart - 227017; 111 | end 112 | end 113 | /******************************************************************************\ 114 | output R 115 | \******************************************************************************/ 116 | always@(posedge i_sys_clk) 117 | begin 118 | if(i_convert_en) begin 119 | if(r_r_sum[31:10]>255)begin 120 | o_red <= 8'hff; 121 | end 122 | else 123 | begin 124 | o_red <= r_r_sum[31:10]; 125 | end 126 | end 127 | end 128 | /******************************************************************************\ 129 | output G 130 | \******************************************************************************/ 131 | always@(posedge i_sys_clk) 132 | begin 133 | if(i_convert_en) 134 | begin if(r_g_sum[31:10]>255) 135 | begin 136 | o_green <= 8'hff; 137 | end 138 | else 139 | begin 140 | o_green <= r_g_sum[31:10]; 141 | end 142 | end 143 | end 144 | /******************************************************************************\ 145 | output B 146 | \******************************************************************************/ 147 | always@(posedge i_sys_clk) 148 | begin 149 | if(i_convert_en) 150 | begin 151 | if(r_b_sum[31:10]>255) 152 | begin 153 | o_blue <= 8'hff; 154 | end 155 | else 156 | begin 157 | o_blue <= r_b_sum[31:10]; 158 | end 159 | end 160 | end 161 | 162 | endmodule -------------------------------------------------------------------------------- /1.RTL/tb/haze_removal_tb.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | module haze_removal_tb(); 3 | 4 | `define Modelsim_Sim 5 | // `define Vivado_Sim 6 | 7 | //-------------------------------------------------------------------------------- 8 | `ifdef Modelsim_Sim 9 | localparam PIC_INPUT_PATH = "..\\6.Pic\\duck.bmp" ; 10 | localparam PIC_OUTPUT_PATH = "..\\6.Pic\\outcom.bmp" ; 11 | `endif 12 | //-------------------------------------------------------------------------------- 13 | `ifdef Vivado_Sim 14 | localparam PIC_INPUT_PATH = "../../../../../6.Pic/duck.bmp" ; 15 | localparam PIC_OUTPUT_PATH = "../../../../../6.Pic/outcom.bmp" ; 16 | `endif 17 | 18 | localparam PIC_WIDTH = 640 ; 19 | localparam PIC_HEIGHT = 480 ; 20 | 21 | reg cmos_clk = 0; 22 | reg cmos_rst_n = 0; 23 | 24 | wire cmos_vsync ; 25 | wire cmos_href ; 26 | wire cmos_clken ; 27 | wire [23:0] cmos_data ; 28 | 29 | wire haze_removal_vsync ; 30 | wire haze_removal_hsync ; 31 | wire haze_removal_de ; 32 | wire [23:0] haze_removal_data ; 33 | 34 | parameter cmos0_period = 6; 35 | 36 | always#(cmos0_period/2) cmos_clk = ~cmos_clk; 37 | initial #(20*cmos0_period) cmos_rst_n = 1; 38 | 39 | //-------------------------------------------------- 40 | //Camera Simulation 41 | sim_cmos #( 42 | .PIC_PATH (PIC_INPUT_PATH ) 43 | , .IMG_HDISP (PIC_WIDTH ) 44 | , .IMG_VDISP (PIC_HEIGHT ) 45 | )u_sim_cmos0( 46 | .clk (cmos_clk ) 47 | , .rst_n (cmos_rst_n ) 48 | , .CMOS_VSYNC (cmos_vsync ) 49 | , .CMOS_HREF (cmos_href ) 50 | , .CMOS_CLKEN (cmos_clken ) 51 | , .CMOS_DATA (cmos_data ) 52 | , .X_POS () 53 | , .Y_POS () 54 | ); 55 | 56 | //-------------------------------------------------- 57 | //Image Processing 58 | haze_removal_top #( 59 | .Y_ENHANCE_ENABLE (0 ) 60 | , .PIC_WIDTH (PIC_WIDTH ) 61 | )u_haze_removal_top( 62 | .clk (cmos_clk ) 63 | , .rst_n (cmos_rst_n ) 64 | //处理前数据 65 | , .pre_frame_vsync (cmos_vsync ) 66 | , .pre_frame_href (cmos_href ) 67 | , .pre_frame_clken (cmos_clken ) 68 | , .pre_img (cmos_data ) 69 | //处理后的数据 70 | , .post_frame_vsync (haze_removal_vsync ) 71 | , .post_frame_href (haze_removal_hsync ) 72 | , .post_frame_clken (haze_removal_de ) 73 | , .post_img (haze_removal_data ) 74 | ); 75 | 76 | //-------------------------------------------------- 77 | //Video saving 78 | video_to_pic #( 79 | .PIC_PATH (PIC_OUTPUT_PATH ) 80 | , .START_FRAME (2 ) 81 | , .IMG_HDISP (PIC_WIDTH ) 82 | , .IMG_VDISP (PIC_HEIGHT ) 83 | )u_video_to_pic0( 84 | .clk (cmos_clk ) 85 | , .rst_n (cmos_rst_n ) 86 | , .video_vsync (haze_removal_vsync ) 87 | , .video_hsync (haze_removal_hsync ) 88 | , .video_de (haze_removal_de ) 89 | , .video_data (haze_removal_data ) 90 | ); 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | endmodule -------------------------------------------------------------------------------- /1.RTL/tb/sim_cmos_tb.sv: -------------------------------------------------------------------------------- 1 | module sim_cmos#( 2 | parameter PIC_PATH = "../../../../../../pic/duck_fog.bmp" 3 | , parameter IMG_HDISP = 640 4 | , parameter IMG_VDISP = 480 5 | )( 6 | input clk 7 | , input rst_n 8 | 9 | , output CMOS_VSYNC 10 | , output CMOS_HREF 11 | , output CMOS_CLKEN 12 | , output [23:0] CMOS_DATA 13 | , output [10:0] X_POS 14 | , output [10:0] Y_POS 15 | ); 16 | 17 | integer iBmpFileId; 18 | 19 | integer oTxtFileId; 20 | 21 | integer iIndex = 0; 22 | 23 | integer iCode; 24 | 25 | integer iBmpWidth; //输入BMP 宽度 26 | integer iBmpHight; //输入BMP 高度 27 | integer iBmpSize; //输入BMP 字节数 28 | integer iDataStartIndex; //输入BMP 像素数据偏移量 29 | 30 | localparam BMP_SIZE = 54 + IMG_HDISP * IMG_VDISP * 3 - 1; //输出BMP 字节数 31 | 32 | reg [ 7:0] rBmpData [0:BMP_SIZE]; 33 | 34 | integer i,j; 35 | 36 | 37 | //--------------------------------------------- 38 | initial begin 39 | iBmpFileId = $fopen(PIC_PATH,"rb"); 40 | 41 | iCode = $fread(rBmpData,iBmpFileId); 42 | 43 | //根据BMP图片文件头的格式,分别计算出图片的 宽度 /高度 /像素数据偏移量 /图片字节数 44 | iBmpWidth = {rBmpData[21],rBmpData[20],rBmpData[19],rBmpData[18]}; 45 | iBmpHight = {rBmpData[25],rBmpData[24],rBmpData[23],rBmpData[22]}; 46 | iBmpSize = {rBmpData[ 5],rBmpData[ 4],rBmpData[ 3],rBmpData[ 2]}; 47 | iDataStartIndex = {rBmpData[13],rBmpData[12],rBmpData[11],rBmpData[10]}; 48 | 49 | //关闭输入BMP图片 50 | $fclose(iBmpFileId); 51 | // if((iBmpWidth!= IMG_HDISP) | (iBmpHight!=IMG_VDISP)) begin 52 | // $display("Resolution mismatching.\n"); 53 | // $stop; 54 | // end 55 | end 56 | 57 | //--------------------------------------------- 58 | //产生摄像头时序 59 | 60 | wire cmos_vsync ; 61 | reg cmos_href; 62 | wire cmos_clken; 63 | reg [23:0] cmos_data; 64 | 65 | reg cmos_clken_r; 66 | 67 | reg [31:0] cmos_index; 68 | 69 | localparam H_SYNC = 11'd10; 70 | localparam H_BACK = 11'd10; 71 | localparam H_DISP = IMG_HDISP; 72 | localparam H_FRONT = 11'd10; 73 | localparam H_TOTAL = H_SYNC + H_BACK + H_DISP + H_FRONT; 74 | 75 | localparam V_SYNC = 11'd10; 76 | localparam V_BACK = 11'd10; 77 | localparam V_DISP = IMG_VDISP; 78 | localparam V_FRONT = 11'd10; 79 | localparam V_TOTAL = V_SYNC + V_BACK + V_DISP + V_FRONT; 80 | 81 | //--------------------------------------------- 82 | //模拟 OV7725/OV5640 驱动模块输出的时钟使能 83 | always@(posedge clk or negedge rst_n) begin 84 | if(!rst_n) 85 | cmos_clken_r <= 0; 86 | else 87 | cmos_clken_r <= ~cmos_clken_r; 88 | end 89 | 90 | //--------------------------------------------- 91 | //水平计数器 92 | reg [10:0] hcnt; 93 | always@(posedge clk or negedge rst_n) begin 94 | if(!rst_n) 95 | hcnt <= 11'd0; 96 | else if(cmos_clken_r) 97 | hcnt <= (hcnt < H_TOTAL - 1'b1) ? hcnt + 1'b1 : 11'd0; 98 | end 99 | 100 | //--------------------------------------------- 101 | //竖直计数器 102 | reg [10:0] vcnt; 103 | always@(posedge clk or negedge rst_n) begin 104 | if(!rst_n) 105 | vcnt <= 11'd0; 106 | else if(cmos_clken_r) begin 107 | if(hcnt == H_TOTAL - 1'b1) 108 | vcnt <= (vcnt < V_TOTAL - 1'b1) ? vcnt + 1'b1 : 11'd0; 109 | else 110 | vcnt <= vcnt; 111 | end 112 | end 113 | 114 | //--------------------------------------------- 115 | //场同步 116 | reg cmos_vsync_r; 117 | always@(posedge clk or negedge rst_n) begin 118 | if(!rst_n) 119 | cmos_vsync_r <= 1'b0; //H: Vaild, L: inVaild 120 | else begin 121 | if(vcnt <= V_SYNC - 1'b1) 122 | cmos_vsync_r <= 1'b0; //H: Vaild, L: inVaild 123 | else 124 | cmos_vsync_r <= 1'b1; //H: Vaild, L: inVaild 125 | end 126 | end 127 | assign cmos_vsync = cmos_vsync_r; 128 | 129 | //--------------------------------------------- 130 | //行有效 131 | wire frame_valid_ahead = ( vcnt >= V_SYNC + V_BACK && vcnt < V_SYNC + V_BACK + V_DISP 132 | && hcnt >= H_SYNC + H_BACK && hcnt < H_SYNC + H_BACK + H_DISP ) 133 | ? 1'b1 : 1'b0; 134 | 135 | reg cmos_href_r; 136 | always@(posedge clk or negedge rst_n) begin 137 | if(!rst_n) 138 | cmos_href_r <= 0; 139 | else begin 140 | if(frame_valid_ahead) 141 | cmos_href_r <= 1; 142 | else 143 | cmos_href_r <= 0; 144 | end 145 | end 146 | 147 | always@(posedge clk or negedge rst_n) begin 148 | if(!rst_n) 149 | cmos_href <= 0; 150 | else 151 | cmos_href <= cmos_href_r; 152 | end 153 | 154 | assign cmos_clken = cmos_href & cmos_clken_r; 155 | 156 | //------------------------------------- 157 | //从数组中以视频格式输出像素数据 158 | wire [10:0] x_pos; 159 | wire [10:0] y_pos; 160 | 161 | assign x_pos = frame_valid_ahead ? (hcnt - (H_SYNC + H_BACK )) : 0; 162 | assign y_pos = frame_valid_ahead ? (vcnt - (V_SYNC + V_BACK )) : 0; 163 | 164 | always@(posedge clk or negedge rst_n)begin 165 | if(!rst_n) begin 166 | cmos_index <= 0; 167 | cmos_data <= 24'd0; 168 | end 169 | else begin 170 | cmos_index <= y_pos * IMG_HDISP * 3 + x_pos * 3 + 54; // 3*(y*640 + x) + 54 171 | cmos_data <= {rBmpData[cmos_index], rBmpData[cmos_index+1] , rBmpData[cmos_index+2]}; 172 | end 173 | end 174 | 175 | reg [10:0] x_pos_d [0 : 10]; 176 | reg [10:0] y_pos_d [0 : 10]; 177 | 178 | always@(posedge clk or negedge rst_n)begin 179 | if(!rst_n)begin 180 | for(i = 0; i < 11; i = i + 1)begin 181 | x_pos_d[i] <= 0; 182 | y_pos_d[i] <= 0; 183 | end 184 | end 185 | else begin 186 | x_pos_d[0] <= x_pos; 187 | y_pos_d[0] <= y_pos; 188 | for(i = 1; i < 11; i = i + 1)begin 189 | x_pos_d[i] <= x_pos_d[i-1]; 190 | y_pos_d[i] <= y_pos_d[i-1]; 191 | end 192 | end 193 | end 194 | 195 | assign CMOS_VSYNC = cmos_vsync; 196 | assign CMOS_HREF = cmos_href; 197 | assign CMOS_CLKEN = cmos_clken; 198 | assign CMOS_DATA = cmos_data; 199 | assign X_POS = x_pos; 200 | assign Y_POS = y_pos; 201 | 202 | 203 | endmodule -------------------------------------------------------------------------------- /1.RTL/tb/video_to_pic.sv: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ns 2 | module video_to_pic#( 3 | parameter PIC_PATH = "..\\pic\\outcom.bmp" 4 | , parameter START_FRAME = 1 5 | , parameter IMG_HDISP = 640 6 | , parameter IMG_VDISP = 480 7 | )( 8 | input clk 9 | , input rst_n 10 | , input video_vsync 11 | , input video_hsync 12 | , input video_de 13 | , input [23:0] video_data 14 | ); 15 | 16 | integer iCode; 17 | integer iBmpFileId; 18 | integer iBmpWidth; 19 | integer iBmpHight; 20 | integer iBmpSize; 21 | integer iDataStartIndex; 22 | integer iIndex = 0; 23 | 24 | localparam BMP_SIZE = 54 + IMG_HDISP * IMG_VDISP * 3 - 1; 25 | reg [ 7:0] BmpHead [0:53]; 26 | reg [ 7:0] Vip_BmpData [0:BMP_SIZE]; 27 | reg [ 7:0] vip_pixel_data [0:BMP_SIZE-54]; 28 | reg [31:0] rBmpWord; 29 | 30 | reg video_vsync_d1 = 0; 31 | reg [11:0] frame_cnt = 0; 32 | reg [31:0] PIC_cnt = 0; 33 | 34 | wire [7:0] PIC_img_R; 35 | wire [7:0] PIC_img_G; 36 | wire [7:0] PIC_img_B; 37 | assign PIC_img_R = video_data[16+:8]; 38 | assign PIC_img_G = video_data[ 8+:8]; 39 | assign PIC_img_B = video_data[ 0+:8]; 40 | 41 | 42 | always@(posedge clk or negedge rst_n)begin 43 | if(!rst_n)begin 44 | video_vsync_d1 <= 0; 45 | end 46 | else begin 47 | video_vsync_d1 <= video_vsync; 48 | end 49 | end 50 | 51 | always@(posedge clk or negedge rst_n)begin 52 | if(!rst_n)begin 53 | frame_cnt <= 0; 54 | end 55 | else if(video_vsync_d1 & !video_vsync)begin 56 | frame_cnt <= frame_cnt + 1; 57 | end 58 | end 59 | 60 | 61 | 62 | always@(posedge clk or negedge rst_n)begin 63 | if(!rst_n) begin 64 | PIC_cnt <= 32'd0; 65 | end 66 | else if(video_de) begin 67 | if(frame_cnt == START_FRAME - 1) begin 68 | PIC_cnt <= PIC_cnt + 3; 69 | vip_pixel_data[PIC_cnt+0] <= PIC_img_R; 70 | vip_pixel_data[PIC_cnt+1] <= PIC_img_G; 71 | vip_pixel_data[PIC_cnt+2] <= PIC_img_B; 72 | end 73 | end 74 | end 75 | 76 | 77 | //--------------------------------------------- 78 | //initial the BMP file header 79 | //The detail BMP file header is inpart from https://blog.csdn.net/Meteor_s/article/details/82414155 and inpart from my test. 80 | initial begin 81 | for(iIndex = 0; iIndex < 54; iIndex = iIndex + 1) begin 82 | BmpHead[iIndex] = 0; 83 | end 84 | #2 85 | {BmpHead[1],BmpHead[0]} = {8'h4D,8'h42}; 86 | {BmpHead[5],BmpHead[4],BmpHead[3],BmpHead[2]} = BMP_SIZE + 1;//File Size (Bytes) 87 | BmpHead[10] = 8'd54;//Bitmap Data Offset 88 | BmpHead[14] = 8'h28;//Bitmap Header Size 89 | {BmpHead[21],BmpHead[20],BmpHead[19],BmpHead[18]} = IMG_HDISP;//Width 90 | {BmpHead[25],BmpHead[24],BmpHead[23],BmpHead[22]} = IMG_VDISP;//Height 91 | BmpHead[26] = 8'd1;//Number of Color Planes 92 | BmpHead[28] = 8'd24;//Bits per Pixel 93 | end 94 | 95 | 96 | 97 | //--------------------------------------------- 98 | //write the data to the output bmp file 99 | initial begin 100 | //--------------------------------------------- 101 | //waiting for the start frame 102 | wait(frame_cnt == START_FRAME); 103 | 104 | iBmpFileId = $fopen(PIC_PATH,"wb+"); 105 | for (iIndex = 0; iIndex < BMP_SIZE + 1; iIndex = iIndex + 1) begin 106 | if(iIndex < 54) begin 107 | Vip_BmpData[iIndex] = BmpHead[iIndex]; 108 | end 109 | else begin 110 | Vip_BmpData[iIndex] = vip_pixel_data[iIndex-54]; 111 | end 112 | end 113 | for (iIndex = 0; iIndex < BMP_SIZE + 1; iIndex = iIndex + 1) begin 114 | $fwrite(iBmpFileId,"%c",Vip_BmpData[iIndex]); 115 | end 116 | $fclose(iBmpFileId); 117 | $display("The picture is saved in %s",PIC_PATH); 118 | $stop; 119 | end 120 | 121 | 122 | 123 | 124 | endmodule -------------------------------------------------------------------------------- /2.C++_Model/Haze Removal Verification/Haze Removal Verification.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include"function.h" 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace std; 11 | using namespace cv; 12 | 13 | int main() 14 | { 15 | Mat src = imread("../../6.Pic/duck.bmp"); 16 | Mat dst; 17 | Mat dark_channel_mat = dark_channel(src, 3);//输出的是暗通道图像 18 | 19 | int A = calculate_A(src, dark_channel_mat); 20 | Mat tx = calculate_tx(src, A, dark_channel_mat); 21 | 22 | cvtColor(src, dst, COLOR_RGB2GRAY); 23 | Mat tx_ = guidedfilter_revise(dst, tx, 5, 0.001);//导向滤波后的tx,dst为引导图像 24 | 25 | Mat haze_removal_image = haze_removal_img(src, A, tx_); 26 | 27 | imshow("原始图", src); 28 | //imshow("灰度图", dst); 29 | //imshow("暗通道图", dark_channel_mat); 30 | //imshow("透射率函数", tx); 31 | imshow("导向滤波优化", tx_); 32 | imshow("去雾图", haze_removal_image); 33 | 34 | waitKey(0); 35 | return 0; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /2.C++_Model/Haze Removal Verification/function.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOUDIU/Hardware-Implementation-of-the-Dark-Channel-Prior-Haze-Removal-Algorithm/558adccb7800acd472b9b20145cb2aa874f601fd/2.C++_Model/Haze Removal Verification/function.h -------------------------------------------------------------------------------- /3.Matlab_Model/enhance_y.m: -------------------------------------------------------------------------------- 1 | close all 2 | clear all 3 | clc 4 | 5 | I=imread('..\6.Pic\outcom.bmp'); 6 | 7 | [H ,W ,D]=size(I); 8 | 9 | R=double(I(:,:,1)); 10 | G=double(I(:,:,2)); 11 | B=double(I(:,:,3)); 12 | 13 | 14 | Y0= double(zeros(H,W)); 15 | Y1= double(zeros(H,W)); 16 | Cb0 =double(zeros(H,W)); 17 | Cr0 = double(zeros(H,W)); 18 | 19 | R0= double(zeros(H,W)); 20 | G0 =double(zeros(H,W)); 21 | B0 = double(zeros(H,W)); 22 | 23 | %RGB to YCbCr444 24 | for i = 1:H 25 | for j = 1:W 26 | Y0(i, j) = 0.299*R(i, j) + 0.587*G(i, j) + 0.114*B(i, j); 27 | Cb0(i, j) = -0.172*R(i, j) - 0.339*G(i, j) + 0.511*B(i, j) + 128; 28 | Cr0(i, j) = 0.511*R(i, j) - 0.428*G(i, j) - 0.083*B(i, j) + 128; 29 | end 30 | end 31 | 32 | for i = 1:H 33 | for j = 1:W 34 | Y1(i,j) = Y0(i,j) + 50; 35 | end 36 | end 37 | 38 | for i = 1:H 39 | for j = 1:W 40 | RGB(i, j,1) =Y1(i,j)+1.371*(Cr0(i,j)-128); 41 | RGB(i, j,2) =Y1(i,j)-0.689*(Cr0(i,j)-128)-0.336*(Cb0(i,j)-128); 42 | RGB(i, j,3) =Y1(i,j)+1.732*(Cb0(i,j)-128); 43 | end 44 | end 45 | 46 | YCbCr(:,:,1)=Y0; 47 | YCbCr(:,:,2)=Cb0; 48 | YCbCr(:,:,3)=Cr0; 49 | 50 | YCbCr=uint8(YCbCr); 51 | 52 | RGB=uint8(RGB); 53 | 54 | %figure(1), 55 | %imshow(YCbCr),title('YCbCr'); 56 | 57 | figure(1), 58 | imshow(I),title('origine'); 59 | figure(2), 60 | imshow(RGB),title('after'); 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /4.Vivado_Project/haze_removal.xpr: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 195 | 196 | 197 | 198 | 199 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 244 | 245 | 246 | 247 | 248 | 250 | 251 | 252 | 253 | 254 | 257 | 258 | 260 | 261 | 263 | 264 | 266 | 267 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | default_dashboard 326 | 327 | 328 | 329 | -------------------------------------------------------------------------------- /4.Vivado_Project/haze_removal_tb_behav.wcfg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | clk 25 | clk 26 | 27 | 28 | rst_n 29 | rst_n 30 | 31 | 32 | INPUT 33 | label 34 | 35 | 36 | pre_frame_vsync 37 | pre_frame_vsync 38 | 39 | 40 | pre_frame_href 41 | pre_frame_href 42 | 43 | 44 | pre_frame_clken 45 | pre_frame_clken 46 | 47 | 48 | pre_img[23:0] 49 | pre_img[23:0] 50 | 51 | 52 | OUTPUT 53 | label 54 | 55 | 56 | post_frame_vsync 57 | post_frame_vsync 58 | 59 | 60 | post_frame_href 61 | post_frame_href 62 | 63 | 64 | post_frame_clken 65 | post_frame_clken 66 | 67 | 68 | post_img[23:0] 69 | post_img[23:0] 70 | 71 | 72 | -------------------------------------------------------------------------------- /5.QuestaSim/readme.md: -------------------------------------------------------------------------------- 1 | # build your modelsim project here! -------------------------------------------------------------------------------- /6.Pic/combine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOUDIU/Hardware-Implementation-of-the-Dark-Channel-Prior-Haze-Removal-Algorithm/558adccb7800acd472b9b20145cb2aa874f601fd/6.Pic/combine.png -------------------------------------------------------------------------------- /6.Pic/duck.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOUDIU/Hardware-Implementation-of-the-Dark-Channel-Prior-Haze-Removal-Algorithm/558adccb7800acd472b9b20145cb2aa874f601fd/6.Pic/duck.bmp -------------------------------------------------------------------------------- /6.Pic/forest.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOUDIU/Hardware-Implementation-of-the-Dark-Channel-Prior-Haze-Removal-Algorithm/558adccb7800acd472b9b20145cb2aa874f601fd/6.Pic/forest.bmp -------------------------------------------------------------------------------- /6.Pic/outcom.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOUDIU/Hardware-Implementation-of-the-Dark-Channel-Prior-Haze-Removal-Algorithm/558adccb7800acd472b9b20145cb2aa874f601fd/6.Pic/outcom.bmp -------------------------------------------------------------------------------- /6.Pic/reademe_pic/KaiMingHe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/DOUDIU/Hardware-Implementation-of-the-Dark-Channel-Prior-Haze-Removal-Algorithm/558adccb7800acd472b9b20145cb2aa874f601fd/6.Pic/reademe_pic/KaiMingHe.png -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## 基于暗通道先验去雾算法的FPGA实现 2 | 3 | ![combine](6.Pic/combine.png) 4 | 5 | 有完整C++实现代码,PPT里面有算法具体实现的思路,如有疑惑欢迎提交补充。 6 | 7 | 如果有帮助的话,不要忘记点赞关注订阅哦! 8 | 9 | ### Introduction 10 | 11 | ​ 这个工程是基于暗通道先验去雾算法的FPGA实现,其中最小值卷积窗利用FIFO实现,可通过提高流水级数实现高精准度。所有代码由Verilog编写,并未使用一些IP,将很便利的移植到各种开发平台上,如Altera与Xilinx的各类FPGA。 12 | 13 | ​ C代码中有加导向滤波,实际上效果会好很多,但是FPGA实现的时候没有加上去,目前实现了图像的去雾,图片的A值是用上一帧的A值作为现有帧的A值,实际上应用的话应该不会有太大影响。 14 | 15 | ​ 原提交版本实现了去雾,但是如效果展示图所示,结果比较暗,当前版本通过调整Y值,使图片相对显示的正常一些。 16 | 17 | ​ 建议看一下何凯明的那篇论文,讲的还是很清楚的,FPGA上实际上粗糙的实现了功能。 18 | 19 | ### Folder Structure 20 | 21 | ​ 其中***RTL工程***文件如下: 22 | 23 | > | Folder | Function | 24 | > | :-------------------------------: | :----------------------------------------------------------: | 25 | > | ***1.RTL*** | #存放着所有源代码及仿真代码 | 26 | > | ***4.Vivado_Project*** | #工程及波形文件(当前版本**Vivado2023.2**,仅供参考,建议自行创建工程) | 27 | > | ***5.QuestaSim*** | #存放Modelsim/QuestaSim的工程(为空,需自己创建工程至此目录) | 28 | 29 | 注:请把Modelsim工程创建到Questasim文件夹,添加RTL文件下所有源文件,选择顶层***haze_removal_tb.sv***进行仿真,仿真完会自动暂停的。 30 | 31 | ​ 其中***验证工程***如下: 32 | 33 | > | Folder | Function | 34 | > | :-------------------------------: | :----------------------------------------------------------: | 35 | > | ***2.C++_Model*** | #基于opencv验证的暗通道先验去雾算法的验证方案(自行配置opencv环境) | 36 | > | ***3.Matlab_Model*** | #提高亮度以使去雾图片看起来正常点的代码 | 37 | 38 | ​ ***PPT演示文档***如下: 39 | 40 | https://docs.google.com/presentation/d/1hftrReSJX6RB1ljNpfOpNf5uYBZNhLuOinfR8WJm7VA/edit?usp=sharing 41 | 42 | ### Reference 43 | 44 | 何凯明个人主页(内有论文、SLIDE) 45 | 46 | > https://kaiminghe.github.io/ 47 | > 48 | > - 1.Single Image Haze Removal Using Dark Channel Prior 49 | > 50 | > - 2.Guided Image Filtering 51 | 52 | 去雾算法相关介绍: 53 | 54 | > https://www.jianshu.com/p/df9c963a392a 55 | > 56 | > [暗通道先验去雾(single image haze removal using dark channel prior) - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/28875405) 57 | 58 | 部分公式推导: 59 | 60 | > https://zhuanlan.zhihu.com/p/438206777 61 | > 62 | > [(34条消息) 导向滤波(Guided Filter)公式详解_lsflll的博客-CSDN博客_导向滤波](https://blog.csdn.net/weixin_43194305/article/details/88959183) 63 | 64 | ### Tips: 65 | 66 | ​ 本工程中的仿真文件中读取bmp与保存bmp用的读取函数都是使用***相对路径***,如果不想自己重新切换下路径的话,上述三个文件夹及Vivado工程创建路径需与此教程一致。 67 | 68 | ​ 本工程可以使用***Modelsim Simulator***或者***Vivado Simulator***进行仿真,仅需在仿真顶层**haze_removal_tb.sv**的4-5两行注释另一仿真器代码,即可实现两个仿真器任意运行。但Vivado仿真比较慢,推荐使用Modelsim仿真。 69 | 70 | ​ 要进行处理的图片需经过win10自带的3D绘图保存为对应尺寸的bmp,可以查看大小是否正确来验证图片是否可以应用仿真。(如输入640x480的图像,每个真彩色像素是3个字节,bmp的帧头是54个字节,可以自己算一下,该图像大小应为640x480x3+54=900KB) 71 | 72 | **走过路过,不要忘记点赞关注订阅哟!** 73 | --------------------------------------------------------------------------------