工业相机采图方式、图像格式(BYTE、HObject和Mat)转换

1、概述

机器视觉项目中,如何采集到合适的图像是项目的第一步,也是最重要的一步,直接关系到后面图像处理算法及最终执行的结果。所以采用不同的工业相机成像以及如何转换成图像处理库所需要的格式成为项目开发中首先要考虑的问题。

2、工业相机图像采集方式

这里工业相机选择就不赘述了,因为相对于项目或设备来讲,需要根据项目需要挑选适合的硬件,而针对图像采集也有基于SDK开发或直接采用Halcon的相机采集助手。

2.1 相机自带的SDK采图

这种方式是厂家比较推荐的,也是比较常用的方法,原因之一是每个厂家对自己的产品比较熟知,提供的SDK也是比较稳定的,而且也会有一定的技术支持;第二个原因就是基于SDK的开发可以获取更多相机及图像的原始参数,这样在做项目中的灵活度也会更高,一般大一些的品牌相机的SDK和demo程序会更详细,而且针对相机封装的函数也更完善,这里我在项目中用的较多的是Dalsa和basler,国产的用的较多的是海康、京航和方诚。这里针对Dalsa和balsa的面阵相机做一下简单的介绍。(编程环境是Qt5)

2.1.1 Dalsa相机采图方式

初始化相机

