python-串口助手(OV7670图传)

代码

主python文件

import serial
import serial.tools.list_ports
import time
import tkinter as tk
from tkinter import ttk
import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import threading
from queue import Queue
from PIL import Image, ImageTk
import tkinter as tk
import LightSwitch
import tkinter as tk
from datetime import datetime
import cv2 as cv
import cv2
import numpy as np
import os
'''
智能红绿灯上位机和MCU通信协议:
MCU->上位机 0x01 0xfe ...(320*240*2)BYTE...0xfe 0x01
上位机->MCU 0x02 0xff 0xXX 0xXX 0xXX 0xXX 0xff 0x02
字节2:高5bit传输当前系统时间0h-23h;低3bit传输时间增减标志位(0非深夜和高峰模式 1高峰模式  2深夜模式)
字节3:按钮值(0无按键 1按键+   2按键-   3按键切换灯)
字节4:0空闲(识别关闭);如果无按键和深夜或者高峰模式(判断标志位),当接收到图像数据后进行识别,否则接收到的图像数据丢弃,若图片中方形白色>20个,高4bit发送绿灯增加5s标志位1;当白色方块0<白色方块数<20,正常计时标志2(也为默认开启值);当白色方形==0,发送下次红灯长红标志位3。
字节5:识别到的车辆数量
'''
# 初始化窗口和控件
window = tk.Tk()
window.title('智能红绿灯串口助手')
window.geometry('900x600+200+100')
serialName = []#串口名称
ser = serial.Serial()  # 串口实例对象def opencom(*args):if not ser.is_open:ser.open()setbaudrate()setPort()setstop()setShujv()setcheck()if ser.is_open:print(f"串口已打开")light.turn_on()def closecom(*args):if ser.is_open:ser.close()if not ser.is_open:print(f"串口已关闭")light.turn_off()def clearreceive(*args):t0.delete(1.0, 'end')def send(*args):passdef hex_string_to_byte_list(hex_str):if len(hex_str) % 2 != 0:raise ValueError("Hex string length must be even.")return [int(hex_str[i:i+2], 16) for i in range(0, len(hex_str), 2)]Str_Get_List = []#存储接收到的Hex字符串转成的十六进制字节列表
Get_Picture_List = [] #存储图像数据
PackHead = [1,254]
PackEnd = [254,1]
PackHeadGetFlag = False
PackGetFlag = False
Picture_ByteLen = 320*240*2+4
lock = threading.Lock()# 创建一个线程锁
rgb_array = []#存储RGB888转换的数组数据,用于保存图片
SendData = [0x02,0xff,0x00,0x00,0x00,0x00,0xff,0x02]#存储发送数据包
IdentificationCount = 0 #图像识别数量
def showdata(*args):global Str_GetStringglobal Str_Get_Listglobal PackHeadGetFlagglobal PackGetFlagwhile not stop_event.is_set():if ser.is_open:try:try:with lock:  # 使用锁确保线程安全s = ser.read_all()  # 获取字节对象if s:sHex = s.hex()  # 获取Hex字符串 ,2个字符表示一个十六进制1字节t0.delete("1.0", tk.END)t0.insert('end', sHex)t0.see('end')  # 自动滚动到最新接收到的数据# Str_Get_List = Str_Get_List.append(hex_string_to_byte_list(sHex))# print(sHex,len(Str_Get))#获取数据列表sHexList = hex_string_to_byte_list(sHex)for i in sHexList:Str_Get_List.append(i)#处理数据和发送相关数据包if Hour_CarFlag ==0:pictureDataDispose()else:print("特殊模式,摄像头不启用")#情况接收到的数据Str_Get_List = []except Exception as e:print(f"Unexpected error: {e}")except serial.SerialException as e:print(f"Error reading from serial port: {e}")except Exception as e:print(f"Unexpected error: {e}")else:passdef pictureDataDispose(*args):global PackHeadGetFlagglobal Get_Picture_Listglobal Picture_ByteLenglobal PackHeadglobal Str_Get_Listglobal rgb_array#print(Str_Get_List)if not PackHeadGetFlag:#未接收到包头index_Str_Get_List = find_sublist(Str_Get_List,PackHead)if index_Str_Get_List!=-1:Get_Picture_List = Str_Get_List[index_Str_Get_List:]PackHeadGetFlag = Trueprint(f"Element {PackHead} found at index {index_Str_Get_List}")else:print(f"Element {PackHead} not found")else:Get_Picture_List.extend(Str_Get_List)#添加所有元素到尾部if len(Get_Picture_List) >= Picture_ByteLen:Get_Picture_List_PackEnd = Get_Picture_List[Picture_ByteLen-2:Picture_ByteLen]index_PackEnd = find_sublist(Get_Picture_List_PackEnd,PackEnd)if index_PackEnd==0:print("接收到一帧图片数据",print(len(Get_Picture_List)))PictureData = Get_Picture_List[2:Picture_ByteLen-2]# 转换图像数据rgb565_values = [(PictureData[i] << 8 | PictureData[i + 1]) for i in range(0, len(PictureData), 2)]rgb888_values = [rgb565_to_rgb888(val) for val in rgb565_values]#print(rgb888_values, len(rgb888_values), len(rgb565_values))update_image(rgb888_values)# 将RGB数据转换为numpy数组,并调整其形状以匹配图像尺寸和通道数(高度, 宽度, 通道)rgb_array = np.array(rgb888_values).reshape((240, 320, 3))#print(rgb_array)SavePicture(rgb_array)PictureIdentification()#---------------------处理第二帧图片包头Get_Picture_List = []PackHeadGetFlag = Falseelse:Get_Picture_List = []PackHeadGetFlag = Falsedef PictureIdentification(*args):global IdentificationCountimg = cv.imread('./image/2.jpg')# cv_show('img', img)#print(img)HSV = cv.cvtColor(img, cv.COLOR_BGR2HSV)  # 转换图像lowerColor = np.array([0, 0, 200])  # 设置最低阈值  np.array([Hmin, Smin, Vmin])upperColor = np.array([180, 20, 255])  # 设置最高阈值# 因为要保留的就是白色区域,因此根据白色阈值填入,提取白色部分(指定区域变白,其他变黑)binary = cv.inRange(HSV, lowerColor, upperColor)#print(binary)# 运用中值滤波去除噪声median = cv.medianBlur(binary, 9)# 显示二值图#cv_show('median', median)  # 这里是我自己写的cv_show()函数,函数声明可放开头contours, hierachy = cv.findContours(median, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE)# 后两个为轮廓检索模式和轮廓逼近模式res = cv.drawContours(img, contours, -1, (0, 0, 255), 4)#cv_show('res', res)# 4、原图白色中心点L = len(contours)  # contours轮廓数据是数组,因此用len()测数组长度,为了循环画点使用IdentificationCount = L#识别白色块的数量for i in range(L):cnt = contours[i]  # cnt表示第i个白色快的轮廓信息(x, y), radius = cv.minEnclosingCircle(cnt)  # 得到白色块外接圆的圆心坐标和半径center = (int(x), int(y))  # 画center圆心时。x,y必须是整数# 标出中心点img2 = cv.circle(img, center, 3, (0, 0, 255), 5)  # 传入圆心信息,并画在原图上print(center)  # 输出各个中心点# 显示有中心点的图像#cv_show("frame", img2)  # 展示花了中心点的魔方图# 写一个显示函数
def cv_show(name, img):cv.imshow(name, img)cv.waitKey(0)cv.destroyAllWindows()def SavePicture(*args):global rgb_array# 检查并创建保存图像的目录(如果不存在)output_dir = './image'os.makedirs(output_dir, exist_ok=True)# 图像保存路径output_path = os.path.join(output_dir, '2.jpg')# 使用OpenCV将RGB图像保存为JPEG格式cv2.imwrite(output_path, rgb_array[:, :, ::-1])  # 注意这里对颜色通道进行了转换(BGR到RGB)print(f"Image saved successfully at {output_path}")# def dispose_LastData(*args):
#     global PackHeadGetFlag
#     global Get_Picture_List
#     global Picture_ByteLen
#     global PackHead
#
#     if len(Get_Picture_List[Picture_ByteLen:]) >= 2:
#         Get_Picture_List_last = Get_Picture_List[Picture_ByteLen:]  # 保留剩下的数据
#         index_Str_Get_List = find_sublist(Get_Picture_List_last, PackHead)  # 判断剩下的数据
#         if index_Str_Get_List != -1:
#             Get_Picture_List = Get_Picture_List_last[index_Str_Get_List:]
#             print(f"Element {PackHead} found at index {index_Str_Get_List}")
#         else:
#             print(f"Element {PackHead} not found")
#             Get_Picture_List = []
#             PackHeadGetFlag = False
#             print(f"剩余非图片数据")
#     else :
#         Get_Picture_List = []
#         PackHeadGetFlag = Falsedef update_image(rgb888_data):"""更新Canvas显示图像"""image = Image.new('RGB', (320, 240))image.putdata(rgb888_data)tk_image = ImageTk.PhotoImage(image)# 保持图像引用if hasattr(canvas, 'image'):canvas.image = tk_imageelse:canvas.image = tk_imagecanvas.create_image(0, 0, anchor="nw", image=tk_image)print("图像已更新")def rgb565_to_rgb888(rgb565):"""将单个RGB565值转换为RGB888元组"""# 提取红色部分 (5位),并将其从5位扩展到8位r = (rgb565 & 0xF800) >> 11r = int(r * 255 / 31)# 提取绿色部分 (6位),并将其从6位扩展到8位g = (rgb565 & 0x07E0) >> 5g = int(g * 255 / 63)# 提取蓝色部分 (5位),并将其从5位扩展到8位b = rgb565 & 0x001Fb = int(b * 255 / 31)return (r, g, b)# 设置串口参数
def setPort(*args):ser.port = comboxlist0.get()# 获取可用串口列表
port_list = list(serial.tools.list_ports.comports())
for port in port_list:serialName.append(port[0])def closethread(*args):while ser.is_open:ser.close()if not ser.is_open:breakwhile not ser.is_open:print(f"串口已关闭")stop_event.set()stop_event1.set()stop_event2.set()if stop_event.is_set() and stop_event1.is_set() and stop_event2.is_set():breakwhile stop_event2.is_set():print(f"时间线程等待stop_event2事件关闭")th2.join()if not th2.is_alive():breakwhile stop_event1.is_set():print(f"时间线程等待stop_event1事件关闭")th1.join()if not th1.is_alive():breakwhile stop_event.is_set():print(f"串口线程等待stop_event事件关闭")th0.join()window.quit()if not th0.is_alive():breakdef printfData(*args):if not ser.is_open:print("串口未打开")returnser.write(SendData)def find_sublist(main_list, sub_list):"""查找子列表在主列表中的位置"""len_main, len_sub = len(main_list), len(sub_list)if len_sub == 0 or len_main < len_sub:return -1for i in range(len_main - len_sub + 1):if main_list[i:i+len_sub] == sub_list:return ireturn -1# 设置串口参数
def setPort(*args):ser.port = comboxlist0.get()def setbaudrate(*args):while True:baudrate = int(comboxlist1.get())ser.baudrate = baudrateif ser.baudrate == baudrate:breakdef setShujv(*args):ser.bytesize = int(comboxlist2.get())check = {"N": serial.PARITY_NONE, "E": serial.PARITY_EVEN, "O": serial.PARITY_ODD}
def setcheck(*args):ser.parity = check[comboxlist3.get()]stop = {"1": serial.STOPBITS_ONE, "1.5": serial.STOPBITS_ONE_POINT_FIVE, "2": serial.STOPBITS_TWO}
def setstop(*args):ser.stopbits = stop[comboxlist4.get()]# 获取当前系统时间的小时并更新 Label
def get_current_hour():global current_hourglobal Hour_CarFlag# 获取当前时间now = datetime.now()# 提取小时(0-23)current_hour = now.hour# 更新 Label 的文本label6.config(text = f"{now}")label8.config(text=f"{IdentificationCount}")#当前时间对应模式和标志位判断'''current_hour其他时间 : 0 正常模式(使用摄像头功能)7-9 and 16-18 : 1 ,早晚高峰,绿灯增加10s22-23 and 0-3 : 2 ,深夜模式,红灯时间变为20s'''if (current_hour>=7 and current_hour<=9)or(current_hour>=16 and current_hour<=18):Hour_CarFlag = 1elif (current_hour>=22 and current_hour<=23)or(current_hour>=0 and current_hour<=3):Hour_CarFlag = 2else:Hour_CarFlag = 0current_hour = 0 #当前h
Hour_CarFlag = 0 #模式标志位 0正常模式(使用摄像头)  1早晚高峰模式  2深夜模式
#th1线程
def TimeShow(*args):while not stop_event1.is_set():get_current_hour()time.sleep(0.5)#th2线程
def SendDatathread(*args):global SendDataglobal current_hourglobal IdentificationCountwhile not stop_event2.is_set():time.sleep(1)#1s发送1次数据#修改发送的数据if Hour_CarFlag == 0:#正常模式if IdentificationCount==0:SendData[4] = 3 #下次红灯停止计数标志elif IdentificationCount >= 20:SendData[4] = 1 #车多,绿灯增加5s标志位,正常计时elif IdentificationCount > 0 and IdentificationCount < 20:SendData[4] = 2 #正常计时标志位elif Hour_CarFlag == 1:#高峰模式SendData[4] = 0 #摄像头失能  正常计时IdentificationCount = 0 #识别车辆数清零elif Hour_CarFlag == 2:#夜间模式SendData[4] = 0 #摄像头失能  正常计时IdentificationCount = 0 #识别车辆数清零SendData[2] = ((current_hour<<3)&0xff)+Hour_CarFlagSendData[3] = 0 #按键清空,方式按键事件重复SendData[5] = IdentificationCount #备用 当前采集车辆#发送if not ser.is_open:print("串口未打开")else:ser.write(SendData)print(SendData)#信号灯时间增点击事件
def LightTimeIncrease(*args):global SendData'''SendData[3]无按键:0当前灯时间增加:1  当前信号灯增加10s 最大99s当前灯时间减少:2  当前信号灯减少10s 最小5s切换灯:3  当前信号灯变为5s'''SendData[3] = 1  # 按键清空ser.write(SendData)SendData[3] = 0  # 按键清空#信号灯时间减点击事件
def LightTimeDecrease(*args):SendData[3] = 2  # 按键清空ser.write(SendData)SendData[3] = 0  # 按键清空#信号灯切换点击事件
def SwihchOver(*args):SendData[3] = 3  # 按键清空ser.write(SendData)SendData[3] = 0  # 按键清空# 创建文本控件和下拉列表控件
label0 = tk.Label(window, text='串口', font=10)
label0.place(y=40, x=50)
label1 = tk.Label(window, text='波特率', font=10)
label1.place(y=70, x=50)
label2 = tk.Label(window, text='数据位', font=10)
label2.place(y=100, x=50)
label3 = tk.Label(window, text='校验位', font=10)
label3.place(y=130, x=50)
label4 = tk.Label(window, text='停止位', font=10)
label4.place(y=160, x=50)
label5 = tk.Label(window, text='时间:', font=10)
label5.place(y=5, x=350)
label6 = tk.Label(window, text='XXXX', font=10)
label6.place(y=5, x=420)
label7 = tk.Label(window, text='车辆:', font=10)
label7.place(y=5, x=700)
label8 = tk.Label(window, text='XXXX', font=10)
label8.place(y=5, x=770)comvalue0 = tk.StringVar()
comboxlist0 = ttk.Combobox(window, textvariable=comvalue0)
comboxlist0["values"] = tuple(serialName)
comboxlist0.bind("<<ComboboxSelected>>", setPort)
comboxlist0.place(y=40, x=150)#波特率下拉框
comvalue1 = tk.StringVar()
comboxlist1 = ttk.Combobox(window, textvariable=comvalue1)
comboxlist1["values"] = (1200, 2400, 4800, 9600, 14400, 19200, 115200, 256000)
comboxlist1.current(7)
comboxlist1.bind("<<ComboboxSelected>>", setbaudrate)
comboxlist1.place(y=70, x=150)#数据位下拉框
comvalue2 = tk.StringVar()
comboxlist2 = ttk.Combobox(window, textvariable=comvalue2)
comboxlist2["values"] = ("8", "7", "6", "5")
comboxlist2.current(0)
comboxlist2.bind("<<ComboboxSelected>>", setShujv)
comboxlist2.place(y=100, x=150)#校验位下拉框
comvalue3 = tk.StringVar()
comboxlist3 = ttk.Combobox(window, textvariable=comvalue3)
comboxlist3["values"] = ("N", "E", "O")
comboxlist3.current(0)
comboxlist3.bind("<<ComboboxSelected>>", setcheck)
comboxlist3.place(y=130, x=150)#停止位下拉框
comvalue4 = tk.StringVar()
comboxlist4 = ttk.Combobox(window, textvariable=comvalue4)
comboxlist4["values"] = ("1", "1.5", "2")
comboxlist4.current(0)
comboxlist4.bind("<<ComboboxSelected>>", setstop)
comboxlist4.place(y=160, x=150)b4 = tk.Button(window, text='关闭线程', width=35, height=1, command=closethread)
b4.place(y=0, x=0)
b0 = tk.Button(window, text='打开串口', width=35, height=1, command=opencom)
b0.place(y=190, x=50)
light = LightSwitch.BooleanLight(window, size=35, x=10, y=190)#串口连接状态显示灯b1 = tk.Button(window, text='清除接收', width=35, height=1, command=clearreceive)
b1.place(y=250, x=50)
b2 = tk.Button(window, text='关闭串口', width=35, height=1, command=closecom)
b2.place(y=220, x=50)
e0 = tk.Entry(window, show=None, width=35)
e0.place(y=290, x=50)
b5 = tk.Button(window, text='Send', width=35, height=1, command=send)
b5.place(y=320, x=50)
t0 = tk.Text(window, width=65, height=3)
t0.place(y=50, x=350)
b6 = tk.Button(window, text='输出接收到的数据-测试按钮', width=35, height=1, command=printfData)
b6.place(y=350, x=50)
b6 = tk.Button(window, text='当前信号灯时间+', width=35, height=1, command=LightTimeIncrease)
b6.place(y=380, x=50)
b6 = tk.Button(window, text='当前信号灯时间-', width=35, height=1, command=LightTimeDecrease)
b6.place(y=410, x=50)
b6 = tk.Button(window, text='切换信号灯', width=35, height=1, command=SwihchOver)
b6.place(y=440, x=50)
label5 = tk.Label(window, text='Canvas', font=10)
label5.place(y=100, x=350)
# 图像参数
canvas = tk.Canvas(window,width=320, height=240,bg='#{:02x}{:02x}{:02x}'.format(*(255,255,255)),bd=1,highlightthickness=1,relief="groove")
canvas.place(x=420, y=125)if __name__ == '__main__':stop_event = threading.Event()  #等待线程th0停止事件stop_event1 = threading.Event()  # 等待线程th1停止事件stop_event2 = threading.Event()  # 等待线程th2停止事件th0 = threading.Thread(target=showdata)th0.start()th1 = threading.Thread(target=TimeShow)th1.start()th2 = threading.Thread(target=SendDatathread)th2.start()window.mainloop()

 从文件,同目录下LightSwitch.py

