finish Grey World White Balance

This commit is contained in:
SikongJueluo 2024-07-03 21:50:29 +08:00
parent 649d34415f
commit 1154da3307
No known key found for this signature in database
GPG Key ID: D2D3D29A993716EA
12 changed files with 526 additions and 239 deletions

View File

@ -34,7 +34,7 @@ module ColorBlender #(
reg [2:0] state, nextState;
reg [BUFF_SIZE - 1:0] data_cal[3]; // 用于保存运算结果,防止溢出
always @(posedge clk or posedge reset) begin
always @(posedge clk) begin
if (reset) begin
state <= READ_DATA;
end else begin
@ -55,7 +55,7 @@ module ColorBlender #(
assign out_ready = (!in_en && state == READ_DATA) ? 1 : 0;
assign out_receive = (in_en && state == READ_DATA) ? 1 : 0;
always @(posedge clk or posedge reset) begin
always @(posedge clk) begin
if (reset) begin
// 初始化
data_cal[0] <= 0;

View File

@ -25,7 +25,7 @@ module GammaCorrection2 #(
reg [7:0] data_cache[3];
always @(posedge clk or posedge reset) begin
always @(posedge clk) begin
if (reset) state <= READ_DATA;
else state <= nextState;
end
@ -41,7 +41,7 @@ module GammaCorrection2 #(
assign out_ready = (!in_en && state == READ_DATA) ? 1 : 0;
assign out_receive = (in_en && state == READ_DATA) ? 1 : 0;
always @(posedge clk or posedge reset) begin
always @(posedge clk) begin
if (reset) begin
out_en <= 0;
out_data[0] <= 0;

134
Color/GreyWorld.sv Normal file
View File

