Segformer模型的平台部署和项目应用

最近因为离职太忙了之前的很多内容没有更新,离开BYD进入新的环境中成长。
本文包含了Segformer的网络结构重构后如何部署到算法平台中方便标注训练推理的过程,以及如何应用到项目中(BYD最后一个项目:异物检测系统)

C++做Segformer的推理加速,Python做Segformer平台部署,C#调用算法接口实现项目开发。


前言

本章将前面的segfomer网络结构的学习和重构、segformer双显卡推理部署、算法平台开发、c#使用pythonnet调用python多进程项目、windows forms图形界面的开发,c++加cuda对模型推理加速的所有内容贯穿起来完成一个大型项目的整个开发起来。

一、算法平台的开发


1、在现有的算法平台添加该深度学习模块,避免后面的项目用到该模型重复造轮子,增加标注训练功能和推理工具

2、推理功能接口提供pytorch\onnx\tensort三种推理方式

3、项目逻辑功能:实现相机和电机和机械手的控制

4、图片算法逻辑功能实现,输出分割区域

二、c++和cuda 实现segformer推理加速

c++推理代码

int load_model(std::string modelPath, int cudaDevice,int width,int height,int batchSize, int classNum)
{
    cudaSetDevice(cudaDevice);
    /*******************************************************************************************************
    一、读取本地模型
    *******************************************************************************************************/
    //引擎文件绝对地址
    //std::string engine_name = R"(D:\Drivers\TensorRT-8.5.3.1\bin\models_YW240619.trt)"; //D:\Drivers\TensorRT - 8.5.3.1\bin\models_YW240619.trt
    std::string engine_name = modelPath;//R"(D:\model\models.trt)"; //D:\Drivers\TensorRT - 8.5.3.1\bin\models_YW240619.trt    F:\model\models_YW240619.trt
    //该文件保存了模型的所有信息以及电脑的配置信息,因此该模型文件不支持在不同电脑上使用。
    std::ifstream file(engine_name, std::ios::binary);
    if (!file.good())
        std::cerr << "文件无法打开,请确定文件是否可用!" << std::endl;
    size_t size = 0;
    file.seekg(0, file.end);	// 将读指针从文件末尾开始移动0个字节
    size = file.tellg();	// 返回读指针的位置,此时读指针的位置就是文件的字节数
    file.seekg(0, file.beg);	// 将读指针从文件开头开始移动0个字节
    char* modelStream = new char[size];
    //将模型文件信息读取到内存中
    file.read(modelStream, size);
    file.close();

    /*******************************************************************************************************
    二、构建引擎
    *******************************************************************************************************/
 
    //创建反序列化引擎并使用日志记录接口---使用全局 TensorRT API 方法用于创建 iRuntime 类型的对象
    this->runtime = nvinfer1::createInferRuntime(glogger);
    
    //调用反序列化引擎来创建推理引擎,即反序列化获取模型(modelStream)中的引擎---通过调用运行时方法 deserializeCudaEngine() 来创建引擎
    this->engine = runtime->deserializeCudaEngine(modelStream, size, nullptr);
    //判断推理引擎是否为空
    if (engine == NULL) {
        printf("modelStream 为空,模型加载失败");
        delete[] modelStream;
        return 0;
    }
    else
    {
        //创建推理上下文---为后面进行模型推理的类
        this->context = this->engine->createExecutionContext();
        delete[] modelStream;
        //创建GPU缓存区,使用这些索引,创建buffers指向 GPU 上输入和输出缓冲区
        std::string inputBindingname = this->engine->getBindingName(inputBindingindex);
        std::string outputBindingname = this->engine->getBindingName(outputBindingindex);
        this->inputIndex = this->engine->getBindingIndex(inputBindingname.c_str());
        this->outputIndex = this->engine->getBindingIndex(outputBindingname.c_str());

        inputDims.nbDims = 4;
        inputDims.d[0] = 1;
        inputDims.d[1] = 3;
        inputDims.d[2] = 512;
        inputDims.d[3] = 512;
        this->context->setBindingDimensions(this->inputIndex, inputDims);

        //创建GPU显存输入缓存区---输入推理数据(GPU)
        cudaMalloc(&buffers[this->inputIndex], (3 * 512 * 512) * sizeof(float));
        //创建GPU显存输出缓存区--输出推理结果数据(GPU)
        cudaMalloc(&buffers[this->outputIndex], (classNum * 512 * 512) * sizeof(float));
        cudaMalloc((void**)&srcDevData, sizeof(uchar) * (width * height * 3 * batchSize));
        cudaMalloc((void**)&srcResizeData, sizeof(uchar) * (512 * 512 * 3 * batchSize));
        //使用CUDA流数据加载,将结果数据(CPU内存)输出到float变量中
        cudaMalloc((void**)&post_device_data, sizeof(uchar) * (512 * 512 * batchSize));
        cudaMalloc((void**)&post_resize_data, sizeof(uchar) * (width * height * batchSize));
        scr = new uchar[batchSize * 3 * width * height];
        post_host_data = new uchar[width * height * batchSize];
        return 1;
    }
}

