finish Grey World White Balance

This commit is contained in:
SikongJueluo
2024-07-03 21:50:29 +08:00
parent 649d34415f
commit 1154da3307
12 changed files with 526 additions and 239 deletions

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;
}