C#之Delta并联机械手的视觉相机标定与形状匹配

news2024/10/5 14:23:48

本文导读

上节课程我们讲述了如何建立Delta并联机械手正逆解,本节课程我们主要讲解如何通过C#语言开发正运动Delta并联机械手视觉流水线同步分拣的视觉部分。

VPLC711硬件介绍

VPLC711是正运动推出的一款基于x86平台和Windows操作系统的高性能机器视觉EtherCAT运动控制器,具备强大的运算能力和灵活性。它具有出色的实时性能和多路高速硬件输入与多路高速PSO输出,能够精准控制多轴同步运动,并与外部设备实现多协议的高速通信。

在这里插入图片描述

VPLC711支持多种硬件接口和通信协议,方便与其他设备的连接和集成。除此之外,VPLC711还具备视觉处理功能,能够实时处理图像数据,实现视觉检测、测量和定位等应用。

在这里插入图片描述

VPLC711内置Windows运动控制实时内核MotionRT7,形成一种开放式IPC形态实时软控制器/软PLC,为用户提供灵活集成的运动控制+视觉一体化解决方案。

在这里插入图片描述

VPLC711硬件参数

1.采用x86高性能CPU,EtherCAT可支持1ms 64轴同步运行;

2.板载RS232,RS485,EtherNet5,EtherCAT,USB3.04硬件接口;

3.板载20DI,其中4个高速色标锁存,2组高速单端编码器;

4.板载20DO,其中4个高速单端脉冲轴,4组高速PWM;

5.支持DVI-D,HDMI显示,支持双网口不同IP设置。

想要了解更多关于VPLC711的详情介绍,可以点击“x86平台实时Windows机器视觉EtherCAT运动控制器VPLC711”查看。

一、C#语言进行Delta并联机械手的开发之运动库和视觉库的添加

1.在VS2010菜单“文件”→“新建”→“项目”,启动创建项目向导。

在这里插入图片描述

2.选择开发语言为“Visual C#”和.NET Framework 4以及Windows窗体应用程序。

在这里插入图片描述

3.找到厂家提供的光盘资料里面的C#函数库,路径如下(32位库为例)。

1)进入厂商提供的光盘资料找到“04PC函数”文件夹,并点击进入。

在这里插入图片描述

2)选择“函数库2.1”文件夹。

在这里插入图片描述

3)选择“Windows平台”文件夹。

在这里插入图片描述

4)根据需要选择对应的函数库,这里选择32位库。

在这里插入图片描述

5)解压C#压缩包,里面有C#对应的函数库。

在这里插入图片描述

6)函数库具体路径如下。

在这里插入图片描述

4.将厂商提供的C#库文件以及相关文件复制到新建的项目中(注意这里面的PC函数库默认提供的是运动库,如果使用视觉功能还需要获取视觉库,视觉库可以找厂商的相关销售或技术人员获取)。

1)将Zmcaux.cs(运动库)和Zvision.cs(视觉库)文件复制到新建的项目里面中。

在这里插入图片描述

2)将zauxdll.dll、zmotion.dll和zvision.dll文件放入bin\debug文件夹中。

在这里插入图片描述

5.用vs打开新建的项目文件,在右边的解决方案资源管理器中点击显示所有文件,然后鼠标右击Zmcaux.cs与 Zvision.cs文件,点击包括在项目中。

在这里插入图片描述

6.双击Form1.cs里面的Form1,出现代码编辑界面,在文件开头写入using cszmcaux,using ZVision并声明控制器句柄g_handle。

在这里插入图片描述

二、PC函数介绍

1.PC函数手册可在光盘资料查看,具体路径如下。

在这里插入图片描述

2.链接控制器,获取链接句柄。

在这里插入图片描述

3.相机扫描接口说明。

在这里插入图片描述

4.相机采集图像。

在这里插入图片描述

5.用图像创建模板。

在这里插入图片描述

6.形状匹配并输出轮廓状态。

在这里插入图片描述

三、C#例程建设之视觉相机标定与形状匹配