import tkinter as tk
class BooleanLight(tk.Canvas):def __init__(self, master=None, size=50, x=0, y=0):super().__init__(master, width=size, height=size)self.pack()self.place(x=x, y=y)self.size = sizeself.is_light_on = False  # 初始状态为关闭# 创建初始的圆形表示灯的状态self.light = self.create_oval(5, 5, size - 5, size - 5, fill="gray")def turn_on(self):"""打开灯"""self.itemconfig(self.light, fill="green")self.is_light_on = Truedef turn_off(self):"""关闭灯"""self.itemconfig(self.light, fill="gray")self.is_light_on = Falsedef toggle(self):"""切换灯的状态"""if self.is_light_on:self.turn_off()else:self.turn_on()

 完成功能

  1. tk、ttk基础的UI界面建立,并建立相关列表和按钮的电机事件方法。
  2. 选择串口参数,每次打开时自动获取串口端口列表,可以选择后在进行连接(显示连接成功)。
  3. 通过多线程,串口接收数据,十六进制字节对象字符串显示。按钮发送输入框内容(有函数但是目前没写,可以自己写,比较简单)。
  4. 建立3个线程(和三个线程关闭事件,防止线程异常不能正确结束导致的死循环),分别用来接收数据包、发送数据包、更新界面显示内容。
  5. 根据接收的数据包,在canvas进行图像显示(先将获取的RGB565数据转换为RGB888,数据进行保存成图片保存在文件夹中、然后从文件夹内读出,进行HSV处理,阈值化处理,边框圈出,计算白色内容数量)。
  6. 实时显示系统时间和接收数据包图像采集的车辆数量。
  7. 手动关闭线程,每次点击关闭线程来关闭应用,确保线程彻底关闭。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/72591.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

