From daf1f454fe18679c4146c6c43697e40c519ba828 Mon Sep 17 00:00:00 2001 From: SikongJueluo Date: Mon, 20 May 2024 18:46:26 +0800 Subject: [PATCH] add color correction function into chanels to RGB --- Crop/crop.v | 17 ++-- Merge/chanels_to_RGB.v | 26 ++++-- isp.v | 17 +++- sim/sc_main.cpp | 18 ++++ sim/software/demosaic.cpp | 88 ++++++++++++-------- sim/software/demosaic2.cpp | 163 +++++++++++++++++++++++++++++++++++++ 6 files changed, 275 insertions(+), 54 deletions(-) create mode 100644 sim/software/demosaic2.cpp diff --git a/Crop/crop.v b/Crop/crop.v index ae27c84..fc8299e 100644 --- a/Crop/crop.v +++ b/Crop/crop.v @@ -60,24 +60,23 @@ module crop #( end HANDLE_DATA: begin - if (OFFSET_Y <= cnt_y && cnt_y < (OFFSET_Y + OUT_HEIGHT - 1)) begin - if (OFFSET_X <= cnt_x && cnt_x < (OFFSET_X + OUT_WIDTH - 1)) begin + if (OFFSET_Y <= cnt_y && cnt_y <= (OFFSET_Y + OUT_HEIGHT - 1)) begin + if (OFFSET_X <= cnt_x && cnt_x <= (OFFSET_X + OUT_WIDTH)) begin out_en <= 1; end end - if (cnt_x >= IN_WIDTH - 3) begin + if (cnt_x >= IN_WIDTH - 1) begin cnt_x <= 0; - if (cnt_y >= IN_HEIGHT - 3) begin - cnt_y <= 0; - end - else begin - cnt_y <= cnt_y + 1; - end + cnt_y <= cnt_y + 1; end else begin cnt_x <= cnt_x + 1; end + + if (cnt_y >= IN_HEIGHT - 1) begin + cnt_y <= 0; + end end SEND_DATA: begin diff --git a/Merge/chanels_to_RGB.v b/Merge/chanels_to_RGB.v index 8a6508e..75ca6ae 100644 --- a/Merge/chanels_to_RGB.v +++ b/Merge/chanels_to_RGB.v @@ -3,7 +3,11 @@ // 三通道图像合成一个RGB图像 module chanels_to_RGB #( parameter IN_DEPTH = 12, // 输入图像的色深 - parameter OUT_DEPTH = 8 // 输出图像的色深 + parameter OUT_DEPTH = 8, // 输出图像的色深 + parameter GAIN_RED = 120, // 红色增益系数(除以10^小数位数) + parameter GAIN_GREEN = 50, // 绿色增益系数 + parameter GAIN_BLUE = 95, // 蓝色增益系数 + parameter DECIMAL = 2 // 小数位数 ) ( input clk, input reset, @@ -14,13 +18,16 @@ module chanels_to_RGB #( // 输出相关 input out_que, // 数据请求 output out_en, - output [3 * OUT_DEPTH - 1:0] data_out + output [3 * OUT_DEPTH - 1:0] data_out, + + // 颜色校正 + input wire color_correction ); localparam READ_DATA = 0; localparam SEND_DATA = 1; reg [1:0] state, nextState; - reg [15:0] data_cal [2:0]; // 用于保存运算结果,防止溢出 + reg [31:0] data_cal [2:0]; // 用于保存运算结果,防止溢出 reg fifo_en; reg [3 * OUT_DEPTH - 1:0] fifo_in; // 输入fifo中缓存 wire fifo_empty, fifo_que; @@ -56,9 +63,16 @@ module chanels_to_RGB #( fifo_en <= 0; if (in_en) begin - data_cal[0] <= data_in[0] >> (IN_DEPTH - OUT_DEPTH); - data_cal[1] <= data_in[1] >> (IN_DEPTH - OUT_DEPTH); - data_cal[2] <= data_in[2] >> (IN_DEPTH - OUT_DEPTH); + if (color_correction) begin + data_cal[0] <= ( {16'b0, data_in[0] } >> (IN_DEPTH - OUT_DEPTH) ) * GAIN_RED / (10 ** DECIMAL); + data_cal[1] <= ( {16'b0, data_in[1] } >> (IN_DEPTH - OUT_DEPTH) ) * GAIN_GREEN / (10 ** DECIMAL); + data_cal[2] <= ( {16'b0, data_in[2] } >> (IN_DEPTH - OUT_DEPTH) ) * GAIN_BLUE / (10 ** DECIMAL); + end + else begin + data_cal[0] <= ( {16'b0, data_in[0] } >> (IN_DEPTH - OUT_DEPTH) ); + data_cal[1] <= ( {16'b0, data_in[1] } >> (IN_DEPTH - OUT_DEPTH) ); + data_cal[2] <= ( {16'b0, data_in[2] } >> (IN_DEPTH - OUT_DEPTH) ); + end end end diff --git a/isp.v b/isp.v index f1c11ae..aef7f03 100644 --- a/isp.v +++ b/isp.v @@ -19,7 +19,9 @@ module isp #( output wire out_clk, output wire out_en, - output reg [3 * COLOR_DEPTH - 1:0] data_out + output reg [3 * COLOR_DEPTH - 1:0] data_out, + + input wire color_correction ); localparam BAYER_WIDTH = IN_WIDTH - 2; localparam BAYER_HEIGHT = IN_HEIGHT - 2; @@ -56,7 +58,15 @@ module isp #( .out_b(im_blue) ); - chanels_to_RGB merge_toRGB( + chanels_to_RGB #( + .IN_DEPTH(12), + .OUT_DEPTH(8), + + .GAIN_RED(120), + .GAIN_GREEN(50), + .GAIN_BLUE(95), + .DECIMAL(2) + ) merge_toRGB( .clk(clk), .reset(reset), .in_en(rgb_en), @@ -64,7 +74,8 @@ module isp #( .out_que(scale_in_que), .out_en(scale_in_en), - .data_out(scale_in_data) + .data_out(scale_in_data), + .color_correction(color_correction) ); crop #( diff --git a/sim/sc_main.cpp b/sim/sc_main.cpp index e1aa7b0..009d728 100644 --- a/sim/sc_main.cpp +++ b/sim/sc_main.cpp @@ -25,6 +25,10 @@ #define OUT_HEIGHT 1080 #define OUT_SIZE (OUT_WIDTH * OUT_HEIGHT) +// const float red_gain = 1.2f; // Adjust these values as necessary +// const float green_gain = 0.5f; +// const float blue_gain = 0.95f; + using namespace std; using namespace sc_core; using namespace sc_dt; @@ -103,6 +107,7 @@ SC_MODULE (TB_ISP) { cnt++; if (cnt >= 10000) { is_done.write(1); + printf("x=%d, y=%d\n",pos_x, pos_y); } } else { cnt = 0; @@ -179,6 +184,8 @@ int sc_main(int argc, char* argv[]) { sc_signal out_en; sc_signal data_out; + sc_signal color_correction; + sc_signal flag_done; @@ -196,6 +203,9 @@ int sc_main(int argc, char* argv[]) { isp->out_clk(out_clk); isp->out_en(out_en); isp->data_out(data_out); + isp->color_correction(color_correction); + + color_correction.write(true); // enable color correction // Construct testbench module TB_ISP tb_isp("tb_isp"); @@ -264,6 +274,8 @@ int sc_main(int argc, char* argv[]) { // out_image.write((const char *)&tb_isp.out[y * OUT_WIDTH + x], sizeof(tb_isp.out[0])); // out_image.close(); + + // save to image uint8_t* data = new uint8_t[OUT_WIDTH * OUT_HEIGHT * 3]; // RGB24格式像素数据 for (int32_t y = 0; y < OUT_HEIGHT; ++y) { @@ -286,6 +298,12 @@ int sc_main(int argc, char* argv[]) { } } + // for (int i = 0; i < OUT_WIDTH * OUT_HEIGHT * 3; i += 3) { + // data[i + 0] = std::min(255, static_cast(data[i + 0] * + // red_gain)); data[i + 1] = std::min(255, static_cast(data[i + 1] + // * green_gain)); data[i + 2] = std::min(255, static_cast(data[i + + // 2] * blue_gain)); + // } write_bmp("test.bmp", data, OUT_WIDTH, OUT_HEIGHT); delete[] data; diff --git a/sim/software/demosaic.cpp b/sim/software/demosaic.cpp index 45f988a..3cb3112 100644 --- a/sim/software/demosaic.cpp +++ b/sim/software/demosaic.cpp @@ -4,15 +4,20 @@ #include "bmp.hpp" +enum BayerPattern { GRBG, RGGB, BGGR, GBRG }; const int IN_WIDTH = 1920; const int IN_HEIGHT = 1080; const int IN_SIZE = IN_WIDTH * IN_HEIGHT; const int OUT_WIDTH = 1280; const int OUT_HEIGHT = 720; const int OUT_SIZE = OUT_WIDTH * OUT_HEIGHT; -const int RAW_TYPE = 1; +const BayerPattern RAW_TYPE = RGGB; const int COLOR_DEPTH = 10; +// const float red_gain = 1.2f; // Adjust these values as necessary +// const float green_gain = 0.83f; +// const float blue_gain = 0.95f; + int main() { std::ifstream in_image; in_image.open("./test.RAW", std::ios::in | std::ios::binary); @@ -26,7 +31,7 @@ int main() { image[y][x] = buf[0] + ((uint16_t)buf[1] << 8); } - int raw_type = RAW_TYPE; + BayerPattern raw_type = RAW_TYPE; uint8_t* data = new uint8_t[OUT_WIDTH * OUT_HEIGHT * 3]; // RGB24格式像素数据 for (int32_t y = 0; y < OUT_HEIGHT; ++y) { @@ -34,67 +39,72 @@ int main() { int32_t index = (y * OUT_WIDTH + x) * 3; uint16_t red = 0, green = 0, blue = 0; - uint16_t data_cache[3][3] = { - {image[y][x], image[y][x + 1], image[y][x + 2]}, - {image[y + 1][x], image[y + 1][x + 1], image[y + 1][x + 2]}, - {image[y + 2][x], image[y + 2][x + 1], image[y + 2][x + 2]}, - }; + uint16_t data_cache[9] = {0}; + for (int i = 0; i < 3; i++) + for (int j = 0; j < 3; j++) { + data_cache[i * 3 + j] = image[y + i][x + j]; + } + // data case 0 case 1 case 2 case 3 + // 0 1 2 G R G R G R B G B G B G + // 3 4 5 B G B G B G G R G R G R + // 6 7 8 G R G R G R B G B G B G switch (raw_type) { case 0: // Missing B, R on G - blue = (data_cache[1][0] + data_cache[1][2]) / 2; - red = (data_cache[0][1] + data_cache[2][1]) / 2; - green = data_cache[1][1]; + red = (data_cache[1] + data_cache[7]) / 2; + blue = (data_cache[3] + data_cache[5]) / 2; + green = data_cache[4]; break; case 1: // Missing G, R on B - green = (data_cache[0][1] + data_cache[1][0] + - data_cache[1][2] + data_cache[2][1]) / + green = (data_cache[1] + data_cache[3] + data_cache[5] + + data_cache[7]) / 4; - red = (data_cache[0][0] + data_cache[0][2] + - data_cache[2][0] + data_cache[2][2]) / + red = (data_cache[0] + data_cache[2] + data_cache[6] + + data_cache[8]) / 4; - blue = data_cache[1][1]; + blue = data_cache[4]; break; case 2: // Missing G, B on R - green = (data_cache[0][1] + data_cache[1][0] + - data_cache[1][2] + data_cache[2][1]) / + green = (data_cache[1] + data_cache[3] + data_cache[5] + + data_cache[7]) / 4; - blue = (data_cache[0][0] + data_cache[0][2] + - data_cache[2][0] + data_cache[2][2]) / + blue = (data_cache[0] + data_cache[2] + data_cache[6] + + data_cache[8]) / 4; - red = data_cache[1][1]; + red = data_cache[4]; break; case 3: // Missing B, R on G - red = (data_cache[1][0] + data_cache[1][2]) / 2; - blue = (data_cache[0][1] + data_cache[2][1]) / 2; - green = data_cache[1][1]; + blue = (data_cache[1] + data_cache[7]) / 2; + red = (data_cache[3] + data_cache[5]) / 2; + green = data_cache[4]; break; } - printf("x=%4d, y=%4d, red=0x%03x, green=0x%03x, blue=0x%03x, raw_type=%d\n", x, - y, red, green, blue, raw_type); + printf( + "x=%4d, y=%4d, red=0x%03x, green=0x%03x, blue=0x%03x, " + "raw_type=%d\n", + x, y, red, green, blue, raw_type); switch (raw_type) { case 0: - raw_type = 1; + raw_type = RGGB; break; case 1: - raw_type = 0; + raw_type = GRBG; break; case 2: - raw_type = 3; + raw_type = GBRG; break; case 3: - raw_type = 2; + raw_type = BGGR; break; } - data[index + 0] = red >> (COLOR_DEPTH - 8); // R - data[index + 1] = green >> (COLOR_DEPTH - 8); // G - data[index + 2] = blue >> (COLOR_DEPTH - 8); // B + data[index + 1] = green >> (COLOR_DEPTH - 8); // G + data[index + 2] = blue >> (COLOR_DEPTH - 8); // B } if (y % 2) { @@ -102,21 +112,27 @@ int main() { } else { switch (RAW_TYPE) { case 0: - raw_type = 2; + raw_type = BGGR; break; case 1: - raw_type = 3; + raw_type = GBRG; break; case 2: - raw_type = 0; + raw_type = GRBG; break; case 3: - raw_type = 1; + raw_type = RGGB; break; } } } + // for (int i = 0; i < OUT_WIDTH * OUT_HEIGHT * 3; i += 3) { + // data[i + 0] = std::min(255, static_cast(data[i + 0] * red_gain)); + // data[i + 1] = std::min(255, static_cast(data[i + 1] * green_gain)); + // data[i + 2] = std::min(255, static_cast(data[i + 2] * blue_gain)); + // } + write_bmp("test.bmp", data, OUT_WIDTH, OUT_HEIGHT); delete[] data; diff --git a/sim/software/demosaic2.cpp b/sim/software/demosaic2.cpp new file mode 100644 index 0000000..fcdf046 --- /dev/null +++ b/sim/software/demosaic2.cpp @@ -0,0 +1,163 @@ +#include +#include +#include + +#include "bmp.hpp" + +enum BayerPattern { GRBG, RGGB, BGGR, GBRG }; +const int IN_WIDTH = 1936; +const int IN_HEIGHT = 1088; +const int IN_SIZE = IN_WIDTH * IN_HEIGHT; +const int OUT_WIDTH = 1280; +const int OUT_HEIGHT = 720; +const int OUT_SIZE = OUT_WIDTH * OUT_HEIGHT; +const BayerPattern RAW_TYPE = GBRG; +const int COLOR_DEPTH = 12; + +// const float red_gain = 1.2f; // Adjust these values as necessary +// const float green_gain = 0.5f; +// const float blue_gain = 0.95f; + +int main() { + std::ifstream in_image; + in_image.open("./test.bin", std::ios::in | std::ios::binary); + auto image = std::vector>( + IN_HEIGHT, std::vector(IN_WIDTH, 0)); + for (int y = 0; y < IN_HEIGHT; y++) + for (int x = 0; x < IN_WIDTH; x++) { + uint8_t buf[2] = {0}; + in_image.read((char*)buf, sizeof(buf)); + + image[y][x] = buf[0] + ((uint16_t)buf[1] << 8); + } + + BayerPattern raw_type = RAW_TYPE; + uint8_t* data = + new uint8_t[OUT_WIDTH * OUT_HEIGHT * 3]; // RGB24格式像素数据 + 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; + + uint16_t red = 0, green = 0, blue = 0; + uint16_t cache[25] = {0}; + for (int i = 0; i < 5; i++) + for (int j = 0; j < 5; j++) { + cache[i * 5 + j] = image[y + i][x + j]; + } + // data case GRBG case RGGB case BGGR case GBRG + // 00 01 02 03 04 G R G R G R G R G R B G B G B G B G B G + // 05 06 07 08 09 B G B G B G B G B G G R G R G R G R G R + // 10 11 12 13 14 G R G R G R G R G R B G B G B G B G B G + // 15 16 17 18 19 B G B G B G B G B G G R G R G R G R G R + // 20 21 22 23 24 G R G R G R G R G R B G B G B G B G B G + + switch (raw_type) { + case GRBG: + green = cache[12]; + blue = + (cache[7] + cache[17]) / 2 + cache[12] - + ((cache[2] + cache[6] + cache[8] + cache[12]) / 4 + + (cache[22] + cache[16] + cache[18] + cache[12]) / 4) / + 2; + red = (cache[11] + cache[13]) / 2 + cache[12] - + ((cache[10] + cache[6] + cache[16] + cache[12]) / 4 + + (cache[14] + cache[8] + cache[18] + cache[12]) / 4) / + 2; + break; + + case RGGB: + red = cache[12]; + green = (cache[7] + cache[11] + cache[13] + cache[17]) / 4; + blue = + (cache[6] + cache[8] + cache[16] + cache[18]) / 4 + + (cache[7] + cache[11] + cache[13] + cache[17]) / 4 - + ((cache[1] + cache[5] + cache[7] + cache[11]) / 4 + + (cache[3] + cache[7] + cache[9] + cache[13]) / 4 + + (cache[11] + cache[15] + cache[17] + cache[18]) / 4 + + (cache[13] + cache[17] + cache[19] + cache[23]) / 4) / + 4; + break; + + case BGGR: + blue = cache[12]; + green = (cache[7] + cache[11] + cache[13] + cache[17]) / 4; + red = + (cache[6] + cache[8] + cache[16] + cache[18]) / 4 + + (cache[7] + cache[11] + cache[13] + cache[17]) / 4 - + ((cache[1] + cache[5] + cache[7] + cache[11]) / 4 + + (cache[3] + cache[7] + cache[9] + cache[13]) / 4 + + (cache[11] + cache[15] + cache[17] + cache[18]) / 4 + + (cache[13] + cache[17] + cache[19] + cache[23]) / 4) / + 4; + break; + case GBRG: + green = cache[12]; + red = + (cache[7] + cache[17]) / 2 + cache[12] - + ((cache[2] + cache[6] + cache[8] + cache[12]) / 4 + + (cache[22] + cache[16] + cache[18] + cache[12]) / 4) / + 2; + blue = + (cache[11] + cache[13]) / 2 + cache[12] - + ((cache[10] + cache[6] + cache[16] + cache[12]) / 4 + + (cache[14] + cache[8] + cache[18] + cache[12]) / 4) / + 2; + break; + } + printf( + "x=%4d, y=%4d, red=0x%03x, green=0x%03x, blue=0x%03x, " + "raw_type=%d\n", + x, y, red, green, blue, raw_type); + + switch (raw_type) { + case 0: + raw_type = RGGB; + break; + case 1: + raw_type = GRBG; + break; + case 2: + raw_type = GBRG; + break; + case 3: + raw_type = BGGR; + break; + } + + data[index + 0] = red >> (COLOR_DEPTH - 8); // R + data[index + 1] = green >> (COLOR_DEPTH - 8); // G + data[index + 2] = blue >> (COLOR_DEPTH - 8); // B + } + + if (y % 2) { + raw_type = RAW_TYPE; + } else { + switch (RAW_TYPE) { + case 0: + raw_type = BGGR; + break; + case 1: + raw_type = GBRG; + break; + case 2: + raw_type = GRBG; + break; + case 3: + raw_type = RGGB; + break; + } + } + } + + // for (int i = 0; i < OUT_WIDTH * OUT_HEIGHT * 3; i += 3) { + // data[i + 0] = std::min(255, static_cast(data[i + 0] * + // red_gain)); data[i + 1] = std::min(255, static_cast(data[i + 1] + // * green_gain)); data[i + 2] = std::min(255, static_cast(data[i + + // 2] * blue_gain)); + // } + + write_bmp("test1.bmp", data, OUT_WIDTH, OUT_HEIGHT); + delete[] data; + + return 0; +}