1.视觉配置文件的下载

因为正运动的视觉算法是在控制器里面执行的,所以上位机开发前需要先在控制器里面定义好视觉处理的相关变量。

正运动控制器里面的视觉变量统一使用ZVOBJECT来修饰,我们可以新建一个.bas的文件,然后输入“GLOBAL ZVOBJECT ZVOBJ(1000)”进行视觉变量数组的定义,保存后通过上位机接口在上位机系统初始化的时候把这个.bas文件下载到控制器即可。

在这里插入图片描述

//下载相关脚本到控制器,进行视觉变量的定义
string BasPath = "";
BasPath = string.Format(@"{0}", Application.StartupPath) + @"\Icon\视觉变量定义.bas";
//.bas文件下载到控制器
zmcaux.ZAux_BasDown(g_Handle,BasPath,0);

2.相机标定

在这里插入图片描述

1)相机标定操作步骤

在这里插入图片描述

2)相关功能代码

/************************************************************************************
'任务编号:无
'函数功能:视觉提取标定板上实心圆的像素坐标,获取标定板圆心的像素坐标的矩阵
'Input:无
'Output:无 
'返回值:无             
**************************************************************************************/
private void GetPictureMark()
{
    float[] temp_thresh = new float[2];
    int Err = 0;
    //提取圆心图像坐标,得到像素坐标矩阵Inppts
    Err = Zvision.ZV_CALGETSCAPTS(form.g_Handle, grabimg, inppts, Convert.ToUInt32(C_CalibThresh.Text), Convert.ToUInt32(C_CalibPolar.Text), Convert.ToUInt32(C_CalibMinArea.Text), Convert.ToUInt32(C_CalibMaxArea.Text));
    int[] inppts_info = { 0, 0, 0 };
    //获取矩阵行数和列数,行数表示识别到实心圆的个数
    Err = Zvision.ZV_MATINFO(form.g_Handle, inppts, inppts_info);
    int row, col;
    row = (int)inppts_info[0];
    col = (int)inppts_info[1];
    //视觉识别到9个实心圆和标定板的实心圆数目一致
    if (row == 9)
    {
        Err = Zvision.ZV_GRAYTORGB(form.g_Handle, grabimg, calibshowimg);
        //inppts排好序输出排好序的像素坐标矩阵ppts
        Err = Zvision.ZV_CALGETPTSMAP(form.g_Handle, inppts, ppts, wpts, Convert.ToSingle(C_CalibDis.Text));
        Err = Zvision.ZV_MATINFO(form.g_Handle, ppts, inppts_info);
        row = (int)inppts_info[0];
        col = (int)inppts_info[1];
        if (row >= 9)
        {
            uint i;
            DataGridView1.Rows.Clear();
            for (i = 0; i < row; i++)
            {
                //像素坐标在WinFrom的UI界面是显示出来
                string[] tempstr = new string[4];
                float[] outvalue = { 0, 0 };
                Zvision.ZV_MATGETROW(form.g_Handle, wpts, i, 2, outvalue);
                tempstr[2] = "0";
                tempstr[3] = "0";
                Zvision.ZV_MATGETROW(form.g_Handle, ppts, i, 2, outvalue);
                tempstr[0] = outvalue[0].ToString();
                tempstr[1] = outvalue[1].ToString();
                DataGridView1.Rows.Add(tempstr);
                //在原图是画出识别到的实心圆,并标记,然后在Ui界面上显示出图像
                Zvision.ZV_MARKER(form.g_Handle, calibshowimg, outvalue[0], outvalue[1], 0, 40, 0, 255, 0);
                Zvision.ZV_TEXT(form.g_Handle, calibshowimg, i.ToString(), outvalue[0] - 20, outvalue[1] - 20, 40, 0, 255, 0);
                Zvision.ZV_LATCHCLEAR(form.g_Handle, 0);
                Zvision.ZV_LATCHSETSIZE(form.g_Handle, 0, Convert.ToUInt32(pictureBox5.Width), Convert.ToUInt32(pictureBox5.Height));                    pictureBox5.Image = Zvision.ZV_LATCH(form.g_Handle, calibshowimg, 0);
            }
        }
        else
        {
            MessageBox.Show("提取mark点失败!", "提示");
        }
    }
    else
    {
        MessageBox.Show("提取mark点失败!", "提示");
    }
}
/************************************************************************************
'任务编号:无
'函数功能:相机标定
'Input:无
'Output:无 
'返回值:无
'备注:计算像素坐标和世界坐标的转换关系
'备注:标定板圆心的世界坐标可以通过示教的方式获取            
**************************************************************************************/
private void CamCalib()
{
    //矩阵行和式
    uint row, col;
    row = 9;
    col = 2;
    //从Ui界面上获取世界坐标的矩阵数据
    float[] wPontsValue = new float[row * col];
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            wPontsValue[col * i + j] = float.Parse(DataGridView1.Rows[i].Cells[j + 2].Value.ToString());
        }
    }
    //重新生成世界坐标矩阵
    Zvision.ZV_MATGENDATA(form.g_Handle, wpts, row, col, wPontsValue);
    //图像坐标矩阵数据
    float[] pPontsValue = new float[row * col];
    for (int i = 0; i < row; i++)
    {
        for (int j = 0; j < col; j++)
        {
            pPontsValue[col * i + j] = float.Parse(DataGridView1.Rows[i].Cells[j].Value.ToString());
        }
    }
    //重新生成图像坐标矩阵
    Zvision.ZV_MATGENDATA(form.g_Handle, ppts, row, col, pPontsValue);
    float[] outimginfo = { 0, 0, 0, 0, 0 };
    //获取图像信息
    Zvision.ZV_IMGINFO(form.g_Handle, grabimg, outimginfo);
    //进行相机标定
    Zvision.ZV_CALCAM(form.g_Handle, ppts, wpts, ZmotionCalPara, (ushort)outimginfo[0], (ushort)outimginfo[1], (uint)Convert.ToInt32(C_CalibType.Text));
    float[] outcaliberror = { 0, 0, 0 };
    //获取标定误差
    Zvision.ZV_CALERROR(form.g_Handle, ZmotionCalPara, ppts, wpts, outcaliberror);
    //平均误差小于0.5内算是优,0.5--1为良,1--1.5为一般,1.5以上建议重新标定
    if (outcaliberror[0] >= 1.5)
    {
        MessageBox.Show("标定平均误差过大请重新标定");
    }
    else
    {
        //保存标定参数
        Zvision.ZV_CALWRITE(form.g_Handle, ZmotionCalPara, form.CalFileDir);
    }
}