筑牢网络安全防线:守护您的数据安全

在数字化时代&#xff0c;数据安全已成为企业和个人不容忽视的重要议题。近日印尼国家数据中心遭黑客袭击的事件&#xff0c;不仅扰乱了机场的移民检查&#xff0c;还影响了众多机构的服务运行。黑客利用恶意软件对数据中心进行攻击&#xff0c;索要巨额赎金&#xff0c;给印尼…

Vue 3 整合 WangEditor 富文本编辑器:从基础到高级实践

本文将详细介绍如何在 Vue 3 项目中集成 WangEditor 富文本编辑器&#xff0c;实现图文混排、自定义扩展等高阶功能。 一、为什么选择 WangEditor&#xff1f; 作为国内流行的开源富文本编辑器&#xff0c;WangEditor 具有以下优势&#xff1a; 轻量高效&#xff1a;压缩后仅…

FastGPT 引申:信息抽取到知识图谱的衔接流程

文章目录 信息抽取到知识图谱的衔接流程步骤1&#xff1a;原始信息抽取结果步骤2&#xff1a;数据标准化处理&#xff08;Python示例&#xff09;步骤3&#xff1a;Cypher代码动态生成&#xff08;Python驱动&#xff09; 关键衔接逻辑说明1. 唯一标识符生成规则2. 数据映射策略…

Webshell 入侵与防御全攻略

Webshell&#xff0c;是指攻击者上传到网站的远程控制后门&#xff0c;允许黑客像管理员一样远程控制网站&#xff0c;执行恶意命令&#xff0c;甚至完全接管网站。本文将带你深入了解 Webshell 的入侵方式以及相应的防御措施&#xff0c;帮助你加固自己的网站防线。 什么是 W…

NL2SQL-基于Dify+阿里通义千问大模型,实现自然语音自动生产SQL语句

本文基于Dify阿里通义千问大模型&#xff0c;实现自然语音自动生产SQL语句功能&#xff0c;话不多说直接上效果图 我们可以试着问他几个问题 查询每个部门的员工数量SELECT d.dept_name, COUNT(e.emp_no) AS employee_count FROM employees e JOIN dept_emp de ON e.emp_no d…

双链路提升网络传输的可靠性扩展可用带宽

为了提升网络传输的可靠性或增加网络可用带宽&#xff0c; 通常使用双链路冗余备份或者双链路聚合的方式。 本文介绍几种双链路网络通信的案例。 5GWiFi冗余传输 双Socket绑定不同网络接口&#xff1a;通过Android的ConnectivityManager绑定5G蜂窝网络和WiFi的Socket连接&…

Ubuntu22.04安装Ollama部署DeepSeek-R1:32B模型

一、环境准备 1.硬件要求 GPU: 至少 NVIDIA A30/A100 (显存 ≥ 24GB)内存: ≥ 64GB RAM存储: ≥ 100GB 可用空间 (模型文件约 60GB)2.软件依赖 # 验证NVIDIA驱动 nvidia-smi二、Ollama安装 方法 1:install.sh安装 运行一下安装命令: curl -fsSL https://ollama.com/inst…

LeetCode 解题思路 10(Hot 100)

解题思路&#xff1a; 上边&#xff1a; 从左到右遍历顶行&#xff0c;完成后上边界下移&#xff08;top&#xff09;。右边&#xff1a; 从上到下遍历右列&#xff0c;完成后右边界左移&#xff08;right–&#xff09;。下边&#xff1a; 从右到左遍历底行&#xff0c;完成后…

Checkpoint 模型与Stable Diffusion XL(SDXL)模型的区别

Checkpoint 模型与 Stable Diffusion XL&#xff08;SDXL&#xff09;模型 在功能、架构和应用场景上有显著区别&#xff0c;以下是主要差异的总结&#xff1a; 1. 基础架构与定位 Checkpoint 模型 是基于 Stable Diffusion 官方基础模型&#xff08;如 SD 1.4/1.5&#xff09;…

GCC RISCV 后端 -- C语言语法分析过程