@ -0,0 +1,134 @@
`timescale 1ns / 1ps
// 三通道图像合成一个RGB图像
module GreyWorld #(
parameter reg [4:0] COLOR_DEPTH = 8,
parameter reg [31:0] IM_SIZE = 1920 * 1080
) (
input wire clk,
input wire reset,
input wire in_en,
input wire [7:0] in_data[3], // 0:R 1:G 2:B
output wire out_ready,
output wire out_receive,
// 输出相关
input wire in_ready,
input wire in_receive,
output reg out_en,
output reg [COLOR_DEPTH - 1:0] out_data[3],
// Gain: red = 0.803881, green = 0.885894, blue = 1.594308
input wire enable,
input wire [8:0] flame_rate,
input wire [31:0] white_gain[3]
);
reg [2:0] state, nextState;
localparam reg [2:0] READ_DATA = 0;
localparam reg [2:0] CALC_DATA = 1;
localparam reg [2:0] SEND_DATA = 2;
reg [8:0] cnt_flame;
reg [31:0] red_total, green_total, blue_total, r_white_gain[3];
reg [31:0] data_cal[3], data_cache[3];
reg [31:0] cnt_pexels;
wire [31:0] average;
always @(posedge clk) begin
if (reset) state <= READ_DATA;
else state <= nextState;
end
always @(*) begin
case (state)
READ_DATA: nextState = in_en ? CALC_DATA : READ_DATA;
CALC_DATA: nextState = SEND_DATA;
SEND_DATA: nextState = in_receive ? READ_DATA : SEND_DATA;
default: nextState = READ_DATA;
endcase
end
assign out_ready = (!in_en && !reset) ? 1 : 0;
assign out_receive = (in_en && !reset) ? 1 : 0;
assign average = ((red_total + green_total + blue_total) << 8) / (3 * IM_SIZE);
always @(posedge clk) begin
if (reset) begin
red_total <= 0;
green_total <= 0;
blue_total <= 0;
cnt_flame <= flame_rate;
cnt_pexels <= 0;
r_white_gain[0] <= white_gain[0];
r_white_gain[1] <= white_gain[1];
r_white_gain[2] <= white_gain[2];
data_cache[0] <= 0;
data_cache[1] <= 0;
data_cache[2] <= 0;
out_en <= 0;
out_data[0] <= 0;
out_data[1] <= 0;
out_data[2] <= 0;
end else begin
case (state)
READ_DATA: begin
if (in_en) begin
data_cache[0] <= {24'b0, in_data[0]};
data_cache[1] <= {24'b0, in_data[1]};
data_cache[2] <= {24'b0, in_data[2]};
if (cnt_flame == flame_rate) begin
red_total <= red_total + {24'b0, in_data[0]};
green_total <= green_total + {24'b0, in_data[0]};
blue_total <= blue_total + {24'b0, in_data[0]};
end
if (cnt_pexels < IM_SIZE) begin
cnt_pexels <= cnt_pexels + 1;
end else begin
cnt_pexels <= 0;
if (cnt_flame < flame_rate) cnt_flame <= cnt_flame + 1;
else cnt_flame <= 0;
end
end
end
CALC_DATA: begin
if (cnt_pexels >= IM_SIZE && cnt_flame == flame_rate) begin
r_white_gain[0] <= (average * ( IM_SIZE << 8 )) / red_total;
r_white_gain[1] <= (average * ( IM_SIZE << 8)) / green_total;
r_white_gain[2] <= (average * ( IM_SIZE << 8)) / blue_total;
end
data_cal[0] <= (data_cache[0] * r_white_gain[0]);
data_cal[1] <= (data_cache[1] * r_white_gain[1]);
data_cal[2] <= (data_cache[2] * r_white_gain[2]);
end
SEND_DATA: begin
if (in_ready) begin
out_en <= 1;
if (enable) begin
out_data[0] <= (|data_cal[0][31:16]) ? 255 : (data_cal[0] > 0 ? data_cal[0][15:8] : 0);
out_data[1] <= (|data_cal[1][31:16]) ? 255 : (data_cal[1] > 0 ? data_cal[1][15:8] : 0);
out_data[2] <= (|data_cal[2][31:16]) ? 255 : (data_cal[2] > 0 ? data_cal[2][15:8] : 0);
end else begin
out_data[0] <= data_cache[0][7:0];
out_data[1] <= data_cache[1][7:0];
out_data[2] <= data_cache[2][7:0];
end
end else out_en <= 0;
end
default: ;
endcase
end
end
endmodule

View File

@ -27,7 +27,7 @@ module SaturationCorrection #(
reg signed [31:0] data_cal[3], data_cache[3];
wire signed [31:0] max, min, delta, value, light, saturation, alpha;
always @(posedge clk or posedge reset) begin
always @(posedge clk) begin
if (reset) state <= READ_DATA;
else state <= nextState;
end
@ -60,7 +60,7 @@ module SaturationCorrection #(
? (65536 / saturation) - 256 : (65536 / (256 - saturation_inc)) - 256)
: (saturation_inc);
always @(posedge clk or posedge reset) begin
always @(posedge clk) begin
if (reset) begin
out_en <= 0;
out_data[0] <= 0;
@ -101,9 +101,9 @@ module SaturationCorrection #(
if (in_ready) begin
out_en <= 1;
if (enable && delta != 0) begin
out_data[0] <= (data_cal[0] <= 65535) ? (data_cal[0] > 0 ? data_cal[0][15:8] : 0) : 255;
out_data[1] <= (data_cal[1] <= 65535) ? (data_cal[1] > 1 ? data_cal[1][15:8] : 1) : 255;
out_data[2] <= (data_cal[2] <= 65535) ? (data_cal[2] > 2 ? data_cal[2][15:8] : 2) : 255;
out_data[0] <= (|data_cal[0][31:16]) ? 255 : (data_cal[0] > 0 ? data_cal[0][15:8] : 0);
out_data[1] <= (|data_cal[1][31:16]) ? 255 : (data_cal[1] > 0 ? data_cal[1][15:8] : 0);
out_data[2] <= (|data_cal[2][31:16]) ? 255 : (data_cal[2] > 0 ? data_cal[2][15:8] : 0);
end else begin
out_data[0] <= data_cache[0][7:0];
out_data[1] <= data_cache[1][7:0];

View File

@ -2,9 +2,11 @@
// 三通道图像合成一个RGB图像
module WhiteBalance #(
parameter reg [4:0] IN_DEPTH = 12, // 输入图像的色深
parameter reg [4:0] OUT_DEPTH = 8, // 输出图像的色深
parameter reg [8:0] BUFF_SIZE = 32
parameter reg [4:0] IN_DEPTH = 12, // 输入图像的色深
parameter reg [4:0] OUT_DEPTH = 8, // 输出图像的色深
parameter reg [8:0] BUFF_SIZE = 32,
parameter reg [31:0] RAM_BEGIN_ADDR = 0,
parameter reg [31:0] IM_SIZE = 1920 * 1080
) (
input wire clk,
input wire reset,
@ -17,22 +19,116 @@ module WhiteBalance #(
// 输出相关
input wire in_ready,
input wire in_receive,
output reg out_en,
output reg [OUT_DEPTH - 1:0] out_data[3],
output wire out_en,
output wire [OUT_DEPTH - 1:0] out_data[3],
input wire enable,
input wire [8:0] flame_rate
input wire [8:0] flame_rate,
input wire [31:0] white_gain[3]
);
assign out_ready = (!reset) ? 1 : 0;
assign out_receive = (in_en && !reset) ? 1 : 0;
wire ram_read_en, ram_write_en, ram_read_ready, ram_write_ready;
wire [31:0] ram_read_data, ram_read_addr, ram_write_data, ram_write_addr;
reg [8:0] cnt_flame;
reg [31:0] cnt_in_pic, cnt_out_pic, cnt_pixels;
reg [31:0] red_total, green_total, blue_total;
reg [31:0] r_white_gain[3];
wire is_finish_cal;
always @(*) begin
if (cnt_in_pic >= IM_SIZE) is_finish_cal = 1;
else if (cnt_out_pic >= IM_SIZE) is_finish_cal = 0;
else is_finish_cal = is_finish_cal;
end
assign ram_read_addr = cnt_out_pic;
assign ram_write_addr = cnt_in_pic;
assign cnt_pixels = (is_finish_cal)
? IM_SIZE - cnt_out_pic + cnt_in_pic
: cnt_in_pic - cnt_out_pic;
assign out_ready = (!in_en && !reset && cnt_pixels < IM_SIZE) ? 1 : 0;
assign out_receive = (in_en && !reset && cnt_in_pic < IM_SIZE) ? 1 : 0;
DiffWidthSyncFIFO #(
.DATA_WIDTH (8),
.DATA_DEPTH (12),
.READ_DEPTH (4),
.WRITE_DEPTH(3)
) in_fifo (
.clk(clk),
.reset(reset),
.read_ready(ram_write_ready),
.read_en(ram_write_en),
.read_data(ram_write_data),
.write_ready(in_ready),
.write_en(in_en),
.write_data(in_data)
);
)
DiffWidthSyncFIFO #(
.DATA_WIDTH (8),
.DATA_DEPTH (12),
.READ_DEPTH (3),
.WRITE_DEPTH(4)
) out_fifo (
.clk(clk),
.reset(reset),
.read_ready(out_ready),
.read_en(out_en),
.read_data(out_data),
.write_ready(ram_read_ready),
.write_en(ram_read_en),
.write_data(ram_read_data)
);
SDRAM inst_RAM (
.clk(clk),
.read_en(ram_read_en),
.read_addr(ram_read_addr),
.read_data(ram_read_data),
.read_ready(ram_read_ready),
.write_en(ram_write_en),
.write_addr(ram_write_addr),
.write_data(ram_write_data),
.write_ready(ram_write_ready)
);
// calculate white gain
always @(posedge clk) begin
if(reset) begin
if (reset) begin
red_total <= 0;
green_total <= 0;
blue_total <= 0;
cnt_flame <= 0;
cnt_in_pic <= 0;
r_white_gain[0] <= white_gain[0];
r_white_gain[1] <= white_gain[1];
r_white_gain[2] <= white_gain[2];
end else begin
if (in_en && cnt_pixels < IM_SIZE) begin
red_total <= red_total + in_data[0];
green_total <= green_total + in_data[1];
blue_total <= blue_total + in_data[2];
if (cnt_in_pic < IM_SIZE) cnt_in_pic <= cnt_in_pic + 1;
else cnt_in_pic <= 0;
end else begin
end
end
end
// calculate out data
always @(posedge clk) begin
if (reset) begin
cnt_out_pic <= 0;
end else begin
if (out_ready && is_finish_cal) begin
out_en <= 1;
end else begin
out_en <= 0;
end
end
end

View File

@ -13,12 +13,12 @@ module Crop #(
input wire in_en,
output wire out_ready,
output wire out_receive,
input wire [3 * COLOR_DEPTH - 1:0] in_data,
input wire [COLOR_DEPTH - 1:0] in_data[3],
input wire in_ready,
input wire in_receive,
output reg out_en,
output reg [3 * COLOR_DEPTH - 1:0] out_data
output reg [COLOR_DEPTH - 1:0] out_data[3]
);
reg [1:0] state, nextState;
localparam reg [1:0] READ_DATA = 0;
@ -26,11 +26,11 @@ module Crop #(
localparam reg [1:0] SEND_DATA = 2;
reg [15:0] cnt_x, cnt_y;
reg [3 * COLOR_DEPTH - 1:0] data;
reg [COLOR_DEPTH - 1:0] data[3];
wire is_valid;
// 状态切换
always @(posedge clk or posedge reset) begin
always @(posedge clk) begin
if (reset) state <= READ_DATA;
else state <= nextState;
end
@ -50,19 +50,25 @@ module Crop #(
assign is_valid = ((OFFSET_Y <= cnt_y && cnt_y <= (OFFSET_Y + OUT_HEIGHT - 1)) &&
(OFFSET_X <= cnt_x && cnt_x <= (OFFSET_X + OUT_WIDTH))) ? 1 : 0;
always @(posedge clk or posedge reset) begin
always @(posedge clk) begin
if (reset) begin
cnt_x <= 0;
cnt_y <= 0;
data <= 0;
data[0] <= 0;
data[1] <= 0;
data[2] <= 0;
out_en <= 0;
out_data <= 0;
out_data[0] <= 0;
out_data[1] <= 0;
out_data[2] <= 0;
end else begin
case (state)
READ_DATA: begin
if (in_en) begin
data <= in_data;
data[0] <= in_data[0];
data[1] <= in_data[1];
data[2] <= in_data[2];
end
end
@ -82,7 +88,9 @@ module Crop #(
SEND_DATA: begin
if (in_ready && !in_receive && is_valid) begin
out_en <= 1;
out_data <= data;
out_data[0] <= data[0];
out_data[1] <= data[1];
out_data[2] <= data[2];
end else out_en <= 0;
end

View File

@ -41,7 +41,7 @@ module Demosaic2 #(
// 三段状态机实现,窗口滑动,颜色计算
// 状态切换
always @(posedge clk or posedge reset) begin
always @(posedge clk) begin
if (reset) state <= READ_DATA;
else state <= nextState;
end
@ -64,7 +64,7 @@ module Demosaic2 #(
assign out_receive = (in_en && state == READ_DATA) ? 1 : 0;
// 各状态执行的操作
always @(posedge clk or posedge reset) begin
always @(posedge clk) begin
if (reset) begin
// 外部输出初始化
out_en <= 0;

29
RAM/SDRAM.v Normal file
View File

@ -0,0 +1,29 @@
module SDRAM (
input wire clk,
input wire read_en,
input wire [31:0] read_addr,
output wire [31:0] read_data,
output wire read_ready,
input wire write_en,
input wire [31:0] write_addr,
input reg [31:0] write_data,
output wire write_ready
);
reg [31:0] ram[1920*1080];
assign read_ready = (!read_en) ? 1 : 0;
assign write_ready = (!write_en) ? 1 : 0;
always @(posedge clk) begin
if (read_en)
ram[read_addr] <= read_data;
end
always @(posedge clk) begin
if (write_en)
write_data <= ram[write_addr];
end
endmodule

154
isp.sv
View File

@ -32,36 +32,44 @@ module isp #(
// Gamma矫正低八位为小数位
// input wire [7:0] gamma_inverse,
input wire [7:0] gamma_table [256],
input wire [7:0] gamma_table[256],
input wire gamma_enable,
// 白平衡
input wire [31:0] white_gain[3],
input wire [8:0] flame_rate,
input wire white_enable,
// 饱和度校正
input wire signed [31:0] saturation_inc,
input wire saturation_enable // -256~256
input wire saturation_enable // -256~256
);
localparam reg [15:0] BAYER_WIDTH = IN_WIDTH - 2;
localparam reg [15:0] BAYER_HEIGHT = IN_HEIGHT - 2;
// 三通道合成RGB图像
wire [COLOR_DEPTH - 1:0] w_out_data[3];
assign out_data = {w_out_data[2], w_out_data[1], w_out_data[0]};
// 颜色校正,并改变色深
wire blender_en, blender_ready, blender_receive;
wire [15:0] blender_r, blender_g, blender_b;
// 裁切图像
wire crop_en, crop_ready, crop_receive; // scaler 请求数据
reg [COLOR_DEPTH - 1:0] crop_data[3];
// Gamma矫正
wire gamma_en, gamma_ready, gamma_receive;
wire [COLOR_DEPTH - 1 : 0] gamma_data[3];
// 白平衡
wire white_en, white_ready, white_receive;
wire [COLOR_DEPTH - 1 : 0] white_data[3];
// 饱和度校正
wire saturation_en, saturation_ready, saturation_receive;
wire [COLOR_DEPTH - 1 : 0] saturation_data[3];
// 任意比例缩放图像
wire crop_en, crop_ready, crop_receive; // scaler 请求数据
reg [COLOR_DEPTH - 1:0] crop_data[3];
// 写入RAM
// wire RAM_in_en;
// wire RAM_in_que; // RAM 请求数据
// wire [3 * COLOR_DEPTH - 1:0] RAM_in_data;
assign out_clk = clk;
Demosaic2 #(
@ -86,7 +94,7 @@ module isp #(
ColorBlender #(
.IN_DEPTH (12),
.OUT_DEPTH(8)
.OUT_DEPTH(COLOR_DEPTH)
) inst_blender (
.clk (clk),
.reset(reset),
@ -96,10 +104,10 @@ module isp #(
.out_ready(blender_ready),
.out_receive(blender_receive),
.in_ready(gamma_ready),
.in_receive(gamma_receive),
.out_en(gamma_en),
.out_data(gamma_data),
.in_ready(crop_ready),
.in_receive(crop_receive),
.out_en(crop_en),
.out_data(crop_data),
.gain_red(gain_red),
.gain_green(gain_green),
@ -107,26 +115,26 @@ module isp #(
.enable(blender_enable)
);
// 计算型Gamma校正
// GammaCorrection #(
// .COLOR_DEPTH(COLOR_DEPTH)
// ) inst_gamma (
// .clk (clk),
// .reset(reset),
Crop #(
.IN_WIDTH(BAYER_WIDTH),
.IN_HEIGHT(BAYER_HEIGHT),
.OUT_WIDTH(OUT_WIDTH),
.OUT_HEIGHT(OUT_HEIGHT),
.COLOR_DEPTH(COLOR_DEPTH)
) inst_crop (
.clk (clk),
.reset(reset),
// .in_en(gamma_en),
// .in_data(gamma_data),
// .out_ready(gamma_ready),
// .out_receive(gamma_receive),
.in_en(crop_en),
.out_ready(crop_ready),
.out_receive(crop_receive),
.in_data({crop_data[2], crop_data[1], crop_data[0]}),
// .in_ready(crop_ready),
// .in_receive(crop_receive),
// .out_en(crop_en),
// .out_data(crop_data),
// .gamma_inverse(gamma_inverse),
// .enable(gamma_enable)
// );
.out_en(gamma_en),
.in_ready(gamma_ready),
.in_receive(gamma_receive),
.out_data({gamma_data[2], gamma_data[1], gamma_data[0]})
);
// 查找表型Gamma校正
GammaCorrection2 #(
@ -150,57 +158,47 @@ module isp #(
);
SaturationCorrection #(
.COLOR_DEPTH(COLOR_DEPTH)
) inst_saturation (
.clk (clk),
.reset (reset),
.in_en(saturation_en),
.out_ready(saturation_ready),
.out_receive(saturation_receive),
.in_data(saturation_data),
.in_ready(crop_ready),
.in_receive(crop_receive),
.out_en(crop_en),
.out_data(crop_data),
.saturation_inc(saturation_inc),
.enable(saturation_enable)
);
Crop #(
.IN_WIDTH(BAYER_WIDTH),
.IN_HEIGHT(BAYER_HEIGHT),
.OUT_WIDTH(OUT_WIDTH),
.OUT_HEIGHT(OUT_HEIGHT),
.COLOR_DEPTH(COLOR_DEPTH)
) inst_crop (
) inst_saturation (
.clk (clk),
.reset(reset),
.in_en(crop_en),
.out_ready(crop_ready),
.out_receive(crop_receive),
.in_data({crop_data[2], crop_data[1], crop_data[0]}),
.in_en(saturation_en),
.out_ready(saturation_ready),
.out_receive(saturation_receive),
.in_data(saturation_data),
.out_en(out_en),
.in_ready(in_ready),
.in_receive(in_receive),
.out_data(out_data)
.in_ready(white_ready),
.in_receive(white_receive),
.out_en(white_en),
.out_data(white_data),
.saturation_inc(saturation_inc),
.enable(saturation_enable)
);
// RGB_to_RAM write_to_RAM (
// .clk(clk),
// .reset(reset),
GreyWorld #(
.COLOR_DEPTH(COLOR_DEPTH),
.IM_SIZE({16'b0, OUT_WIDTH} * {16'b0, OUT_HEIGHT})
) inst_whitebalance (
.clk (clk),
.reset(reset),
.in_en(white_en),
.in_data(white_data),
.out_ready(white_ready),
.out_receive(white_receive),
.in_ready(in_ready),
.in_receive(in_receive),
.out_en(out_en),
.out_data(w_out_data),
.enable(white_enable),
.flame_rate(flame_rate),
.white_gain(white_gain)
);
// .in_en(RAM_in_en),
// .in_que(RAM_in_que),
// .in_data(RAM_in_data),
// .write_que(out_que),
// .write_en(out_en),
// .data_write(out_data)
// );
endmodule

View File

@ -32,6 +32,9 @@ VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
endif
VERILATOR_FLAGS =
# Specify top module
TOP_MODULE = isp
VERILATOR_FLAGS += --top-module $(TOP_MODULE)
# Generate SystemC in executable form
VERILATOR_FLAGS += -sc --exe
# Generate makefile dependencies (not shown as complicates the Makefile)
@ -52,12 +55,11 @@ VERILATOR_FLAGS += --threads 14
#VERILATOR_FLAGS += --debug
# Add this trace to get a backtrace in gdb
#VERILATOR_FLAGS += --gdbbt
# Specify top module
TOP_MODULE = isp
VERILATOR_FLAGS += -top $(TOP_MODULE)
# Input files for Verilator
VERILATOR_INPUT = ../isp.sv *.cpp ../Demosaic/Demosaic2.sv ../Crop/*.sv ../Color/*.sv ../RAM/*.sv
# Input files for Verilator
SOURCES := $(wildcard ../isp.sv *.cpp ../Demosaic/Demosaic2.sv ../Crop/*.sv ../Color/*.sv)
EXCLUDES := $(wildcard ../Color/WhiteBalance.sv ../Color/GammaCorrection.sv)
VERILATOR_INPUT := $(filter-out $(EXCLUDES), $(SOURCES))
# Check if SC exists via a verilator call (empty if not)
SYSTEMC_EXISTS := $(shell $(VERILATOR) --get-supported SYSTEMC)

View File

@ -23,10 +23,11 @@
static const uint16_t IN_WIDTH = 1936;
static const uint16_t IN_HEIGHT = 1088;
#define IN_SIZE (IN_WIDTH * IN_HEIGHT)
static const uint32_t IN_SIZE = (IN_WIDTH * IN_HEIGHT);
static const uint16_t OUT_WIDTH = 1920;
static const uint16_t OUT_HEIGHT = 1080;
#define OUT_SIZE (OUT_WIDTH * OUT_HEIGHT)
static const uint32_t OUT_SIZE = (OUT_WIDTH * OUT_HEIGHT);
static const uint32_t FLAMES = 2;
// color gain for correcting color
struct color_gain {
@ -42,6 +43,8 @@ static const double white_radio = 0.1;
using namespace sc_core;
using namespace sc_dt;
bool picProcess(uint32_t* image, uint16_t number);
SC_MODULE(TB_ISP) {
sc_in_clk clk;
sc_in<bool> reset;
@ -69,9 +72,10 @@ SC_MODULE(TB_ISP) {
}
void send_Data(void) {
uint16_t pos_x = 0, pos_y = 0;
uint16_t pos_x = 0, pos_y = 0, cnt_flame = 0;
bool is_finish = false;
while (true) {
if (in_ready.read() && pos_y < IN_HEIGHT - 2) {
if (in_ready.read() && !is_finish) {
out_en.write(1);
printf("x=%4d, y=%4d, data=0x%04x\t", pos_x, pos_y,
@ -85,13 +89,18 @@ SC_MODULE(TB_ISP) {
out_data[1].write(image[(pos_y + 1) * IN_WIDTH + pos_x]);
out_data[2].write(image[(pos_y + 2) * IN_WIDTH + pos_x]);
// wait(1);
// out_en.write(0);
if (++pos_x >= IN_WIDTH) {
pos_x++;
if (pos_x >= IN_WIDTH) {
pos_x = 0;
pos_y++;
}
if (pos_y >= IN_HEIGHT - 2) {
pos_y = 0;
cnt_flame++;
}
if (cnt_flame >= FLAMES) {
is_finish = true;
}
} else {
out_en.write(0);
}
@ -102,11 +111,11 @@ SC_MODULE(TB_ISP) {
void read_Data(void) {
is_done.write(0);
uint16_t pos_x = 0, pos_y = 0;
uint32_t last_data = 0;
uint32_t cnt = 0;
uint16_t pos_x = 0, pos_y = 0, cnt_flame = 0;
uint32_t last_data = 0, cnt = 0;
bool is_finish = false;
while (true) {
if (im_en.read()) {
if (im_en.read() && !is_finish) {
out_ready.write(false);
out_receceive.write(true);
@ -116,13 +125,21 @@ SC_MODULE(TB_ISP) {
pos_x = 0;
pos_y++;
}
if (pos_y >= OUT_HEIGHT) {
pos_y = 0;
picProcess(out.get(), cnt_flame);
cnt_flame++;
}
if (cnt_flame >= FLAMES) {
is_finish = true;
}
} else {
out_ready.write(true);
out_receceive.write(false);
}
// when data didn't change some time, it end
if (last_data == im_data.read()) {
if (last_data == im_data.read() && is_finish) {
cnt++;
if (cnt >= 100000L) {
is_done.write(1);
@ -138,13 +155,111 @@ SC_MODULE(TB_ISP) {
}
};
bool picProcess(uint32_t* image, uint16_t number) {
uint8_t* data =
new uint8_t[OUT_WIDTH * OUT_HEIGHT * 3]; // RGB24格式像素数据
// software algorthms analyze
uint32_t red_total = 0, green_total = 0, blue_total = 0;
uint8_t red_max = 0, green_max = 0, blue_max = 0;
for (int32_t y = 0; y < OUT_HEIGHT; ++y) {
for (int32_t x = 0; x < OUT_WIDTH; ++x) {
int32_t index = (y * OUT_WIDTH + x) * 3;
uint8_t red = (image[y * OUT_WIDTH + x] & 0x00ff0000) >> 16;
uint8_t green = (image[y * OUT_WIDTH + x] & 0x0000ff00) >> 8;
uint8_t blue = (image[y * OUT_WIDTH + x] & 0x000000ff);
// Adjust gamma line
// red = 255 * std::pow(red / 255.0, 1 / gamma_value);
// green = 255 * std::pow(green / 255.0, 1 / gamma_value);
// blue = 255 * std::pow(blue / 255.0, 1 / gamma_value);
// Calculate white balance data
// red_max = std::max(red_max, red);
// green_max = std::max(green_max, green);
// blue_max = std::max(blue_max, blue);
// red_total += red;
// green_total += green;
// blue_total += blue;
// Adjust vibrance
// uint8_t max = std::max({red, green, blue});
// uint8_t min = std::min({red, green, blue});
// double delta = (max - min) / 255.0;
// double value = (max + min) / 255.0;
// if (delta != 0) {
// double L = value / 2.0;
// // double S = (L <= 0.5) ? delta / value : delta / (2 -
// value); double S = delta / max; double alpha = 0.0; if
// (saturation_inc >= 0) {
// if ((saturation_inc + S) >= 1)
// alpha = S;
// else
// alpha = 1 - saturation_inc;
// alpha = 1 / alpha - 1;
// red = static_cast<uchar>(red + (red - L * 255) * alpha);
// green =
// static_cast<uchar>(green + (green - L * 255) *
// alpha);
// blue = static_cast<uchar>(blue + (blue - L * 255) *
// alpha);
// } else {
// alpha = saturation_inc;
// red = static_cast<uchar>(L * 255 +
// (red - L * 255) * (1 + alpha));
// green = static_cast<uchar>(L * 255 +
// (green - L * 255) * (1 +
// alpha));
// blue = static_cast<uchar>(L * 255 +
// (blue - L * 255) * (1 +
// alpha));
// }
// }
// save data
data[index + 0] = red; // R
data[index + 1] = green; // G
data[index + 2] = blue; // B
}
}
// Adjust White Balance : Grey World Color Correction
// double K = static_cast<double>(red_total + green_total + blue_total) /
// (3 * OUT_SIZE);
// white_gain.red = static_cast<double>(K * OUT_SIZE) / red_total;
// white_gain.green = static_cast<double>(K * OUT_SIZE) / green_total;
// white_gain.blue = static_cast<double>(K * OUT_SIZE) / blue_total;
// printf("Gain: red = %f, green = %f, blue = %f", white_gain.red,
// white_gain.green, white_gain.blue);
// for (int32_t y = 0; y < OUT_HEIGHT; ++y) {
// for (int32_t x = 0; x < OUT_WIDTH; ++x) {
// int32_t index = (y * OUT_WIDTH + x) * 3;
// data[index + 0] =
// static_cast<uint8_t>(white_gain.red * data[index + 0]);
// data[index + 1] =
// static_cast<uint8_t>(white_gain.green * data[index + 1]);
// data[index + 2] =
// static_cast<uint8_t>(white_gain.blue * data[index + 2]);
// }
// }
// save to bmp
std::cout << "Ready to save raw RGB image" << std::endl;
char file_name[64] = {0};
snprintf(file_name, sizeof(file_name), "pic_%d.bmp", number);
write_bmp(file_name, data, OUT_WIDTH, OUT_HEIGHT);
delete[] data;
return true;
}
int sc_main(int argc, char* argv[]) {
std::cout << "Get into sc_main" << std::endl;
// Open image
std::ifstream in_image;
std::ofstream out_image;
in_image.open("./transform/test.bin", std::ios::in | std::ios::binary);
// out_image.open("./transform/out.bin", std::ios::out | std::ios::binary);
if (!in_image.is_open()) {
std::cout << "Open image fail" << std::endl;
exit(0);
@ -218,6 +333,10 @@ int sc_main(int argc, char* argv[]) {
sc_signal<uint32_t> gamma_inverse;
sc_signal<uint32_t> gamma_table[256];
sc_signal<uint32_t> white_gain[3];
sc_signal<uint32_t> flame_rate;
sc_signal<bool> white_enable;
sc_signal<bool> saturation_enable;
sc_signal<uint32_t> saturation_increase;
@ -250,6 +369,12 @@ int sc_main(int argc, char* argv[]) {
isp->gamma_enable(gamma_enable);
// isp->gamma_inverse(gamma_inverse);
isp->white_enable(white_enable);
isp->flame_rate(flame_rate);
isp->white_gain[0](white_gain[0]);
isp->white_gain[1](white_gain[1]);
isp->white_gain[2](white_gain[2]);
isp->saturation_enable(saturation_enable);
isp->saturation_inc(saturation_increase);
@ -266,6 +391,12 @@ int sc_main(int argc, char* argv[]) {
gamma_table[i] = (uint32_t)(255 * pow(i / 255.0, 1.0 / gamma_value));
}
white_enable = true;
flame_rate = 0;
white_gain[0] = 255;
white_gain[1] = 255;
white_gain[2] = 255;
saturation_enable = true;
saturation_increase =
(int32_t)((saturation_inc >= 0) ? (saturation_inc * std::pow(2, 8))
@ -333,117 +464,6 @@ int sc_main(int argc, char* argv[]) {
tfp = nullptr;
}
uint8_t* data =
new uint8_t[OUT_WIDTH * OUT_HEIGHT * 3]; // RGB24格式像素数据
// software algorthms analyze
uint32_t red_total = 0, green_total = 0, blue_total = 0;
uint8_t red_max = 0, green_max = 0, blue_max = 0;
for (int32_t y = 0; y < OUT_HEIGHT; ++y) {
for (int32_t x = 0; x < OUT_WIDTH; ++x) {
int32_t index = (y * OUT_WIDTH + x) * 3;
uint8_t red = (tb_isp.out[y * OUT_WIDTH + x] & 0x00ff0000) >> 16;
uint8_t green = (tb_isp.out[y * OUT_WIDTH + x] & 0x0000ff00) >> 8;
uint8_t blue = (tb_isp.out[y * OUT_WIDTH + x] & 0x000000ff);
// Adjust gamma line
// red = 255 * std::pow(red / 255.0, 1 / gamma_value);
// green = 255 * std::pow(green / 255.0, 1 / gamma_value);
// blue = 255 * std::pow(blue / 255.0, 1 / gamma_value);
// Calculate white balance data
red_max = std::max(red_max, red);
green_max = std::max(green_max, green);
blue_max = std::max(blue_max, blue);
red_total += red;
green_total += green;
blue_total += blue;
// Adjust vibrance
// uint8_t max = std::max({red, green, blue});
// uint8_t min = std::min({red, green, blue});
// double delta = (max - min) / 255.0;
// double value = (max + min) / 255.0;
// if (delta != 0) {
// double L = value / 2.0;
// // double S = (L <= 0.5) ? delta / value : delta / (2 -
// value); double S = delta / max; double alpha = 0.0; if
// (saturation_inc >= 0) {
// if ((saturation_inc + S) >= 1)
// alpha = S;
// else
// alpha = 1 - saturation_inc;
// alpha = 1 / alpha - 1;
// red = static_cast<uchar>(red + (red - L * 255) * alpha);
// green =
// static_cast<uchar>(green + (green - L * 255) *
// alpha);
// blue = static_cast<uchar>(blue + (blue - L * 255) *
// alpha);
// } else {
// alpha = saturation_inc;
// red = static_cast<uchar>(L * 255 +
// (red - L * 255) * (1 + alpha));
// green = static_cast<uchar>(L * 255 +
// (green - L * 255) * (1 +
// alpha));
// blue = static_cast<uchar>(L * 255 +
// (blue - L * 255) * (1 +
// alpha));
// }
// }
data[index + 0] = red; // R
data[index + 1] = green; // G
data[index + 2] = blue; // B
}
}
// Adjust White Balance : Grey World Color Correction
double K = static_cast<double>(red_total + green_total + blue_total) / (3 * OUT_SIZE);
white_gain.red = static_cast<double>(K * OUT_SIZE) / red_total;
white_gain.green = static_cast<double>(K * OUT_SIZE) / green_total;
white_gain.blue = static_cast<double>(K * OUT_SIZE) / blue_total;
printf("Gain: red = %f, green = %f, blue = %f", white_gain.red,
white_gain.green, white_gain.blue);
for (int32_t y = 0; y < OUT_HEIGHT; ++y) {
for (int32_t x = 0; x < OUT_WIDTH; ++x) {
int32_t index = (y * OUT_WIDTH + x) * 3;
data[index + 0] =
static_cast<uint8_t>(white_gain.red * data[index + 0]);
data[index + 1] =
static_cast<uint8_t>(white_gain.green * data[index + 1]);
data[index + 2] =
static_cast<uint8_t>(white_gain.blue * data[index + 2]);
}
}
// save to bin
std::cout << "Ready to save raw RGB image" << std::endl;
// for (int32_t y = 0; y < OUT_HEIGHT; ++y) {
// for (int32_t x = 0; x < OUT_WIDTH; ++x) {
// int32_t index = (y * OUT_WIDTH + x) * 3;
// uint8_t red = data[index + 0];
// uint8_t green = data[index + 1];
// uint8_t blue = data[index + 2];
// out_image.write((const char*)&red, sizeof(red));
// out_image.write((const char*)&green, sizeof(green));
// out_image.write((const char*)&blue, sizeof(blue));
// printf("x=%4d, y=%4d, red=0x%02x, green=0x%02x, blue=0x%02x\n",
// x,
// y, red, green, blue);
// }
// }
// save to bmp
write_bmp("test.bmp", data, OUT_WIDTH, OUT_HEIGHT);
delete[] data;
// Return good completion status
return 0;
}