当前位置: 首页 > news >正文

【Python】基于OpenCV人脸追踪、手势识别控制的求生之路FPS游戏操作

【Python】基于OpenCV人脸追踪、手势识别控制的求生之路FPS游戏操作

文章目录

  • 手势识别
  • 人脸追踪
  • 键盘控制
  • 整体代码
  • 附录:列表的赋值类型和py打包
    • 列表赋值
      • BUG复现
      • 代码改进
      • 优化
      • 总结
    • py打包

视频:

基于OpenCV人脸追踪、手势识别控制的求实之路FPS游戏操作

手势识别

采用MediaPipe模块来完成手势识别 同时通过计算各个关键点与手掌平面的角度来判断手指是否弯曲、伸展
在这里插入图片描述
如上图为各个关键点的ID序号

比如蜘蛛侠手势:

 elif (angle_list[0]<thr_angle_s)  and (angle_list[1]<thr_angle_s) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]<thr_angle_s):gesture_str = "Spider-Man"

就是判断拇指 食指 小指伸展 其他闭合

在这里插入图片描述
【优秀课设】基于OpenCV+MediaPipe的手势识别(数字、石头剪刀布等手势识别)

def vector_2d_angle(v1,v2):'''求解二维向量的角度'''v1_x=v1[0]v1_y=v1[1]v2_x=v2[0]v2_y=v2[1]try:angle_= math.degrees(math.acos((v1_x*v2_x+v1_y*v2_y)/(((v1_x**2+v1_y**2)**0.5)*((v2_x**2+v2_y**2)**0.5))))except:angle_ =65535.if angle_ > 180.:angle_ = 65535.return angle_def hand_angle(hand_):'''获取对应手相关向量的二维角度,根据角度确定手势'''angle_list = []#---------------------------- thumb 大拇指角度angle_ = vector_2d_angle(((int(hand_[0][0])- int(hand_[2][0])),(int(hand_[0][1])-int(hand_[2][1]))),((int(hand_[3][0])- int(hand_[4][0])),(int(hand_[3][1])- int(hand_[4][1]))))angle_list.append(angle_)#---------------------------- index 食指角度angle_ = vector_2d_angle(((int(hand_[0][0])-int(hand_[6][0])),(int(hand_[0][1])- int(hand_[6][1]))),((int(hand_[7][0])- int(hand_[8][0])),(int(hand_[7][1])- int(hand_[8][1]))))angle_list.append(angle_)#---------------------------- middle 中指角度angle_ = vector_2d_angle(((int(hand_[0][0])- int(hand_[10][0])),(int(hand_[0][1])- int(hand_[10][1]))),((int(hand_[11][0])- int(hand_[12][0])),(int(hand_[11][1])- int(hand_[12][1]))))angle_list.append(angle_)#---------------------------- ring 无名指角度angle_ = vector_2d_angle(((int(hand_[0][0])- int(hand_[14][0])),(int(hand_[0][1])- int(hand_[14][1]))),((int(hand_[15][0])- int(hand_[16][0])),(int(hand_[15][1])- int(hand_[16][1]))))angle_list.append(angle_)#---------------------------- pink 小拇指角度angle_ = vector_2d_angle(((int(hand_[0][0])- int(hand_[18][0])),(int(hand_[0][1])- int(hand_[18][1]))),((int(hand_[19][0])- int(hand_[20][0])),(int(hand_[19][1])- int(hand_[20][1]))))angle_list.append(angle_)return angle_listdef h_gesture(angle_list):'''# 二维约束的方法定义手势# fist five gun love one six three thumbup yeah'''thr_angle = 65.  #手指闭合则大于这个值(大拇指除外)thr_angle_thumb = 53.  #大拇指闭合则大于这个值thr_angle_s = 49.  #手指张开则小于这个值gesture_str = "Unknown"if 65535. not in angle_list:if (angle_list[0]>thr_angle_thumb) and (angle_list[1]>thr_angle) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]>thr_angle):gesture_str = "0"elif (angle_list[0]>thr_angle_thumb)  and (angle_list[1]<thr_angle_s) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]>thr_angle):gesture_str = "1"elif (angle_list[0]>thr_angle_thumb)  and (angle_list[1]<thr_angle_s) and (angle_list[2]<thr_angle_s) and (angle_list[3]>thr_angle) and (angle_list[4]>thr_angle):gesture_str = "2"elif (angle_list[0]>thr_angle_thumb)  and (angle_list[1]<thr_angle_s) and (angle_list[2]<thr_angle_s) and (angle_list[3]<thr_angle_s) and (angle_list[4]>thr_angle):gesture_str = "3"elif (angle_list[0]>thr_angle_thumb) and (angle_list[1]<thr_angle_s) and (angle_list[2]<thr_angle_s) and (angle_list[3]<thr_angle_s) and (angle_list[4]<thr_angle_s):gesture_str = "4"elif (angle_list[0]<thr_angle_s) and (angle_list[1]<thr_angle_s) and (angle_list[2]<thr_angle_s) and (angle_list[3]<thr_angle_s) and (angle_list[4]<thr_angle_s):gesture_str = "5"elif (angle_list[0]<thr_angle_s)  and (angle_list[1]>thr_angle) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]<thr_angle_s):gesture_str = "6"elif (angle_list[0]<thr_angle_s)  and (angle_list[1]<thr_angle_s) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]>thr_angle):gesture_str = "8"elif (angle_list[0]>thr_angle_thumb) and (angle_list[1]>thr_angle) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]<thr_angle_s):gesture_str = "Pink Up"elif (angle_list[0]<thr_angle_s)  and (angle_list[1]>thr_angle) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]>thr_angle):gesture_str = "Thumb Up"elif (angle_list[0]>thr_angle_thumb) and (angle_list[1]>thr_angle) and (angle_list[2]<thr_angle_s) and (angle_list[3]>thr_angle) and (angle_list[4]>thr_angle):gesture_str = "Fuck"elif (angle_list[0]>thr_angle_thumb) and (angle_list[1]>thr_angle) and (angle_list[2]<thr_angle_s) and (angle_list[3]<thr_angle_s) and (angle_list[4]<thr_angle_s):gesture_str = "Princess"elif (angle_list[0]<thr_angle_s)  and (angle_list[1]<thr_angle_s) and (angle_list[2]<thr_angle_s) and (angle_list[3]>thr_angle) and (angle_list[4]>thr_angle):gesture_str = "Bye"elif (angle_list[0]<thr_angle_s)  and (angle_list[1]<thr_angle_s) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]<thr_angle_s):gesture_str = "Spider-Man"elif (angle_list[0]>thr_angle_thumb)  and (angle_list[1]<thr_angle_s) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]<thr_angle_s):gesture_str = "Rock'n'Roll"return gesture_strdef hand_detect():global qglobal kill_all_flagglobal cam_imgbye_flag = 0bye_time = time.time()hand_jugg = Nonegesture_str = Nonewhile True:time.sleep(0.1)while q==0:time.sleep(0.1)frame = cv2.cvtColor(cam_img, cv2.COLOR_BGR2RGB)results = hands.process(frame)if results.multi_handedness:                for hand_label in results.multi_handedness:hand_jugg=str(hand_label).split('"')[1]+" Hand"print(hand_jugg)
#                    cv2.putText(faceImg,hand_jugg,(50,200),0,1.3,(0,0,255),2)if results.multi_hand_landmarks:for hand_landmarks in results.multi_hand_landmarks:
#                    mp_drawing.draw_landmarks(faceImg, hand_landmarks, mp_hands.HAND_CONNECTIONS)hand_local = []for i in range(21):x = hand_landmarks.landmark[i].x*frame.shape[1]y = hand_landmarks.landmark[i].y*frame.shape[0]hand_local.append((x,y))if hand_local:angle_list = hand_angle(hand_local)gesture_str = h_gesture(angle_list)print(gesture_str)
#                        cv2.putText(faceImg,gesture_str,(50,100),0,1.3,(0,0,255),2)if gesture_str == "Bye":if bye_flag == 0:bye_flag = 1elif bye_flag == 1 and time.time() - bye_time >= 3:kill_all_flag = 1q = 1print("Good-Bye")else:bye_flag = 1                    else:Keyborad(hand_jugg,gesture_str)bye_flag = 0hand_jugg = Nonegesture_str = Noneif q == 1:breakif kill_all_flag == 1:breakreturn 