在 GCC 编译一个 C 源代码时&#xff0c;先会通过宏处理&#xff0c;形成 一个叫转译单元&#xff08;translation_unit&#xff09;&#xff0c;接着进行语法分析&#xff0c;C 的语法分析入口是 static void c_parser_translation_unit(c_parser *parser); 接着就通过类似递…

第十五届蓝桥杯Scratch12月stema选拔赛真题—消失的水母

消失的水母 编程实现&#xff1a; 消失的水母。&#xff08;角色、背景非源素材&#xff09; 具体要求&#xff1a; 1、每次点击绿旗&#xff0c;水母说“请输入 2&#xff5e;10 的整数”&#xff0c;同时在舞台下方显示输入框&#xff0c;如图所示; 完整题目可点击下方链…

Redis设计与实现-数据结构

Redis数据结构 1、RedisObject对象2、简单动态字符串2.1 SDS定义2.2 SDS与C语言的区别2.3 SDS的空间分配策略2.3.1 空间预分配2.3.2 惰性空间释放 2.4 SDS的API 3、链表3.1 链表的定义3.2 链表的API 4、字典4.1 字典的定义4.2 哈希算法4.3 哈希表的扩缩4.3.1 哈希表扩缩的判断依…

由麻省理工学院计算机科学与人工智能实验室等机构创建低成本、高效率的物理驱动数据生成框架,助力接触丰富的机器人操作任务

2025-02-28&#xff0c;由麻省理工学院计算机科学与人工智能实验室&#xff08;CSAIL&#xff09;和机器人与人工智能研究所的研究团队创建了一种低成本的数据生成框架&#xff0c;通过结合物理模拟、人类演示和基于模型的规划&#xff0c;高效生成大规模、高质量的接触丰富型机…

RK3588开发笔记-fiq_debugger: cpu 0 not responding, reverting to cpu 3问题解决

目录 前言 一、FIQ Debugger介绍 二、rockchip平台配置方法 三、问题分析定位 IRQF_NOBALANCING 的含义 总结 前言 在进行 RK3588 开发的过程中,我们可能会遇到各种棘手的问题。其中,“fiq_debugger: cpu 0 not responding, reverting to cpu 3” 这个错误出现在RK3588的…

计算机视觉|ViT详解:打破视觉与语言界限

一、ViT 的诞生背景 在计算机视觉领域的发展中&#xff0c;卷积神经网络&#xff08;CNN&#xff09;一直占据重要地位。自 2012 年 AlexNet 在 ImageNet 大赛中取得优异成绩后&#xff0c;CNN 在图像分类任务中显示出强大能力。随后&#xff0c;VGG、ResNet 等深度网络架构不…

SpringTask 引起的错误

SpringTask 引起的错误 1. 场景 在使用 SpringBoot 编写后台程序时&#xff0c;当在浏览器页面中发起请求时&#xff0c;MP 自动填充来完成一些字段的填充&#xff0c;例如创建时间、创建人、更新时间、更新人等。但是当编写微信小程序时&#xff0c;由于一些字段无法进行自动…

FPGA学习篇——Verilog学习4

1.1 结构语句 结构语句主要是initial语句和always语句&#xff0c;initial 语句它在模块中只执行一次&#xff0c;而always语句则不断重复执行&#xff0c;以下是一个比较好解释的图: (图片来源于知乎博主罗成&#xff0c;画的很好很直观&#xff01;) 1.1.1 initial语句 ini…

【Linux】【网络】UDP打洞-->不同子网下的客户端和服务器通信(未成功版)

【Linux】【网络】UDP打洞–>不同子网下的客户端和服务器通信&#xff08;未成功版&#xff09; 上次说基于UDP的打洞程序改了五版一直没有成功&#xff0c;要写一下问题所在&#xff0c;但是我后续又查询了一些资料&#xff0c;成功实现了&#xff0c;这次先写一下未成功的…

【Python编程】高性能Python Web服务部署架构解析

一、FastAPI 与 Uvicorn/Gunicorn 的协同 1. 开发环境&#xff1a;Uvicorn 直接驱动 作用&#xff1a;Uvicorn 作为 ASGI 服务器&#xff0c;原生支持 FastAPI 的异步特性&#xff0c;提供热重载&#xff08;--reload&#xff09;和高效异步请求处理。 启动命令&#xff1a; u…

前端权限流程(基于rbac实现思想)

1. 权限控制 1.1. 实现思想 基于rbac权限控制思想实现&#xff0c;给用户分配角色&#xff0c;给角色分配权限 给用户分配角色业务 注意&#xff1a;上方图片是个示例图&#xff0c;代表给用户分配职位(角色)&#xff0c;页面中使用了Element-plus的el- checkbox组件…