3)形状匹配后根据标定系数可获得匹配到目标点的实际世界坐标。

在这里插入图片描述

3.形状匹配

在这里插入图片描述

1)形状匹配操作步骤

在这里插入图片描述

2)相关功能代码

/************************************************************************************
'任务编号:无
'函数功能:通过相机采集图像
'Input:无
'Output:无 
'返回值:无             
**************************************************************************************/
public Image CameAcquisition()
{
    float Temp = 0;
    Image ImageBuff = null;
    Zvision.CAM_COUNT(form.g_Handle, ref Cam_Num);
    //选择相机
    Zvision.CAM_SEL(form.g_Handle, 0);
    //采集一张图像
    Zvision.CAM_TRIGGER(form.g_Handle);
    //更新皮带位置
    zauxBrr = zmcaux.ZAux_Direct_GetMpos(form.g_Handle, form.ConveyorAxisId, ref Temp);
    form.BeltMpos = Temp;
    //从相机缓存取里面获取刚刚采集的图像
    Zvision.CAM_GET(form.g_Handle, grabimg, 0);
    //RGB转灰度
    Zvision.ZV_RGBTOGRAY(form.g_Handle, grabimg, grabimg);
    //锁存数据清空
    Zvision.ZV_LATCHCLEAR(form.g_Handle, 0);
    //设置锁存的大小为图片显示控件的大小
    Zvision.ZV_LATCHSETSIZE(form.g_Handle, 0, Convert.ToUInt32(ImgShow1.Width), Convert.ToUInt32(ImgShow1.Height));  
    //获取锁存中的图像
    ImgShow1.Image = Zvision.ZV_LATCH(form.g_Handle, grabimg, 0);
    //导出获取到的图像信息
    return ImgShow1.Image;
}
/************************************************************************************
'任务编号:无
'函数功能:创建形状模版
'Input:无
'Output:无 
'返回值:无             
**************************************************************************************/
private void CreateTemplate()
{
    //通过图像创建模板
    Zvision.ZV_SHAPECREATERE(form.g_Handle, SubImg, mod_re, shape_mod, Convert.ToInt32(modStartAngle.Text), Convert.ToInt32(modEndAngle.Text), Convert.ToInt32(modMinScale.Text), Convert.ToInt32(modMaxScale.Text), Convert.ToUInt32(modThresh.Text), Convert.ToUInt32(modNum_Level.Text), Convert.ToUInt32(modPt_Reduce.Text), Convert.ToInt32(modAngle_Step.Text), Convert.ToInt32(modScale_Step.Text), 20);
    //获取模板轮廓
    Zvision.ZV_SHAPECONTOURS(form.g_Handle, shape_mod, modconlist, 0);
    //灰度转rgb
    Zvision.ZV_GRAYTORGB(form.g_Handle, cutimg, modimg);
    float[] getimginfo = { 0, 0, 0, 0, 0 };
    //图像信息
    Zvision.ZV_IMGINFO(form.g_Handle, modimg, getimginfo);
    //刚性变换
    Zvision.ZV_GETRIGIDVECTOR(form.g_Handle, mod_matrigid, 0, 0, 0, getimginfo[0] / 2, getimginfo[1] / 2, 0);
    //仿射变换
    Zvision.ZV_CONTAFFINE(form.g_Handle, modconlist, mod_matrigid, tsmodconlist);
    //绘制轮廓到图像上
    Zvision.ZV_CONTLIST(form.g_Handle, modimg, tsmodconlist, 0, 255, 0, 1);
    //清空控制器的锁存缓冲区
    Zvision.ZV_LATCHCLEAR(form.g_Handle, 1);
    //设置锁存缓冲区大小,设置锁存通道大小和显示控件picgbox控件一样大
    Zvision.ZV_LATCHSETSIZE(form.g_Handle, 1, Convert.ToUInt32(pictureBox2.Width), Convert.ToUInt32(pictureBox2.Height));                                                                                                            //显示图像
    pictureBox2.Image = Zvision.ZV_LATCH(form.g_Handle, modimg,1); //截取图像显示到ui上
    pictureBox3.Image = pictureBox2.Image;
    //清空控制器的锁存缓冲区
    Zvision.ZV_LATCHCLEAR(form.g_Handle, 1);
    //设置锁存缓冲区大小
    Zvision.ZV_LATCHSETSIZE(form.g_Handle, 1, Convert.ToUInt32(pictureBox4.Width), Convert.ToUInt32(pictureBox4.Height));    //设置锁存通道大小和picgbox控件一样大
                                                                                                                      //显示图像
    pictureBox4.Image = Zvision.ZV_LATCH(form.g_Handle, modimg, 1);//截取图像显示到Ui上
}
/************************************************************************************
'任务编号:无
'函数功能:形状匹配,在图像是查找模板
'Input:无
'Output:无 
'返回值:无             
**************************************************************************************/
public Image ShapeFind()
{
    //结果数组清空
    for (int m = 0; m < 10; m++)
    {
        for (int n = 0; n < 5; n++)
        {
            form.VisionRst[m, n] = 0;
        }
    }
    //形状模板匹配
    Zvision.ZV_SHAPEFIND(form.g_Handle, shape_mod, grabimg, find_outlist, Convert.ToInt32(findminscore.Text), Convert.ToUInt32(findnum.Text), Convert.ToInt32(findmindis.Text), Convert.ToInt32(findthresh.Text), Convert.ToUInt32(findaccuracy.Text), Convert.ToInt32(findspeed.Text), Convert.ToUInt32(findpolar.Text));
    int[] mat_info = { 0, 0, 0 };
    //输出信息
    Zvision.ZV_MATINFO(form.g_Handle, find_outlist, mat_info);
    //生成绘制彩图
    Zvision.ZV_GRAYTORGB(form.g_Handle, grabimg, show_img);
    //匹配到目标了
    if ((int)mat_info[0] > 0)
    {
        for (uint i = 0; i < (int)mat_info[0]; i++)
        {
            float[] rst_value = { 0, 0, 0, 0, 0 };
            Zvision.ZV_MATGETROW(form.g_Handle, find_outlist, i, 5, rst_value);
            rstScore.Text = rst_value[0].ToString();
            rstPixX.Text = rst_value[1].ToString();
            rstPixY.Text = rst_value[2].ToString();
            rstAngle.Text = rst_value[3].ToString();
            rstScale.Text = rst_value[4].ToString();
            //分数筛选
            if (rst_value[0] >= form.VisionScore)
            {
                //输出结果
                for (int k = 0; k < 5; k++)
                {
                    form.VisionRst[i, k] = rst_value[k];
                }
                float[] outworldpos = { 0, 0 };
                //像素转世界坐标
                Zvision.ZV_CALTRANSW(form.g_Handle, ZmotionCalPara, rst_value[1], rst_value[2], outworldpos);
                rstWorldX.Text = outworldpos[0].ToString();
                rstWorldY.Text = outworldpos[1].ToString();
                //输出世界坐标
                for (int k = 1; k < 3; k++)
                {
                    form.VisionRst[i, k] = outworldpos[k - 1];
                }
                //显示匹配结果
                string RstWorldStr;
                RstWorldStr = "OK_坐标(" + rstWorldX.Text + "," + rstWorldY.Text + ")";
                Zvision.ZV_TEXT(form.g_Handle, show_img, RstWorldStr, rst_value[1], rst_value[2], 50, 0, 255, 0);
                //计算刚性变换矩阵
                Zvision.ZV_GETRIGIDVECTOR(form.g_Handle, find_matrigid, 0, 0, 0, rst_value[1], rst_value[2], rst_value[3]);
                //轮廓序列仿射变换
                Zvision.ZV_CONTAFFINE(form.g_Handle, modconlist, find_matrigid, tsmodconlist2);
                //绘制轮廓数列
                Zvision.ZV_CONTLIST(form.g_Handle, show_img, tsmodconlist2, 0, 255, 0, 1);
                Zvision.ZV_TEXT(form.g_Handle, show_img, i.ToString(), rst_value[1], rst_value[2], 40, 255, 0, 0);
            }
        }
    }
    else
    {
        //显示匹配结果
        string RstWorldStr;
        RstWorldStr = "NG";
        Zvision.ZV_TEXT(form.g_Handle, show_img, RstWorldStr, 20, 120, 100, 0, 255, 0);
    }
    //清空缓冲区显示图片
    Zvision.ZV_LATCHCLEAR(form.g_Handle, 0);
    Zvision.ZV_LATCHSETSIZE(form.g_Handle, 0, Convert.ToUInt32(ImgShow1.Width), Convert.ToUInt32(ImgShow1.Height));    //设置锁存通道大小和picgbox控件一样大
    ImgShow1.Image = Zvision.ZV_LATCH(form.g_Handle, show_img, 0);//截取图像显示到图像上
    return ImgShow1.Image;
}

本次,正运动技术C#之Delta并联机械手的视觉相机标定与形状匹配,就分享到这里。

更多精彩内容请关注“正运动小助手”公众号,需要相关开发环境与例程代码,请咨询正运动技术销售工程师。

本文由正运动技术原创,欢迎大家转载,共同学习,一起提高中国智能制造水平。文章版权归正运动技术所有,如有转载请注明文章来源。

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

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

相关文章

75. UE5 RPG 创建场景摆放部件蓝图

这一篇文章来点简单的内容&#xff0c;相当于我们使用蓝图创建类似于unity的预制体。 创建一个一个柱子蓝图 首先&#xff0c;我们创建一个立柱的蓝图&#xff0c;将我们之前创建的柱子上面含有火焰和灯光的部分合并成一个蓝图&#xff0c;方便往场景内添加。 点击创建一个基…

Docker系列之安全

Docker的安全前言一、Docker 容器与虚拟机的区别 1. 隔离与共享 2. 性能与损耗二、Docker 存在的安全问题 1.Docker 自身漏洞 2.Docker 源码问题三、 Docker 架构缺陷与安全机制 1. 容器之间的局域网攻击 2. DDoS 攻击耗尽资源 3. 有漏…

ACL 2023事件相关(事件抽取、事件关系抽取、事件预测等)论文汇总

ACL 2023事件抽取相关(事件抽取、事件关系抽取、事件预测等)论文汇总&#xff0c;后续会更新全部的论文讲解。 Event Extraction Code4Struct: Code Generation for Few-Shot Event Structure Prediction 数据集&#xff1a;ACE 2005 动机&#xff1a;与自然语言相比&#xf…

利用maven命令往本地仓库添加jar包

一&#xff1a;遇到问题 有些jar包在中央仓库没有&#xff0c;需要手动往本地仓库添加&#xff0c;方便以后打包使用。 比如&#xff1a;添加红框这个依赖&#xff0c;现在爆红 二&#xff1a;解决办法 **第一步&#xff1a;**打开idea&#xff0c;找到运行按钮旁边的框&am…

Android集成高德地图SDK(2)

1.解压下载的压缩包&#xff0c;找到AMap_Android_SDK_All\AMap3DMap_DemoDocs\AMap_Android_API_3DMap_Demo\AMap3DDemo\app\libs&#xff0c;复制libs里的所有文件&#xff0c;将其粘贴到Android工程的libs目录下&#xff0c;如图所示。 2.打开app下的build.gradle&#xff0…

无忧易售升级:一键设置图片分辨率,赋能十大跨境电商平台

在电商领域&#xff0c;产品图片的品质直接影响着顾客的购买决策与品牌形象的塑造。无忧易售ERP特推出图片分辨率修改功能&#xff0c;为电商卖家们提供更专业的图像优化工具&#xff0c;让每一像素都成为吸引客户的秘密武器&#xff01; 一、Allegro、OZON、Coupang、Cdiscou…

数据分析python基础实战分析

数据分析python基础实战分析 安装python&#xff0c;建议安装Anaconda 【Anaconda下载链接】https://repo.anaconda.com/archive/ 记得勾选上这个框框 安装完后&#xff0c;然后把这两个框框给取消掉再点完成 在电脑搜索框输入"Jupyter"&#xff0c;牛马启动&am…

低代码:释放企业创新力的钥匙

近年来&#xff0c;随着信息技术的不断发展&#xff0c;企业对于快速开发应用程序的需求越来越迫切。然而&#xff0c;传统的软件开发过程常常耗时费力&#xff0c;限制了企业的创新潜力。于是&#xff0c;低代码应运而生&#xff0c;成为解决开发难题的一把利器。 低代码开发…

完整代码Python爬取豆瓣电影详情数据

完整代码Python爬取豆瓣电影详情数据 引言 在数据科学和网络爬虫的世界里&#xff0c;豆瓣电影是一个丰富的数据源。在本文中&#xff0c;我们将探讨如何使用Python语言&#xff0c;结合requests和pyquery库来爬取豆瓣电影的详情页面数据。我们将通过一个具体的电影详情页面作…

节流工具,避免操作太频繁

ThrottleUtil 用于保证某个操作在一定时间内只执行一次的工具。 package com.cashpro.kash.lending.loan.utils;/*** <pre>* Created by zhuguohui* Date: 2024/6/26* Time: 13:43* Desc:用于节流执行任务,限制任务执行的频次* </pre>*/import android.os.Handle…