人脸追踪

【优秀毕设V2.0】基于树莓派的OpenCV-Python摄像头人脸追踪及手势识别、网络地址推流及远程控制系统(多功能系统、含演示视频)
此部分简单易懂
就是靠识别人脸的位置 然后再判断位置就可以了

def track():global qglobal kill_all_flagglobal cam_imgglobal left_pointglobal right_pointwhile True:time.sleep(0.1)while q==0:            time.sleep(0.05) gray = cv2.cvtColor(cam_img,cv2.COLOR_BGR2GRAY)faceRects = classifier.detectMultiScale(gray,scaleFactor=1.2,minNeighbors=3,minSize=(32, 32))if len(faceRects):x,y,w,h = faceRects[0]# 框选出人脸   最后一个参数2是框线宽度 
#                cv2.rectangle(faceImg,(x, y), (x + w, y + h), (0,255,0), 2)central_point = x+w/2 if central_point > left_point:print("Right")Mouse(1)elif central_point < right_point:print("Left")Mouse(2)else:Mouse(0)if q == 1:print("S")breakif kill_all_flag == 1:breakreturn 

键盘控制

采用pyautogui库来进行
以下两个函数分别是鼠标移动和键盘操作

def Mouse(flag):print(flag)if flag==1:pyautogui.moveTo(100, 100, duration=0.25)passelif flag==2:pyautogui.moveRel(-50, 0, duration=0.25)pass
def Keyborad(hand_jugg,gesture_str):print(hand_jugg,gesture_str)if hand_jugg=="Right Hand":if gesture_str=="1":pyautogui.click()elif gesture_str=="2":pyautogui.click(button='right')elif gesture_str=="4":pyautogui.mouseDown()elif gesture_str=="5":pyautogui.mouseUp()

整体代码

整体代码将三个部分整合起来 并且用多线程的方式 将摄像头获取、人脸追踪、手势识别跑起来 互不影响

