FPGA图像处理基础----直方图统计

2023-11-16

直方图统计的原理

  直方图统计从数学上来说,是对图像中的像素点进行统计。图像直方图统计常用于统计灰度图像,表示图像中各个灰度级出现的次数或者概率。统计直方图的实现采用C/C++或者其他高级语言实现十分简单,单采用FPGA来实现直方图的统计就稍显麻烦。若使用Xilinx和Altera的FPGA芯片,可以使用HLS来进行图像的加速处理。但这暂时不是我的重点。

用C语言实现直方图统计:

unsigned int histoBuffer[256];
for(int idxCol = 0; idxCol < imageWidth; idxCol ++)
{
	for(int idxRow = 0; idxRow < imageHeight; idxRow ++)
	{
		histoBuffer[image[idxRow * imageWidth + idxCol]] ++;
	}
}

基于FPGA实现图像直方图

  在前面可以看到基于C/C++或者其他高级语言实现直方图统计十分简单。但是在FPGA中,需要设计具体的时序和电路才能正确地将直方图进行统计。

直方图统计的注意点

  使用FPGA来完成直方图的统计需要注意以下几点:

  1. 对一幅图像进行统计,必须等到当前的图像“流过”后才能完成。这使得采用FPGA相较于其他方式并没有太大的优势。
  2. 在统计的过程中,需要对已经统计的像素的统计值进行缓存。
  3. 在下一帧图像来临的时候,需要将RAM中的数据清空。

设计统计模块

  根据上面的要点,在设计直方图统计电路的时候可以按照如下思路来进行:

  1. 新的一帧图像来临是,需要将上一帧图像的直方图统计结果清零。
  2. 在新一帧图像数据有效时,进行统计
  3. 一帧图像数据统计完成后,将统计结果读出,并将统计结果输出到外部。

状态机设计:

在复位或空闲状态下,系统处于IDLE状态,当检测到新一帧图像(vsync信号的上升沿)时,状态跳转到CLEAR状态,清空RAM中保存的上一帧图像的数据。当RAM中的图像数据清空完成后,进入到直方图统计状态CALCULATE,在该状态下进行直方图的统计当一帧图像统计完成后,将本帧图像的统计结果输出,也即GET_HISTO状态。
在这里插入图片描述

CLEAR状态:

  下图是CLEAR状态下的时序设计图,拉高一个clear_flag信号,向RAM中写入0,将上一帧图像的统计结果清零。
在这里插入图片描述

