finish Grey World White Balance
This commit is contained in:
parent
649d34415f
commit
1154da3307
|
@ -34,7 +34,7 @@ module ColorBlender #(
|
||||||
reg [2:0] state, nextState;
|
reg [2:0] state, nextState;
|
||||||
reg [BUFF_SIZE - 1:0] data_cal[3]; // 用于保存运算结果,防止溢出
|
reg [BUFF_SIZE - 1:0] data_cal[3]; // 用于保存运算结果,防止溢出
|
||||||
|
|
||||||
always @(posedge clk or posedge reset) begin
|
always @(posedge clk) begin
|
||||||
if (reset) begin
|
if (reset) begin
|
||||||
state <= READ_DATA;
|
state <= READ_DATA;
|
||||||
end else begin
|
end else begin
|
||||||
|
@ -55,7 +55,7 @@ module ColorBlender #(
|
||||||
assign out_ready = (!in_en && state == READ_DATA) ? 1 : 0;
|
assign out_ready = (!in_en && state == READ_DATA) ? 1 : 0;
|
||||||
assign out_receive = (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
|
if (reset) begin
|
||||||
// 初始化
|
// 初始化
|
||||||
data_cal[0] <= 0;
|
data_cal[0] <= 0;
|
||||||
|
|
|
@ -25,7 +25,7 @@ module GammaCorrection2 #(
|
||||||
|
|
||||||
reg [7:0] data_cache[3];
|
reg [7:0] data_cache[3];
|
||||||
|
|
||||||
always @(posedge clk or posedge reset) begin
|
always @(posedge clk) begin
|
||||||
if (reset) state <= READ_DATA;
|
if (reset) state <= READ_DATA;
|
||||||
else state <= nextState;
|
else state <= nextState;
|
||||||
end
|
end
|
||||||
|
@ -41,7 +41,7 @@ module GammaCorrection2 #(
|
||||||
assign out_ready = (!in_en && state == READ_DATA) ? 1 : 0;
|
assign out_ready = (!in_en && state == READ_DATA) ? 1 : 0;
|
||||||
assign out_receive = (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
|
if (reset) begin
|
||||||
out_en <= 0;
|
out_en <= 0;
|
||||||
out_data[0] <= 0;
|
out_data[0] <= 0;
|
||||||
|
|
|
@ -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
|
|
@ -27,7 +27,7 @@ module SaturationCorrection #(
|
||||||
reg signed [31:0] data_cal[3], data_cache[3];
|
reg signed [31:0] data_cal[3], data_cache[3];
|
||||||
wire signed [31:0] max, min, delta, value, light, saturation, alpha;
|
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;
|
if (reset) state <= READ_DATA;
|
||||||
else state <= nextState;
|
else state <= nextState;
|
||||||
end
|
end
|
||||||
|
@ -60,7 +60,7 @@ module SaturationCorrection #(
|
||||||
? (65536 / saturation) - 256 : (65536 / (256 - saturation_inc)) - 256)
|
? (65536 / saturation) - 256 : (65536 / (256 - saturation_inc)) - 256)
|
||||||
: (saturation_inc);
|
: (saturation_inc);
|
||||||
|
|
||||||
always @(posedge clk or posedge reset) begin
|
always @(posedge clk) begin
|
||||||
if (reset) begin
|
if (reset) begin
|
||||||
out_en <= 0;
|
out_en <= 0;
|
||||||
out_data[0] <= 0;
|
out_data[0] <= 0;
|
||||||
|
@ -101,9 +101,9 @@ module SaturationCorrection #(
|
||||||
if (in_ready) begin
|
if (in_ready) begin
|
||||||
out_en <= 1;
|
out_en <= 1;
|
||||||
if (enable && delta != 0) begin
|
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[0] <= (|data_cal[0][31:16]) ? 255 : (data_cal[0] > 0 ? data_cal[0][15:8] : 0);
|
||||||
out_data[1] <= (data_cal[1] <= 65535) ? (data_cal[1] > 1 ? data_cal[1][15:8] : 1) : 255;
|
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] <= 65535) ? (data_cal[2] > 2 ? data_cal[2][15:8] : 2) : 255;
|
out_data[2] <= (|data_cal[2][31:16]) ? 255 : (data_cal[2] > 0 ? data_cal[2][15:8] : 0);
|
||||||
end else begin
|
end else begin
|
||||||
out_data[0] <= data_cache[0][7:0];
|
out_data[0] <= data_cache[0][7:0];
|
||||||
out_data[1] <= data_cache[1][7:0];
|
out_data[1] <= data_cache[1][7:0];
|
||||||
|
|
|
@ -2,9 +2,11 @@
|
||||||
|
|
||||||
// 三通道图像合成一个RGB图像
|
// 三通道图像合成一个RGB图像
|
||||||
module WhiteBalance #(
|
module WhiteBalance #(
|
||||||
parameter reg [4:0] IN_DEPTH = 12, // 输入图像的色深
|
parameter reg [4:0] IN_DEPTH = 12, // 输入图像的色深
|
||||||
parameter reg [4:0] OUT_DEPTH = 8, // 输出图像的色深
|
parameter reg [4:0] OUT_DEPTH = 8, // 输出图像的色深
|
||||||
parameter reg [8:0] BUFF_SIZE = 32
|
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 clk,
|
||||||
input wire reset,
|
input wire reset,
|
||||||
|
@ -17,22 +19,116 @@ module WhiteBalance #(
|
||||||
// 输出相关
|
// 输出相关
|
||||||
input wire in_ready,
|
input wire in_ready,
|
||||||
input wire in_receive,
|
input wire in_receive,
|
||||||
output reg out_en,
|
output wire out_en,
|
||||||
output reg [OUT_DEPTH - 1:0] out_data[3],
|
output wire [OUT_DEPTH - 1:0] out_data[3],
|
||||||
|
|
||||||
input wire enable,
|
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;
|
wire ram_read_en, ram_write_en, ram_read_ready, ram_write_ready;
|
||||||
assign out_receive = (in_en && !reset) ? 1 : 0;
|
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 #(
|
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
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -13,12 +13,12 @@ module Crop #(
|
||||||
input wire in_en,
|
input wire in_en,
|
||||||
output wire out_ready,
|
output wire out_ready,
|
||||||
output wire out_receive,
|
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_ready,
|
||||||
input wire in_receive,
|
input wire in_receive,
|
||||||
output reg out_en,
|
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;
|
reg [1:0] state, nextState;
|
||||||
localparam reg [1:0] READ_DATA = 0;
|
localparam reg [1:0] READ_DATA = 0;
|
||||||
|
@ -26,11 +26,11 @@ module Crop #(
|
||||||
localparam reg [1:0] SEND_DATA = 2;
|
localparam reg [1:0] SEND_DATA = 2;
|
||||||
|
|
||||||
reg [15:0] cnt_x, cnt_y;
|
reg [15:0] cnt_x, cnt_y;
|
||||||
reg [3 * COLOR_DEPTH - 1:0] data;
|
reg [COLOR_DEPTH - 1:0] data[3];
|
||||||
wire is_valid;
|
wire is_valid;
|
||||||
|
|
||||||
// 状态切换
|
// 状态切换
|
||||||
always @(posedge clk or posedge reset) begin
|
always @(posedge clk) begin
|
||||||
if (reset) state <= READ_DATA;
|
if (reset) state <= READ_DATA;
|
||||||
else state <= nextState;
|
else state <= nextState;
|
||||||
end
|
end
|
||||||
|
@ -50,19 +50,25 @@ module Crop #(
|
||||||
assign is_valid = ((OFFSET_Y <= cnt_y && cnt_y <= (OFFSET_Y + OUT_HEIGHT - 1)) &&
|
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;
|
(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
|
if (reset) begin
|
||||||
cnt_x <= 0;
|
cnt_x <= 0;
|
||||||
cnt_y <= 0;
|
cnt_y <= 0;
|
||||||
data <= 0;
|
data[0] <= 0;
|
||||||
|
data[1] <= 0;
|
||||||
|
data[2] <= 0;
|
||||||
|
|
||||||
out_en <= 0;
|
out_en <= 0;
|
||||||
out_data <= 0;
|
out_data[0] <= 0;
|
||||||
|
out_data[1] <= 0;
|
||||||
|
out_data[2] <= 0;
|
||||||
end else begin
|
end else begin
|
||||||
case (state)
|
case (state)
|
||||||
READ_DATA: begin
|
READ_DATA: begin
|
||||||
if (in_en) 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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -82,7 +88,9 @@ module Crop #(
|
||||||
SEND_DATA: begin
|
SEND_DATA: begin
|
||||||
if (in_ready && !in_receive && is_valid) begin
|
if (in_ready && !in_receive && is_valid) begin
|
||||||
out_en <= 1;
|
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 else out_en <= 0;
|
||||||
end
|
end
|
||||||
|
|
|
@ -41,7 +41,7 @@ module Demosaic2 #(
|
||||||
|
|
||||||
// 三段状态机实现,窗口滑动,颜色计算
|
// 三段状态机实现,窗口滑动,颜色计算
|
||||||
// 状态切换
|
// 状态切换
|
||||||
always @(posedge clk or posedge reset) begin
|
always @(posedge clk) begin
|
||||||
if (reset) state <= READ_DATA;
|
if (reset) state <= READ_DATA;
|
||||||
else state <= nextState;
|
else state <= nextState;
|
||||||
end
|
end
|
||||||
|
@ -64,7 +64,7 @@ module Demosaic2 #(
|
||||||
assign out_receive = (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
|
if (reset) begin
|
||||||
// 外部输出初始化
|
// 外部输出初始化
|
||||||
out_en <= 0;
|
out_en <= 0;
|
||||||
|
|
|
@ -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
154
isp.sv
|
@ -32,36 +32,44 @@ module isp #(
|
||||||
|
|
||||||
// Gamma矫正,低八位为小数位
|
// Gamma矫正,低八位为小数位
|
||||||
// input wire [7:0] gamma_inverse,
|
// 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 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 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_WIDTH = IN_WIDTH - 2;
|
||||||
localparam reg [15:0] BAYER_HEIGHT = IN_HEIGHT - 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 blender_en, blender_ready, blender_receive;
|
||||||
wire [15:0] blender_r, blender_g, blender_b;
|
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矫正
|
// Gamma矫正
|
||||||
wire gamma_en, gamma_ready, gamma_receive;
|
wire gamma_en, gamma_ready, gamma_receive;
|
||||||
wire [COLOR_DEPTH - 1 : 0] gamma_data[3];
|
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 saturation_en, saturation_ready, saturation_receive;
|
||||||
wire [COLOR_DEPTH - 1 : 0] saturation_data[3];
|
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;
|
assign out_clk = clk;
|
||||||
|
|
||||||
Demosaic2 #(
|
Demosaic2 #(
|
||||||
|
@ -86,7 +94,7 @@ module isp #(
|
||||||
|
|
||||||
ColorBlender #(
|
ColorBlender #(
|
||||||
.IN_DEPTH (12),
|
.IN_DEPTH (12),
|
||||||
.OUT_DEPTH(8)
|
.OUT_DEPTH(COLOR_DEPTH)
|
||||||
) inst_blender (
|
) inst_blender (
|
||||||
.clk (clk),
|
.clk (clk),
|
||||||
.reset(reset),
|
.reset(reset),
|
||||||
|
@ -96,10 +104,10 @@ module isp #(
|
||||||
.out_ready(blender_ready),
|
.out_ready(blender_ready),
|
||||||
.out_receive(blender_receive),
|
.out_receive(blender_receive),
|
||||||
|
|
||||||
.in_ready(gamma_ready),
|
.in_ready(crop_ready),
|
||||||
.in_receive(gamma_receive),
|
.in_receive(crop_receive),
|
||||||
.out_en(gamma_en),
|
.out_en(crop_en),
|
||||||
.out_data(gamma_data),
|
.out_data(crop_data),
|
||||||
|
|
||||||
.gain_red(gain_red),
|
.gain_red(gain_red),
|
||||||
.gain_green(gain_green),
|
.gain_green(gain_green),
|
||||||
|
@ -107,26 +115,26 @@ module isp #(
|
||||||
.enable(blender_enable)
|
.enable(blender_enable)
|
||||||
);
|
);
|
||||||
|
|
||||||
// 计算型Gamma校正
|
Crop #(
|
||||||
// GammaCorrection #(
|
.IN_WIDTH(BAYER_WIDTH),
|
||||||
// .COLOR_DEPTH(COLOR_DEPTH)
|
.IN_HEIGHT(BAYER_HEIGHT),
|
||||||
// ) inst_gamma (
|
.OUT_WIDTH(OUT_WIDTH),
|
||||||
// .clk (clk),
|
.OUT_HEIGHT(OUT_HEIGHT),
|
||||||
// .reset(reset),
|
.COLOR_DEPTH(COLOR_DEPTH)
|
||||||
|
) inst_crop (
|
||||||
|
.clk (clk),
|
||||||
|
.reset(reset),
|
||||||
|
|
||||||
// .in_en(gamma_en),
|
.in_en(crop_en),
|
||||||
// .in_data(gamma_data),
|
.out_ready(crop_ready),
|
||||||
// .out_ready(gamma_ready),
|
.out_receive(crop_receive),
|
||||||
// .out_receive(gamma_receive),
|
.in_data({crop_data[2], crop_data[1], crop_data[0]}),
|
||||||
|
|
||||||
// .in_ready(crop_ready),
|
.out_en(gamma_en),
|
||||||
// .in_receive(crop_receive),
|
.in_ready(gamma_ready),
|
||||||
// .out_en(crop_en),
|
.in_receive(gamma_receive),
|
||||||
// .out_data(crop_data),
|
.out_data({gamma_data[2], gamma_data[1], gamma_data[0]})
|
||||||
|
);
|
||||||
// .gamma_inverse(gamma_inverse),
|
|
||||||
// .enable(gamma_enable)
|
|
||||||
// );
|
|
||||||
|
|
||||||
// 查找表型Gamma校正
|
// 查找表型Gamma校正
|
||||||
GammaCorrection2 #(
|
GammaCorrection2 #(
|
||||||
|
@ -150,57 +158,47 @@ module isp #(
|
||||||
);
|
);
|
||||||
|
|
||||||
SaturationCorrection #(
|
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)
|
.COLOR_DEPTH(COLOR_DEPTH)
|
||||||
) inst_crop (
|
) inst_saturation (
|
||||||
.clk (clk),
|
.clk (clk),
|
||||||
.reset(reset),
|
.reset(reset),
|
||||||
|
|
||||||
.in_en(crop_en),
|
.in_en(saturation_en),
|
||||||
.out_ready(crop_ready),
|
.out_ready(saturation_ready),
|
||||||
.out_receive(crop_receive),
|
.out_receive(saturation_receive),
|
||||||
.in_data({crop_data[2], crop_data[1], crop_data[0]}),
|
.in_data(saturation_data),
|
||||||
|
|
||||||
.out_en(out_en),
|
.in_ready(white_ready),
|
||||||
.in_ready(in_ready),
|
.in_receive(white_receive),
|
||||||
.in_receive(in_receive),
|
.out_en(white_en),
|
||||||
.out_data(out_data)
|
.out_data(white_data),
|
||||||
|
|
||||||
|
.saturation_inc(saturation_inc),
|
||||||
|
.enable(saturation_enable)
|
||||||
);
|
);
|
||||||
|
|
||||||
// RGB_to_RAM write_to_RAM (
|
GreyWorld #(
|
||||||
// .clk(clk),
|
.COLOR_DEPTH(COLOR_DEPTH),
|
||||||
// .reset(reset),
|
.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
|
endmodule
|
||||||
|
|
12
sim/Makefile
12
sim/Makefile
|
@ -32,6 +32,9 @@ VERILATOR_COVERAGE = $(VERILATOR_ROOT)/bin/verilator_coverage
|
||||||
endif
|
endif
|
||||||
|
|
||||||
VERILATOR_FLAGS =
|
VERILATOR_FLAGS =
|
||||||
|
# Specify top module
|
||||||
|
TOP_MODULE = isp
|
||||||
|
VERILATOR_FLAGS += --top-module $(TOP_MODULE)
|
||||||
# Generate SystemC in executable form
|
# Generate SystemC in executable form
|
||||||
VERILATOR_FLAGS += -sc --exe
|
VERILATOR_FLAGS += -sc --exe
|
||||||
# Generate makefile dependencies (not shown as complicates the Makefile)
|
# Generate makefile dependencies (not shown as complicates the Makefile)
|
||||||
|
@ -52,12 +55,11 @@ VERILATOR_FLAGS += --threads 14
|
||||||
#VERILATOR_FLAGS += --debug
|
#VERILATOR_FLAGS += --debug
|
||||||
# Add this trace to get a backtrace in gdb
|
# Add this trace to get a backtrace in gdb
|
||||||
#VERILATOR_FLAGS += --gdbbt
|
#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)
|
# Check if SC exists via a verilator call (empty if not)
|
||||||
SYSTEMC_EXISTS := $(shell $(VERILATOR) --get-supported SYSTEMC)
|
SYSTEMC_EXISTS := $(shell $(VERILATOR) --get-supported SYSTEMC)
|
||||||
|
|
||||||
|
|
272
sim/sc_main.cpp
272
sim/sc_main.cpp
|
@ -23,10 +23,11 @@
|
||||||
|
|
||||||
static const uint16_t IN_WIDTH = 1936;
|
static const uint16_t IN_WIDTH = 1936;
|
||||||
static const uint16_t IN_HEIGHT = 1088;
|
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_WIDTH = 1920;
|
||||||
static const uint16_t OUT_HEIGHT = 1080;
|
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
|
// color gain for correcting color
|
||||||
struct color_gain {
|
struct color_gain {
|
||||||
|
@ -42,6 +43,8 @@ static const double white_radio = 0.1;
|
||||||
using namespace sc_core;
|
using namespace sc_core;
|
||||||
using namespace sc_dt;
|
using namespace sc_dt;
|
||||||
|
|
||||||
|
bool picProcess(uint32_t* image, uint16_t number);
|
||||||
|
|
||||||
SC_MODULE(TB_ISP) {
|
SC_MODULE(TB_ISP) {
|
||||||
sc_in_clk clk;
|
sc_in_clk clk;
|
||||||
sc_in<bool> reset;
|
sc_in<bool> reset;
|
||||||
|
@ -69,9 +72,10 @@ SC_MODULE(TB_ISP) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_Data(void) {
|
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) {
|
while (true) {
|
||||||
if (in_ready.read() && pos_y < IN_HEIGHT - 2) {
|
if (in_ready.read() && !is_finish) {
|
||||||
out_en.write(1);
|
out_en.write(1);
|
||||||
|
|
||||||
printf("x=%4d, y=%4d, data=0x%04x\t", pos_x, pos_y,
|
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[1].write(image[(pos_y + 1) * IN_WIDTH + pos_x]);
|
||||||
out_data[2].write(image[(pos_y + 2) * IN_WIDTH + pos_x]);
|
out_data[2].write(image[(pos_y + 2) * IN_WIDTH + pos_x]);
|
||||||
|
|
||||||
// wait(1);
|
pos_x++;
|
||||||
// out_en.write(0);
|
if (pos_x >= IN_WIDTH) {
|
||||||
|
|
||||||
if (++pos_x >= IN_WIDTH) {
|
|
||||||
pos_x = 0;
|
pos_x = 0;
|
||||||
pos_y++;
|
pos_y++;
|
||||||
}
|
}
|
||||||
|
if (pos_y >= IN_HEIGHT - 2) {
|
||||||
|
pos_y = 0;
|
||||||
|
cnt_flame++;
|
||||||
|
}
|
||||||
|
if (cnt_flame >= FLAMES) {
|
||||||
|
is_finish = true;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
out_en.write(0);
|
out_en.write(0);
|
||||||
}
|
}
|
||||||
|
@ -102,11 +111,11 @@ SC_MODULE(TB_ISP) {
|
||||||
|
|
||||||
void read_Data(void) {
|
void read_Data(void) {
|
||||||
is_done.write(0);
|
is_done.write(0);
|
||||||
uint16_t pos_x = 0, pos_y = 0;
|
uint16_t pos_x = 0, pos_y = 0, cnt_flame = 0;
|
||||||
uint32_t last_data = 0;
|
uint32_t last_data = 0, cnt = 0;
|
||||||
uint32_t cnt = 0;
|
bool is_finish = false;
|
||||||
while (true) {
|
while (true) {
|
||||||
if (im_en.read()) {
|
if (im_en.read() && !is_finish) {
|
||||||
out_ready.write(false);
|
out_ready.write(false);
|
||||||
out_receceive.write(true);
|
out_receceive.write(true);
|
||||||
|
|
||||||
|
@ -116,13 +125,21 @@ SC_MODULE(TB_ISP) {
|
||||||
pos_x = 0;
|
pos_x = 0;
|
||||||
pos_y++;
|
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 {
|
} else {
|
||||||
out_ready.write(true);
|
out_ready.write(true);
|
||||||
out_receceive.write(false);
|
out_receceive.write(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// when data didn't change some time, it end
|
// when data didn't change some time, it end
|
||||||
if (last_data == im_data.read()) {
|
if (last_data == im_data.read() && is_finish) {
|
||||||
cnt++;
|
cnt++;
|
||||||
if (cnt >= 100000L) {
|
if (cnt >= 100000L) {
|
||||||
is_done.write(1);
|
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[]) {
|
int sc_main(int argc, char* argv[]) {
|
||||||
std::cout << "Get into sc_main" << std::endl;
|
std::cout << "Get into sc_main" << std::endl;
|
||||||
// Open image
|
// Open image
|
||||||
std::ifstream in_image;
|
std::ifstream in_image;
|
||||||
std::ofstream out_image;
|
|
||||||
in_image.open("./transform/test.bin", std::ios::in | std::ios::binary);
|
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()) {
|
if (!in_image.is_open()) {
|
||||||
std::cout << "Open image fail" << std::endl;
|
std::cout << "Open image fail" << std::endl;
|
||||||
exit(0);
|
exit(0);
|
||||||
|
@ -218,6 +333,10 @@ int sc_main(int argc, char* argv[]) {
|
||||||
sc_signal<uint32_t> gamma_inverse;
|
sc_signal<uint32_t> gamma_inverse;
|
||||||
sc_signal<uint32_t> gamma_table[256];
|
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<bool> saturation_enable;
|
||||||
sc_signal<uint32_t> saturation_increase;
|
sc_signal<uint32_t> saturation_increase;
|
||||||
|
|
||||||
|
@ -250,6 +369,12 @@ int sc_main(int argc, char* argv[]) {
|
||||||
isp->gamma_enable(gamma_enable);
|
isp->gamma_enable(gamma_enable);
|
||||||
// isp->gamma_inverse(gamma_inverse);
|
// 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_enable(saturation_enable);
|
||||||
isp->saturation_inc(saturation_increase);
|
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));
|
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_enable = true;
|
||||||
saturation_increase =
|
saturation_increase =
|
||||||
(int32_t)((saturation_inc >= 0) ? (saturation_inc * std::pow(2, 8))
|
(int32_t)((saturation_inc >= 0) ? (saturation_inc * std::pow(2, 8))
|
||||||
|
@ -333,117 +464,6 @@ int sc_main(int argc, char* argv[]) {
|
||||||
tfp = nullptr;
|
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 good completion status
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue