FPGA-simulation read and write bmp pictures


Recently, I want to complete FPGA image processing. Since there is no development board, it is like completing through simulation. Before, it was like converting the image into txt text through python, and finally using verilog to read the txt file and import it, process the pixels, and then process the processed The pixel data is written into txt, and finally converted into a bmp bitmap through python. Later, it was found that verilog can directly read the bmp file and write the data into the bmp file. It is much more convenient.

bitmap description

BMP file storage format
The storage format of bmp files is an image file format widely used in Windows systems. It does not compress images to any degree. It is mainly divided into bitmap header files, bitmap information headers, palette information, and pixel data. Four major parts, since RBG images are usually processed, only the case of RGB is discussed

Bitmap header file : file format, size and other information, the first 14Byte; the main concern is the image size, the starting position of the pixel data.
Bitmap information header: Provide information such as the size of the image data, number of bit planes, compression method, color index, etc., the first 40Byte; the main concern is the image width and image height.
Palette information: words, do not care about
pixel data: pixel data, 8bit one pixel data, that is, 1Byte.

insert image description here

insert image description here

bitmap

insert image description here
I use the above 128*128

24-bit bitmap: also known as RGB true color map, also known as RGB true color map, including 2^24=16 777 216=16M colors, no color table. Each pixel is represented by 3 bytes (hexadecimal code 6 bits), and each byte is responsible for controlling a color, namely blue (Blue), green (Green), red (Red).
A 256×256 24-bit bitmap size calculation method:
bitmap file header (14 bytes) + bitmap information header (40 bytes) + memory occupied by actual pixels (256×256×3 bytes) = 196 662 bytes (Byte)

Note:
Windows has the habit of "zero padding"! That is to say, the number of bytes occupied by each row of pixels of the bitmap must be divisible by 4. If it is not divisible by 4, then "complement" 1 to 3 bytes of "00" at the end of the hexadecimal code of each line of the bitmap.
For example: a 24-bit bitmap with a width of 253×height 256, when Microsoft generates the picture as an actual file, it calculates the bytes occupied by each row of pixels=width 253×3 bytes=759 bytes, and checks that it is divided by 4 If the remainder is 1, add 1 byte at the end of the hexadecimal code of each line, and add "00" to become 760 bytes. Therefore, when we calculate the size of the image, we should first judge whether it is "zero-filled", and then get the algorithm:
the image size = bitmap file header (14 bytes) + bitmap information header (40 bytes) + actual pixel points occupy memory (High 256 × 760 bytes per line) = 194614 bytes (Byte).
"Zero padding" is only checked for the width of the bitmap. For a 24-bit bitmap with a width of 256×height 253,
its size = bitmap file header (14 bytes) + bitmap information header (40 bytes) + actual Pixels occupy memory (height 253 × 768 bytes per row) = 194358 bytes (Byte) < 196 662 bytes (Byte) .
Just reverse the width and height of this image, and the memory occupied by the image becomes smaller.

Verilog code implementation