CALCULATE状态:

  统计状态下完成的任务是最复杂的,由于在图像数据流来领的时候,常常会遇到相邻几个像素点的灰度值是相同的,因此可以将这些点进行统计,然后在将统计值写入到RAM中,将小对RAM的读写操作。
  下面的时序图是一个典型的统计时序设计图,基本包括了图像流入时的像素状态。
  在统计时,主要是来比较当前的像素点和上一个像素点的值是否相同,若相同则像素统计值cal_pixel就会加一,直到相邻两像素值不同或者一行图像结束时,停止加一,并且将当前统计结果cal_pixel和RAM中已经缓存的统计值进行累加,重新写入到RAM中(也即wr_ram_data),同时需要使能RAM的写操作。wr_ram_en。写入RAM的地址,其实就是当前的灰度值。在这之中,需要注意从RAM中读出数据具有1或者2个时钟周期的Latency(根据IP核设置有关。
  在FPGA的直方图统计中,该部分是最重要的。完成了该时序图,也就基本上完成了统计电路。
在这里插入图片描述

GET_HISTO状态:

在这里插入图片描述
  该状态下,就是完成对直方图的统计结果的读出。

程序设计

  FPGA完成直方图的设计,其实就是上面的三个时序图的设计,完成了上述三个时序图后,就能够直方图统计模块。下面的这个模块完成的是一个256*256大小的灰度图的直方图统计,若需要对其他大小的图像进行直方图统计,只需修改其中的参数即可。其实对于我的设计,每一行的像素个数是由上游模块确定的,在本模块中,只需指定图像的高度即可,指定高度,也仅仅是为了将直方图从RAM中读出。
parameter IMG_WIDTH = 256 ;
parameter IMG_HEIGHT = 256 ;


/*============================================
#
# Author: Wcc - 1530604142@qq.com
#
# QQ : 1530604142
#
# Last modified: 2020-07-06 19:48
#
# Filename: calculate_histogram.v
#
# Description: 
#
============================================*/
`timescale 1ns / 1ps
module calculate_histogram(
	input 	wire 			clk 		,
	input	wire 			rst 		,
	input 	wire 			pi_hsync	,
	input	wire 			pi_vsync	,
	input	wire 			pi_data_vld	,
	input 	wire 	[7:0]	pi_data 	,

	output 	wire 			po_histo_vld,
	output 	wire 	[31:0]	po_histo_data			
    );
//==========================================
//parameter define
//==========================================
parameter IMG_WIDTH 	= 	256 	;
parameter IMG_HEIGHT 	=	256 	;
parameter GRAY_LEVEL	= 	256		;//灰度级

parameter IDLE 		= 4'b0001;//空闲状态
parameter CLEAR		= 4'b0010;//清空RAM中数据状态
parameter CALCULATE = 4'b0100;//统计图像直方图状态
parameter GET_HISTO = 4'b1000;//输出直方图


//==========================================
//internal siganls
//==========================================
reg 	[3:0]	state 		;//状态寄存器
reg 	[1:0]	vsync_dd	;//场同步信号寄存

//==========================================
//清空RAM阶段
//==========================================
reg 	[8:0]	cnt_clear 	;
wire			add_cnt_clear;
wire 			end_cnt_clear;
reg 			clear_flag	;//清空RAM指示信号

//==========================================
//统计直方图阶段
//==========================================
reg 	[12:0]	cnt_row 	;
wire 			add_cnt_row ;
wire 			end_cnt_row	;

reg 			data_vld_dd0;//数据有效延时信号
reg 			data_vld_dd1;//数据有效延时信号
reg 	[7:0]	pi_data_dd0	;//有效数据延时
reg 	[7:0]	pi_data_dd1	;//有效数据延时
reg 	[31:0]	cal_pixle	;//相同的像素统计值
reg 	[31:0]	cal_value 	;//写入RAM的统计值
reg 			cal_value_vld;//写入RAM数据有效信号
reg 			cal_one_row_done	;//统计一行图像数据结束
wire 	[7:0]	cal_wr_ram_addr;//统计状态下写RAM的地址
wire 	[7:0]	cal_rd_ram_addr;//统计状态下读RAM的地址

//==========================================
//读出数据阶段
//==========================================
reg 			get_data_flag 	;
reg 	[8:0]	cnt_get 		;
wire 			add_cnt_get 	;
wire 			end_cnt_get 	;
reg 			histo_data_vld 	;
wire 	[31:0]	histo_data 		;

//==========================================
//Block RAM Related Signals
//==========================================
reg 			wr_ram_en 	;//写RAM使能信号
reg 	[7:0]	wr_ram_addr	;//写RAM地址
reg 	[31:0]	wr_ram_data ;//写入RAM的数据
reg  	[7:0]	rd_ram_addr ;//读RAM的地址
wire	[31:0]	rd_ram_data	;//从RAM中读出的数据


assign po_histo_data = (histo_data_vld) ? histo_data : 32'd0;
assign po_histo_vld = histo_data_vld;


//----------------state machine describe------------------
always @(posedge clk) begin
	if (rst==1'b1) begin
		state <= IDLE ;
	end
	else begin
		case(state)
			IDLE : begin
				//检测到新的一帧图像
				if (vsync_dd[0] == 1'b1 && vsync_dd[1] == 1'b0) begin
					state <= CLEAR;
				end
				else begin
					state <= IDLE;
				end
			end

			CLEAR : begin
				//当前RAM中的数据已经清空
				if (end_cnt_clear == 1'b1) begin
					state <= CALCULATE;
				end
				else begin
					state <= CLEAR;
				end
			end
			
			CALCULATE : begin
				//当前一幅图像数据的灰度直方图已经统计完成
				if (end_cnt_row == 1'b1) begin
					state <= GET_HISTO;
				end
				else begin
					state <= CALCULATE;
				end				
			end

			GET_HISTO : begin
				//将RAM中的直方图数据全部读出
				if (end_cnt_get == 1'b1) begin
					state <= IDLE;
				end
				else begin
					state <= GET_HISTO;
				end
				
			end

			default : begin
				state <= IDLE;
			end

		endcase 
	end
end

//----------------vsync_dd------------------
//检测一帧图像
always @(posedge clk) begin
	if (rst==1'b1) begin
		vsync_dd <= 'd0;
	end
	else begin
		vsync_dd <= {vsync_dd[0], pi_vsync};
	end
end

//==========================================
//during the clear state
//==========================================
//----------------cnt_clear------------------
//用于清空RAM的计数器
always @(posedge clk) begin
	if (rst == 1'b1) begin
		cnt_clear <= 'd0;
	end
	else if (add_cnt_clear) begin
		if(end_cnt_clear)
			cnt_clear <= 'd0;
		else
			cnt_clear <= cnt_clear + 1'b1;
	end
	else begin
		cnt_clear <= 'd0;
	end
end

assign add_cnt_clear = 	state == CLEAR && wr_ram_en == 1'b1;
assign end_cnt_clear = add_cnt_clear &&	cnt_clear == GRAY_LEVEL - 1;

//----------------clear_flag------------------
always @(posedge clk) begin
	if (rst==1'b1) begin
		clear_flag <= 1'b0;
	end
	else if (state == CLEAR ) begin
		if (end_cnt_clear == 1'b1) begin
			clear_flag <= 1'b0;
		end
		else begin
			clear_flag <= 1'b1;
		end
	end
	else begin
		clear_flag <= 1'b0;
	end
end


//==========================================
//during the calculate state
//==========================================

//----------------delay------------------
always @(posedge clk) begin
	if (rst==1'b1) begin
		data_vld_dd0 <= 'd0;
		data_vld_dd1 <= 'd0;
		pi_data_dd0	 <= 'd0;
		pi_data_dd1	 <= 'd0;
	end
	else begin
		data_vld_dd0 <= pi_data_vld;
		data_vld_dd1 <= data_vld_dd0;
		pi_data_dd0	 <= pi_data;
		pi_data_dd1	 <= pi_data_dd0;
	end
end

//----------------cal_pixle------------------
always @(posedge clk) begin
	if (rst==1'b1) begin
		cal_pixle <= 'd1;
	end
	else if (state == CALCULATE && data_vld_dd0 == 1'b1 ) begin
		//相邻两个像素点的值不同,统计值回到1
		if (pi_data != pi_data_dd0 ) begin
			cal_pixle <= 'd1;
		end
		//一行图形数据统计结束
		else if (pi_data_vld == 1'b0 ) begin
			cal_pixle <= 'd1;
		end
		//相邻两个像素点的值相同
		else if (pi_data == pi_data_dd0) begin
			cal_pixle <= cal_pixle + 1'b1;
		end
	end
	else begin
		cal_pixle <= 'd1;
	end
end

//----------------cal_value------------------
//写入RAM的数据
always @(posedge clk) begin
	if (rst==1'b1) begin
		cal_value <= 'd0;
		cal_value_vld <= 1'b0;
	end
	else if (state == CALCULATE ) begin
		//相邻两个像素值不同,将当前统计结果写入
		if (pi_data != pi_data_dd0 && data_vld_dd0 == 1'b1) begin
			//从RAM中读出的数据,有一拍的延时,这里保证了数据对齐
			cal_value <= rd_ram_data + cal_pixle;
			cal_value_vld <= 1'b1;
		end
		//一行图像统计结束,将当前结果写入
		else if(pi_data_vld == 1'b0 && data_vld_dd0 == 1'b1)begin
			cal_value <= rd_ram_data + cal_pixle;
			cal_value_vld <= 1'b1;
		end
		else begin
			cal_value <= 'd0;
			cal_value_vld <= 1'b0;
		end
	end
	else begin
		cal_value <= 'd0;
		cal_value_vld <= 1'b0;	
	end
end
//----------------cal_wr_ram_addr/cal_rd_ram_addr------------------
assign cal_wr_ram_addr = pi_data_dd1; 	//写入数据RAM的地址
assign cal_rd_ram_addr = pi_data;		//读出数据RAM的地址

//----------------cal_one_row_done------------------
always @(posedge clk) begin
	if (rst==1'b1) begin
		cal_one_row_done <= 1'b0;
	end
	//一行图像统计完成
	else if (state == CALCULATE && pi_data_vld == 1'b0 && data_vld_dd0 == 1'b1) begin
		cal_one_row_done <= 1'b1;
	end
	else begin
		cal_one_row_done <= 1'b0;
	end
end

//----------------cnt_row------------------
always @(posedge clk) begin
	if (rst == 1'b1) begin
		cnt_row <= 'd0;
	end
	else if (add_cnt_row) begin
		if(end_cnt_row)
			cnt_row <= 'd0;
		else
			cnt_row <= cnt_row + 1'b1;
	end
end

assign add_cnt_row = cal_one_row_done == 1'b1;
assign end_cnt_row = add_cnt_row &&	cnt_row == IMG_HEIGHT - 1;

//==========================================
//during get histogram data state
//==========================================

//----------------get_data_flag------------------
always @(posedge clk) begin
	if (rst==1'b1) begin
		get_data_flag <= 1'b0;
	end
	else if (state == GET_HISTO) begin
		if (end_cnt_get == 1'b1) begin
			get_data_flag <= 1'b0;	
		end
		else begin
			get_data_flag <= 1'b1;
		end
	end
	else begin
		get_data_flag <= 1'b0;
	end
end

//----------------cnt_get------------------
always @(posedge clk) begin
	if (rst == 1'b1) begin
		cnt_get <= 'd0;
	end
	else if (add_cnt_get) begin
		if(end_cnt_get)
			cnt_get <= 'd0;
		else
			cnt_get <= cnt_get + 1'b1;
	end
	else begin
		cnt_get <= 'd0;
	end
end

assign add_cnt_get = get_data_flag == 1'b1;
assign end_cnt_get = add_cnt_get &&	cnt_get == GRAY_LEVEL - 1;

//----------------histo_data_vld------------------
always @(posedge clk) begin
	if (rst==1'b1) begin
		histo_data_vld <= 1'b0;
	end
	else begin
		histo_data_vld <= get_data_flag;
	end
end

assign histo_data = (histo_data_vld) ? rd_ram_data : 'd0 ;

//==========================================
//signals that related to Block RAM
//==========================================
histogram_ram inst_bram_histo (
  	.clka(clk),    // input wire clka
  	.wea(wr_ram_en),      // input wire [0 : 0] wea
  	.addra(wr_ram_addr),  // input wire [7 : 0] addra
  	.dina(wr_ram_data),    // input wire [31 : 0] dina
  	.clkb(clk),    // input wire clkb
  	.addrb(rd_ram_addr),  // input wire [7 : 0] addrb
  	.doutb(rd_ram_data)  // output wire [31 : 0] doutb
);

//----------------wr_ram_addr,wr_ram_data,wr_ram_en------------------
always @(*) begin
	if (state == CLEAR) begin
		wr_ram_addr = cnt_clear;
		wr_ram_en 	= clear_flag;
		wr_ram_data = 'd0;
	end
	else if (state == CALCULATE) begin
		wr_ram_addr = cal_wr_ram_addr;
		wr_ram_en 	= cal_value_vld;
		wr_ram_data = cal_value;
	end
	else begin
		wr_ram_addr = 'd0;
		wr_ram_en 	= 1'b0;
		wr_ram_data = 'd0;
	end
end

//----------------rd_ram_addr------------------
always @(*) begin
	if (state == CALCULATE) begin
		rd_ram_addr = cal_rd_ram_addr;
	end
	else if (state == GET_HISTO) begin
		rd_ram_addr = cnt_get;
	end
	else begin
		rd_ram_addr = 'd0;
	end
end

endmodule

仿真验证

  由于只是算法的一个验证,我并不想使用太多的外部资源,使用片上的存储资源即可。一个2562568bit大小的图像并不会占用多少资源。图像大小是256*256的灰度图,在matlab中完成直方图的统计,是十分简单的,只需使用imhist这个函数即可。
在这里插入图片描述
直方图部分统计结果如下:

在这里插入图片描述
  在modelsim中,对前面所设计的模块进行仿真。仿真的结果如下:
在这里插入图片描述
  可以看到仿真的直方图统计结果与matlab中的仿真结果相比一致。在Modelsim的Memory List中,也可以看到一帧图像统计完成后,RAM中的结果,从结果中可以看到统计结果和matlab一致。
在这里插入图片描述


参考:《基于FPGA的数字图像处理》牟新刚

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FPGA图像处理基础----直方图统计 的相关文章

  • python并行计算(完结篇):并行方法总结

    转自 https zhuanlan zhihu com p 46678895 由于python相当易学易用 现在python也较多地用于有大量的计算需求的任务 本文介绍几个并行模块 以及实现程序并行的入门技术 本文比较枯燥 主要是为后面上工
  • 2023版最新最全React面试题

    React 作为前端使用最多的框架 必然是面试的重点 我们接下来主要从 React 的使用方式 源码层面和周边生态 如 redux react router 等 等几个方便来进行总结 1 使用方式上 这里主要考察的是 在开发使用过程中 对
  • 均匀分布的期望和方差的推导_概率论中均匀分布的数学期望和方差该怎么求啊?...

    展开全部 数学期望是分布区间e68a8462616964757a686964616f31333431343065左右两端和的平均值 方差为分布区间左右两端差值平方的十二分之一 均匀分布是经常遇到的一种分布 其主要特点是 测量值在某一范围中各
  • Ubuntu下安装Matlab步骤

    1 下载matlab iso镜像文件 可以从verycd上下载 搜索matlab unix版可得到 我下的是2010a 2 打开终端 输入sudo mkdir mnt temp 建立临时文件夹存放装载后的iso文件 再输入 sudo mou
  • Come on和我一起做基于深度学习的缺陷检测一(数据准备)

    基于深度学习的织物疵点检测 数据集的制作 数据标注 数据增强 图像和xml文件同时增强 这里有几句话要说 这个项目会持续更新 由于要忙于毕业答辩和论文修改 更新时间不定 由于本人研三 今年毕业要去工作 可能会出现拖更的现象 我把以前Pyth
  • Java从入门到实战总结-3.3、Java的IO处理

    Java从入门到实战总结 3 3 Java的IO处理 文章目录 Java从入门到实战总结 3 3 Java的IO处理 1 java io File 1 类的声明 2 字段 3 类的构造函数 4 类方法 5 示例 2 文件遍历 3 文件过滤器
  • ckplayer 播放视频

    备注 其中引用文件无法上传 如果需要私信即可
  • “GPT+健康医疗”赋能医疗行业“数智化”发展,景联文科技提供高质量医疗数据库

    近日 ChatGPT这个代表着通用版的大型语言模型以其出色的表现在全球互联网上引人注目 它所使用的GPT技术基础为人工智能应用开启了全新的世界 大模型时代已经到来 它已变成基础设施 变成算力 变成生产力 大模型可能有通用技术 但更重要的是如
  • 实体识别和关系抽取的联合模型总结

    实体识别和关系抽取的目标是从非结构化的文本中发现 实体1 关系 实体2 的三元组 它对知识库的构建和问答任务都很重要 是信息抽取的核心问题 现有的关系抽取方法主要有两种 1 使用流水线方法进行抽取 先对句子进行实体识别 然后对识别出的实体两
  • UE常用使用技巧

    UE使用技巧1 如何在行末添加指定字符如 方法 ctrl r 用 p全部替换 n即可 p n 2 如何删除空行 查找 p 替换为空即可 p 空 3 括号自动匹配 Ctrl b4 加书签 Ctrl F2 加书签 Alt F2 在多个书签中进行
  • 调试最长的一帧(第十天)

    依照惯例 先看总体流程 到了更新回调 一边抄一边记忆 OSG更新回调的作用与事件回调有类似之处 由专门的访问器对象 updateVisitor负责场景图形更新遍历 所有的节点和Drawable几何体对象都可以使用setUpdateCallb
  • 数据结构——【堆】

    一 堆的相关概念 1 1 堆的概念 1 堆在逻辑上是一颗完全二叉树 类似于一颗满二叉树只缺了右下角 2 堆的实现利用的是数组 我们通常会利用动态数组来存放元素 这样可以快速拓容也不会很浪费空间 我们是将这颗完全二叉树用层序遍历的方式储存在数
  • 小程序登录授权分析

    登录 小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识 快速建立小程序内的用户体系 在小程序 微信生态体系中 每个用户会有唯一标识的OpenID和UnionID 使用他们可以帮助开发者优化自己的注册和登录逻辑 毕竟 在中
  • the application was unable to start correctly(0x000007b)解决方案

    什麼是錯誤代碼0xc000007b 如果您在Windows 10 8 7中看到 應用程式無法正確啟動 0xc000007b 錯誤 那麼您來對地方了 0xc000007b應用程式錯誤非常常見 與錯誤代碼0x80070002 0x8007005
  • SSL的“四次握手”

    第一次握手 客户端向服务端发送Client Hello报文 该报文中包含了支持的版本信息 加密组件等 加密组建包括加密算法 秘钥长度等内容 第二次握手 这个阶段服务器会向客户端发送三个报文 服务端收到请求后 如果支持SSL通信 会首先以Se

随机推荐

  • SQL Server数据备份

    SQL Server数据库 自动 手动 备份 sql 数据库自动备份 一 为备份文件建一个独立文件夹 sql data autobakup 方便区分 Win R 输入services msc进入服务管理界面查找sqlserver服务 复制此
  • pulseaudio使用过程中遇到的问题

    W pulseaudio main c This program is not intended to be run as root unless system is specified E pulseaudio core util c H
  • Self-study Python Fish-C Note-5 P20-P26 (part2)

    python 中的列表 Part 2 本文主要讲解了python中列表的使用 本文为自学B站上鱼C的python课程随手做的笔记 如有问题 欢迎大家批评指正 原视频链接 https www bilibili com video BV1c44
  • LeetCode算法心得——和可被 K 整除的子数组(前缀和+HashMap)

    大家好 我是晴天学长 同余定理的应用 需要的小伙伴可以关注支持一下哦 后续会继续更新的 1 和可被 K 整除的子数组 题目描述 给定一个整数数组 A 返回其中元素之和可被 K 整除的 连续 非空 子数组的数目 示例 输入 A 4 5 0 2
  • 【极简数据结构】快速了解并实现顺序表,速通玩家的最爱

    顺序表目录 前言 一 线性表 二 顺序表 1 顺序表的概念 2 接口函数 顺序表 初始化 顺序表 尾插 顺序表 打印 顺序表 销毁 顺序表 尾删 顺序表 头插 和 顺序表 扩容 优化顺序表 尾删 顺序表 头删 顺序表 查找 顺序表 任意po
  • Android如何安全的关闭线程

    正常情况下 当线程中的run方法执行完毕后 线程是会自动关闭 不需要我们手动去关闭的 如 new Thread new Runnable Override public void run 执行操作 start 该线程在run方法中的操作执行
  • C语言经典100例题(22)--两个乒乓球队进行比赛,各出三人。甲队为a, b, c三人,乙队为x, y, z三人。已抽签决定//比赛名单,有人向队员打听比赛的名单.a说他不和x比,c说他不和x, z

    目录 题目 问题分析 代码 运行结果 题目 两个乒乓球队进行比赛 各出三人 甲队为a b c三人 乙队为x y z三人 已抽签决定比赛名单 有人向队员打听比赛的名单 a说他不和x比 c说他不和x z比 请编程序找出三队赛手的名单 问题分析
  • linux屏蔽海外流量的两种方法

    方法一 使用大神的开源脚本 屏蔽指定国家地区的IP访问 wget https raw githubusercontent com iiiiiii1 Block IPs from countries master block ips sh s
  • RSA的C++语言描述简单实现

    文章目录 前言 代码仓库 代码特点 大 素 数讨论 部分资料 作者理解 代码 rsa h rsa cpp main cpp 结果 总结 参考资料 作者的话 前言 网络安全中RSA的C 语言描述简单实现 代码仓库 yezhening Prog
  • excel 生成sql

    参考文章 https blog csdn net m0 67695717 article details 127406830 新增语句 INSERT INTO table name column1 column2 VALUES A2 D2
  • 判断一个文件是否为CSV文件的Python代码

    在Python中 我们可以使用os模块的path splitext 函数来获取文件扩展名 然后判断这个扩展名是否为 csv 以下是一个示例代码 import os def is csv file file path file extensi
  • WSL2和Docker for Windows

    文章目录 一 Docker和WSL2概述 二 WSL安装使用 三 基于Docker导入任意WSL分发 参考资料 一 Docker和WSL2概述 Docker 是一个开源的应用容器引擎 让开发者可以打包他们的应用以及依赖包到一个可移植的容器中
  • git中出现“interactive rebase in progress; onto 11dde1e”错误分析与解决方案

    出错原因分析 进行提交前 需提前拉取远程仓库的代码 拉取之后 需要重新add commit 避免仓库的数据被修改 但是再次提交之后会出现上图的错误 原因 是因为你现在正在编辑的提交将要覆盖在 11ddele commited 之前使用过gi
  • 472-I/O阻塞和非阻塞,同步和异步

    阻塞 非阻塞 同步 异步 典型的一次I O的两个阶段是什么 数据准备 和 数据读写 我们作为服务器 接收客户端的请求 得先监听客户端有没有数据过来 这是一个状态 还有就是数据过来了该怎么去读写 这又是一个状态 实际上 阻塞 非阻塞 同步 异
  • 基于51单片机的羽毛球计分器proteus仿真程序设计

    硬件设计 末尾附文件 方案 在像羽毛球这样的竞技比赛中 计分器占着很大的作用 如果我们就只在心里记着双方的比分 显然是不实际的 而且在现在的乒乓球比赛中采用的都是21分制 因此我们不能再用传统的计分方式了 本次课题采用单片机设计了一个羽毛球
  • JetBrains IDE Support 调试工具(页面自动刷新)

    1 谷歌浏览器安装JetBrains IDE Support 插件 2 更改端口 webstorm 和 JetBrains IDE Support 端口不对插件图标会黑 3 debug 4 同步
  • 求定制闲鱼爬虫获取最新发布商品

    闲鱼采集及监控下单软件开发 1 点击宝贝右键打开网页 2 点击宝贝右键拉黑卖家 3 点击宝贝右键清空列表 4 点击宝贝左键显示二维码和主图 5 软件页面显示宝贝二维码 6 软件页面显示宝贝主图 7 软件页面显示检测搜索词及下单宝贝 8 每次
  • 介绍计算机方队,方阵

    f ng zh n 方阵 语音 编辑 锁定 讨论 上传视频 方阵是古代军队作战时采用的一种队形 是把军队在野外开阔地上排列成方形阵式 远古方阵由前军 中军和后军相互嵌套排列而成 方阵平面呈现 回 字形状 反映出远古观念中的一种政治地理结构
  • Java丨JVM虚拟机与类加载器

    一丶JVM 虚拟机介绍 Sun HotSpot VM 这个目前看起来 血统纯正 的虚拟机在最初并非由Sun公司开发 而是由一家名为 Longview Technologies 的小公 司设计的 甚至这个虚拟机最初并非是为Java语言而开发的
  • FPGA图像处理基础----直方图统计

    直方图统计的原理 直方图统计从数学上来说 是对图像中的像素点进行统计 图像直方图统计常用于统计灰度图像 表示图像中各个灰度级出现的次数或者概率 统计直方图的实现采用C C 或者其他高级语言实现十分简单 单采用FPGA来实现直方图的统计就稍显