[{"content":"abstract：记录在远程服务器跑代码遇到的问题和常用的命令行语句\nstory：公用服务器上改代码，显存爆炸后差点把同门进程给杀了，故作此文以记录\n查看GPU状态 nvidia-smi: 关注这几个点：\n上半张表：GPU信息\nMemory-Usage：显存 Volatile GPU-Util：GPU利用率 下半张表：进程信息\nPID：进程号（你会发现1152339进程占了两张卡） xorg：Linux的图形化驱动，不用管 GPU0上1152339进程占了11个G，这就是我显存炸掉的罪魁祸首！我的进程需要的显存大于24-11=13G，自动卡退了 这个进程是谁的呢？\n进程 kill -9 1152339 强行杀死进程 ps -u -p 1152339 看看这个进程是谁的 ps -ef | grep 1152339 搜索所有含有“1152339”名字的进程，并显示完整信息 还可以ps -ef | grep yourusername,查看和你有关的所有进程 ","permalink":"https://Authentic-1412.github.io/posts/%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4/","summary":"\u003cp\u003e\u003cstrong\u003eabstract：记录在远程服务器跑代码遇到的问题和常用的命令行语句\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003estory\u003c/strong\u003e：公用服务器上改代码，显存爆炸后差点把同门进程给杀了，故作此文以记录\u003c/p\u003e\n\u003ch2 id=\"查看gpu状态\"\u003e查看GPU状态\u003c/h2\u003e\n\u003ch3 id=\"nvidia-smi\"\u003e\u003ccode\u003envidia-smi\u003c/code\u003e:\u003c/h3\u003e\n\u003cp\u003e\u003cimg alt=\"gpu\" loading=\"lazy\" src=\"/image/gpu.png\"\u003e\n\u003cstrong\u003e关注这几个点：\u003c/strong\u003e\u003cbr\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e上半张表：GPU信息\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eMemory-Usage\u003c/strong\u003e：显存\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eVolatile GPU-Util\u003c/strong\u003e：GPU利用率\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e下半张表：进程信息\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003ePID\u003c/strong\u003e：进程号（你会发现1152339进程占了两张卡）\u003c/li\u003e\n\u003cli\u003exorg：Linux的图形化驱动，不用管\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eGPU0上1152339进程占了11个G，这就是我显存炸掉的罪魁祸首！我的进程需要的显存大于24-11=13G，自动卡退了\n这个进程是谁的呢？\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"进程\"\u003e进程\u003c/h2\u003e\n\u003ch3 id=\"kill--9-1152339\"\u003e\u003ccode\u003ekill -9 1152339\u003c/code\u003e\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e强行杀死进程\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"ps--u--p-1152339\"\u003e\u003ccode\u003eps -u -p 1152339\u003c/code\u003e\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e看看这个进程是谁的\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"ps--ef--grep-1152339\"\u003e\u003ccode\u003eps -ef | grep 1152339\u003c/code\u003e\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e搜索所有含有“1152339”名字的进程，并显示完整信息\u003c/li\u003e\n\u003cli\u003e还可以\u003ccode\u003eps -ef | grep yourusername\u003c/code\u003e,查看和你有关的所有进程\u003c/li\u003e\n\u003c/ul\u003e","title":"远程服务器常用命令"},{"content":"abstract：如何把一份10G的代码从本地传输到远程服务器\nstory：原来git也会被push死\n以传输HSI_ATTACK2代码为例\n查看子文件夹大小 linux：在母目录下输入：\ndu -h \u0026ndash;max-depth=1 | sort -hr\n-h：hunman redable，人类可读 \u0026ndash;max-depth=1：最大深度，为1则只统计下一级目录的大小，不会具体到文件 |：管道，把数据传输到sort管道里 -hr：按易读数字反向排序，h指明白1G比200M大，r指reverse，逆序\n结果：\n把占用大的数据通过rsync传输，git仅传输代码\n1. Git git不能传输过大文件夹，例如这里的10G直接push会连接超时\n1.1. .gitignore 把不想要的文件类型或文件目录写入.gitignore\nbash: nano .gitignore # 创建并打开.gitignore文件 # 写入 params/ logs/ RESREPORT/ dataset/ abundance_matrix/ # ^X退出编辑 查看文件\nbash: cat .gitignore # 用于查看简短文件 直接将文件内容输出在终端 less .gitignore # 查看长文件 可翻页 按q退出 1.2. 在服务器上建仓库 之前仓库一直都建立在github上，而仓库也可以建立在服务器上，而且仓库可以不托管源代码，只托管代码的“基因”，也就是\u0026ndash;bare，通过克隆仓库复原源代码\n（本地的wsl上：）\n从用du查看的目录大小可以发现，.git托管了所有代码的所有更改，特别臃肿，所以删掉\nrm -rf .git 重新初始化(在本地的HSI_ATTACK2目录下) git init 确保已经编辑好.gitignore后，将更改加入暂存区 git add . 从暂存区提交到本地仓库（.git） git commit -m \u0026ldquo;Initial commit\u0026rdquo;\n（服务器上：）\n回到家目录：\ncd ~ （查看家目录指的是哪个目录：） echo $HOME 创建一个仓库文件夹，并cd进去： mkdir HSI_ATTACK2.git cd HSI_ATTACK2.git 初始化，并且只记录版本更新信息，不记录源代码（可以根据这些信息还原源代码） git init \u0026ndash;bare\n现在这个仓库是空的，要从本机推代码过来。\n（本地wsl上：）\n本地的仓库没有关联远程仓库，故先关联\ngit remote add origin ssh://user@ip:6000/home1/xiechenzhangzhu/HSI_ATTACK2.git 其中origin是给后面那一坨仓库起的名字，后面那一坨是origin的地址，跟在GitHub上面copy下来的http阿巴阿巴是一个意思，告诉本地文件要连接的远程仓库在哪\n把本地仓库的代码（main分支）推送给远程仓库origin的main分支： git push -u origin main\n（远程服务器上：）\n把这个仓库克隆到这个服务器上\ngit clone ~/HSI_ATTACK2.git HSI_WORK\ngit clone 仓库地址 克隆后文件夹 注意，克隆后会在家目录下生成一个HSI_WORK文件夹，若为空，则是没有打开含有文件的分支。进入该文件夹，查看当前分支\ngit branch # 带*的是当前分支 进入有内容的分支 git chekout 分支名 此时克隆后的文件夹中就会有源代码了\n2. rsync okay，源代码通过git传过去了，大的数据用rsync慢慢传。windows系统盘的文件都在wsl的mnt目录下，在wsl打开要传的目录：\nrsync -avzP -e \u0026lsquo;ssh -p 6000\u0026rsquo; ./params ./abundance_matrix ./dataset xiechenzhangzhu@cois.cloud:~/\n-a：最常用,保证文件夹递归同步，并保留文件的修改时间、权限、软链接等属性\n-v：保证文件夹递归同步，并保留文件的修改时间、权限、软链接等属性\n-z：在传输过程中对数据进行压缩，减少带宽占用\n-p：最重要！中断了可以从中断的地方开始继续传，不用重头开始\n-e \u0026lsquo;ssh -p 6000\u0026rsquo;：指定远程端口\n./params ./abundance_matrix ./dataset ：要传输的文件夹们的路径：目录A 目录B 目录C\n重点！！！：\n1. 如果末尾不带/，如这里所示，把 params 文件夹本身搬过去。结果：~/params/\u0026hellip;\n2. 如果结尾带/，./params/，则把 params 文件夹里面的内容搬过去，内容直接散落在 ~/ 下\nxiechenzhangzhu@cois.cloud:~/：远程服务器:目标目录，指明要把文件放在哪\n","permalink":"https://Authentic-1412.github.io/posts/%E8%BF%9C%E7%A8%8B%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%96%87%E4%BB%B6%E4%BC%A0%E8%BE%93/","summary":"\u003cp\u003e\u003cstrong\u003eabstract：如何把一份10G的代码从本地传输到远程服务器\u003c/strong\u003e\u003cbr\u003e\n\u003cstrong\u003estory\u003c/strong\u003e：原来git也会被push死\u003c/p\u003e\n\u003cp\u003e以传输HSI_ATTACK2代码为例\u003c/p\u003e\n\u003ch1 id=\"查看子文件夹大小\"\u003e查看子文件夹大小\u003c/h1\u003e\n\u003cp\u003elinux：在母目录下输入：\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003edu -h \u0026ndash;max-depth=1 | sort -hr\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cul\u003e\n\u003cli\u003e-h：hunman redable，人类可读\u003c/li\u003e\n\u003cli\u003e\u0026ndash;max-depth=1：最大深度，为1则只统计下一级目录的大小，不会具体到文件\u003c/li\u003e\n\u003cli\u003e|：管道，把数据传输到sort管道里\u003c/li\u003e\n\u003cli\u003e-hr：按易读数字反向排序，h指明白1G比200M大，r指reverse，逆序\u003cbr\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e结果：\u003cbr\u003e\n\u003cimg alt=\"alt text\" loading=\"lazy\" src=\"/image/du.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e把占用大的数据通过rsync传输，git仅传输代码\u003c/strong\u003e\u003c/p\u003e\n\u003ch1 id=\"1-git\"\u003e1. Git\u003c/h1\u003e\n\u003cp\u003e\u003cstrong\u003egit不能传输过大文件夹，例如这里的10G直接push会连接超时\u003c/strong\u003e\u003c/p\u003e\n\u003ch2 id=\"11-gitignore\"\u003e1.1. .gitignore\u003c/h2\u003e\n\u003cp\u003e把不想要的文件类型或文件目录写入.gitignore\u003c/p\u003e\n\u003cblockquote\u003e\n\u003c/blockquote\u003e\n\u003cpre\u003e\u003ccode\u003ebash:\nnano .gitignore # 创建并打开.gitignore文件\n# 写入\nparams/\nlogs/\nRESREPORT/\ndataset/\nabundance_matrix/\n# ^X退出编辑\n\u003c/code\u003e\u003c/pre\u003e\n\u003cp\u003e查看文件\u003c/p\u003e\n\u003cblockquote\u003e\n\u003c/blockquote\u003e\n\u003cpre\u003e\u003ccode\u003ebash:\ncat .gitignore # 用于查看简短文件 直接将文件内容输出在终端\nless .gitignore # 查看长文件 可翻页 按q退出\n\u003c/code\u003e\u003c/pre\u003e\n\u003ch2 id=\"12-在服务器上建仓库\"\u003e1.2. 在服务器上建仓库\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003e之前仓库一直都建立在github上，而仓库也可以建立在服务器上，而且仓库可以不托管源代码，只托管代码的“基因”，也就是\u0026ndash;bare，通过克隆仓库复原源代码\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e（本地的wsl上：）\u003c/strong\u003e\u003cbr\u003e\n从用du查看的目录大小可以发现，.git托管了所有代码的所有更改，特别臃肿，所以删掉\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003erm -rf .git\n重新初始化(在本地的HSI_ATTACK2目录下)\ngit init\n确保已经编辑好.gitignore后，将更改加入暂存区\ngit add .\n从暂存区提交到本地仓库（.git）\ngit commit -m \u0026ldquo;Initial commit\u0026rdquo;\u003c/p\u003e","title":"远程服务器文件传输"},{"content":"元件引脚功能 tb6612 左列(连接单片机)\nPWMA：控制A电机转速 通过PWM的占空比控制电机转速 AIN1：和AIN2一起控制A电机转向，电平高低变为0-1信号，即通过两边施力与否控制转向，两两组合： GPIO-A4 0-1：正转 1-0：反转 0-0：空档（两侧均不施力） 1-1：刹车（两侧同时施力） AIN2 GPIO-A5 STBY：控制驱动模块是否工作的开关 BIN1：类似AIN1 BIN2 PWMB GND： 连接单片机接地 右列（连接电机）\nVM：M指的是machine，也就是驱动电机需要的电压（一般为高电压，4.5-15v不等） VCC：cc：逻辑电路，指的是让tb6612这块板子运行起来的电压，一般为3.3v或5v GND：电机接地 AO1：连A电机M+ AO2：M- BO1：连B电机M- BO2: M+ GND：电机接地 这三个GND要共地，否则会故障。出现问题时检查是否共地 霍尔编码器 VCC：3.3v GND A相：接单片机脉冲检测接口 B相 M+：电机接口，接tb6612的AO1 M-：AO2 oled屏幕 VCC GND SCL：接单片机 用于IIC通信 SDA：同上 MPU6050 VCC GND SCL SDA 剩余引脚用于连接电磁传感器形成九轴传感器\n","permalink":"https://Authentic-1412.github.io/posts/stm32%E5%B0%8F%E8%BD%A6%E7%94%B5%E8%B7%AF%E8%AE%BE%E8%AE%A1/","summary":"\u003ch1 id=\"元件引脚功能\"\u003e元件引脚功能\u003c/h1\u003e\n\u003ch2 id=\"tb6612\"\u003etb6612\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e左列(连接单片机)\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ePWMA：控制A电机转速 通过PWM的占空比控制电机转速\u003c/li\u003e\n\u003cli\u003eAIN1：和AIN2一起控制A电机转向，电平高低变为0-1信号，即通过两边施力与否控制转向，两两组合：  GPIO-A4\n\u003cul\u003e\n\u003cli\u003e0-1：正转\u003c/li\u003e\n\u003cli\u003e1-0：反转\u003c/li\u003e\n\u003cli\u003e0-0：空档（两侧均不施力）\u003c/li\u003e\n\u003cli\u003e1-1：刹车（两侧同时施力）\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eAIN2 GPIO-A5\u003c/li\u003e\n\u003cli\u003eSTBY：控制驱动模块是否工作的开关\u003c/li\u003e\n\u003cli\u003eBIN1：类似AIN1\u003c/li\u003e\n\u003cli\u003eBIN2\u003c/li\u003e\n\u003cli\u003ePWMB\u003c/li\u003e\n\u003cli\u003eGND： 连接单片机接地\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e右列（连接电机）\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eVM：M指的是machine，也就是驱动电机需要的电压（一般为高电压，4.5-15v不等）\u003c/li\u003e\n\u003cli\u003eVCC：cc：逻辑电路，指的是让tb6612这块板子运行起来的电压，一般为3.3v或5v\u003c/li\u003e\n\u003cli\u003eGND：电机接地\u003c/li\u003e\n\u003cli\u003eAO1：连A电机M+\u003c/li\u003e\n\u003cli\u003eAO2：M-\u003c/li\u003e\n\u003cli\u003eBO1：连B电机M-\u003c/li\u003e\n\u003cli\u003eBO2: M+\u003c/li\u003e\n\u003cli\u003eGND：电机接地\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cblockquote\u003e\n\u003col\u003e\n\u003cli\u003e这三个GND要共地，否则会故障。出现问题时检查是否共地\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"霍尔编码器\"\u003e霍尔编码器\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eVCC：3.3v\u003c/li\u003e\n\u003cli\u003eGND\u003c/li\u003e\n\u003cli\u003eA相：接单片机脉冲检测接口\u003c/li\u003e\n\u003cli\u003eB相\u003c/li\u003e\n\u003cli\u003eM+：电机接口，接tb6612的AO1\u003c/li\u003e\n\u003cli\u003eM-：AO2\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"oled屏幕\"\u003eoled屏幕\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eVCC\u003c/li\u003e\n\u003cli\u003eGND\u003c/li\u003e\n\u003cli\u003eSCL：接单片机 用于IIC通信\u003c/li\u003e\n\u003cli\u003eSDA：同上\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"mpu6050\"\u003eMPU6050\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eVCC\u003c/li\u003e\n\u003cli\u003eGND\u003c/li\u003e\n\u003cli\u003eSCL\u003c/li\u003e\n\u003cli\u003eSDA\u003c/li\u003e\n\u003c/ul\u003e\n\u003cblockquote\u003e\n\u003cp\u003e剩余引脚用于连接电磁传感器形成九轴传感器\u003c/p\u003e\n\u003c/blockquote\u003e","title":"Stm32小车电路设计"},{"content":"HSI攻击 A. 高光谱图像数据集 高光谱：像素的记录格式不再是rgb，而是按照光谱波段记录\nIndian pine 只有一张图片，分辨率为145*145\n该图片的每个像素作为一个样本，每个像素都由一个200个数字描述，表示各个波段的反射强度，理论上属于0-1\n这张图拍的主要为农作物，共有16个类别，即10249个样本对应16个类别，包括草地、玉米地、林地等\nIndian Pines 数据集的规模: 145*145*200 (width height 波段数)\n下载得到的数据集形式\nIndian_pines.mat ：原始的Indian Pines 数据集: 145*145*220\nIndian_pines_corrected.mat 矫正后的Indian Pines 数据集: 145*145*200\nIndian_pines_gt.mat 标签矩阵 145*145 部分内容引自知乎\nAVIRIS 成像光谱仪成像波长范围为 0.4-2.5μm，是在连续的 220 个波段对地物连续成像的，但是由于第 104-108，第 150-163 和第 220 个波段不能被水反射，因此，我们一般使用的是剔除了这 20 个波段后剩下的 200 个波段作为研究的对象。 145*145 = 21025=10776（背景，黑）+ 10249（多种地物，彩）\n\u0026gt; 10249 = 各类地物占得像素个数。 解混 我们对丰度矩阵A添加扰动，丰度矩阵表示每个像素中不同端元的占比，端元库表示不同端元（纯净）在光谱中200个波段下的值 B. Universal Perturbation 算法：在每一轮迭代中都找到$\\Delta v$ C. 经典神经网络的训练逻辑 DataLoader 一个迭代器 pbar = tqdm(enumerate(attack_loader), total=len(attack_loader)) for index, (_, abun, abun_sum, noise, labels, _) in pbar: # 每次迭代使用一个batch的数据来更新扰动（正常32个，但如果最后一组样本量不足32，那就不足32，不舍弃） 用for迭代，每次迭代使用一个batch的数据来更新扰动（正常32个，但如果最后一组样本量不足32，那就不足32，不舍弃）\n每个batch是一个元组，元组中有多个元素，每个元素都是一个pytorch张量，这些张量有不同的shape，而所有张量的第一维，都是batch_size。例如这里abun的形状就是$[32,6 ,15,15]$，也就是$\\text{[B, C, H, W]}$ $C$：通道数（波段要经过选择 最终只剩6个波段【Indian_pines数据集】） $H、W$：高宽（输入并非一个像素，而是围绕一个像素切割出的15*15的patch，这个切割的过程有点像卷积核对图像的遍历） 每输入一个batch，也就是输入这些张量。 批量梯度下降 公式a：以batch_size=10为例\n$\\theta_j := \\theta_j - \\alpha \\frac{1}{10} \\sum_{k=i}^{(i+9)}(h_{\\theta}(x)-y{(k)})x_j$\n$\\theta_j$：第$j$个参数\n$\\alpha$：步长\n$\\alpha$后面那一坨：目标函数$(h_{\\theta}(x)-y{(k)})$对$x_j$ 的偏导 的平均值\n伪代码：\nfor m in epoch: for n in batch_num: for i in batch_size: 公式a $\\J = sum_{k} 每个epoch要完整遍历一遍数据集\n数据集被划分为很多个batch，依次遍历这些batch\n每个batch内部并行计算，即同时计算所有样本的预测值、损失并求平均\n每算完一个batch更新一次参数：\n清理其他batch的梯度 对之前得到的这个batch的平均损失求梯度 反向传播 更新参数 梯度不累计，每个batch一清理\n参数累计\nD. 攻击算法 sgaa 扰动逻辑\n把perturb当做参数，放入传统神经网络中进行优化 逻辑同深度学习： fsgm 扰动逻辑\nperturb_i = (self.eplison*torch.sum(abun_adv.grad, dim=0).unsqueeze(0).sign()).detach() # 沿着丰度梯度正方向，计算扰动增量 perturb = torch.clamp(perturb+perturb_i, min=-self.eplison, max=self.eplison).detach() # 分离计算图，当做常数，切断上游梯度传递，切断上游参数对梯度的影响，但每次迭代，上游参数的改变会刷新这个分离出的perturb “上游”？：\n参数： $\\mathbf{W}$ (需要梯度的参数) 中间计算： $\\mathbf{A} = \\mathbf{W} \\cdot 2$ 损失 1 (L1)： $\\mathbf{L_1} = \\mathbf{A} \\cdot 5$ 损失 2 (L2)： $\\mathbf{L_2} = \\mathbf{A} \\cdot 10$\n该例子的计算图如下 不涉及optimizer，通过分离计算图获取perturb并在每一次样本训练下更新\n","permalink":"https://Authentic-1412.github.io/posts/hsi%E6%94%BB%E5%87%BB/","summary":"\u003ch1 id=\"hsi攻击\"\u003eHSI攻击\u003c/h1\u003e\n\u003ch2 id=\"a-高光谱图像数据集\"\u003eA. 高光谱图像数据集\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003e高光谱：像素的记录格式不再是rgb，而是按照光谱波段记录\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch3 id=\"indian-pine\"\u003eIndian pine\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e只有一张图片，分辨率为145*145\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e该图片的每个像素作为一个样本，每个像素都由一个200个数字描述，表示各个波段的反射强度，理论上属于0-1\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e这张图拍的主要为\u003cstrong\u003e农作物\u003c/strong\u003e，共有16个类别，即10249个样本对应16个类别，包括草地、玉米地、林地等\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eIndian Pines 数据集的规模: 145*145*200 (width height 波段数)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e下载得到的数据集形式\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIndian_pines.mat ：原始的Indian Pines 数据集: 145*145*220\u003cbr\u003e\u003c/li\u003e\n\u003cli\u003eIndian_pines_corrected.mat 矫正后的Indian Pines 数据集: 145*145*200\u003cbr\u003e\u003c/li\u003e\n\u003cli\u003eIndian_pines_gt.mat 标签矩阵 145*145\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cem\u003e部分内容引自\u003ca href=\"https://zhuanlan.zhihu.com/p/347442423\"\u003e知乎\u003c/a\u003e\u003c/em\u003e\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eAVIRIS 成像光谱仪成像波长范围为 0.4-2.5μm，是在连续的 220 个波段对地物连续成像的，但是由于第 104-108，第 150-163 和第 220 个波段不能被水反射，因此，我们一般使用的是剔除了这 20 个波段后剩下的 200 个波段作为研究的对象。\u003c/li\u003e\n\u003cli\u003e145*145 = 21025=10776（背景，黑）+ 10249（多种地物，彩）\u003cbr\u003e\n\u0026gt; 10249 = 各类地物占得像素个数。\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"解混\"\u003e解混\u003c/h2\u003e\n\u003cp\u003e\u003cimg alt=\"jiehun\" loading=\"lazy\" src=\"/image/jiehun.jpg\"\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e我们对\u003cstrong\u003e丰度矩阵A\u003c/strong\u003e添加扰动，丰度矩阵表示每个像素中不同端元的占比，端元库表示不同端元（纯净）在光谱中200个波段下的值\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"b-universal-perturbation\"\u003eB. Universal Perturbation\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e算法：在每一轮迭代中都找到$\\Delta v$\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"c-经典神经网络的训练逻辑\"\u003eC. 经典神经网络的训练逻辑\u003c/h2\u003e\n\u003ch3 id=\"dataloader\"\u003eDataLoader\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003e一个迭代器\u003c/strong\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cblockquote\u003e\n\u003c/blockquote\u003e\n\u003cpre\u003e\u003ccode\u003epbar = tqdm(enumerate(attack_loader), total=len(attack_loader)) \n    for index, (_, abun, abun_sum, noise, labels, _) in pbar: \n    # 每次迭代使用一个batch的数据来更新扰动（正常32个，但如果最后一组样本量不足32，那就不足32，不舍弃）\n\u003c/code\u003e\u003c/pre\u003e\n\u003cblockquote\u003e\n\u003cp\u003e用for迭代，每次迭代使用一个batch的数据来更新扰动（正常32个，但如果最后一组样本量不足32，那就不足32，不舍弃）\u003c/p\u003e","title":"HSI攻击"},{"content":"记录学习k230的过程\n25.11.11 准备工作、学习摄像模块 准备工作 固件烧录 例程复现 找到了ocr（文字识别）现成例程 小声：结合多平台教程文档，如01studio或嘉楠等等，这个没有的例程，另一个说不定有呢 摄像模块 k230摄像头架构 板子最多搭载三个摄像头 每个摄像头可以接入三个不同的处理模块（对输入图像进行加工处理） 每个模块（camera_device）有三个输出通道，可以多输出并行 摄像头模块编程 sensor基础语法\n创建处理模块 1 2 from media.sensor import * sensor = Sensor(id ,width ,height ,fps) # 实例化，对应架构中的处理模块 id：摄像头id，默认为2\nwidth ,height ,fps:最大输出图像参数 设置图像输出大小和位置\n1 2 3 4 sensor.reset() # 初始化sensor对象及传感器 sensor.set_framesize(chn=CAM_CHN_ID_0, width=640, height=480) sensor.set_framesize(chn=CAM_CHN_ID_3, framesize = Sensor.VGA) framesize参数对应width、height，表示输出图像分辨率，二者作用相同。\nframesize = Sensor.VGA即表示640*480分辨率，除此之外，还有Sensor.HD等表示分辨率的代号，这些代号统称为图像帧尺寸\nchn:channel_number,表示输出通道，即架构中每个模块的三个输出通道 设置图像怎么输出、输出位置\nsensor.set_pixformat(pix_format, chn=CAM_CHN_ID_0) pix_format:输出图像的像素格式，即每个像素在计算机中如何存储，也就是RGB三个通道数据用多少位存储。\n常用有：\nRGB565：R for 5 bits ; G for 6 bits ; B for 5 bits RGB888: R G B for 8 bits respectively 水平与竖直反转 sensor.set_hmirror(True) # 水平 sensor.set_vflip(False) # 竖直 启动、关闭摄像头 sensor.run() sensor.stop() 多个摄像头只用启动一次，但要分别关闭\n指定通道截一帧图片 sensor.snapshot(chn=CAM_CHN_ID_0) 默认为0设备0通道\n25.11.13 GPIO GPIO 原理明确\n硬件之间的通信必须经过通信协议，常用的通信协议有IIC\\SPI\\UART\\CAN\\HTTP等等 这些“通信协议”是一种规则，在硬件上的体现为实现信息收发的逻辑电路，可以作为模块嵌入到MPU芯片里。 当然，不是所有的协议都软硬兼修，HTTP协议就是纯软件协议\n通过设置外设的状态，及外设对应的寄存器的值，实现与外界的交互。\n例如将某引脚（GPIOA_1）设置为输入模式，然后访问指定端口 GPIOx 的 输入数据寄存器（IDR）的值,看引脚的值为高电平还是低电平，外界传给中央的信号（斜体的部分由GPIO_ReadInputDataBit函数完成）\n名词解释\nP-mos N-mos：三极管，作用相当于受电压控制的开关，它俩区别是，P为低于阈值导通，N为超出阈值导通 串口：特指UART协议的硬件电路部分，信息流向：\nMPU ——\u0026gt; 引脚 ——\u0026gt; 串口（片内外设的一种） ——\u0026gt; 外接设备（片外外设） （一个串口可能会用到许多引脚） 外设：片内外设：通信协议等硬件的逻辑电路模块，本质上是把数据、奇偶校验、等等一系列的流程集成到一个电路模块上，可以装在芯片内部；片外外设：与芯片连接的模块，在芯片外面 GPIO干嘛用的？\n四大功能：输入、输出、模拟、复用\n输入 片内外设向MPU输入 分类 下拉输入：无外部输入信号时，MPU读到低电平，只有外部输入为高电平时，MPU才能读到高电平 上拉输入：无外部输入信号时，MPU读到高电平，与上面同理 悬空输入：引脚的电平状态完全由外部输入决定 模拟输入：能接受模拟信号，通过ADC（模数转换器）转为数字信号，传递给MPU 输出 MPU向片内外设输出 分类 推挽输出：P-mos、N-mos均工作（不同时工作），可以主动输出高、低电平 开漏输出：只有N-mos工作，只能主动输出低电平，输出高电平要靠上拉电阻拉上去 # micropython from machine import Pin pin = Pin(index, mode, pull=Pin.PULL_NONE, drive=7) machine.Pin ：控制引脚的输入输出状态 index : 引脚编号\nmode:\nPin.IN Pin.OUT\npull:\nPULL_UP PULL_DOWN PULL_NONE(默认) drive: io驱动能力，默认为7\n复用 此时GPIO像一个容器，可以对应连接到MPU内部的IIC、SPI、UART等协议的硬件模块，所谓通信协议的硬件模块，本质上是把数据、奇偶校验、等等一系列的流程集成到一个电路模块上，也就是通信协议的物理层面实现，随后该引脚与片外外设通过对应的协议通信。 一个GPIO不能同时连接多个协议模块，故要通过编程选择。 **k230芯片共有63个引脚，开发版上可复用引脚有40个，编写代码时用到的pin_index是芯片上引脚的序号，芯片上引脚与开发板上引脚的GPIO序号通常是一致的，例如，fpioa.set_founction(3, FPIOA.UART0_TXD)这里的3在芯片上为第三个引脚，在开发板上为GPIO3。如果某个芯片引脚的序号在GPIO上没有对应的序号，则说明这个引脚可能被其他外设占用了（比如串口的GH1.25-4P座子） 1 2 3 4 5 6 7 8 9 10 11 12 13 14 from machine import FPIOA fpioa = FPIOA() # 实例化 # 查看引脚信息 fpioa.help() # 所有引脚的详细信息 fpioa.help(1) # 引脚1的详细信息 fpioa.help(1,func=False) # 同上 fpioa.help(1,func=True) # 功能1的详细信息（功能编码在 [这里](https://wiki.lckfb.com/zh-hans/lushan-pi-k230/basic/gpio-fpioa.html) # 复用 fpioa.set_founction(3, FPIOA.UART0_TXD) # 把第3个引脚复用为串口0的TX脚 fpioa.get_pin_num(FPIOA.UART0_TXD) # 哪些引脚被配置为UART0_TXD fpioa.get_pin_func(63) # 查看63号引脚的被配置为什么功能 模拟 通过输入、输出模式配置、电平高低变化模拟通信协议，即把硬件外设的功能通过软件模拟了一遍 k230的GPIO引脚没有adc，不能模拟\n总结\nGPIO四大功能：输入、输出、模拟、复用 GPIO可编程，体现为其模拟功能。 25.11.15. GPIO各功能代码示例 25.11.19. UART发送ocr结果 原理明确 不同level的电子设备是不同的圈子，圈子间遵循的通信协议不一样。电脑间遵守USB协议，而嵌入式中一般遵循UART/TTL协议。\n信息的本质是电压变化，TTL（Transistor-Transistor Logic）将电压变化转变为一串0-1信号，而UART（异步串行通信协议）将这串0-1信号按规则进行组织，譬如组织为\n起始位\u0026ndash;数据位\u0026ndash;校验位\u0026ndash;终止位\n随后将组织好的信号传输出去，对面再按这个规则解密就好啦！当然，这是同一圈子内通信\n不同圈子之间通信就要涉及硬件电路了，结合之前片内外设的定义，用硬件电路实现通信并不难理解。比如电脑和单片机间的通信就要通过usb转ttl模块来完成。\nk230端发送数据代码 点击展开查看 OCR 源码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 # ocr源码 from libs.PipeLine import PipeLine, ScopedTiming from libs.AIBase import AIBase from libs.AI2D import Ai2d import os import ujson from media.media import * from media.sensor import * from time import * import nncase_runtime as nn import ulab.numpy as np import time import image import aicube import random import gc import sys from machine import UART,FPIOA # 自定义OCR检测类 class OCRDetectionApp(AIBase): def __init__(self, kmodel_path, model_input_size, mask_threshold=0.5, box_threshold=0.2, rgb888p_size=[224,224], display_size=[1920,1080], debug_mode=0): super().__init__(kmodel_path,model_input_size,rgb888p_size,debug_mode) self.kmodel_path=kmodel_path # 模型输入分辨率 self.model_input_size=model_input_size # 分类阈值 self.mask_threshold=mask_threshold self.box_threshold=box_threshold # sensor给到AI的图像分辨率 self.rgb888p_size=[ALIGN_UP(rgb888p_size[0],16),rgb888p_size[1]] # 显示分辨率 self.display_size=[ALIGN_UP(display_size[0],16),display_size[1]] self.debug_mode=debug_mode # Ai2d实例，用于实现模型预处理 self.ai2d=Ai2d(debug_mode) # 设置Ai2d的输入输出格式和类型 self.ai2d.set_ai2d_dtype(nn.ai2d_format.NCHW_FMT,nn.ai2d_format.NCHW_FMT,np.uint8, np.uint8) # 配置预处理操作，这里使用了pad和resize，Ai2d支持crop/shift/pad/resize/affine，具体代码请打开/sdcard/libs/AI2D.py查看 def config_preprocess(self,input_image_size=None): with ScopedTiming(\u0026#34;set preprocess config\u0026#34;,self.debug_mode \u0026gt; 0): # 初始化ai2d预处理配置，默认为sensor给到AI的尺寸，您可以通过设置input_image_size自行修改输入尺寸 ai2d_input_size=input_image_size if input_image_size else self.rgb888p_size top,bottom,left,right=self.get_padding_param() self.ai2d.pad([0,0,0,0,top,bottom,left,right], 0, [0,0,0]) self.ai2d.resize(nn.interp_method.tf_bilinear, nn.interp_mode.half_pixel) self.ai2d.build([1,3,ai2d_input_size[1],ai2d_input_size[0]],[1,3,self.model_input_size[1],self.model_input_size[0]]) # 自定义当前任务的后处理 def postprocess(self,results): with ScopedTiming(\u0026#34;postprocess\u0026#34;,self.debug_mode \u0026gt; 0): # chw2hwc hwc_array=self.chw2hwc(self.cur_img) # 这里使用了aicube封装的接口ocr_post_process做后处理,返回的det_boxes结构为[[crop_array_nhwc,[p1_x,p1_y,p2_x,p2_y,p3_x,p3_y,p4_x,p4_y]],...] det_boxes = aicube.ocr_post_process(results[0][:,:,:,0].reshape(-1), hwc_array.reshape(-1),self.model_input_size,self.rgb888p_size, self.mask_threshold, self.box_threshold) return det_boxes # 计算padding参数，在config_preprocess中使用 def get_padding_param(self): # 右padding或下padding dst_w = self.model_input_size[0] dst_h = self.model_input_size[1] input_width = self.rgb888p_size[0] input_high = self.rgb888p_size[1] ratio_w = dst_w / input_width ratio_h = dst_h / input_high if ratio_w \u0026lt; ratio_h: ratio = ratio_w else: ratio = ratio_h new_w = (int)(ratio * input_width) new_h = (int)(ratio * input_high) dw = (dst_w - new_w) / 2 dh = (dst_h - new_h) / 2 top = (int)(round(0)) bottom = (int)(round(dh * 2 + 0.1)) left = (int)(round(0)) right = (int)(round(dw * 2 - 0.1)) return top, bottom, left, right # chw2hwc def chw2hwc(self,features): ori_shape = (features.shape[0], features.shape[1], features.shape[2]) c_hw_ = features.reshape((ori_shape[0], ori_shape[1] * ori_shape[2])) hw_c_ = c_hw_.transpose() new_array = hw_c_.copy() hwc_array = new_array.reshape((ori_shape[1], ori_shape[2], ori_shape[0])) del c_hw_ del hw_c_ del new_array return hwc_array # 自定义OCR识别任务类 class OCRRecognitionApp(AIBase): def __init__(self,kmodel_path,model_input_size,dict_path,rgb888p_size=[1920,1080],display_size=[1920,1080],debug_mode=0): super().__init__(kmodel_path,model_input_size,rgb888p_size,debug_mode) # kmodel路径 self.kmodel_path=kmodel_path # 识别模型输入分辨率 self.model_input_size=model_input_size self.dict_path=dict_path # sensor给到AI的图像分辨率，宽16字节对齐 self.rgb888p_size=[ALIGN_UP(rgb888p_size[0],16),rgb888p_size[1]] # 视频输出VO分辨率，宽16字节对齐 self.display_size=[ALIGN_UP(display_size[0],16),display_size[1]] # debug模式 self.debug_mode=debug_mode self.dict_word=None # 读取OCR的字典 self.read_dict() self.ai2d=Ai2d(debug_mode) self.ai2d.set_ai2d_dtype(nn.ai2d_format.RGB_packed,nn.ai2d_format.NCHW_FMT,np.uint8, np.uint8) # 配置预处理操作，这里使用了pad和resize，Ai2d支持crop/shift/pad/resize/affine，具体代码请打开/sdcard/libs/AI2D.py查看 def config_preprocess(self,input_image_size=None,input_np=None): with ScopedTiming(\u0026#34;set preprocess config\u0026#34;,self.debug_mode \u0026gt; 0): ai2d_input_size=input_image_size if input_image_size else self.rgb888p_size top,bottom,left,right=self.get_padding_param(ai2d_input_size,self.model_input_size) self.ai2d.pad([0,0,0,0,top,bottom,left,right], 0, [0,0,0]) self.ai2d.resize(nn.interp_method.tf_bilinear, nn.interp_mode.half_pixel) # 如果传入input_np，输入shape为input_np的shape,如果不传入，输入shape为[1,3,ai2d_input_size[1],ai2d_input_size[0]] self.ai2d.build([input_np.shape[0],input_np.shape[1],input_np.shape[2],input_np.shape[3]],[1,3,self.model_input_size[1],self.model_input_size[0]]) # 自定义后处理，results是模型输出的array列表 def postprocess(self,results): with ScopedTiming(\u0026#34;postprocess\u0026#34;,self.debug_mode \u0026gt; 0): preds = np.argmax(results[0], axis=2).reshape((-1)) output_txt = \u0026#34;\u0026#34; for i in range(len(preds)): # 当前识别字符不是字典的最后一个字符并且和前一个字符不重复（去重），加入识别结果字符串 if preds[i] != (len(self.dict_word) - 1) and (not (i \u0026gt; 0 and preds[i - 1] == preds[i])): output_txt = output_txt + self.dict_word[preds[i]] return output_txt # 计算padding参数 def get_padding_param(self,src_size,dst_size): # 右padding或下padding dst_w = dst_size[0] dst_h = dst_size[1] input_width = src_size[0] input_high = src_size[1] ratio_w = dst_w / input_width ratio_h = dst_h / input_high if ratio_w \u0026lt; ratio_h: ratio = ratio_w else: ratio = ratio_h new_w = (int)(ratio * input_width) new_h = (int)(ratio * input_high) dw = (dst_w - new_w) / 2 dh = (dst_h - new_h) / 2 top = (int)(round(0)) bottom = (int)(round(dh * 2 + 0.1)) left = (int)(round(0)) right = (int)(round(dw * 2 - 0.1)) return top, bottom, left, right def read_dict(self): if self.dict_path!=\u0026#34;\u0026#34;: with open(dict_path, \u0026#39;r\u0026#39;) as file: line_one = file.read(100000) line_list = line_one.split(\u0026#34;\\r\\n\u0026#34;) self.dict_word = {num: char.replace(\u0026#34;\\r\u0026#34;, \u0026#34;\u0026#34;).replace(\u0026#34;\\n\u0026#34;, \u0026#34;\u0026#34;) for num, char in enumerate(line_list)} class OCRDetRec: def __init__(self, ocr_det_kmodel, ocr_rec_kmodel, det_input_size, rec_input_size, dict_path, mask_threshold=0.25, box_threshold=0.3, rgb888p_size=[1920,1080], display_size=[1920,1080], debug_mode=0): # OCR检测模型路径 self.ocr_det_kmodel=ocr_det_kmodel # OCR识别模型路径 self.ocr_rec_kmodel=ocr_rec_kmodel # OCR检测模型输入分辨率 self.det_input_size=det_input_size # OCR识别模型输入分辨率 self.rec_input_size=rec_input_size # 字典路径 self.dict_path=dict_path # 置信度阈值 self.mask_threshold=mask_threshold # nms阈值 self.box_threshold=box_threshold # sensor给到AI的图像分辨率，宽16字节对齐 self.rgb888p_size=[ALIGN_UP(rgb888p_size[0],16),rgb888p_size[1]] # 视频输出VO分辨率，宽16字节对齐 self.display_size=[ALIGN_UP(display_size[0],16),display_size[1]] # debug_mode模式 self.debug_mode=debug_mode self.ocr_det=OCRDetectionApp(self.ocr_det_kmodel, model_input_size=self.det_input_size,mask_threshold=self.mask_threshold,box_threshold=self.box_threshold,rgb888p_size=self.rgb888p_size,display_size=self.display_size, debug_mode=0) self.ocr_rec=OCRRecognitionApp(self.ocr_rec_kmodel, model_input_size=self.rec_input_size,dict_path=self.dict_path, rgb888p_size=self.rgb888p_size,display_size=self.display_size) self.ocr_det.config_preprocess() # run函数 def run(self,input_np): # 先进行OCR检测 det_res=self.ocr_det.run(input_np) boxes=[] ocr_res=[] for det in det_res: # 对得到的每个检测框执行OCR识别 self.ocr_rec.config_preprocess(input_image_size=[det[0].shape[2],det[0].shape[1]],input_np=det[0]) ocr_str=self.ocr_rec.run(det[0]) ocr_res.append(ocr_str) boxes.append(det[1]) gc.collect() return boxes,ocr_res # 绘制OCR检测识别效果 def draw_result(self,pl,det_res,rec_res): pl.osd_img.clear() if det_res: # 循环绘制所有检测到的框 for j in range(len(det_res)): # 将原图的坐标点转换成显示的坐标点，循环绘制四条直线，得到一个矩形框 for i in range(4): x1 = det_res[j][(i * 2)] / self.rgb888p_size[0] * self.display_size[0] y1 = det_res[j][(i * 2 + 1)] / self.rgb888p_size[1] * self.display_size[1] x2 = det_res[j][((i + 1) * 2) % 8] / self.rgb888p_size[0] * self.display_size[0] y2 = det_res[j][((i + 1) * 2 + 1) % 8] / self.rgb888p_size[1] * self.display_size[1] pl.osd_img.draw_line((int(x1), int(y1), int(x2), int(y2)), color=(255, 0, 0, 255),thickness=5) # 在检测框位置显示识别的文字 pl.osd_img.draw_string_advanced(int(x1),int(y1),32,rec_res[j],color=(0,0,255)) if __name__==\u0026#34;__main__\u0026#34;: UART_TX_PIN = 5 UART_RX_PIN = 6 UART_ID = 2 BAUDRATE = 115200 # 初始化fpioa和uart fpioa = FPIOA() fpioa.set_function(UART_TX_PIN, FPIOA.UART2_TXD) fpioa.set_function(UART_RX_PIN, FPIOA.UART2_RXD) uart = UART(UART_ID , BAUDRATE) print(fpioa.help(12)) print(fpioa.help(13)) # 显示模式，可以选择\u0026#34;hdmi\u0026#34;、\u0026#34;lcd3_5\u0026#34;(3.5寸mipi屏)和\u0026#34;lcd2_4\u0026#34;(2.4寸mipi屏) # 配置显示模式 display=\u0026#34;lcd3_5\u0026#34; if display==\u0026#34;hdmi\u0026#34;: display_mode=\u0026#39;hdmi\u0026#39; display_size=[1920,1080] elif display==\u0026#34;lcd3_5\u0026#34;: display_mode= \u0026#39;st7701\u0026#39; display_size=[800,480] elif display==\u0026#34;lcd2_4\u0026#34;: display_mode= \u0026#39;st7701\u0026#39; display_size=[640,480] rgb888p_size=[640,360] #特殊尺寸定义 # OCR检测模型路径 ocr_det_kmodel_path=\u0026#34;/sdcard/examples/kmodel/ocr_det_int16.kmodel\u0026#34; # OCR识别模型路径 ocr_rec_kmodel_path=\u0026#34;/sdcard/examples/kmodel/ocr_rec_int16.kmodel\u0026#34; # 其他参数 dict_path=\u0026#34;/sdcard/examples/utils/dict.txt\u0026#34; # 系统参数 不可改 ocr_det_input_size=[640,640] ocr_rec_input_size=[512,32] # 可改 mask_threshold=0.25 box_threshold=0.3 # 初始化PipeLine，只关注传给AI的图像分辨率，显示的分辨率 pl=PipeLine(rgb888p_size=rgb888p_size, display_size=display_size, display_mode=display_mode) if display ==\u0026#34;lcd2_4\u0026#34;: pl.create(Sensor(width=1280, height=960)) # 创建PipeLine实例，画面4:3 else: pl.create(Sensor(width=1920, height=1080)) # 创建PipeLine实例 ocr=OCRDetRec(ocr_det_kmodel_path, ocr_rec_kmodel_path, det_input_size=ocr_det_input_size,rec_input_size=ocr_rec_input_size, dict_path=dict_path, mask_threshold=mask_threshold, box_threshold=box_threshold, rgb888p_size=rgb888p_size, display_size=display_size) clock = time.clock() # 发送数据的细节处理函数 def send_ocr_data(text, x, y): try: # 数据清洗：去掉文字里可能存在的逗号或换行，防止破坏协议 clean_text = text.replace(\u0026#39;,\u0026#39;, \u0026#39;.\u0026#39;).replace(\u0026#39;\\n\u0026#39;, \u0026#39;\u0026#39;).strip() # 针对字符串类型数据 # 协议格式: @文字,X,Y# packet = \u0026#34;@{},{},{}#\u0026#34;.format(clean_text, x, y) # 编码并发送 uart.write(packet.encode(\u0026#39;utf-8\u0026#39;)) print(f\u0026#34;[UART发送] {packet}\u0026#34;) # 调试用 except Exception as e: print(f\u0026#34;发送失败: {e}\u0026#34;) # 发送时间 last_send_time = 0 SEND_INTERVAL_MS = 100 # 发送间隔100ms 每秒最多10张 while True: # clock.tick() os.exitpoint() # 防卡死机制 img=pl.get_frame() # 获取当前帧 boxes,rec_res=ocr.run(img) # 推理当前帧 if boxes: ocr.draw_result(pl,boxes,rec_res) # 绘制当前帧推理结果 print(boxes,rec_res) # 打印结果 pl.show_image() # 展示当前帧推理结果 current_time = time.ticks_ms() can_send = (time.ticks_diff(current_time, last_send_time) \u0026gt;= SEND_INTERVAL_MS) if can_send: # target = det_res[0] # 只发送第一个检测框 raw_text = rec_res[0] # 文本 rect = boxes[0] # 检测框四个角的坐标 # 计算检测框中心点坐标 center_x = (rect[0] + rect[2] + rect[4] + rect[6]) / 4 center_y = (rect[1] + rect[3] + rect[5] + rect[7]) / 4 # 2. 新增：转换为 STM32 的 240x320 坐标 # 原图宽 640 -\u0026gt; 目标宽 240 scaled_x = int((center_x / 640) * 1920) # 原图高 360 -\u0026gt; 目标高 320 scaled_y = int((center_y / 360) * 1080) # 发送检测框中心点坐标 send_ocr_data(raw_text, scaled_x, scaled_y) last_send_time = current_time gc.collect() 更改说明\n代码在0-1studio官方ocr例程上改动，更改了主程序部分，添加工具函数send_ocr_data 串口定义 发送逻辑(主函数)：\n捕捉当前帧 ——\u0026gt; 推理识别 ——\u0026gt; 满足发送条件（时间间隔）——\u0026gt; 发送\n分辨率变化流：\nSensor input (1920*1080) \u0026mdash;\u0026gt; Pipeline (rgb888p：640*360) \u0026mdash;\u0026gt; orc_dec input(640*640) \u0026mdash;\u0026gt; orc_rec input(512*32) \u0026mdash;\u0026gt; output(640*360) \u0026mdash;\u0026gt; send (1920*1080)\nstm32接收到一个坐标和对应的字符串，它需要确定这个坐标数字在实际视野中的位置，也就是比例，故需要事先告诉stm32视野的范围为多少，也就是send时发送的坐标所使用的坐标系（也就是分辨率），它可以为任意（即通过主函数中转换坐标部分实现），声明清楚接受到的数字的“地图边界”是几，即可计算比例与转动角度。 代码心得\n找到代码逻辑：\n从主函数开始看，搞懂每一行的作用，并链接到哪个模块实现了这个功能 对各个模块，也就是各个类、实例、方法总体浏览一遍，搞懂每个模块的作用，一句话写注释 参数传递（重要！） 模块之间层层嵌套，要理清爽数据流（输入数据经过哪些模块、哪些处理，变成怎样的输出）。分清形参和实参，别被名字骗了 有一些逻辑是打包封装好的，譬如Pipeline中的pl.create(),这种背后的工作流就会藏得很深，慢慢修炼吧~\n26.1.28. 基于颜色色块识别实现地图识别 1. 语法解释 img = sensor.snapshot() blobs = img.find_blobs([black_threshold], pixels_threshold=500, merge=True, margin=15) img.find_blobs：寻找色块的函数\n参数 [black_threshold]：列表，其中每个元素是一个元组，例如black_threshold = (0, 20, -10, 10, -10, 10)，用于定义目标颜色的检测阈值，分别描述这个颜色对应的LAB的最大最小值\n可以包含多个颜色，也就是多个元组，寻找时取并集，并自动对每种颜色二进制编码，例如：\n匹配了第一个阈值的色块，code = 1 (二进制 $2^0$)。 匹配了第二个阈值的色块，code = 2 (二进制 $2^1$)。 匹配了第三个阈值的色块，code = 4 (二进制 $2^2$)。\n应用时使用CanMV IDE的阈值编辑器确定阈值，达到：目标颜色为白色，其余全部为黑色。滑动阈值调整时会发现，对于六个中的每一个参数，满足目标黑白二值状态的值是一个范围，注意不要取这个范围的端点，因为端点值处于识别变化的临界，易受到外界的干扰，鲁棒性低。要取范围中间的值。 pixel_threshold：像素阈值，检测到的总像素小于这个值的色块将会被过滤 merge：合并色块，合并所有没有被过滤的色块。margin参数存在时，还要求这两个色块之间最靠近的像素点距离 $\\le$ margin此时函数返回的对象就是合并后的大色块\n若一个色块同时包含了两种颜色（比如你把红苹果和绿叶子合并成一个大色块），这个大色块的code是其中颜色的code之和，它的 code 就会变成 $1 + 2 = 3$。你可以用blob.code()查看 常用的参数就是这些，下面是其他参数 输出 函数返回一个list：[(x, y, w, h, pixels, cx, cy, rotation, code, count, area, density),(),()...]，这个list的每个元素是一个对象，每个对象有这些属性： rect：blob.rect() 描述颜色块的（x,y,w,h）:左上角坐标、width、hight pixels：blob.pixels()或blob[4] 色块中的像素数 cy cx：x和y的中心点 rotation：目标在画面中是横着的（ $0$ 或 $\\pi$）、竖着的（$\\pi/2$ 约 1.57）还是斜着的。 code：颜色编码 count：合并为该色块的多个色块的数量。只有在调用 image.find_blobs 时设置 merge=True，此数字才会大于1，注意和颜色无关 area：返回色块周围边框的面积（计算方式为 w * h） density：实心色块检测时，密度越小，检测准确度越小 $$Density = \\frac{Pixels（色块实际像素点数）}{Width \\times Height（外接矩形的面积）}$$ 2. 举例：定位水果位置 点击展开查看源码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 import sys import time, os, sys, gc from media.sensor import * from media.display import * from machine import UART,FPIOA # 1. 定义颜色阈值 (LAB 空间) # 黑色网格阈值 (需要根据现场光照微调) black_threshold = (0, 20, -10, 10, -10, 10) # 红色苹果阈值 #apple_threshold = (30, 70, 40, 80, 10, 60) #apple_threshold = (26, 100, 7, 109, 127, -10) apple_threshold = (10, 80, 14, 103, 89, -32) DETECT_WIDTH = ALIGN_UP(320, 16) DETECT_HEIGHT = 240 sensor = None uart = None def camera_init(): global sensor # construct a Sensor object with default configure sensor = Sensor(width=DETECT_WIDTH,height=DETECT_HEIGHT) # sensor reset sensor.reset() # set hmirror # sensor.set_hmirror(False) # sensor vflip # sensor.set_vflip(False) # set chn0 output size sensor.set_framesize(width=DETECT_WIDTH,height=DETECT_HEIGHT) # set chn0 output format sensor.set_pixformat(Sensor.RGB565) # use IDE as display output Display.init(Display.VIRT, width= DETECT_WIDTH, height = DETECT_HEIGHT,fps=100,to_ide = True) # init media manager MediaManager.init() # sensor start run sensor.run() def camera_deinit(): global sensor # sensor stop run sensor.stop() # deinit display Display.deinit() # sleep os.exitpoint(os.EXITPOINT_ENABLE_SLEEP) time.sleep_ms(100) # release media buffer MediaManager.deinit() def check_roi(roi, img_w=320, img_h=240): rx, ry, rw, rh = roi # 确保起点不小于 0 rx = max(0, rx) ry = max(0, ry) # 确保宽高不为负数或 0 rw = max(1, rw) rh = max(1, rh) # 确保终点不超出图像边界 if rx + rw \u0026gt; img_w: rw = img_w - rx if ry + rh \u0026gt; img_h: rh = img_h - ry return (rx, ry, rw, rh) def find_apples_in_grid(): while True: os.exitpoint() img = sensor.snapshot() # --- 步骤 A: 寻找黑色网格 (井字线) --- # merge=True 将被网格切断的黑色线条合并成一个大的对象 # margin=15 确保间距小于 15 像素的黑色部分被视为一体 blobs = img.find_blobs([black_threshold], pixels_threshold=500, merge=True, margin=15) if blobs: # blobs是一个列表，每个元素是一个对象，具有rect、pixels等属性 # print(\u0026#34;type of blobs\u0026#34;,type(blobs)) # list 列表不同位置是对象不同的属性值 print(\u0026#34;blobs\u0026#34;,blobs) # 寻找面积最大的黑色物体，通常就是整个网格阵列 big_blob = max(blobs, key=lambda x: x.pixels()) print(\u0026#34;-----------\u0026#34;) print(\u0026#34;merge number ares\u0026#34;,big_blob.count()) print(\u0026#34;density\u0026#34;,big_blob.density()) print(\u0026#34;rotation\u0026#34;,big_blob.rotation()) print(\u0026#34;-----------\u0026#34;) # 绘制网格的外接矩形（绿色） rect = big_blob.rect() # 元组 描述颜色块的（x,y,w,h）:左上角坐标、width、hight img.draw_rectangle(rect, color=(0, 255, 0), thickness=2) # --- 步骤 B: 逻辑切片 4x4 --- x, y, w, h = rect w_step = w // 4 h_step = h // 4 offset_w = w_step // 5 offset_h = h_step // 5 results = [] # 存储发现水果的坐标索引 for r in range(4): # 行号 0, 1, 2, 3 for c in range(4): # 列号 0, 1, 2, 3 # 计算当前小格子的感兴趣区域 (ROI) # 稍微缩小 ROI (加上 5 像素 offset)，避开边缘黑线的干扰 # roi = (x + c * w_step + 5, y + r * h_step + 5, w_step - 10, h_step - 10) roi = (x + c * w_step + offset_w, y + r * h_step + offset_h, w_step - 2*offset_w, h_step - 2*offset_h) roi = check_roi(roi) # 在这个 ROI 里寻找红色苹果 apple_blobs = img.find_blobs([apple_threshold], roi=roi, pixels_threshold=200) for j in apple_blobs: print(\u0026#34;apple density\u0026#34;,j.density()) if j.density()\u0026gt;=0.7: # 标记发现水果的格子（红色） img.draw_rectangle(roi, color=(255, 0, 0), thickness=2) # 记录坐标 (行列索引从 1 开始) results.append((r + 1, c + 1)) # --- 步骤 C: 打印并发送数据 --- if results: if big_blob.rotation()\u0026gt;=1.0 and big_blob.rotation()\u0026lt;=1.8: print(\u0026#34;识别结果 (行, 列):\u0026#34;, results) # 此处可添加串口代码: uart.write(str(results) + \u0026#39;\\n\u0026#39;) # 显示处理后的图像 Display.show_image(img) gc.collect() # 执行识别 def main(): os.exitpoint(os.EXITPOINT_ENABLE) camera_is_init = False UART_TX_PIN = 5 UART_RX_PIN = 6 UART_ID = 2 BAUDRATE = 115200 # 初始化fpioa和uart global uart fpioa = FPIOA() fpioa.set_function(UART_TX_PIN, FPIOA.UART2_TXD) fpioa.set_function(UART_RX_PIN, FPIOA.UART2_RXD) uart = UART(UART_ID , BAUDRATE) print(\u0026#34;camera init\u0026#34;) camera_init() print(\u0026#34;camera capture\u0026#34;) find_apples_in_grid() if __name__ == \u0026#34;__main__\u0026#34;: main() 结果\n原理 定位黑色外边框：blobs = img.find_blobs([black_threshold], pixels_threshold=500, merge=True, margin=15) 为什么只识别外边框，忽略内部网格？ 首先，寻找黑色矩形，在这里是黑色边框，由于pixels_threshold=500的限制，只有最外层大边框内的像素满足条件。\n其次，merge=True,因为网格线间的空白大于15像素，所以合并的是边框上的像素块，但合并后形成的roi覆盖边框及以内的全部区域，而内部小区域被覆盖，故结果仅识别最外层边框 ","permalink":"https://Authentic-1412.github.io/posts/%E8%A7%86%E8%A7%89-k230%E5%BC%80%E5%8F%91%E5%AE%9E%E8%B7%B5/","summary":"\u003cp\u003e\u003cem\u003e记录学习k230的过程\u003c/em\u003e\u003c/p\u003e\n\u003ch2 id=\"251111-准备工作学习摄像模块\"\u003e25.11.11 准备工作、学习摄像模块\u003c/h2\u003e\n\u003ch3 id=\"准备工作\"\u003e准备工作\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003e固件烧录\u003c/li\u003e\n\u003cli\u003e例程复现\u003c/li\u003e\n\u003cli\u003e找到了ocr（文字识别）现成例程 \u003cbr\u003e\n小声：\u003cstrong\u003e结合多平台教程文档，如01studio或嘉楠等等，这个没有的例程，另一个说不定有呢\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch3 id=\"摄像模块\"\u003e摄像模块\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003ek230摄像头架构\u003c/li\u003e\n\u003c/ol\u003e\n\u003cul\u003e\n\u003cli\u003e板子最多搭载三个摄像头\u003c/li\u003e\n\u003cli\u003e每个摄像头可以接入三个不同的处理模块（对输入图像进行加工处理）\u003c/li\u003e\n\u003cli\u003e每个模块（camera_device）有三个输出通道，可以多输出并行\u003c/li\u003e\n\u003c/ul\u003e\n\u003col start=\"2\"\u003e\n\u003cli\u003e摄像头模块编程\u003c/li\u003e\n\u003c/ol\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003esensor基础语法\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003e创建处理模块\u003c/strong\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e2\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"kn\"\u003efrom\u003c/span\u003e \u003cspan class=\"nn\"\u003emedia.sensor\u003c/span\u003e \u003cspan class=\"kn\"\u003eimport\u003c/span\u003e \u003cspan class=\"o\"\u003e*\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"n\"\u003esensor\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eSensor\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nb\"\u003eid\u003c/span\u003e \u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"n\"\u003ewidth\u003c/span\u003e \u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"n\"\u003eheight\u003c/span\u003e \u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"n\"\u003efps\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"c1\"\u003e# 实例化，对应架构中的处理模块\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cblockquote\u003e\n\u003col\u003e\n\u003cli\u003eid：摄像头id，默认为2\u003cbr\u003e\u003c/li\u003e\n\u003cli\u003ewidth ,height ,fps:\u003cstrong\u003e最大\u003c/strong\u003e输出图像参数\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/blockquote\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003e设置图像输出大小和位置\u003c/strong\u003e\u003cbr\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cdiv class=\"chroma\"\u003e\n\u003ctable class=\"lntable\"\u003e\u003ctr\u003e\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode\u003e\u003cspan class=\"lnt\"\u003e1\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e2\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e3\n\u003c/span\u003e\u003cspan class=\"lnt\"\u003e4\n\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\n\u003ctd class=\"lntd\"\u003e\n\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"n\"\u003esensor\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ereset\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e \u003cspan class=\"c1\"\u003e# 初始化sensor对象及传感器\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"n\"\u003esensor\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eset_framesize\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003echn\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"n\"\u003eCAM_CHN_ID_0\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003ewidth\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"mi\"\u003e640\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003eheight\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"mi\"\u003e480\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"n\"\u003esensor\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eset_framesize\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003echn\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"n\"\u003eCAM_CHN_ID_3\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003eframesize\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003eSensor\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eVGA\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/td\u003e\u003c/tr\u003e\u003c/table\u003e\n\u003c/div\u003e\n\u003c/div\u003e\u003cblockquote\u003e\n\u003col\u003e\n\u003cli\u003eframesize参数对应width、height，表示输出图像分辨率，二者作用相同。\u003cbr\u003e\u003c/li\u003e\n\u003cli\u003eframesize = Sensor.VGA即表示640*480分辨率，除此之外，还有Sensor.HD等表示分辨率的代号，这些代号统称为图像帧尺寸\u003cbr\u003e\u003c/li\u003e\n\u003cli\u003echn:channel_number,表示输出通道，即架构中每个模块的三个输出通道\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/blockquote\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003e设置图像怎么输出、输出位置\u003c/strong\u003e\u003cbr\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cblockquote\u003e\n\u003c/blockquote\u003e\n\u003cpre\u003e\u003ccode\u003e  sensor.set_pixformat(pix_format, chn=CAM_CHN_ID_0)\n\u003c/code\u003e\u003c/pre\u003e\n\u003cblockquote\u003e\n\u003col\u003e\n\u003cli\u003epix_format:输出图像的像素格式，即每个像素在计算机中如何存储，也就是RGB三个通道数据用多少位存储。\u003cbr\u003e\n常用有：\u003cbr\u003e\nRGB565：R for 5 bits ; G for 6 bits ; B for 5 bits \u003cbr\u003e\nRGB888: R G B for 8 bits respectively \u003cbr\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/blockquote\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003e水平与竖直反转\u003c/strong\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cblockquote\u003e\n\u003c/blockquote\u003e\n\u003cpre\u003e\u003ccode\u003e  sensor.set_hmirror(True) # 水平\n  sensor.set_vflip(False) # 竖直\n\u003c/code\u003e\u003c/pre\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003e启动、关闭摄像头\u003c/strong\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cblockquote\u003e\n\u003c/blockquote\u003e\n\u003cpre\u003e\u003ccode\u003e  sensor.run()\n  sensor.stop()\n\u003c/code\u003e\u003c/pre\u003e\n\u003cblockquote\u003e\n\u003cp\u003e多个摄像头只用启动一次，但要分别关闭\u003c/p\u003e","title":"视觉_K230开发实践"},{"content":"个人博客搭建 ==========================================================\nPart 1. hugo搭建并在本地预览 25.11.10. 创建博客总站 新建文件夹，存放你的博客。在该文件夹下运行 hugo new site .\n-初始化站点\n创建一篇文章 hugo new posts/这篇博客的名字.md\n然后，你可以看到在content/posts目录下多了一个md文档 编辑完成后将draft改为false，否则不在网页上显示 主题 git clone你喜欢的主题，并将文件复制到themes文件夹下 在hugo.toml（参数文档）中增加： theme = \u0026ldquo;hugo-PaperMod\u0026rdquo; 别忘记双引号！\n其他设置 在hugo.toml（参数文档）中 [params]\ndescription = \u0026ldquo;my first blog\u0026rdquo;\nauthor = \u0026ldquo;pearl\u0026rdquo;\n本地预览 终端输入 hugo server\n打开终端显示的域名即可 25.11.11 1. 补充：wsl中配置代理 之前登录时wsl会提示： wsl: 检测到 localhost 代理配置，但未镜像到 WSL。NAT 模式下的 WSL 不支持 localhost 代理。\n这句话有两点值得注意\nNAT模式：相当于wsl2运行在一个小虚拟机中，该虚拟机有自己的ip：通常为172. 镜像模式：作为localhost（windows本机）的镜像映射，windows有啥，wsl就有啥 配置WSL镜像 windows的用户目录（30743）下新建建立新文件.wslconfig并写入： [wsl2] networkingMode=mirrored\u0026lt; autoProxy=true 重启wsl 提示消失，wsl可以访问github Part 2. 部署到git page 25.11.14 根据网上“hugo + git page”教程配置即可 注意\nhugo # 构建站点，更新public文件夹 hugo server # 本地测试 不更新public中的网页 ","permalink":"https://Authentic-1412.github.io/posts/%E4%B8%AA%E4%BA%BA%E5%8D%9A%E5%AE%A2%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/","summary":"\u003ch1 id=\"个人博客搭建\"\u003e个人博客搭建\u003c/h1\u003e\n\u003cp\u003e==========================================================\u003c/p\u003e\n\u003ch2 id=\"part-1-hugo搭建并在本地预览\"\u003ePart 1. hugo搭建并在本地预览\u003c/h2\u003e\n\u003ch3 id=\"251110\"\u003e25.11.10.\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003e创建博客总站\u003c/li\u003e\n\u003c/ol\u003e\n\u003cul\u003e\n\u003cli\u003e新建文件夹，存放你的博客。在该文件夹下运行\u003c/li\u003e\n\u003c/ul\u003e\n\u003cblockquote\u003e\n\u003cp\u003ehugo new site .\u003cbr\u003e\n-初始化站点\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003col start=\"2\"\u003e\n\u003cli\u003e创建一篇文章\u003c/li\u003e\n\u003c/ol\u003e\n\u003cblockquote\u003e\n\u003cp\u003ehugo new posts/这篇博客的名字.md\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cul\u003e\n\u003cli\u003e然后，你可以看到在content/posts目录下多了一个md文档\u003c/li\u003e\n\u003cli\u003e编辑完成后将draft改为false，否则不在网页上显示\u003c/li\u003e\n\u003c/ul\u003e\n\u003col start=\"3\"\u003e\n\u003cli\u003e主题\u003c/li\u003e\n\u003c/ol\u003e\n\u003cul\u003e\n\u003cli\u003egit clone你喜欢的主题，并将文件复制到themes文件夹下\u003c/li\u003e\n\u003cli\u003e在hugo.toml（参数文档）中增加：\u003c/li\u003e\n\u003c/ul\u003e\n\u003cblockquote\u003e\n\u003cp\u003etheme = \u0026ldquo;hugo-PaperMod\u0026rdquo;\n\u003cstrong\u003e别忘记双引号！\u003c/strong\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003col start=\"4\"\u003e\n\u003cli\u003e其他设置\u003c/li\u003e\n\u003c/ol\u003e\n\u003cul\u003e\n\u003cli\u003e在hugo.toml（参数文档）中\u003c/li\u003e\n\u003c/ul\u003e\n\u003cblockquote\u003e\n\u003cp\u003e[params]\u003cbr\u003e\ndescription = \u0026ldquo;my first blog\u0026rdquo;\u003cbr\u003e\nauthor = \u0026ldquo;pearl\u0026rdquo;\u003cbr\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003col start=\"5\"\u003e\n\u003cli\u003e本地预览\u003c/li\u003e\n\u003c/ol\u003e\n\u003cul\u003e\n\u003cli\u003e终端输入\u003c/li\u003e\n\u003c/ul\u003e\n\u003cblockquote\u003e\n\u003cp\u003ehugo server\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cul\u003e\n\u003cli\u003e打开终端显示的域名即可\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"251111\"\u003e25.11.11\u003c/h3\u003e\n\u003ch4 id=\"1-补充wsl中配置代理\"\u003e1. 补充：wsl中配置代理\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e之前登录时wsl会提示：\u003c/li\u003e\n\u003c/ul\u003e\n\u003cblockquote\u003e\n\u003cp\u003ewsl: 检测到 localhost 代理配置，但未镜像到 WSL。NAT 模式下的 WSL 不支持 localhost 代理。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e这句话有两点值得注意\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eNAT模式：相当于wsl2运行在一个小虚拟机中，该虚拟机有自己的ip：通常为172.\u003c/li\u003e\n\u003cli\u003e镜像模式：作为localhost（windows本机）的镜像映射，windows有啥，wsl就有啥\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch5 id=\"配置wsl镜像\"\u003e配置WSL镜像\u003c/h5\u003e\n\u003col\u003e\n\u003cli\u003ewindows的用户目录（30743）下新建建立新文件.wslconfig并写入：\u003c/li\u003e\n\u003c/ol\u003e\n\u003cblockquote\u003e\n\u003c/blockquote\u003e\n\u003cpre\u003e\u003ccode\u003e[wsl2]\n\nnetworkingMode=mirrored\u0026lt;\n\nautoProxy=true\n\u003c/code\u003e\u003c/pre\u003e\n\u003col start=\"2\"\u003e\n\u003cli\u003e重启wsl 提示消失，wsl可以访问github\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"part-2-部署到git-page\"\u003ePart 2. 部署到git page\u003c/h2\u003e\n\u003ch3 id=\"251114\"\u003e25.11.14\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003e根据网上“hugo + git page”教程配置即可\u003c/li\u003e\n\u003c/ol\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cstrong\u003e注意\u003c/strong\u003e\u003c/p\u003e","title":"个人博客学习笔记"},{"content":"Hello World! I have borned! ","permalink":"https://Authentic-1412.github.io/posts/my-first-post/","summary":"\u003ch1 id=\"hello-world\"\u003eHello World!\u003c/h1\u003e\n\u003ch2 id=\"i-have-borned\"\u003eI have borned!\u003c/h2\u003e","title":"My First Post"}]