cuda核函数代码

__global__ void process(const uchar* srcData, float* tgtData, const int h, const int w)
{

	int ix = threadIdx.x + blockIdx.x * blockDim.x;
	int iy = threadIdx.y + blockIdx.y * blockDim.y;
	int idx = ix + iy * w;
	int idx3 = idx * 3;

	if (ix < w && iy < h)
	{
		tgtData[idx] = ((float)srcData[idx3 + 2] - 123.675f) / 58.359;  // R pixel
		tgtData[idx + h * w] = ((float)srcData[idx3 + 1] -116.28)/ 57.12;  // G pixel
		tgtData[idx + h * w * 2] = ((float)srcData[idx3] - 103.53) / 57.375;  // B pixel
	}
	//if (idx < 1)
	//{
	//	printf("idx:%d float_a: %f float_b :%f float_c :%f \n", idx, tgtData[idx], tgtData[idx + h * w], tgtData[idx + h * w * 2]);
	//}
}

__global__ void process(const uchar* srcData, float* tgtData, const int h, const int w)
{

	int ix = threadIdx.x + blockIdx.x * blockDim.x;
	int iy = threadIdx.y + blockIdx.y * blockDim.y;
	int idx = ix + iy * w;
	int idx3 = idx * 3;

	if (ix < w && iy < h)
	{
		tgtData[idx] = ((float)srcData[idx3 + 2] - 123.675f) / 58.359;  // R pixel
		tgtData[idx + h * w] = ((float)srcData[idx3 + 1] -116.28)/ 57.12;  // G pixel
		tgtData[idx + h * w * 2] = ((float)srcData[idx3] - 103.53) / 57.375;  // B pixel
	}
	//if (idx < 1)
	//{
	//	printf("idx:%d float_a: %f float_b :%f float_c :%f \n", idx, tgtData[idx], tgtData[idx + h * w], tgtData[idx + h * w * 2]);
	//}
}

__global__ void resize(const uchar* srcData, const int srcH, const int srcW, uchar* tgtData, const int tgtH, const int tgtW)
{
	//灰色图片做
	int ix = threadIdx.x + blockIdx.x * blockDim.x;
	int iy = threadIdx.y + blockIdx.y * blockDim.y;
	int idx = ix + iy * tgtW;
	int idx3 = idx;

	float scaleY = (float)tgtH / (float)srcH;
	float scaleX = (float)tgtW / (float)srcW;

	// (ix,iy)为目标图像坐标
	// (before_x,before_y)原图坐标
	float beforeX = float(ix + 0.5) / scaleX - 0.5;
	float beforeY = float(iy + 0.5) / scaleY - 0.5;
	// 原图像坐标四个相邻点
	// 获得变换前最近的四个顶点,取整
	int topY = static_cast<int>(beforeY);
	int bottomY = topY + 1;
	int leftX = static_cast<int>(beforeX);
	int rightX = leftX + 1;
	//计算变换前坐标的小数部分
	float u = beforeX - leftX;
	float v = beforeY - topY;

	if (ix < tgtW && iy < tgtH)
	{
		// 如果计算的原始图像的像素大于真实原始图像尺寸
		if (topY >= srcH && leftX >= srcW)  //右下角
		{
			for (int k = 0; k < 1; k++)
			{
				//tgtData[idx3 + k] = (1. - u) * (1. - v) * srcData[(leftX + topY * srcW) * 3 + k];
				tgtData[idx3 + k] = srcData[(leftX + topY * srcW) * 3 + k];
				//tgtData[idx3 + k] = 255.0;
			}
		}
		else if (topY >= srcH )  // 最后一行
		{
			for (int k = 0; k < 1; k++)
			{
			/*	tgtData[idx3 + k]
					= (1. - u) * (1. - v) * srcData[(leftX + topY * srcW) * 3 + k]
					+ (u) * (1. - v) * srcData[(rightX + topY * srcW) * 3 + k];*/
				if ((1. - u) >= 0.5 )
					tgtData[idx3 + k] = srcData[(leftX + topY * srcW) * 3 + k];
				else if ((u) > 0.5)
					tgtData[idx3 + k] = srcData[(rightX + topY * srcW) * 3 + k];
				else
					tgtData[idx3 + k] = srcData[(rightX + topY * srcW) * 3 + k];

			}
		}
		else if (leftX >= srcW)  // 最后一列
		{
			for (int k = 0; k < 1; k++)
			{
				/*tgtData[idx3 + k]
					= (1. - u) * (1. - v) * srcData[(leftX + topY * srcW) * 3 + k]
					+ (1. - u) * (v)*srcData[(leftX + bottomY * srcW) * 3 + k];*/
				if ((1. - v) >= 0.5)
					tgtData[idx3 + k] = srcData[(leftX + topY * srcW) * 3 + k];
				else if ( (v) > 0.5)
					tgtData[idx3 + k] = srcData[(leftX + bottomY * srcW) * 3 + k];
				else
					tgtData[idx3 + k] = srcData[(leftX + bottomY * srcW) * 3 + k];
			}
		}
		else  // 非最后一行或最后一列情况
		{
			for (int k = 0; k < 1; k++)
			{
				if ((1. - u) >=0.5 && (1. - v) >=0.5)
					tgtData[idx3 + k] = srcData[(leftX + topY * srcW) + k];
				else if ((u)>0.5 && (1. - v) > 0.5)
					tgtData[idx3 + k] = srcData[(rightX + topY * srcW) + k];
				else if ((1. - u)>0.5 && (v) > 0.5)
					tgtData[idx3 + k] = srcData[(leftX + bottomY * srcW) + k];
				else if (u >0.5&& v > 0.5)
					tgtData[idx3 + k] =srcData[(rightX + bottomY * srcW) + k];
				else
					tgtData[idx3 + k] = srcData[(rightX + bottomY * srcW)  + k];
			/*	tgtData[idx3 + k] = (1. - u) * (1. - v) * srcData[(leftX + topY * srcW) + k]
					+ (u) * (1. - v) * srcData[(rightX + topY * srcW)  + k]
					+ (1. - u) * (v)*srcData[(leftX + bottomY * srcW) + k]
					+ u * v * srcData[(rightX + bottomY * srcW) + k];*/
			
			}
		}
	}
}

三、C#利用pythonnet通过序列化文件调用python多进程算法平台开发好的算法

序列化文件利用pickle库储存有所有调用算法的组合链接方式和参数,python可直接调用运行、c++可以转json读取算法参数和链接方式直接运行和生成组合后的dll、那这里为啥这里要用C#来调用呢,主要是方便其他同事后续的修改(主要用C#),所里C#调用的方式相对复杂一点(涉及到python多进程的处理)