给前端小白的11个建议(少走弯路)

作为一个编程4年的的前端工程师&#xff0c;一路走来踩过许多坑。希望我的经验能让你少踩些坑&#xff0c;在编程的路上走的更顺些&#xff01; 1. 禁用var声明 只使用const或let声明变量。并且首选const&#xff0c;当一个变量需要重新赋值时&#xff0c;才使用let。并且在创…

旧衣回收小程序开发:回收市场的新机遇

当下&#xff0c;旧衣服回收已经成为了一种流行趋势&#xff0c;居民都将闲置的衣物进行回收&#xff0c;旧衣回收市场规模在不断增加。随着市场规模的扩大&#xff0c;为了让居民更加便利地进行回收&#xff0c;线上回收小程序也应运而生&#xff0c;为大众打造了一个线上回收…

windows安装Nacos并使用

Nacos&#xff08;前身为阿里巴巴的Nacos Config和Nacos Discovery&#xff09;是一个开源的动态服务发现、配置和服务管理平台&#xff0c;由阿里巴巴开发并维护。它提供了一种简单且易于使用的方式来管理微服务架构中的服务注册、发现和配置管理。 主要功能包括&#xff1a;…

[leetcode]move-zeroes 移动零

. - 力扣&#xff08;LeetCode&#xff09; class Solution { public:void moveZeroes(vector<int>& nums) {int n nums.size(), left 0, right 0;while (right < n) {if (nums[right]) {swap(nums[left], nums[right]);left;}right;}} };

web渗透-SSRF漏洞及discuz论坛网站测试

一、简介 ssrf(server-side request forgery:服务器端请求伪造&#xff09;是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下&#xff0c;ssrf是要目标网站的内部系统。(因为他是从内部系统访问的&#xff0c;所有可以通过它攻击外网无法访问的内部系统&…

一文搞懂Linux多线程【下】

目录 &#x1f6a9;多线程代码的健壮性 &#x1f6a9;多线程控制 &#x1f6a9;线程返回值问题 &#x1f6a9;关于Linux线程库 &#x1f6a9;对Linux线程简单的封装 在观看本博客之前&#xff0c;建议大家先看一文搞懂Linux多线程【上】由于上一篇博客篇幅太长&#xff0c;为…

一键掌握多渠道推广效果!Xinstall超级渠道功能,让你的App推广更高效

在App运营的大潮中&#xff0c;如何高效、精准地推广App&#xff0c;成为每一位运营者关注的焦点。传统的推广方式&#xff0c;如地推、代理、分销、广告等&#xff0c;虽然能够带来一定的用户增长&#xff0c;但如何衡量推广效果、如何与合作伙伴结算、如何管理下属渠道等问题…

一个项目学习Vue3---快速认识TypeScript

问题1&#xff1a;什么是TypeScript TypeScript是一种由微软开发的开源编程语言&#xff0c;它是JavaScript的一个超集。TypeScript添加了静态类型检查功能&#xff0c;并且可以编译为纯JavaScript代码&#xff0c;使得开发者可以利用JavaScript的生态系统和工具。TypeScript的…

拉普拉斯变换与卷积

前面描述 卷积&#xff0c;本文由卷积引入拉普拉斯变换。 拉普拉斯变换就是给傅里叶变换的 iωt 加了个实部&#xff0c;也可以反着理解&#xff0c;原函数乘以 e − β t e^{-\beta t} e−βt 再做傅里叶变换&#xff0c;本质上都是傅里叶变换的扩展。 加入实部的拉普拉斯变…

门店客流统计)

门店客流统计 代码部分效果 代码部分 import cv2 import numpy as np from tracker import * import cvzone import timebg_subtractor cv2.createBackgroundSubtractorMOG2(history200, varThreshold140)# Open a video capture video_capture cv2.VideoCapture(r"sto…