diff --git a/.gitignore b/.gitignore index 9e3ae78..3ed462e 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,6 @@ *.bin *.dat *.png -!im.tif \ No newline at end of file +!im.tif +*.bmp +*.out \ No newline at end of file diff --git a/Crop/crop.v b/Crop/crop.v index f8e998e..16e1f63 100644 --- a/Crop/crop.v +++ b/Crop/crop.v @@ -1,6 +1,6 @@ module crop #( - parameter IN_WIDTH = 1936, - parameter IN_HEIGHT = 1088, + parameter IN_WIDTH = 1934, + parameter IN_HEIGHT = 1086, parameter OFFSET_X = 8, parameter OFFSET_Y = 4, parameter OUT_WIDTH = 640, @@ -60,15 +60,15 @@ module crop #( end HANDLE_DATA: begin - if (OFFSET_Y <= cnt_y && cnt_y < (OFFSET_Y + OUT_HEIGHT)) begin - if (OFFSET_X <= cnt_x && cnt_x < (OFFSET_X + OUT_WIDTH)) 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 out_en <= 1; end end - if (cnt_x >= IN_WIDTH) begin + if (cnt_x >= IN_WIDTH - 1) begin cnt_x <= 0; - if (cnt_y >= IN_HEIGHT) begin + if (cnt_y >= IN_HEIGHT - 1) begin cnt_y <= 0; end else begin diff --git a/Demosaic/demosaic2.v b/Demosaic/demosaic2.v index db0300d..488f175 100644 --- a/Demosaic/demosaic2.v +++ b/Demosaic/demosaic2.v @@ -152,13 +152,14 @@ module demosaic2 #( pos_y <= pos_y + 1; if (pos_y >= IM_HEIGHT - 2 - 1) begin pos_y <= 0; - case (RAW_TYPE) - 0: raw_type <= 2; - 1: raw_type <= 3; - 2: raw_type <= 0; - 3: raw_type <= 1; - endcase end + // 换行后切换Bayer格式 + case (RAW_TYPE) + 0: raw_type <= 2; + 1: raw_type <= 3; + 2: raw_type <= 0; + 3: raw_type <= 1; + endcase end else begin cnt_data <= 2; diff --git a/isp.v b/isp.v index 24d228e..f1c11ae 100644 --- a/isp.v +++ b/isp.v @@ -1,10 +1,10 @@ `timescale 1ns/1ps module isp #( - parameter IN_WIDTH = 700, - parameter IN_HEIGHT = 500, - parameter OUT_WIDTH = 640, - parameter OUT_HEIGHT = 480, + parameter IN_WIDTH = 1936, + parameter IN_HEIGHT = 1088, + parameter OUT_WIDTH = 1920, + parameter OUT_HEIGHT = 1080, parameter COLOR_DEPTH = 8, parameter RAW_TYPE = 3 // 0:grbg 1:rggb 2:bggr 3:gbrg ) ( diff --git a/sim/Makefile b/sim/Makefile index 614465e..5fd29a8 100644 --- a/sim/Makefile +++ b/sim/Makefile @@ -56,7 +56,7 @@ VERILATOR_FLAGS += --assert TOP_MODULE = isp VERILATOR_FLAGS += -top $(TOP_MODULE) # Input files for Verilator -VERILATOR_INPUT = ../isp.v sc_main.cpp ../Demosaic/demosaic2.v ../Crop/*.v ../FIFO/*.v ../Merge/*.v ../RAM/*.v +VERILATOR_INPUT = ../isp.v *.cpp ../Demosaic/demosaic2.v ../Crop/*.v ../FIFO/*.v ../Merge/*.v ../RAM/*.v # Check if SC exists via a verilator call (empty if not) SYSTEMC_EXISTS := $(shell $(VERILATOR) --get-supported SYSTEMC) @@ -88,9 +88,10 @@ run: @echo @echo "-- RUN ---------------------" - @rm -rf logs - @mkdir -p logs - obj_dir/V$(TOP_MODULE) +trace + # @rm -rf logs + # @mkdir -p logs + # obj_dir/V$(TOP_MODULE) +trace + obj_dir/V$(TOP_MODULE) # @echo # @echo "-- COVERAGE ----------------" diff --git a/sim/bmp.cpp b/sim/bmp.cpp new file mode 100644 index 0000000..a82c004 --- /dev/null +++ b/sim/bmp.cpp @@ -0,0 +1,46 @@ +#include "bmp.hpp" + +#include +#include + +// 将RGB24格式像素数据封装为BMP图像 +bool write_bmp(const char* filename, uint8_t* data, int32_t width, + int32_t height) { + BMPFileHeader file_header = {0}; + BMPInfoHeader info_header = {0}; + std::ofstream ofs(filename, std::ios::binary); + if (!ofs) { + std::cerr << "Failed to create file: " << filename << std::endl; + return false; + } + // BMP文件头 + file_header.type = 0x4D42; // BM + file_header.size = + sizeof(BMPFileHeader) + sizeof(BMPInfoHeader) + width * height * 3; + file_header.offset = sizeof(BMPFileHeader) + sizeof(BMPInfoHeader); + ofs.write(reinterpret_cast(&file_header), sizeof(file_header)); + + // BMP位图信息头 + info_header.size = sizeof(BMPInfoHeader); + info_header.width = width; + info_header.height = height; + info_header.planes = 1; + info_header.bit_count = 24; + info_header.size_image = width * height * 3; + ofs.write(reinterpret_cast(&info_header), sizeof(info_header)); + + // 像素数据 + int32_t row_size = (((width + 1) * 3) / 4) * 4; // 行字节数,必须为4的倍数 + uint8_t* row_data = new uint8_t[row_size]; + for (int32_t y = height - 1; y >= 0; --y) { // BMP图像的行是从下往上存储的 + for (int32_t x = 0; x < width; ++x) { + row_data[x * 3 + 2] = data[(y * width + x) * 3 + 0]; // B + row_data[x * 3 + 1] = data[(y * width + x) * 3 + 1]; // G + row_data[x * 3 + 0] = data[(y * width + x) * 3 + 2]; // R + } + ofs.write(reinterpret_cast(row_data), row_size); + } + delete[] row_data; + ofs.close(); + return true; +} \ No newline at end of file diff --git a/sim/bmp.hpp b/sim/bmp.hpp new file mode 100644 index 0000000..8afcffc --- /dev/null +++ b/sim/bmp.hpp @@ -0,0 +1,35 @@ +#ifndef __BMP_H__ +#define __BMP_H__ + +#include +#pragma pack(push, 1) // 1字节对齐 + +// BMP文件头结构体 +struct BMPFileHeader { + uint16_t type; // 文件类型,必须为"BM" + uint32_t size; // 文件大小,单位为字节 + uint16_t reserved1; // 保留字段,必须为0 + uint16_t reserved2; // 保留字段,必须为0 + uint32_t offset; // 像素数据起始位置,单位为字节 +}; + +// BMP位图信息头结构体 +struct BMPInfoHeader { + uint32_t size; // 信息头大小,必须为40 + int32_t width; // 图像宽度,单位为像素 + int32_t height; // 图像高度,单位为像素 + uint16_t planes; // 颜色平面数,必须为1 + uint16_t bit_count; // 每个像素的位数,必须为24 + uint32_t compression; // 压缩方式,必须为0 + uint32_t size_image; // 像素数据大小,单位为字节 + int32_t x_pels_per_meter; // X方向像素数/米 + int32_t y_pels_per_meter; // Y方向像素数/米 + uint32_t clr_used; // 使用的颜色数,必须为0 + uint32_t clr_important; // 重要的颜色数,必须为0 +}; + +#pragma pack(pop) + +bool write_bmp(const char* filename, uint8_t* data, int32_t width, int32_t height); + +#endif \ No newline at end of file diff --git a/sim/sc_main.cpp b/sim/sc_main.cpp index 0d94667..e1aa7b0 100644 --- a/sim/sc_main.cpp +++ b/sim/sc_main.cpp @@ -16,12 +16,13 @@ // Handle file #include #include +#include "bmp.hpp" -#define IN_WIDTH 700 -#define IN_HEIGHT 500 +#define IN_WIDTH 1936 +#define IN_HEIGHT 1088 #define IN_SIZE (IN_WIDTH * IN_HEIGHT) -#define OUT_WIDTH 640 -#define OUT_HEIGHT 480 +#define OUT_WIDTH 1920 +#define OUT_HEIGHT 1080 #define OUT_SIZE (OUT_WIDTH * OUT_HEIGHT) using namespace std; @@ -41,7 +42,7 @@ SC_MODULE (TB_ISP) { sc_in im_data; sc_out is_done; - unique_ptr image; + unique_ptr image = make_unique(IN_SIZE); unique_ptr out = make_unique(OUT_SIZE); SC_CTOR (TB_ISP) { @@ -69,7 +70,7 @@ SC_MODULE (TB_ISP) { wait(1); data_en.write(0); - if (pos_x++ >= IN_WIDTH) { + if (++pos_x >= IN_WIDTH) { pos_x = 0; pos_y++; } @@ -100,7 +101,7 @@ SC_MODULE (TB_ISP) { if (last_data == im_data.read()) { cnt++; - if (cnt >= 100) { + if (cnt >= 10000) { is_done.write(1); } } else { @@ -129,7 +130,6 @@ int sc_main(int argc, char* argv[]) { // Read image auto buf = make_unique(2 * IN_SIZE); - // vector> buf(IN_HEIGHT, vector(IN_WIDTH, 0)); in_image.read((char*)buf.get(), IN_SIZE * 2); in_image.close(); // Reshape data @@ -259,10 +259,35 @@ int sc_main(int argc, char* argv[]) { // Save output image cout << "Ready to save raw RGB image" << endl; - for (int y = 0; y < OUT_HEIGHT; y++) - for(int x = 0; x < OUT_WIDTH; x++) - out_image.write((const char *)&tb_isp.out[y * OUT_WIDTH + x], sizeof(tb_isp.out[0])); - out_image.close(); + // for (int y = 0; y < OUT_HEIGHT; y++) + // for(int x = 0; x < OUT_WIDTH; x++) + // 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) { + 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 ); + + 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); + + data[index + 0] = red; // R + data[index + 1] = green; // G + data[index + 2] = blue; // B + } + } + + write_bmp("test.bmp", data, OUT_WIDTH, OUT_HEIGHT); + delete[] data; // Return good completion status return 0; diff --git a/sim/software/demosaic.cpp b/sim/software/demosaic.cpp new file mode 100644 index 0000000..51555f0 --- /dev/null +++ b/sim/software/demosaic.cpp @@ -0,0 +1,126 @@ +#include +#include +#include + +#include "bmp.hpp" + +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 = 3; + +int main() { + std::ifstream in_image; + in_image.open("./test.RAW", 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] + (buf[1] << 8); + } + + int 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 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]}, + }; + + 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]; + 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]) / + 4; + red = (data_cache[0][0] + data_cache[0][2] + + data_cache[2][0] + data_cache[2][2]) / + 4; + blue = data_cache[1][1]; + 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]) / + 4; + blue = (data_cache[0][0] + data_cache[0][2] + + data_cache[2][0] + data_cache[2][2]) / + 4; + red = data_cache[1][1]; + 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]; + 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 = 1; + break; + case 1: + raw_type = 0; + break; + case 2: + raw_type = 3; + break; + case 3: + raw_type = 2; + break; + } + + + // data[index + 0] = red * 8 / 12; // R + data[index + 1] = green * 8 / 12; // G + // data[index + 2] = blue * 8 / 12; // B + data[index + 0] = 0; // R + // data[index + 1] = 0; // G + data[index + 2] = 0; // B + } + + if (y % 2) { + raw_type = RAW_TYPE; + } else { + switch (RAW_TYPE) { + case 0: + raw_type = 2; + break; + case 1: + raw_type = 3; + break; + case 2: + raw_type = 0; + break; + case 3: + raw_type = 1; + break; + } + } + } + + write_bmp("test.bmp", data, OUT_WIDTH, OUT_HEIGHT); + delete[] data; + + return 0; +} diff --git a/sim/software/test.RAW b/sim/software/test.RAW new file mode 100644 index 0000000..8e73d57 Binary files /dev/null and b/sim/software/test.RAW differ diff --git a/sim/transform/raw_cut.py b/sim/transform/raw_cut.py index 6395e19..2cf7443 100644 --- a/sim/transform/raw_cut.py +++ b/sim/transform/raw_cut.py @@ -1,8 +1,8 @@ import imageio import numpy as np -cut_width = 700 -cut_height = 500 +cut_width = 1936 +cut_height = 1088 if __name__ == '__main__': # txt = open('./test.dat', 'w') diff --git a/sim/transform/raw_to_image.py b/sim/transform/raw_to_image.py deleted file mode 100644 index 3959ce5..0000000 --- a/sim/transform/raw_to_image.py +++ /dev/null @@ -1,10 +0,0 @@ -import imageio -import numpy as np - -im_width = 640 -im_height = 480 - -if __name__ == '__main__': - raw = np.fromfile('./out.bin', dtype=np.int32) - image = raw.reshape((im_height, im_width)) - imageio.imsave("./out.png", image)