c#图形界面可以看前面的内容

调用代码:

        /// <summary>
        /// 初始化VisionTool的运行pyhton环境
        /// </summary>
        public static void InitVisionTool()
        {
            try
            {
                //初始化python引擎
                var pythonPathBuilder = new StringBuilder();
                detects.Add(new Detect("CCD1"));
                detects.Add(new Detect("CCD2"));
                pythonPathBuilder.Append(@"D:\AllLargeProject\Visontool\windows版本VT\vt_windows_software_1.3.7.0;");
                pythonPathBuilder.Append(@"D:\AllLargeProject\Visontool\windows版本VT\vt_windows_software_1.3.7.0\visiontool\core\common\datatype;");
                pythonPathBuilder.Append(@"C:\Users\xbb1995\anaconda3\envs\visiontool\Lib\encodings;");
                pythonPathBuilder.Append(@"C:\Users\xbb1995\anaconda3\envs\visiontool\xbb\visiontool\DLLs;");
                pythonPathBuilder.Append(@"C:\Users\xbb1995\anaconda3\envs\visiontool;");
                pythonPathBuilder.Append(@"C:\Users\xbb1995\anaconda3\envs\visiontool\Lib;");
                pythonPathBuilder.Append(@"C:\Users\xbb1995\anaconda3\envs\visiontool\Lib\site-packages;");
                //pythonPathBuilder.Append(@"D:\xbb\VT\vt_windows_software_1.3.7.0\torch\lib;");
                PythonEngine.PythonPath = pythonPathBuilder.ToString();
                PythonEngine.Initialize();
                PythonEngine.BeginAllowThreads();
                using (Py.GIL())
                {
                    unsafe
                    {
                        //初始化相关库
                        pickle = Py.Import("pickle");//pickle库,导入模块,导出模块
                        cv2 = Py.Import("cv2");
                        numpy = Py.Import("numpy");
                        ctypes = Py.Import("ctypes");
                        ImageTypeConvert = Py.Import("ImageTypeConvert");//图片格式转换
                        builtins = Py.Import("builtins");
                        VisionTool_Project = pickle.load(builtins.open(@"D:\TEMP_File\project11.vtpro", "rb"));
                        //VisionTool_Project = pickle.load(builtins.open(@"D:\向斌斌\产线程序\装配\潍柴\QH2.0\异物检测\程序\程序\异物检测程序(重新最新版本)\VisionProgram\bin\x64\Debug\Vtpro\project.vtpro", "rb"));//模块:所有深度学习模型、机器学习模块的参数数组模型
                        //VisionTool_Project = pickle.load(builtins.open(@"D:\xbb(勿删)\vtpro\project_deep.vtpro", "rb"));//模块:所有深度学习模型、机器学习模块的参数数组模型
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("python环境参数配置有误!VisionTool初始化失败!请检查参数配置!", ex);
            }
        }
        /// <summary>
        /// VisionTool运行(处理手动传入图片)
        /// </summary>
        public static VisionToolRunInfo RunVisionToolFlow1(int Index, WuKongData img_intptr)
        {
            try
            {
                unsafe
                {
                    using (Py.GIL())
                    {
                        if (img_intptr.Images.Count == 1)//手动测试图片
                        {
                            //1、传入VisionTool图片
                            //VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__2").getTool("ImageSplicingTool_1").input_image1 =
                            //    IntPtr2GrayImage(img_intptr.Images["1"].datas, img_intptr.Images["1"].nWidth, img_intptr.Images["1"].nHeight);
                            //VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__2").getTool("ImageSplicingTool_1").input_image2 =
                            //    IntPtr2GrayImage(img_intptr.Images["1"].datas, img_intptr.Images["1"].nWidth, img_intptr.Images["1"].nHeight);
                            //VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__2").getTool("ImageSplicingTool_1").input_image3 =
                            //    IntPtr2GrayImage(img_intptr.Images["1"].datas, img_intptr.Images["1"].nWidth, img_intptr.Images["1"].nHeight);
                            //VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__2").getTool("ImageSplicingTool_1").input_image4 =
                            //    IntPtr2GrayImage(img_intptr.Images["1"].datas, img_intptr.Images["1"].nWidth, img_intptr.Images["1"].nHeight);

                            //2、运行VisonTool算法流程
                            //VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__2").run();

                            //3、获得VisionTool检测结果
                            //vt_result.rectangleNum = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").result.blobs.len;
                            //vt_result.YiWuNum = vt_result.rectangleNum;
                            //if (vt_result.rectangleNum > 10)
                            //    vt_result.rectangleNum = 10;
                            //float area = 0;
                            //for (int i = 0; i < vt_result.rectangleNum; i++)
                            //{
                            //    vt_result.rectanglenNdarry[0 + i * 4] = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").result.blobs[i].bounding_box.x
                            //        + VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("SegformerPredictTool_1").region.x;
                            //    vt_result.rectanglenNdarry[1 + i * 4] = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").result.blobs[i].bounding_box.y
                            //        + VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("SegformerPredictTool_1").region.y;
                            //    vt_result.rectanglenNdarry[2 + i * 4] = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").result.blobs[i].bounding_box.width;
                            //    vt_result.rectanglenNdarry[3 + i * 4] = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").result.blobs[i].bounding_box.height;
                            //    float cur_area = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").result.blobs[i].area;
                            //    if (area < cur_area)
                            //        area = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").result.blobs[i].area;
                            //}
                            //vt_result.YiWuArea = area;
                            return vt_result;
                        }
                        else if (img_intptr.Images.Count == 2)//手动测试图片
                        {
                            //1、传入VisionTool图片
                            //VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("SegformerPredictTool_1").input_image = IntPtr2ColorImage(img_intptr.Images["1"].datas, img_intptr.Images["1"].nWidth, img_intptr.Images["1"].nHeight);
                            2、运行VisonTool算法流程In  CogImage8Grey((Bitmap)data.Images[j + "_" + i])
                            //VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("SegformerPredictTool_1").run();
                            //VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").input_image = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("SegformerPredictTool_1").result.image;
                            //VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").run();
                            3、获得VisionTool检测结果
                            //vt_result.rectangleNum = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").result.blobs.len;
                            //vt_result.YiWuNum = vt_result.rectangleNum;
                            //if (vt_result.rectangleNum > 10)
                            //    vt_result.rectangleNum = 10;
                            //float area = 0;
                            //for (int i = 0; i < vt_result.rectangleNum; i++)
                            //{
                            //    vt_result.rectanglenNdarry[0 + i * 4] = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").result.blobs[i].bounding_box.x
                            //        + VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("SegformerPredictTool_1").region.x;
                            //    vt_result.rectanglenNdarry[1 + i * 4] = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").result.blobs[i].bounding_box.y
                            //        + VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("SegformerPredictTool_1").region.y;
                            //    vt_result.rectanglenNdarry[2 + i * 4] = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").result.blobs[i].bounding_box.width;
                            //    vt_result.rectanglenNdarry[3 + i * 4] = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").result.blobs[i].bounding_box.height;
                            //    float cur_area = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").result.blobs[i].area;
                            //    if (area < cur_area)
                            //        area = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").result.blobs[i].area;
                            //}
                            //vt_result.YiWuArea = area;
                            return vt_result;
                        }
                        else if (img_intptr.Images.Count == 12)//自动检测
                        {
                            //1、传入VisionTool图片

                            VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__2").getTool("ImageSplicingTool_1").input_image1 =
                                Bitmap2GrayImage(img_intptr.Images["1_0"]);
                            VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__2").getTool("ImageSplicingTool_1").input_image2 =
                                Bitmap2GrayImage(img_intptr.Images["2_0"]);
                            VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__2").getTool("ImageSplicingTool_1").input_image3 =
                                Bitmap2GrayImage(img_intptr.Images["3_0"]);
                            VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__2").getTool("ImageSplicingTool_1").input_image4 =
                                Bitmap2GrayImage(img_intptr.Images["4_0"]);

                            VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__2").getTool("ImageSplicingTool_2").input_image1 =
                                Bitmap2GrayImage(img_intptr.Images["1_1"]);
                            VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__2").getTool("ImageSplicingTool_2").input_image2 =
                                Bitmap2GrayImage(img_intptr.Images["2_1"]);
                            VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__2").getTool("ImageSplicingTool_2").input_image3 =
                                Bitmap2GrayImage(img_intptr.Images["3_1"]);
                            VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__2").getTool("ImageSplicingTool_2").input_image4 =
                               Bitmap2GrayImage(img_intptr.Images["4_1"]);

                            VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__2").getTool("ImageSplicingTool_3").input_image1 =
                                Bitmap2GrayImage(img_intptr.Images["1_2"]);
                            VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__2").getTool("ImageSplicingTool_3").input_image2 =
                               Bitmap2GrayImage(img_intptr.Images["2_2"]);
                            VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__2").getTool("ImageSplicingTool_3").input_image3 =
                                Bitmap2GrayImage(img_intptr.Images["3_2"]);
                            VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__2").getTool("ImageSplicingTool_3").input_image4 =
                                Bitmap2GrayImage(img_intptr.Images["4_2"]);


                            //2、运行VisonTool算法流程In  CogImage8Grey((Bitmap)data.Images[j + "_" + i])
                            VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__2").run();
                            //3、获得VisionTool检测结果
                            outputColorImage = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__2").getTool("ImgThreshMergeTool_1").result.output_merge_image;
                            //vt_result.OutImage = ColorImage2Bitmap(outputColorImage, img_intptr.Images["4_2"].Height*4, img_intptr.Images["4_2"].Width);
                            vt_result.OutImage.Save("D:\\1.bmp", ImageFormat.Bmp);
                            image = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__2").getTool("ImgThreshMergeTool_1").input_gchannel_image;
                            int a = image[2300][2400];
                            //vt_result.rectangleNum = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").result.blobs.len;
                            //vt_result.YiWuNum = vt_result.rectangleNum;
                            if (vt_result.rectangleNum > 10)
                                vt_result.rectangleNum = 10;
                            //float area = 0;
                            //for (int i = 0; i < vt_result.rectangleNum; i++)
                            //{
                            //    vt_result.rectanglenNdarry[0 + i * 4] = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").result.blobs[i].bounding_box.x
                            //        + VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("SegformerPredictTool_1").region.x;
                            //    vt_result.rectanglenNdarry[1 + i * 4] = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").result.blobs[i].bounding_box.y
                            //        + VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("SegformerPredictTool_1").region.y;
                            //    vt_result.rectanglenNdarry[2 + i * 4] = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").result.blobs[i].bounding_box.width;
                            //    vt_result.rectanglenNdarry[3 + i * 4] = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").result.blobs[i].bounding_box.height;
                            //    float cur_area = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").result.blobs[i].area;
                            //    int leibei = image[vt_result.rectanglenNdarry[1 + i * 4] + vt_result.rectanglenNdarry[3 + i * 4] / 2][vt_result.rectanglenNdarry[0 + i * 4] + vt_result.rectanglenNdarry[2 + i * 4] / 2];
                            //    if (area < cur_area)
                            //        area = VisionTool_Project.getTask($"task{Index + 1}").getBlock("Vision__3").getTool("BlobTool_2").result.blobs[i].area;
                            //}
                            //vt_result.YiWuArea = area;
                            return vt_result;
                        }

                    }
                    return null;
                }
            }
            catch (Exception ex)
            {
                return vt_result;
                //throw new Exception($"运行VisionTool算法失败:{ex.Message}");
                //return false;
            }
        }

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

react redux用法学习

参考资料&#xff1a; https://www.bilibili.com/video/BV1ZB4y1Z7o8 https://cn.redux.js.org/tutorials/essentials/part-5-async-logic AI工具&#xff1a;deepseek&#xff0c;通义灵码 第一天 安装相关依赖&#xff1a; 使用redux的中间件&#xff1a; npm i react-redu…

【2025 Unity Meta Quest MR 开发教程】透视 Passthrough 模块配置(戴上头显看见现实画面)

XR 开发者社区&#xff1a;https://www.spatialxr.tech/ 文章目录 &#x1f4d5;导入透视模块&#x1f4d5;OVRManager&#x1f4d5;OVRPassthroughLayer 脚本&#x1f4d5;相机 教程中使用的 SDK&#xff1a;Meta XR SDK v72&#xff08;可以从 Unity 资源商店添加 Meta XR A…

UWB功耗大数据插桩调研

一、摘要 UWB功耗点 插桩点 日志关键字 电流 蓝牙持锁 BatteryStats的锁统计 vendor_bluetooth_lock 30~40mA 测距 UwbSessionManager.startRanging UwbSessionManager.stoptRanging 或接入fadiKey Uwb状态广播 "com.fadiui.dkservice.action.uwb.state.change&q…

旅游行业内容管理系统CMS提升网站建设效率与体验

内容概要 在如今快速发展的互联网时代&#xff0c;旅游行业对网站的要求越来越高&#xff0c;内容管理系统&#xff08;CMS&#xff09;的应用不可或缺。以 Baklib 为代表的先进CMS可显著提高旅游网站的建设效率与用户体验。为了满足不断变化的市场需求&#xff0c;这些系统通…

【vscode+latex】实现overleaf本地高效编译

overleaf本地高效编译 1. 配置本地latex环境2. vscode插件与配置3. 使用 之前觉得用overleaf在线写论文很方便&#xff0c;特别是有辅助生成latex格式公式的网页&#xff0c;不需要在word上一个一个手打调格式。 然而&#xff0c;最近在写一篇论文的时候&#xff0c;由于这篇论…

消费电子产品中的噪声对TPS54202的影响

本文章是笔者整理的备忘笔记。希望在帮助自己温习避免遗忘的同时&#xff0c;也能帮助其他需要参考的朋友。如有谬误&#xff0c;欢迎大家进行指正。 一、概述 在白色家电领域&#xff0c;降压转换器的应用非常广泛&#xff0c;为了实现不同的功能就需要不同的电源轨。TPS542…

51c自动驾驶~合集49

我自己的原文哦~ https://blog.51cto.com/whaosoft/13164876 #Ultra-AV 轨迹预测新基准&#xff01;清华开源&#xff1a;统一自动驾驶纵向轨迹数据集 自动驾驶车辆在交通运输领域展现出巨大潜力&#xff0c;而理解其纵向驾驶行为是实现安全高效自动驾驶的关键。现有的开…

IGBT的两级关断

IGBT&#xff08;绝缘栅双极型晶体管&#xff09;的两级关断&#xff08;Two-stage turn-off&#xff09;是一种优化关断过程的方法&#xff0c;主要用于减少关断时的电压过冲和dv/dt&#xff08;电压变化率&#xff09;过高的问题&#xff0c;特别是在大功率应用中&#xff08…

centos 7 关于引用stdatomic.h的问题

问题&#xff1a;/tmp/tmp4usxmdso/main.c:6:23: fatal error: stdatomic.h: No such file or directory #include <stdatomic.h> 解决步骤&#xff1a; 1.这个错误是因为缺少C编译器的标准原子操作头文件 stdatomic.h。在Linux系统中&#xff0c;我们需要安装开发工具…

20250211解决荣品的RK3566核心板在Android13下出现charge_extrem_low_power的问题

20250211解决荣品的RK3566核心板在Android13下出现charge_extrem_low_power的问题 2025/2/11 17:45 缘起&#xff1a;荣品的RK3566核心板在Android13下&#xff0c;出现charge_extrem_low_power之后就直接挂住了。 由于我司使用了CW2217这个电量计&#xff0c;没有使用核心板自…

动手学深度学习---深层神经网络

目录 一、神经网络1.1、模型训练1.2、损失函数1.2.1、分类&#xff1a;hinge loss/合页损失/支持向量机损失1.2.2、分类&#xff1a;交叉熵损失(softmax分类器)1.2.2.1 二分类交叉熵损失1.2.2.2 多分类交叉熵损失 1.2.3、回归&#xff1a;误差平方和&#xff08;SSE&#xff09…

(定时器,绘制事件,qt简单服务器的搭建)2025.2.11

作业 笔记&#xff08;复习补充&#xff09; 1> 制作一个闹钟软件 头文件 #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QPushButton> //按钮类 #include <QTimer> //定时器类 #include <QTime> //…

STM32_USART通用同步/异步收发器

目录 背景 程序 STM32浮空输入的概念 1.基本概念 2. STM32浮空输入的特点 3. STM32浮空输入的应用场景 STM32推挽输出详解 1. 基本概念 2. 工作原理 3. 应用场景 使能外设时钟 TXE 和 TC的区别 USART_IT_TXE USART_IT_TC 使能串口外设 中断处理函数 背景 单片…

大语言模型多代理协作(MACNET)

大语言模型多代理协作(MACNET) Scaling Large-Language-Model-based Multi-Agent Collaboration 提出多智能体协作网络(MACNET),以探究多智能体协作中增加智能体数量是否存在类似神经缩放定律的规律。研究发现了小世界协作现象和协作缩放定律,为LLM系统资源预测和优化…

安川伺服控制器MP系列优势特点及行业应用

在工业自动化领域&#xff0c;运动控制器的性能直接决定了设备的精度、效率和可靠性。作为全球领先的运动控制品牌&#xff0c;安川电机伺服控制器凭借其卓越的技术优势和广泛的应用场景&#xff0c;正在为智能制造注入强劲动力&#xff01; MP3100&#xff1a;主板型运动控制…

AIoT时代来临,物联网技术如何颠覆未来生活?

在这个万物互联的时代&#xff0c;“物联网”&#xff08;IoT&#xff09;正以前所未有的速度改变我们的生活&#xff0c;而“AIoT”则是在物联网基础上融入人工智能技术&#xff0c;赋予设备更高的智能和自主决策能力。随着5G、边缘计算和云技术的不断发展&#xff0c;物联网正…

2025.2.11

1> 制作一个闹钟软件 .h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QLabel> #include <QLineEdit> #include <QPushButton> #include <QTime> #include <QTimer> #include <QTimeEdit> #include <QDa…

安装OpenJDK21(linux、macos)

文章目录 安装OpenJDK21java21linux下安装配置mac下安装 安装OpenJDK21 java21 封神&#xff01;Java 21正式发布了&#xff0c;迎来了史诗级新特性&#xff0c;堪称版本最强&#xff01;&#xff01;&#xff01; 视频链接&#xff1a;https://www.bilibili.com/video/BV1E8…

PortSwigger——WebSockets vulnerabilities

文章目录 一、WebSockets二、Lab: Manipulating WebSocket messages to exploit vulnerabilities三、Lab: Manipulating the WebSocket handshake to exploit vulnerabilities四、Using cross-site WebSockets to exploit vulnerabilities4.1 跨站WebSocket劫持&#xff08;cro…

SpringBootWeb三层架构分层解耦

SpringBootWeb 1. SpringBootWeb案例1.1 控制层未拆分代码1.2 实体类1.3 静态资源文件1.4 txt文件1.5 运行界面展示 2. 三层架构拆分2.1 控制层&#xff08;Controller&#xff09;2.1.1 功能2.1.2 用户信息控制层 2.2 业务逻辑层&#xff08;Service&#xff09;2.2.2 功能2.2…