# -*- coding: utf-8 -*-
"""
Created on Sun Sep 10 10:54:53 2023@author: ZHOU
"""import cv2
import threading
import mediapipe as mp
import math
import timeimport pyautoguipyautogui.FAILSAFE = True  # 启用自动防故障功能,左上角的坐标为(0,0),将鼠标移到屏幕的左上角,来抛出failSafeException异常global q
q = 0
global kill_all_flag
kill_all_flag = 0cap = cv2.VideoCapture(0)  # 开启摄像头
classifier = cv2.CascadeClassifier('./haarcascade_frontalface_alt2.xml')global cam_img
ok, cam_img = cap.read()  # 读取摄像头图像
if ok is False:q = 1kill_all_flag = 1print('无法读取到摄像头!')
high=cam_img.shape[0]
width=cam_img.shape[1]
global left_point
global right_point
left_point = width/2+width*0.04
right_point = width/2-width*0.04mp_drawing = mp.solutions.drawing_utils
mp_hands = mp.solutions.hands
hands = mp_hands.Hands(static_image_mode=False,max_num_hands=1,min_detection_confidence=0.6,min_tracking_confidence=0.75)def Mouse(flag):print(flag)if flag==1:
#        pyautogui.moveTo(100, 100, duration=0.25)passelif flag==2:
#        pyautogui.moveRel(-50, 0, duration=0.25)pass
def Keyborad(hand_jugg,gesture_str):print(hand_jugg,gesture_str)if hand_jugg=="Right Hand":if gesture_str=="1":pyautogui.click()elif gesture_str=="2":pyautogui.click(button='right')elif gesture_str=="4":pyautogui.mouseDown()elif gesture_str=="5":pyautogui.mouseUp()def vector_2d_angle(v1,v2):'''求解二维向量的角度'''v1_x=v1[0]v1_y=v1[1]v2_x=v2[0]v2_y=v2[1]try:angle_= math.degrees(math.acos((v1_x*v2_x+v1_y*v2_y)/(((v1_x**2+v1_y**2)**0.5)*((v2_x**2+v2_y**2)**0.5))))except:angle_ =65535.if angle_ > 180.:angle_ = 65535.return angle_def hand_angle(hand_):'''获取对应手相关向量的二维角度,根据角度确定手势'''angle_list = []#---------------------------- thumb 大拇指角度angle_ = vector_2d_angle(((int(hand_[0][0])- int(hand_[2][0])),(int(hand_[0][1])-int(hand_[2][1]))),((int(hand_[3][0])- int(hand_[4][0])),(int(hand_[3][1])- int(hand_[4][1]))))angle_list.append(angle_)#---------------------------- index 食指角度angle_ = vector_2d_angle(((int(hand_[0][0])-int(hand_[6][0])),(int(hand_[0][1])- int(hand_[6][1]))),((int(hand_[7][0])- int(hand_[8][0])),(int(hand_[7][1])- int(hand_[8][1]))))angle_list.append(angle_)#---------------------------- middle 中指角度angle_ = vector_2d_angle(((int(hand_[0][0])- int(hand_[10][0])),(int(hand_[0][1])- int(hand_[10][1]))),((int(hand_[11][0])- int(hand_[12][0])),(int(hand_[11][1])- int(hand_[12][1]))))angle_list.append(angle_)#---------------------------- ring 无名指角度angle_ = vector_2d_angle(((int(hand_[0][0])- int(hand_[14][0])),(int(hand_[0][1])- int(hand_[14][1]))),((int(hand_[15][0])- int(hand_[16][0])),(int(hand_[15][1])- int(hand_[16][1]))))angle_list.append(angle_)#---------------------------- pink 小拇指角度angle_ = vector_2d_angle(((int(hand_[0][0])- int(hand_[18][0])),(int(hand_[0][1])- int(hand_[18][1]))),((int(hand_[19][0])- int(hand_[20][0])),(int(hand_[19][1])- int(hand_[20][1]))))angle_list.append(angle_)return angle_listdef h_gesture(angle_list):'''# 二维约束的方法定义手势# fist five gun love one six three thumbup yeah'''thr_angle = 65.  #手指闭合则大于这个值(大拇指除外)thr_angle_thumb = 53.  #大拇指闭合则大于这个值thr_angle_s = 49.  #手指张开则小于这个值gesture_str = "Unknown"if 65535. not in angle_list:if (angle_list[0]>thr_angle_thumb) and (angle_list[1]>thr_angle) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]>thr_angle):gesture_str = "0"elif (angle_list[0]>thr_angle_thumb)  and (angle_list[1]<thr_angle_s) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]>thr_angle):gesture_str = "1"elif (angle_list[0]>thr_angle_thumb)  and (angle_list[1]<thr_angle_s) and (angle_list[2]<thr_angle_s) and (angle_list[3]>thr_angle) and (angle_list[4]>thr_angle):gesture_str = "2"elif (angle_list[0]>thr_angle_thumb)  and (angle_list[1]<thr_angle_s) and (angle_list[2]<thr_angle_s) and (angle_list[3]<thr_angle_s) and (angle_list[4]>thr_angle):gesture_str = "3"elif (angle_list[0]>thr_angle_thumb) and (angle_list[1]<thr_angle_s) and (angle_list[2]<thr_angle_s) and (angle_list[3]<thr_angle_s) and (angle_list[4]<thr_angle_s):gesture_str = "4"elif (angle_list[0]<thr_angle_s) and (angle_list[1]<thr_angle_s) and (angle_list[2]<thr_angle_s) and (angle_list[3]<thr_angle_s) and (angle_list[4]<thr_angle_s):gesture_str = "5"elif (angle_list[0]<thr_angle_s)  and (angle_list[1]>thr_angle) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]<thr_angle_s):gesture_str = "6"elif (angle_list[0]<thr_angle_s)  and (angle_list[1]<thr_angle_s) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]>thr_angle):gesture_str = "8"elif (angle_list[0]>thr_angle_thumb) and (angle_list[1]>thr_angle) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]<thr_angle_s):gesture_str = "Pink Up"elif (angle_list[0]<thr_angle_s)  and (angle_list[1]>thr_angle) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]>thr_angle):gesture_str = "Thumb Up"elif (angle_list[0]>thr_angle_thumb) and (angle_list[1]>thr_angle) and (angle_list[2]<thr_angle_s) and (angle_list[3]>thr_angle) and (angle_list[4]>thr_angle):gesture_str = "Fuck"elif (angle_list[0]>thr_angle_thumb) and (angle_list[1]>thr_angle) and (angle_list[2]<thr_angle_s) and (angle_list[3]<thr_angle_s) and (angle_list[4]<thr_angle_s):gesture_str = "Princess"elif (angle_list[0]<thr_angle_s)  and (angle_list[1]<thr_angle_s) and (angle_list[2]<thr_angle_s) and (angle_list[3]>thr_angle) and (angle_list[4]>thr_angle):gesture_str = "Bye"elif (angle_list[0]<thr_angle_s)  and (angle_list[1]<thr_angle_s) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]<thr_angle_s):gesture_str = "Spider-Man"elif (angle_list[0]>thr_angle_thumb)  and (angle_list[1]<thr_angle_s) and (angle_list[2]>thr_angle) and (angle_list[3]>thr_angle) and (angle_list[4]<thr_angle_s):gesture_str = "Rock'n'Roll"return gesture_strdef hand_detect():global qglobal kill_all_flagglobal cam_imgbye_flag = 0bye_time = time.time()hand_jugg = Nonegesture_str = Nonewhile True:time.sleep(0.1)while q==0:time.sleep(0.1)frame = cv2.cvtColor(cam_img, cv2.COLOR_BGR2RGB)results = hands.process(frame)if results.multi_handedness:                for hand_label in results.multi_handedness:hand_jugg=str(hand_label).split('"')[1]+" Hand"print(hand_jugg)
#                    cv2.putText(faceImg,hand_jugg,(50,200),0,1.3,(0,0,255),2)if results.multi_hand_landmarks:for hand_landmarks in results.multi_hand_landmarks:
#                    mp_drawing.draw_landmarks(faceImg, hand_landmarks, mp_hands.HAND_CONNECTIONS)hand_local = []for i in range(21):x = hand_landmarks.landmark[i].x*frame.shape[1]y = hand_landmarks.landmark[i].y*frame.shape[0]hand_local.append((x,y))if hand_local:angle_list = hand_angle(hand_local)gesture_str = h_gesture(angle_list)print(gesture_str)
#                        cv2.putText(faceImg,gesture_str,(50,100),0,1.3,(0,0,255),2)if gesture_str == "Bye":if bye_flag == 0:bye_flag = 1elif bye_flag == 1 and time.time() - bye_time >= 3:kill_all_flag = 1q = 1print("Good-Bye")else:bye_flag = 1                    else:Keyborad(hand_jugg,gesture_str)bye_flag = 0hand_jugg = Nonegesture_str = Noneif q == 1:breakif kill_all_flag == 1:breakreturn def track():global qglobal kill_all_flagglobal cam_imgglobal left_pointglobal right_pointwhile True:time.sleep(0.1)while q==0:            time.sleep(0.05) gray = cv2.cvtColor(cam_img,cv2.COLOR_BGR2GRAY)faceRects = classifier.detectMultiScale(gray,scaleFactor=1.2,minNeighbors=3,minSize=(32, 32))if len(faceRects):x,y,w,h = faceRects[0]# 框选出人脸   最后一个参数2是框线宽度 
#                cv2.rectangle(faceImg,(x, y), (x + w, y + h), (0,255,0), 2)central_point = x+w/2 if central_point > left_point:print("Right")Mouse(1)elif central_point < right_point:print("Left")Mouse(2)else:Mouse(0)if q == 1:print("S")breakif kill_all_flag == 1:breakreturn def img_main():global qglobal kill_all_flagglobal cam_img thread_track = threading.Thread(target=track)thread_track.setDaemon(True)thread_track.start()thread_hand = threading.Thread(target=hand_detect)thread_hand.setDaemon(True)thread_hand.start()   while True:time.sleep(0.1)while q==0:cam_img = cv2.flip(cap.read()[1],1)cv2.imshow("video_feed",cam_img)# 展示图像            if q == 1:   # 通过esc键退出摄像q = 1print("暂停程序")cv2.destroyAllWindows()breakif cv2.waitKey(10) == 27:kill_all_flag = 1q = 1print("结束程序")cv2.destroyAllWindows()breakif kill_all_flag == 1:breakcap.release()print("全部退出")return def main():img_main()    time.sleep(1)print("已退出所有程序")return if __name__ == "__main__":    main()