void CaptureThread::initCamera()
{m_AcqDevice = new SapAcqDevice(SapLocation("Nano-M2420_1", 0),false);BOOL Status = m_AcqDevice->Create();if(Status){qDebug()<<"相机连接成功"<<endl;m_Buffers = new SapBufferWithTrash(3,m_AcqDevice);m_AcqDevice->GetFeatureValue("Width",&Img_Width);m_AcqDevice->GetFeatureValue("Height",&Img_Height);//        qDebug()<<"Width:"<<Img_Width<<"Height:"<<Img_Height<<endl;m_Xfer    = new SapAcqDeviceToBuf(m_AcqDevice,m_Buffers,XferCallback,this);}if (!CreateObjects()) { return; }
}

回调函数主要是用于获取图像数据

void CaptureThread::XferCallback(SapXferCallbackInfo *pInfo)
{CaptureThread *pDlg = (CaptureThread *) pInfo->GetContext();if(pInfo->IsTrash()){qDebug()<<"IsTrash"<<endl;return;}//    qDebug()<<"相机向缓存中写入数据"<<endl;HObject hv_Current_Image;BYTE *pData;pDlg->m_Buffers->GetAddress((void**)&pData);GenImage1(&hv_Current_Image,"byte",pDlg->Img_Width,pDlg->Img_Height,(Hlong)pData);//    GenImageInterleaved(&hv_Current_Image,(Hlong)pData,"rgb",pDlg->Img_Width,pDlg->Img_Height,-1,"byte",0,0,0,0,-1,0);//判断图像处理工作方式if(pDlg->TestImg_WorkType == 0){emit pDlg->startImgProcess(hv_Current_Image);pDlg->TestImg_WorkType = -1;}else if(pDlg->TestImg_WorkType == 1){emit pDlg->startImgProcess(hv_Current_Image);}else{emit pDlg->canShowImg(hv_Current_Image);}pDlg->m_Buffers->ReleaseAddress((void *)pData);pDlg->m_Buffers->Clear(pDlg->m_Buffers->GetIndex());
}

最后是调用Dalsa相机的采图函数来触发

void CaptureThread::OnGrab()
{m_Xfer->Grab();
}void CaptureThread::OnSnap()
{m_Xfer->Snap();
}void CaptureThread::OnFreeze()
{SnapSignal = true;m_Xfer->Freeze();
}

2.1.2 basler相机采图方式

首先初始化相机:

void CBaslerCameraControl::initCamera()
{PylonInitialize();      //初始化相机m_basler.RegisterImageEventHandler(this, RegistrationMode_Append, Cleanup_Delete);     //注册图像事件程序,模式为Append插入;//    m_basler.RegisterConfiguration(this, RegistrationMode_ReplaceAll, Cleanup_None);     //注册图像事件,模式为单张覆盖;m_basler.Attach(CTlFactory::GetInstance().CreateFirstDevice(),Cleanup_Delete);qDebug()<<"Using device " << m_basler.GetDeviceInfo().GetModelName()<<endl;m_basler.Open();        //打开相机if (!m_basler.IsOpen() || m_basler.IsGrabbing()){qDebug()<<"camera open failed"<<endl;return;}
}

下一步就可以调用库函数进行采集

//连续采图的回调函数
void CBaslerCameraControl::OnImageGrabbed(CInstantCamera &camera, const CGrabResultPtr &grabResult)
{m_mutexLock.lock();if (grabResult->GrabSucceeded()){m_ptrGrabResult = grabResult;//将捕获到的图像传递出去
//        qDebug() <<"Captureok"<<endl;HObject hv_CurrentImg;CopyImgToHObject(m_ptrGrabResult,hv_CurrentImg);emit canShowImg(hv_CurrentImg);qDebug() <<"Captureok"<<endl;}m_mutexLock.unlock();
}void CBaslerCameraControl::StartAcquire()
{if ( !m_basler.IsGrabbing() ){GrabOnLine_Signal = true;m_basler.StartGrabbing(GrabStrategy_LatestImageOnly,GrabLoop_ProvidedByInstantCamera);}
}void CBaslerCameraControl::StartSnap()
{m_basler.StartGrabbing(1);CBaslerUniversalGrabResultPtr ptrGrabResult;m_basler.RetrieveResult( 5000, ptrGrabResult, TimeoutHandling_ThrowException);if (ptrGrabResult->GrabSucceeded()){qDebug()<<"snapok"<<endl;HObject hv_CurrentImg;CopyImgToHObject(ptrGrabResult,hv_CurrentImg);emit canShowImg(hv_CurrentImg);}
}void CBaslerCameraControl::CloseCamera()
{if(m_basler.IsOpen()) {m_basler.DetachDevice();m_basler.Close();m_basler.DestroyDevice();m_ptrGrabResult.Release();}
}void CBaslerCameraControl::deleteAll()
{//停止采集if(m_isOpenAcquire) {StopAcquire();}//关闭摄像头try{CloseCamera();m_basler.DeregisterImageEventHandler(this);//关闭库qDebug() << "SBaslerCameraControl deleteAll: PylonTerminate" ;PylonTerminate();}catch (const Pylon::GenericException& e){qDebug() << e.what();}
}

2.1.3 小结

大部分的相机SDK大体都类似,都是通过相机句柄去调用图像采集的回调函数或图像buff,在以上介绍的程序中SDK获取的是图像的buff,再通过buff里的图像数据转换成HObject或者Mat格式,这个详细操作下节再讲。通过相机SDK进行Grab或Snap,其优势是成像高效稳定,搞懂相机自带的SDK程序和Demo程序,可以很快的实现采图测试,而且BYTE格式的原始图像数据,可以使用c++进行paint或转成Qt的Qimage进行显示操作。其不便之处就在于,将BYTE转换成HObject或Mat的耗时,可能会影响图像实时显示,所以需要考虑图像显示和处理的效率问题。对于有编程基础的同学,推荐使用此方法进行图像采集。
##2.2 Halcon自带的图像采集助手进行采图
1.使用basler相机自带的 IPConfigurator软件设置好电脑的ip地址,保证电脑和相机已连接成功,然后使用basler的采图工具pylon viewer测试是否能采集到图像;
2.打开halcon,助手选项下选择“打开新的Image Acquisition”
相机助手.png
3.自动检测接口,选择对应的相机接口文件,如“pylon”,然后点击“代码生成”即可
相机接口文件.PNG

2.3 采图方法总结

使用Halcon采图助手进行采图比较适合新手,没有太大的编程量,也可以用于项目前期的方案制定,图像处理评估等;第一种采图方法的适用性更广,可以满足不同项目的开发需求。

3、图像格式的互相转换(BYTE、HObject、Mat和QImage)

在项目开发过程中,会用到不同的图像处理库、不同的图形显示环境,所以需要针对图像的格式进行对应的转换

3.1 BYTE转HObject

这个比较常用,通过相机SDK采集后的图像数据转换成Halcon格式,便于后期的图像处理操作;

void CBaslerCameraControl::CopyImgToHObject(CGrabResultPtr pInBuffer, HObject &hv_Image)
{HBYTE *pData = (HBYTE*)pInBuffer->GetBuffer();int nHeight = pInBuffer->GetHeight();int nWidth = pInBuffer->GetWidth();GenImage1(&hv_Image,"byte",nWidth,nHeight,(Hlong)pData);
//    HObject hv_Current_Image;
//    //图像格式转换方法一:数据拷贝
//    //    int size = (pDlg->Img_Width)* (pDlg->Img_Height)*sizeof(BYTE);
//    //    BYTE *dataBuf = new BYTE[size];
//    //    dataBuf = (byte *)malloc(size);
//    //    pDlg->m_Buffers->Read(0,(pDlg->Img_Width)* (pDlg->Img_Height),dataBuf);
//    //    GenImage1(&hv_Current_Image,"byte",pDlg->Img_Width,pDlg->Img_Height,(Hlong)dataBuf);
//    //图像格式转换方法二:数据指针
//    BYTE *pData;
//    pDlg->m_Buffers->GetAddress((void**)&pData);
//    GenImage1(&hv_Current_Image,"byte",pDlg->Img_Width,pDlg->Img_Height,(Hlong)pData);
//    //    GenImageInterleaved(&hv_Current_Image,(Hlong)pData,"rgb",pDlg->Img_Width,pDlg->Img_Height,-1,"byte",0,0,0,0,-1,0);
}

上述转换有两种方法,一种使用数据拷贝,一种使用数据指针,相比较第二种耗时少,推荐使用。

3.2 BYTE转Mat、QImage

void CBaslerCameraControl::CopyImgToMat(CGrabResultPtr pInBuffer, Mat &Mat_Img)
{HBYTE *pData = (HBYTE*)pInBuffer->GetBuffer();int nHeight = pInBuffer->GetHeight();int nWidth = pInBuffer->GetWidth();unsigned char *pImageBuffer = (unsigned char *)pInBuffer->GetBuffer();//黑白图像const uint8_t *pImageBuffer = (uint8_t *) ptrGrabResult->GetBuffer();Mat_img =Mat(cv::Size(nWidth , nHeight ), CV_8U, (void*)pImageBuffer, cv::Mat::AUTO_STEP);QImg = QImage(pImageBuffer ,nWidth ,nHeight ,QImage::Format_Indexed8);//彩色图像// 新建pylon ImageFormatConverter对象.CImageFormatConverter formatConverter;//确定输出像素格式formatConverter.OutputPixelFormat = PixelType_BGR8packed;//将抓取的缓冲数据转化成pylon image.formatConverter.Convert(m_bitmapImage, pInBuffer);// 将 pylon image转成OpenCV image.Mat_img = cv::Mat(pInBuffer->GetHeight(), pInBuffer->GetWidth(), CV_8UC3, (uint8_t *)m_bitmapImage.GetBuffer());QImg = QImage(pImageBuffer ,nWidth /3,nHeight ,nWidth ,QImage::Format_RGB888);
}

3.3 HObject与Mat互转

using namespace cv;
using namespace Halcon;//HObject转Mat
Mat HObject2Mat(HObject Hobj)
{HTuple htCh = HTuple();HString cType;cv::Mat Image;ConvertImageType(Hobj,&Hobj,"byte");CountChannels(Hobj,&htch);Hlong wid = 0;Hlong hgt = 0;if(htch[0].I() == 1){HImage hImg(Hobj);void *ptr = hImg.GetImagePointer1(&cType,&wid,&hgt);int W = wid;int H = hgt;Image.create(H,W,CV_8UC1);unsigned char *pdata = static_case<unsigned char*>(ptr);memcpy(Image.data,pdata,W*H);}else if (htch[0].I()  == 3){void *Rptr;void *Gptr;void *Bptr;HImage hImg(Hobj);hImg.GetImagePointer3(&Rptr,&Gptr,&Bptr,&cType,&wid,&hgt);int W = wid;int H = hgt;Image.create(H,W,CV_8UC3);vector<cv::Mat> VecM(3);VecM[0].create(H,W,CV_8UC1);VecM[1].create(H,W,CV_8UC1);VecM[2].create(H,W,CV_8UC1);unsigned char *R = (unsigned char *)Rptr;unsigned char *G = (unsigned char *)Gptr;unsigned char *B = (unsigned char *)Bptr;memcpy(VecM[2].data,R,W*H);memcpy(VecM[1].data,G,W*H);memcpy(VecM[0].data,B,W*H);cv::merge(VecM,Image);}return Image;
}
//Mat转Hobject
Hobject Mat2Hobject(Mat& image)
{Hobject Hobj = Hobject();int hgt = image.rows;int wid = image.cols;int i;if (image.type() == CV_8UC3){vector<Mat> imgchannel;split(image, imgchannel);Mat imgB = imgchannel[0];Mat imgG = imgchannel[1];Mat imgR = imgchannel[2];uchar* dataR = new uchar[hgt*wid];uchar* dataG = new uchar[hgt*wid];uchar* dataB = new uchar[hgt*wid];for (i = 0; i < hgt; i++){memcpy(dataR + wid*i, imgR.data + imgR.step*i, wid);memcpy(dataG + wid*i, imgG.data + imgG.step*i, wid);memcpy(dataB + wid*i, imgB.data + imgB.step*i, wid);}gen_image3(&Hobj, "byte", wid, hgt, (Hlong)dataR, (Hlong)dataG, (Hlong)dataB);delete[]dataR;delete[]dataG;delete[]dataB;dataR = NULL;dataG = NULL;dataB = NULL;}else if (image.type() == CV_8UC1){uchar* data = new uchar[hgt*wid];for (i = 0; i < hgt; i++)memcpy(data + wid*i, image.data + image.step*i, wid);gen_image1(&Hobj, "byte", wid, hgt, (Hlong)data);delete[] data;data = NULL;}return Hobj;
}

3.4 HObject转QImage

void HObjectToQImage(HObject hv_image, QImage &qimage)
{HTuple hChannels,htype,hpointer;HTuple width=0;HTuple height=0;ConvertImageType(hv_image,&hv_image,"byte");//将图片转化成byte类型CountChannels(hv_image,&hChannels);       //判断图像通道数if(hChannels[0].I()==1)//单通道图{unsigned char *ptr;GetImagePointer1(hv_image,&hpointer,&htype,&width,&height);ptr=(unsigned char *)hpointer[0].L();qimage= QImage(ptr,width,height,QImage::Format_Indexed8);}else if(hChannels[0].I()==3)//三通道图{unsigned char *ptr3;HObject ho_ImageInterleaved;rgb3_to_interleaved(hv_image, &ho_ImageInterleaved);GetImagePointer1(ho_ImageInterleaved, &hpointer, &htype, &width, &height);ptr3=(unsigned char *)hpointer[0].L();qimage= QImage(ptr3,width/3,height,width,QImage::Format_RGB888);}
}
void rgb3_to_interleaved (HObject ho_ImageRGB, HObject *ho_ImageInterleaved)
{// Local iconic variablesHObject  ho_ImageAffineTrans, ho_ImageRed, ho_ImageGreen;HObject  ho_ImageBlue, ho_RegionGrid, ho_RegionMoved, ho_RegionClipped;// Local control variablesHTuple  hv_PointerRed, hv_PointerGreen, hv_PointerBlue;HTuple  hv_Type, hv_Width, hv_Height, hv_HomMat2DIdentity;HTuple  hv_HomMat2DScale;GetImagePointer3(ho_ImageRGB, &hv_PointerRed, &hv_PointerGreen, &hv_PointerBlue,&hv_Type, &hv_Width, &hv_Height);GenImageConst(&(*ho_ImageInterleaved), "byte", hv_Width*3, hv_Height);//HomMat2dIdentity(&hv_HomMat2DIdentity);HomMat2dScale(hv_HomMat2DIdentity, 1, 3, 0, 0, &hv_HomMat2DScale);AffineTransImageSize(ho_ImageRGB, &ho_ImageAffineTrans, hv_HomMat2DScale, "constant",hv_Width*3, hv_Height);//Decompose3(ho_ImageAffineTrans, &ho_ImageRed, &ho_ImageGreen, &ho_ImageBlue);GenGridRegion(&ho_RegionGrid, 2*hv_Height, 3, "lines", hv_Width*3, hv_Height+1);MoveRegion(ho_RegionGrid, &ho_RegionMoved, -1, 0);ClipRegion(ho_RegionMoved, &ho_RegionClipped, 0, 0, hv_Height-1, (3*hv_Width)-1);ReduceDomain(ho_ImageRed, ho_RegionClipped, &ho_ImageRed);MoveRegion(ho_RegionGrid, &ho_RegionMoved, -1, 1);ClipRegion(ho_RegionMoved, &ho_RegionClipped, 0, 0, hv_Height-1, (3*hv_Width)-1);ReduceDomain(ho_ImageGreen, ho_RegionClipped, &ho_ImageGreen);MoveRegion(ho_RegionGrid, &ho_RegionMoved, -1, 2);ClipRegion(ho_RegionMoved, &ho_RegionClipped, 0, 0, hv_Height-1, (3*hv_Width)-1);ReduceDomain(ho_ImageBlue, ho_RegionClipped, &ho_ImageBlue);OverpaintGray((*ho_ImageInterleaved), ho_ImageRed);OverpaintGray((*ho_ImageInterleaved), ho_ImageGreen);OverpaintGray((*ho_ImageInterleaved), ho_ImageBlue);return;
}

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

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

相关文章

微服务day05(中) -- ES索引库操作

索引库就类似数据库表&#xff0c;mapping映射就类似表的结构。 我们要向es中存储数据&#xff0c;必须先创建“库”和“表”。 2.1.mapping映射属性 mapping是对索引库中文档的约束&#xff0c;常见的mapping属性包括&#xff1a; type&#xff1a;字段数据类型&#xff0c;…

数据分析-Pandas序列滑动窗口配置参数

数据分析-Pandas序列滑动窗口配置参数 数据分析和处理中&#xff0c;难免会遇到各种数据&#xff0c;那么数据呈现怎样的规律呢&#xff1f;不管金融数据&#xff0c;风控数据&#xff0c;营销数据等等&#xff0c;莫不如此。如何通过图示展示数据的规律&#xff1f; 数据表&…

【DataWhale】灵境Agent开发——低代码创建AI智能体

灵境Agent开发——低代码创建AI智能体 3 灵境 Agent 低代码开发 ​ 低代码模式支持开发者通过编排工作流的方式快速构建智能体&#xff0c;您可以通过拖拽和组合模型、提示词、代码等模块&#xff0c;实现准确的、复杂的业务流程。 ​ 个人体验下来&#xff0c;目前这个低代…

【Entity Framework】 EF中DbContext类详解

【Entity Framework】 EF中DbContext类详解 一、概述 DbContext类是实体框架的重要组成部分。它是应用域或实例类与数据库交互的桥梁。 从上图可以看出DbContext是负责与数据交互作为对象的主要类。DbContext负责以下活动&#xff1a; EntitySet&#xff1a;DbContext包含…

【linux】CentOS查看系统信息

一、查看版本号 在CentOS中&#xff0c;可以通过多种方法来查看版本号。以下是几种常用的方法&#xff1a; 使用cat命令查看/etc/centos-release文件&#xff1a; CentOS的版本信息存储在/etc/centos-release文件中。可以使用cat命令来显示该文件的内容&#xff0c;从而获得C…

鸿蒙ArkTS实战开发-Native XComponent组件的使用

介绍 本篇Codelab主要介绍如何使用XComponent组件调用NAPI来创建EGL/GLES环境&#xff0c;实现在主页面绘制一个正方形&#xff0c;并可以改变正方形的颜色。本篇CodeLab使用Native C模板创建。 如图所示&#xff0c;点击绘制矩形按钮&#xff0c;XComponent组件绘制区域中渲…

递归和递推的区别

目录 1、递推 2、递归 3、结言 递归 递推 1、递推 递推就是说从初值出发后一直运算到所需的结果。 ——从已知到未知。&#xff08;从小到大&#xff09; 举一个简单的例子&#xff1a; 每天能学习一个小时的编程&#xff0c;那么一个月之后可以学到三十小时的编程知识。…

同义词的作用

oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 同义词 同义词本质上属于近义词的概念&#xff0c;它是表、索引、视图等模式对象的一个别名 通过为模式对象创建同义词&#xff0c;可以隐藏对象的实际名称和所有者信息&a…

Linux安装Nacos

安装前必要准备 准备Java环境 &#xff0c;8以上的版本&#xff0c;mysql&#xff08;集群相关信息&#xff09;&#xff0c;nginx&#xff08;进行代理&#xff09; 安装Nacos 首先我们要有一个nacos的包&#xff0c;我们可以在线下载&#xff0c;也可以提前下载好&#xf…

【爬取网易财经文章】

引言 在信息爆炸的时代&#xff0c;获取实时的财经资讯对于投资者和金融从业者来说至关重要。然而&#xff0c;手动浏览网页收集财经文章耗时费力&#xff0c;为了解决这一问题&#xff0c;本文将介绍如何使用Python编写一个爬虫程序来自动爬取网易财经下关于财经的文章 1. 爬…

【史上最全面arduino esp32教程】I2C接口LCD1602的使用

文章目录 前言一、安装驱动库二、LCD1602的各种操作2.1 点亮LCD16022.2 LCD1602其他函数清除显示屏上的所有字符将光标位置移动到显示屏的起始位置关闭显示屏&#xff0c;不会显示任何字符打开显示屏&#xff0c;开始显示字符关闭光标闪烁打开光标闪烁&#xff0c;使光标呈现闪…

踩了一天Prophet的fbprophet坑

pip怎么安装Prophet 安装了这个不行,要安装fbprophet 然后安装不起 哦豁 anaconda虚拟环境安装好将其导入pycharm from fbprophet import Prophet 然后不报错了,很稀奇对吧,不报错了 但是运行还是给你显示 没有fbprophet 绝望了,找人吧 通过官方网站安装最新版Prophet,但是…

洛谷_P1873 [COCI 2011/2012 #5] EKO / 砍树_python写法

P1873 [COCI 2011/2012 #5] EKO / 砍树 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) n, m map(int,input().split())data list(map(int,input().split())) h 0 def check(mid):h 0for i in data:if i>mid:h (i-mid)if h < m:return Trueelse:return Falsel 0 r …

游戏反云手机检测方案

游戏风险环境&#xff0c;是指独立于原有设备或破坏设备原有系统的环境。常见的游戏风险环境有&#xff1a;云手机、虚拟机、虚拟框架、iOS越狱、安卓设备root等。 这类风险环境可以为游戏外挂、破解提供所需的高级别设备权限&#xff0c;当游戏处于这些风险环境下&#xff0c…

【保姆级】前端使用node.js基础教程

文章目录 安装和版本管理&#xff1a;npm 命令&#xff08;Node 包管理器&#xff09;&#xff1a;运行 Node.js 脚本&#xff1a;调试和开发工具&#xff1a;其他常用命令&#xff1a;模块管理&#xff1a;包管理&#xff1a;调试工具&#xff1a;异步编程和包管理&#xff1a…

python的O2O生鲜食品订购flask-django-nodejs-php

用户只能通过一些类似软件进行查看生鲜超市&#xff0c;这样的管理方式仍然是比较机械传统的&#xff0c;本文通过对市面上常见的线上管理系统与现实生活中结合问题的讨论&#xff0c;从一个微信小程序的O2O生鲜食品订购角度进行需求分析&#xff0c;提供一些新的思路&#xff…

使用Lerna搭建业务组件库

Lerna基本概念 Lerna 是一个用来优化托管在 git\npm 上的多 package 代码库的工作流的一个管理工具,可以让你在主项目下管理多个子项目&#xff0c;从而解决了多个包互相依赖&#xff0c;且发布时需要手动维护多个包的问题。 主要功能&#xff1a; 为单个包或多个包运行命令 …

基于Gabor滤波器的指纹图像识别,Matlab实现

博主简介&#xff1a; 专注、专一于Matlab图像处理学习、交流&#xff0c;matlab图像代码代做/项目合作可以联系&#xff08;QQ:3249726188&#xff09; 个人主页&#xff1a;Matlab_ImagePro-CSDN博客 原则&#xff1a;代码均由本人编写完成&#xff0c;非中介&#xff0c;提供…

vben admin路由跳转拿不到param参数问题

vben admin路由跳转拿不到param参数问题 问题原因&#xff1a; 也就是说&#xff0c;从Vue Router的2022-8-22 这次更新后&#xff0c;我们使用上面的方式在新页面无法获取&#xff1a; vue也给我们提出了解决方案&#xff1a; ​ 1.使用 query 的方式传参 ​ 2.将参数放…

阿里云服务器租用一年多少钱?2024年最新阿里云租用价格

2024年阿里云服务器租用费用&#xff0c;云服务器ECS经济型e实例2核2G、3M固定带宽99元一年&#xff0c;轻量应用服务器2核2G3M带宽轻量服务器一年61元&#xff0c;ECS u1服务器2核4G5M固定带宽199元一年&#xff0c;2核4G4M带宽轻量服务器一年165元12个月&#xff0c;2核4G服务…