/*******************************************************************************
*                                                                              *
*     (c) Copyright 1995-2017 TAIHO ELE Co,Ltd.                                *
*     All rights reserved.                                                     *
*                                                                              *
********************************************************************************
*                                                                               
*       FileName     :       top_tb.v                                  
*       Abstract     :       This module is an example for coding.              
*       Author       :       Mouhongbing                                         
*       Version      :       1.1                                                
*       Release      :       2022.9.29                                   
*       Revision     :                                                          
*           Version Date        Author          Modification description        
*           1.0                 Mouhongbing      2022.9.29                
*                                                                               
******************************************************************************/ 
`timescale 1ns / 1ns

module top_tb;

//图像属性:图像宽度 图像高度 图像尺寸 图像像素点起始位
integer bmp_width;
integer bmp_high;
integer bmp_size;
integer start_index;

//bmp file id
integer bmp_file_id;
integer bmp_dout_id;
integer dout_txt_id;

//文件句柄
integer h;
//文件bmp文件数据
reg		[7:0]	rd_data  [0:49300];//根据自己图片大小

//写操作
reg		[23:0]	wr_data;
integer i = 0;
integer index;

initial
begin
    clk=1'b1;
	//打开原始图像
	bmp_file_id = $fopen("D:\\python\\pic\\lena.bmp","rb");
	//打开输出图像
	bmp_dout_id = $fopen("D:\\python\\pic\\output_file.bmp","wb");
	//打开输出数据
	dout_txt_id = $fopen("D:\\python\\pic\\output_file.txt","w+");

	//读取bmp文件
	h = $fread(rd_data,bmp_file_id);

    // 图像宽度
	bmp_width = {
    
    rd_data[21], rd_data[20], rd_data[19], rd_data[18]};
	// 图像宽度
	bmp_high = {
    
    rd_data[25], rd_data[24], rd_data[23], rd_data[22]};
	// 像素起始位置
	start_index = {
    
    rd_data[13], rd_data[12], rd_data[11], rd_data[10]};
	// 图像尺寸
	bmp_size = {
    
    rd_data[5], rd_data[4], rd_data[3], rd_data[2]};
	$fclose(bmp_file_id);



	//输出BMP
	for(i = 0; i < bmp_size; i = i + 1)begin
             $fwrite(bmp_dout_id, "%c", rd_data[i]);//注意参数%c
    end
    $fclose(bmp_dout_id);
    
    //输出txt,只存像素点
    for(index = start_index; index < bmp_size-2; index = index + 3)begin
        wr_data = {
    
    rd_data[index + 2], rd_data[index + 1], rd_data[index]};
        $fwrite(dout_txt_id, "%d,", wr_data[7:0]);
        $fwrite(dout_txt_id, "%d,", wr_data[15:8]);
        $fwrite(dout_txt_id, "%d\n", wr_data[23:16]);
    end
    $fclose(dout_txt_id);
end

endmodule

insert image description here

Python processing code (attached)

Image to txt

import cv2     # h, w, c
import numpy
import matplotlib.pyplot as plt

img = cv2.imread("./pic/th.bmp" , 1)
print("图像的形状,返回一个图像的(行数,列数,通道数):", img.shape)
print("图像的像素数目:", img.size)
print("图像的数据类型:", img.dtype)
#img = cv2.resize(img,(280,280))    可以改变图片的大小

fname = open("./pic/th.txt",'w')
# fname.write("图像的形状,返回一个图像的(行数,列数,通道数):"+str(img.shape)+'\n')
# fname.write("图像的像素数目:"+str(img.size)+'\n')
# fname.write("图像的数据类型:"+str(img.dtype)+'\n')
Ylenth = img.shape[1]          # 图片列数
Xlenth = img.shape[0]          # 图片行数

for i in range(Xlenth):
    for j in range(Ylenth):
        fname.write(str(img[i][j][0])+','+str(img[i][j][1])+','+str(img[i][j][2])+'\n')
    # fname.write('\n')
fname.close()


cv2.imshow('image',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

txt to bmp

# -*- coding:utf8 -
from PIL import Image
x = 128    #x坐标  通过对txt里的行数进行整数分解
y = 128  #y坐标  x*y=行数 13500行,150和900也可以
 
im = Image.new("RGB", (x,y))
file = open('./pic/output_file.txt')
 
for i in range(0,x):
    for j in range(0,y):
        #line = file.readline().replace('[','').replace(']','')  #获取一行rgb值,并且把()都替换为空
        line=file.readline()
        rgb = line.split(",") #逗号分割
        im.putpixel((i, j), (int(rgb[2]), int(rgb[1]), int(rgb[0]))) #(i,j)为坐标,后面的是像素点
file.close()
im.save("./pic/output_file.bmp")

Guess you like

Origin blog.csdn.net/Mouer__/article/details/127110566