附录:列表的赋值类型和py打包

列表赋值

BUG复现

闲来无事写了个小程序 代码如下:

# -*- coding: utf-8 -*-
"""
Created on Fri Nov 19 19:47:01 2021@author: 16016
"""a_list = ['0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15']
#print(len(a_list))
#b_list = ['','','','','','','','','','','','','','','','']
c_list = [[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]
#for i in range(16):
if len(a_list):for j in range(16):a_list[j]=str(a_list[j])+'_'+str(j)print("序号:",j)print('a_list:\n',a_list)c_list[j]=a_listprint('c_list[0]:\n',c_list[0])print('\n')
#        b_list[j]=a_list[7],a_list[8]
#        print(b_list[j])# 写入到Excel:
#print(c_list,'\n')    

我在程序中 做了一个16次的for循环 把列表a的每个值后面依次加上"_"和循环序号
比如循环第x次 就是把第x位加上_x 这一位变成x_x 我在输出测试中 列表a的每一次输出也是对的
循环16次后列表a应该变成[‘0_0’, ‘1_1’, ‘2_2’, ‘3_3’, ‘4_4’, ‘5_5’, ‘6_6’, ‘7_7’, ‘8_8’, ‘9_9’, ‘10_10’, ‘11_11’, ‘12_12’, ‘13_13’, ‘14_14’, ‘15_15’] 这也是对的

同时 我将每一次循环时列表a的值 写入到空列表c中 比如第x次循环 就是把更改以后的列表a的值 写入到列表c的第x位
第0次循环后 c[0]的值应该是[‘0_0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, ‘10’, ‘11’, ‘12’, ‘13’, ‘14’, ‘15’] 这也是对的
但是在第1次循环以后 c[0]的值就一直在变 变成了c[x]的值
相当于把c_list[0]变成了c_list[1]…以此类推 最后得出的列表c的值也是每一项完全一样
我不明白这是怎么回事
我的c[0]只在第0次循环时被赋值了 但是后面它的值跟着在改变

如图:
在这里插入图片描述
第一次老出bug 赋值以后 每次循环都改变c[0]的值 搞了半天都没搞出来
无论是用appen函数添加 还是用二维数组定义 或者增加第三个空数组来过渡 都无法解决

代码改进

后来在我华科同学的指导下 突然想到赋值可以赋的是个地址 地址里面的值一直变化 导致赋值也一直变化 于是用第二张图的循环套循环深度复制实现了

代码如下:

# -*- coding: utf-8 -*-
"""
Created on Fri Nov 19 19:47:01 2021@author: 16016
"""a_list = ['0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15']
#print(len(a_list))
#b_list = ['','','','','','','','','','','','','','','','']
c_list = [[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]
#for i in range(16):
if len(a_list):for j in range(16):a_list[j]=str(a_list[j])+'_'+str(j)print("序号:",j)print('a_list:\n',a_list)for i in range(16):c_list[j].append(a_list[i])print('c_list[0]:\n',c_list[0])print('\n')
#        b_list[j]=a_list[7],a_list[8]
#        print(b_list[j])# 写入到Excel:
print(c_list,'\n')    

解决了问题

在这里插入图片描述

优化

第三次是请教了老师 用copy函数来赋真值

代码如下:

# -*- coding: utf-8 -*-
"""
Created on Fri Nov 19 19:47:01 2021@author: 16016
"""a_list = ['0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15']
#print(len(a_list))
#b_list = ['','','','','','','','','','','','','','','','']
c_list = [[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]
#for i in range(16):
if len(a_list):for j in range(16):a_list[j]=str(a_list[j])+'_'+str(j)print("序号:",j)print('a_list:\n',a_list)c_list[j]=a_list.copy()print('c_list[0]:\n',c_list[0])print('\n')
#        b_list[j]=a_list[7],a_list[8]
#        print(b_list[j])# 写入到Excel:
#print(c_list,'\n')    

同样能解决问题
在这里插入图片描述
最后得出问题 就是指针惹的祸!

a_list指向的是个地址 而不是值 a_list[i]指向的才是单个的值 copy()函数也是复制值而不是地址

如果这个用C语言来写 就直观一些了 难怪C语言是基础 光学Python不学C 遇到这样的问题就解决不了

C语言yyds Python是什么垃圾弱智语言

总结

由于Python无法单独定义一个值为指针或者独立的值 所以只能用列表来传送
只要赋值是指向一个列表整体的 那么就是指向的一个指针内存地址 解决方法只有一个 那就是将每个值深度复制赋值(子列表内的元素提取出来重新依次连接) 或者用copy函数单独赋值

如图测试:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
部分代码:

# -*- coding: utf-8 -*-
"""
Created on Sat Nov 20 16:45:48 2021@author: 16016
"""def text1():A=[1,2,3]B=[[],[],[]]for i in range(len(A)):A[i]=A[i]+iB[i]=Aprint(B)def text2():A=[1,2,3]B=[[],[],[]]A[0]=A[0]+0B[0]=Aprint(B)A[1]=A[1]+1B[1]=Aprint(B)A[2]=A[2]+2B[2]=Aprint(B)if __name__ == '__main__':text1()print('\n')text2()

py打包

Pyinstaller打包exe(包括打包资源文件 绝不出错版)

依赖包及其对应的版本号

PyQt5 5.10.1
PyQt5-Qt5 5.15.2
PyQt5-sip 12.9.0

pyinstaller 4.5.1
pyinstaller-hooks-contrib 2021.3

Pyinstaller -F setup.py 打包exe

Pyinstaller -F -w setup.py 不带控制台的打包

Pyinstaller -F -i xx.ico setup.py 打包指定exe图标打包

打包exe参数说明:

-F:打包后只生成单个exe格式文件;

-D:默认选项,创建一个目录,包含exe文件以及大量依赖文件;

-c:默认选项,使用控制台(就是类似cmd的黑框);

-w:不使用控制台;

-p:添加搜索路径,让其找到对应的库;

-i:改变生成程序的icon图标。

如果要打包资源文件
则需要对代码中的路径进行转换处理
另外要注意的是 如果要打包资源文件 则py程序里面的路径要从./xxx/yy换成xxx/yy 并且进行路径转换
但如果不打包资源文件的话 最好路径还是用作./xxx/yy 并且不进行路径转换

def get_resource_path(relative_path):if hasattr(sys, '_MEIPASS'):return os.path.join(sys._MEIPASS, relative_path)return os.path.join(os.path.abspath("."), relative_path)

而后再spec文件中的datas部分加入目录
如:

a = Analysis(['cxk.py'],pathex=['D:\\Python Test\\cxk'],binaries=[],datas=[('root','root')],hiddenimports=[],hookspath=[],hooksconfig={},runtime_hooks=[],excludes=[],win_no_prefer_redirects=False,win_private_assemblies=False,cipher=block_cipher,noarchive=False)

而后直接Pyinstaller -F setup.spec即可

如果打包的文件过大则更改spec文件中的excludes 把不需要的库写进去(但是已经在环境中安装了的)就行

这些不要了的库在上一次编译时的shell里面输出
比如:
在这里插入图片描述

在这里插入图片描述
然后用pyinstaller --clean -F 某某.spec

相关文章:

【Python】基于OpenCV人脸追踪、手势识别控制的求生之路FPS游戏操作

【Python】基于OpenCV人脸追踪、手势识别控制的求生之路FPS游戏操作 文章目录 手势识别人脸追踪键盘控制整体代码附录&#xff1a;列表的赋值类型和py打包列表赋值BUG复现代码改进优化总结 py打包 视频&#xff1a; 基于OpenCV人脸追踪、手势识别控制的求实之路FPS游戏操作 手…...

约束优化算法(optimtool.constrain)

import optimtool as oo from optimtool.base import np, sp, pltpip install optimtool>2.4.2约束优化算法&#xff08;optimtool.constrain&#xff09; import optimtool.constrain as oc oc.[方法名].[函数名]([目标函数], [参数表], [等式约束表], [不等式约数表], [初…...

如何查看postgresql中的数据库大小?

你可以使用以下命令来查看PostgreSQL数据库的大小&#xff1a; SELECT pg_database.datname as "database_name", pg_size_pretty(pg_database_size(pg_database.datname)) AS size_in_mb FROM pg_database ORDER by size_in_mb DESC;这将返回一个表格&#xff0…...

使用python-opencv检测图片中的人像

最简单的方法进行图片中的人像检测 使用python-opencv配合yolov3模型进行图片中的人像检测 1、安装python-opencv、numpy pip install opencv-python pip install numpy 2、下载yolo模型文件和配置文件&#xff1a; 下载地址&#xff1a; https://download.csdn.net/down…...

项目进展(三)-电机驱动起来了,发现了很多关键点,也遇到了一些低级错误,

一、前言 昨天电机没有驱动起来&#xff0c;头发掉一堆&#xff0c;不过今天&#xff0c;终于终于终于把电机驱动起来了&#xff01;&#xff01;&#xff01;&#xff01;&#xff0c;特别开心&#xff0c;哈哈哈哈&#xff0c;后续继续努力完善&#xff01;&#xff01;&…...

目标检测算法改进系列之Backbone替换为RepViT

RepViT简介 轻量级模型研究一直是计算机视觉任务中的一个焦点&#xff0c;其目标是在降低计算成本的同时达到优秀的性能。轻量级模型与资源受限的移动设备尤其相关&#xff0c;使得视觉模型的边缘部署成为可能。在过去十年中&#xff0c;研究人员主要关注轻量级卷积神经网络&a…...

学习 Kubernetes的难点和安排

Kubernetes 技术栈的特点可以用四个字来概括&#xff0c;那就是“新、广、杂、深”&#xff1a; 1.“新”是指 Kubernetes 用到的基本上都是比较前沿、陌生的技术&#xff0c;而且版本升级很快&#xff0c;经常变来变去。 2.“广”是指 Kubernetes 涉及的应用领域很多、覆盖面非…...

【MATLAB源码-第42期】基于matlab的人民币面额识别系统(GUI)。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 基于 MATLAB 的人民币面额识别系统设计可以分为以下步骤&#xff1a; 1. 数据收集与预处理 数据收集&#xff1a; 收集不同面额的人民币照片&#xff0c;如 1 元、5 元、10 元、20 元、50 元和 100 元。确保在不同环境、不…...

【软件测试】软件测试的基础概念

一、一个优秀的测试人员需要具备的素质 技能方面&#xff1a; 优秀的测试用例设计能力&#xff1a;测试用例设计能力是指&#xff0c;无论对于什么类型的测试&#xff0c;都能够设计出高效的发现缺陷&#xff0c;保证产品质量的优秀测试用例。这就需要我们掌握设计测试用例的方…...

Docker-mysql,redis安装

安装MySQL 下载MySQL镜像 终端运行命令 docker pull mysql:8.0.29镜像下载完成后&#xff0c;需要配置持久化数据到本地 这是mysql的配置文件和存储数据用的目录 切换到终端&#xff0c;输入命令&#xff0c;第一次启动MySQL容器 docker run --restartalways --name mysq…...

五种I/O模型

目录 1、阻塞IO模型2、非阻塞IO模型3、IO多路复用模型4、信号驱动IO模型5、异步IO模型总结 blockingIO - 阻塞IOnonblockingIO - 非阻塞IOIOmultiplexing - IO多路复用signaldrivenIO - 信号驱动IOasynchronousIO - 异步IO 5种模型的前4种模型为同步IO&#xff0c;只有异步IO模…...

用nativescript开发ios程序常用命令?

NativeScript是一个用于跨平台移动应用程序开发的开源框架&#xff0c;允许您使用JavaScript或TypeScript构建原生iOS和Android应用程序。以下是一些常用的NativeScript命令&#xff0c;用于开发iOS应用程序&#xff1a; 1、创建新NativeScript项目&#xff1a; tns create m…...

6.Tensors For Beginners-What are Convector

Covectors &#xff08;协向量&#xff09; What‘s a covector Covectors are “basically” Row Vectors 在一定程度上&#xff0c;可认为 协向量 基本上就像 行向量。 但不能简单地认为 这就是列向量进行转置&#xff01; 行向量 和 列向量 是根本不同类型的对象。 …...

Linux多线程网络通信

思路&#xff1a;主线程&#xff08;只有一个&#xff09;建立连接&#xff0c;就创建子线程。子线程开始通信。 共享资源&#xff1a;全局数据区&#xff0c;堆区&#xff0c;内核区描述符。 线程同步不同步需要取决于线程对共享资源区的数据的操作&#xff0c;如果是只读就不…...

矩阵的c++实现(2)

上一次我们了解了矩阵的运算和如何使用矩阵解决斐波那契数列&#xff0c;这一次我们多看看例题&#xff0c;了解什么情况下用矩阵比较合适。 先看例题 1.洛谷P1939 【模板】矩阵加速&#xff08;数列&#xff09; 模板题应该很简单。 补&#xff1a;1<n<10^9 10^9肯定…...

RPC 框架之Thrift入门(一)

&#x1f4cb; 个人简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是阿牛&#xff0c;全栈领域优质创作者。&#x1f61c;&#x1f4dd; 个人主页&#xff1a;馆主阿牛&#x1f525;&#x1f389; 支持我&#xff1a;点赞&#x1f44d;收藏⭐️留言&#x1f4d…...

【C++】运算符重载 ⑥ ( 一元运算符重载 | 后置运算符重载 | 前置运算符重载 与 后置运算符重载 的区别 | 后置运算符重载添加 int 占位参数 )

文章目录 一、后置运算符重载1、前置运算符重载 与 后置运算符重载 的区别2、后置运算符重载添加 int 占位参数 上 2 2 2 篇博客 【C】运算符重载 ④ ( 一元运算符重载 | 使用 全局函数 实现 前置 自增运算符重载 | 使用 全局函数 实现 前置 - - 自减运算符重载 )【C】运算符…...

538. 把二叉搜索树转换为累加树

题目描述 给出二叉 搜索 树的根节点&#xff0c;该树的节点值各不相同&#xff0c;请你将其转换为累加树&#xff08;Greater Sum Tree&#xff09;&#xff0c;使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和。 提醒一下&#xff0c;二叉搜索树满足下列约束…...

java8日期时间工具类

【README】 1&#xff09;本文总结了java8中日期时间常用工具方法&#xff1b;包括&#xff1a; 日期时间对象格式化为字符串&#xff1b;日期时间字符串解析为日期时间对象&#xff1b;日期时间对象转换&#xff1b; 转换过程中&#xff0c;需要注意的是&#xff1a; Instan…...

算法-动态规划/trie树-单词拆分

算法-动态规划/trie树-单词拆分 1 题目概述 1.1 题目出处 https://leetcode.cn/problems/word-break/description/?envTypestudy-plan-v2&envIdtop-interview-150 1.2 题目描述 2 动态规划 2.1 解题思路 dp[i]表示[0, i)字符串可否构建那么dp[i]可构建的条件是&…...

React框架核心原理

一、整体架构 三大核心库与对应的组件 history -> react-router -> react-router-dom react-router 可视为react-router-dom 的核心&#xff0c;里面封装了<Router>&#xff0c;<Route>&#xff0c;<Switch>等核心组件,实现了从路由的改变到组件的更新…...

python-pytorch 利用pytorch对堆叠自编码器进行训练和验证

利用pytorch对堆叠自编码器进行训练和验证 一、数据生成二、定义自编码器模型三、训练函数四、训练堆叠自编码器五、将已训练的自编码器级联六、微调整个堆叠自编码器 一、数据生成 随机生成一些数据来模拟训练和验证数据集&#xff1a; import torch# 随机生成数据 n_sample…...

制作 3 档可调灯程序编写

PWM 0~255 可以将数据映射到0 75 150 225 尽可能均匀电压间隔...

源码分享-M3U8数据流ts的AES-128解密并合并---GoLang实现

之前使用C语言实现了一次&#xff0c;见M3U8数据流ts的AES-128解密并合并。 学习了Go语言后&#xff0c;又用Go重新实现了一遍。源码如下&#xff0c;无第三方库依赖。 package mainimport ("crypto/aes""crypto/cipher""encoding/binary"&quo…...

CSDN Q: “这段代码算是在STC89C52RC51单片机上完成PWM呼吸灯了吗?“

这是 CSDN上的一个问题 这段代码算是在STC89C52RC51单片机上完成PWM呼吸灯了吗&#xff0c;还是说得用上定时器和中断函数#include <regx52.h> 我个人认为: 效果上来说, 是的! 码以 以Time / 100-Time 调 Duty, 而 for i loop成 Period, 加上延时, 实现了 PWM周期, 虽然…...

Linux系统编程系列之线程池

Linux系统编程系列&#xff08;16篇管饱&#xff0c;吃货都投降了&#xff01;&#xff09; 1、Linux系统编程系列之进程基础 2、Linux系统编程系列之进程间通信(IPC)-信号 3、Linux系统编程系列之进程间通信(IPC)-管道 4、Linux系统编程系列之进程间通信-IPC对象 5、Linux系统…...

Linux CentOS7 vim多文件与多窗口操作

窗口是可视化的分割区域。Windows中窗口的概念与linux中基本相同。连接xshell就是在Windows中新建一个窗口。而vim打开一个文件默认创建一个窗口。同时&#xff0c;Vim打开一个文件也就会建立一个缓冲区&#xff0c;打开多个文件就会创建多个缓冲区。 本文讨论vim中打开多个文…...

SPI 通信协议

1. SPI通信 1. 什么是SPI通信协议 2. SPI的通信过程 在一开始会先把发送缓冲器的数据&#xff08;8位&#xff09;。一次性放到移位寄存器里。 移位寄存器会一位一位发送出去。但是要先放到锁存器里。然后从机来读取。从机的过程也一样。当移位寄存器的数据全部发送完。其实…...

【图像处理】使用各向异性滤波器和分割图像处理从MRI图像检测脑肿瘤(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

5个适合初学者的初级网络安全工作,网络安全就业必看

前言 网络安全涉及保护计算机系统、网络和数据免受未经授权的访问、破坏和盗窃 - 防止数字活动和数据访问的中断 - 同时也保护用户的资产和隐私。鉴于公共事业、医疗保健、金融以及联邦政府等行业的网络犯罪攻击不断升级&#xff0c;对网络专业人员的需求很高&#xff0c;这并…...

阿里万网站建设/新闻发稿平台有哪些?

1、概述 Linux三剑客&#xff1a;grep、sed、awk。grep主打查找功能&#xff0c;sed主要是编辑行&#xff0c;awk主要是分割列处理。本篇文章我们详细介绍grep命令。 grep &#xff08;global search regular expression(RE) and print out the line&#xff0c;全面搜索正则…...

免费外贸网站大全/优化大师客服

目录前言一、vue单界面高度铺满全屏总结前言 在平常的开发中&#xff0c;vue单界面的高度&#xff0c;默认是自动撑开的&#xff0c;但是我们在实际的需求中&#xff0c;是需要实现高度全屏铺满的&#xff0c;下面的方法是我在vue项目中&#xff0c;实现单页面高度撑满的方法。…...

网站定制文章列表项怎么做/整合营销传播的定义

本文学习使用 Redis 实现消息队列。1 概述 我们平时使用的消息队列有 RabbitMQ、RocketMQ、ActiveMQ 以及大数据里边的 Kafka&#xff0c;他们都非常专业&#xff0c;提供了很多功能。如果我们的需求或场景非常简单&#xff0c;用他们就有点大材小用了&#xff0c;比如我们只需…...

哪个网站做试卷吧有答案/seo排名赚app最新版本

进入about:config.修改dom.ipc.plugins.enabled.npctrl.dll&#xff0c;把它由true改成false重启Firefox就可以调试了。转载于:https://www.cnblogs.com/lfzwenzhu/archive/2011/02/23/1962198.html...

网站建设书/seo就业前景

SHELL[07]转载于:https://www.cnblogs.com/motadou/archive/2010/01/11/1644409.html...

门户网站代做/推广平台的方法

完全自主实现&#xff0c;bloat-free。再次声明&#xff0c;这不是UE、U3D、CE、KlayGE! 老规矩&#xff0c;先贴图。后面有时间再补充描述。 1. 支持多跳间接全局光照2. 支持vxao/so、vxdiff/spec等全功能3. 支持近乎完美的全局遮蔽&#xff0c;屏幕空间遮蔽可以直接扔了4. 全…...