C#处理Gauss光斑图像[通过OpenGL和MathNet]

article/2025/8/23 9:49:38

在这里插入图片描述

C# 处理高斯光束的光斑图像

    • 1 基础操作
    • 2 图片截取
    • 3 转灰度图
    • 4 SharpGL画三维点云图
    • 5 MathNet拟合,OxyPlot作图

1 基础操作

.Net平台必备VS,新建WinForm项目,项目名称Gauss,位置任选。然后就会进入窗口编辑页面,我们开始拖控件。

考虑到我们的需求无非是

  1. 读取图片
  2. 图片转灰度
  3. 展示图像灰度
  4. 高斯拟合

所以先排上四个按钮,分别用于这四种需求,如下图所示

在这里插入图片描述

然后我们首先想办法满足第一个功能,即打开图片。双击打开图片的按钮,进入函数编辑页面,对btnOpen_Click进行编辑。这个函数顾名思义,即当我们点击按钮btnOpen时将要执行的操作。

我们首先通过一个文件对话框OpenFileDialog来读取文件路径。

为了验证我们的代码,可以在Form1面板上添加一个textBox,其添加方式与button如出一辙。添加之后,将其(Name)改为textMessage,用于存放调试信息。

则得到代码如下

private void btnOpen_Click(object sender, EventArgs e)
{string strFileName = "";    //用于存储图片路径OpenFileDialog ofd = new OpenFileDialog();ofd.Filter = "图片文件(*.bmp)|*.bmp";if (ofd.ShowDialog() == DialogResult.OK)strFileName = ofd.FileName;textMessage.Text = strFileName;
}

按下F5运行,然后点击打开图像按钮,可以进入我们熟悉的文件对话框,选择图片后可以看到在textMessage中返回了图片路径。

在这里插入图片描述

接下来,开始进行读图操作,在C#中,提供了Bitmap的读取操作,我们可以直接在获取图像路径之后,通过Image.FromFile()函数进行图片的读取。

而图片读取之后,则需要进行展示,为此我们同样从工具箱中拖取PictureBox控件,来展示我们打开的图像,将其(Name)改为Facula,然后修改btnOpen_Click函数如下

private void btnOpen_Click(object sender, EventArgs e)
{string strFileName = "";OpenFileDialog ofd = new OpenFileDialog();ofd.Filter = "图片文件(*.bmp)|*.bmp";if (ofd.ShowDialog() == DialogResult.OK)strFileName = ofd.FileName;Bitmap facula = (Bitmap)Image.FromFile(strFileName);Facula.Image = facula.Clone() as Image;
}

运行之后,选择我们将要处理的图像,运行结果为

在这里插入图片描述

2 图片截取

由于光斑图片大部分是背景,故需截取感兴趣的区域。我们希望实现一种操作逻辑,即通过鼠标框选感兴趣区域,从而实现截图功能。在此可以把框选分为两个过程,即鼠标按下,然后拖动鼠标,最后鼠标松开。

所以需要封装两个函数,双击解决方案资源管理器中的Form.Designer.cs,进入代码编辑页面,Ctrl+F找到Facula的位置,在下面添加

this.Facula.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Facule_Down);
this.Facula.MouseUp += new System.Windows.Forms.MouseEventHandler(this.Facule_Up);

其中,MouseDown表示按下鼠标左键触发的行为;MouseUp表示松开鼠标左键时的行为。只要我们分别可以记下按下和松开时的鼠标位置,就可以返回一个矩形框。

在C#中,Control.MousePosition表示当前鼠标相对于屏幕左上角的位置;this.Location表示窗体左上角相对于屏幕左上角的位置;Facula.Location表示我们创建的控件Facula相对于窗体左上角的位置。

考虑到我们需要在两个动作中调用同一参数,所以最好新建两个全局变量,存储按下鼠标时的坐标。然后新建一个函数,用于处理当前鼠标位置,并将其转化为图像坐标。

Bitmap facula;      //存放图像
int xAxis,yAxis;    //在后面调用
private float getAxis(char flag)
{float axis;if(flag == 'x')axis = (int)(Control.MousePosition.X - this.Location.X - Facula.Location.X-10)/ Facula.Width * facula.Width;elseaxis = (float)(Control.MousePosition.Y - this.Location.Y - Facula.Location.Y-38) / Facula.Height* facula.Height;return axis;
}//鼠标按下时的操作
private void Facule_Down(object sender, EventArgs e)
{this.xAxis = getAxis('x');this.yAxis = getAxis('y');
}
//鼠标抬起时的操作
private void Facule_Up(object sender, EventArgs e)
{//先放在这一会儿再写
}

注意,我们所有的代码都写在public partial class Form1 : Form这个类里面。其中getAxis可以通过三元表达式写成更简洁的形式

private int getAxis(char flag)
{return flag=='x' ? (Control.MousePosition.X - this.Location.X - Facula.Location.X - 10)* facula.Width / Facula.Width: (Control.MousePosition.Y - this.Location.Y - Facula.Location.Y - 38)* facula.Height / Facula.Height;
}

在C#中,提供了Clone方法,可以实现Bitmap类的裁剪功能,其输入参数为一个Rectangle,即矩形,代表我们将要分割的感兴趣区域。

private void Facule_Up(object sender, EventArgs e)
{int xStart = Math.Min(getAxis('x'), xAxis);int yStart = Math.Min(getAxis('y'), yAxis);int width = Math.Abs(getAxis('x') - xAxis);int height = Math.Abs(getAxis('y') - yAxis);//此即我们感兴趣的区域Rectangle roi = new Rectangle(xStart,yStart,width,height);facula = facula.Clone(roi,facula.PixelFormat);//图像裁剪Facula.Image = facula.Clone() as Image;        //更改图片显示
}

由于裁剪前后图像尺寸相去甚远,所以需要将我们创建的PictureBox控件FaculaSizeMode设为ScratchImage

其效果如图所示

在这里插入图片描述

3 转灰度图

我们看到的光斑图像虽然是黑白的,但并不是一个灰度图,因为这张图片仍然有四个通道,分别存放r, g, b以及alpha四个值,只不过透明度为0,且r, g, b相等,所以自然没有色彩。

为了将其转化为真·灰度图,我们需要稍微了解一下位图的编码方式。一张图片,主要包含两个部分,即文件头与数据,文件头一般占据54个字节,声明这是一张图片,并告诉我们这张图片的长宽信息;而其色彩信息则线性地存放在数据区里。图片软件通过文件头,获知这是一张图片,再根据其长宽,对数据进行扫描,呈现到屏幕上,我们就看到图了。

这里面有两个问题,

  1. 由于图片的像素值的大小是有限的,一般是8位无符号整型;但文件在操作系统中可能以64位为一个最小的存储单元,所以图片中的一行未必能够正好塞满64的倍数个bit,所以需要有一个数据对齐的问题。
  2. 红绿蓝三原色如何反演出灰度图像,直接取平均是否可行?对于我们的光斑图像来说是无所谓的,但比较流行的方案是 gray = 0.11 r + 0.59 g + 0.3 b \text{gray}=0.11r+0.59g+0.3b gray=0.11r+0.59g+0.3b,我们的代码中也采取这个形式。

接下来,双击转灰度按钮,进入btnGray_Click函数的编辑位置,其代码为

byte[,] matFacula;        //创建一个全局变量来存储强度数据
private void btnGray_Click(object sender, EventArgs e)
{int width = facula.Width;     //图片宽度int height = facula.Height;   //图片高度//创建数据交换区,用来读取facula中的数据var bmdata = facula.LockBits(new Rectangle(Point.Empty, facula.Size),ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);byte[] buffer = new byte[bmdata.Stride* bmdata.Height]; Marshal.Copy(bmdata.Scan0, buffer, 0, buffer.Length); //复制图像数据facula.UnlockBits(bmdata);  //bmdata解锁matFacula = new byte[height, width]; //新建一个8位灰度图像,宽高分别是width,heightfacula = new Bitmap(width, height, PixelFormat.Format8bppIndexed);//这回用来写facula中的数据bmdata = facula.LockBits(new Rectangle(Point.Empty, facula.Size),ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);int stride = bmdata.Stride;      //扫描行字节数byte[] grayValues = new byte[stride * height];   // 为图像数据分配内存int op = 0;    //用来遍历rgb与alpha通道for (int i = 0; i < height; i++)for (int j = 0; j < width; j++){matFacula[i, j] = (byte)(buffer[op++] * 0.11 + buffer[op++] * 0.59 + buffer[op++] * 0.3);op++;//跳过alpha通道grayValues[i*stride+j] = matFacula[i, j];}//参数分别是被复制数据,初始位置,目标指针,目标长度Marshal.Copy(grayValues, 0, bmdata.Scan0, stride * height);facula.UnlockBits(bmdata);  // 解锁内存区域  // 修改生成位图的索引表ColorPalette palette = facula.Palette;for (int i = 0; i < 256; i++)palette.Entries[i] = Color.FromArgb(i, i, i);facula.Palette = palette;Facula.Image = facula.Clone() as Image;
}

其中PixelFormat.Format32bppArgb代表32位Argb图像,A即alpha,代表透明度;rgb分别代表红绿蓝,四个通道每个通道都是8位,合在一起就是32位;PixelFormat.Format8bppIndexed代表8位索引图像,即只有一个通道,但这个通道可以根据颜色表进行对照,我们想做出灰度图像,所以颜色表中的rgb值应该是 1 : 1 : 1 1:1:1 1:1:1

MarshalSystem.Runtime.InteropServices中的一个类,可进行一些内存操作,其中Copy函数即将一个内存区域复制给另一个变量。以Marshal.Copy(bmdata.Scan0, buffer, 0, buffer.Length);为例,其复制的起始位置为bmdata.Scan0,将复制给buffer,偏移量为0,复制buffer.Length个字节。

ColorPalette是位于System.Drawing.Imaging中的一个类,可以定义调色板的颜色的数组,可以理解为位图的一个属性。

最终效果如下图所示

在这里插入图片描述

在以上代码中,有一个貌似没用上的变量matFacula,我们将用这个二维数组进行一些数学计算,并绘制强度图。

4 SharpGL画三维点云图

这里所谓的三维图,目的是把光斑的强度分布展示出来,很遗憾C#在三维作图这一点上远远不如专用的科学计算语言,但方法总比问题多,我们选择Sharp GL,即OpenGL的C#版本,来进行三维图的绘制。

点击VS菜单栏的工具NuGet包管理器管理解决方案的Nuget包,选择浏览,然后搜索SharpGL,选择搜索结果中的SharpGL以及SharpGL.WinForms进行安装。

安装成功后,工具箱中会出现SharpGL.WinForms组,里面有一些SharpGL控件。

细心的朋友可能会发现我刚刚展示的图片中多了一个选项卡,即光斑图像画图,这个看上去很高大上的东西也能在工具箱中找到,是Continer中的TabControl,一时之间找不到的话可以直接在工具箱中搜索。将选项卡控件拖放到窗口中后,可以看到这个控件右上角有一个侧三角图标,可以进行添加或删除Page的操作,很符合人的直觉;改名字之类的操作与其他控件相同,不再赘述。

我们把之前的PictureBox控件拖入光斑图像选项卡中,然后在画图选项卡中拖入OpenGLControl(SharpGL)控件,取个名字叫glMesh。然后点击三维图按钮,进入btnMesh_Click函数的编辑位置。

  private void btnMesh_Click(object sender, EventArgs e){OpenGL gl = this.glMesh.OpenGL;   //新建openGL对象//清除缓冲区gl.Clear(OpenGL.GL_COLOR_BUFFER_BIT | OpenGL.GL_DEPTH_BUFFER_BIT);gl.MatrixMode(OpenGL.GL_PROJECTION);//设置工作模式gl.LoadIdentity();                    //生成单位阵gl.Perspective(65, 1.0, 1.0, 1000);  // 投影矩阵( y 45度,纵横比1:1,near截平面1,far截平面10000.)gl.LookAt(-10, -10, 150, 0.5*(double)facula.Width, 0.5 * (double)facula.Height, 0.0f, 1.0f, 1.0f, -1.0f); //defines a viewing transformationfloat z;//用来存放像素点的强度信息//查找matFacula的最大值for (int i = 0; i < facula.Height; i++)for (int j = 0; j < facula.Width; j++)zMax = zMax > matFacula[i,j] ? zMax : matFacula[i,j];gl.Begin(OpenGL.GL_POINTS);   //开始画图for (int x = 0; x < facula.Height; x += 1)for (int y = 0; y < facula.Width; y += 1){z = (float)matFacula[x,y];gl.Color(z/zMax,0.3,0);        //设置点的颜色gl.Vertex(x,y, z);                //绘制点的位置}gl.End();         //画图完毕gl.Flush();       //更新图像
}

由于电脑屏幕无论如何也只能进行二维的显示,所以模型做好之后,需要用一个“相机”把模型拍下来,使之成为一张图片显示在屏幕上。

其中,gl.Perspective的用途是定义相机的性能,输入的四个参数分别代表:视场角、纵横比,后面两个代表焦深,即相机能看到的距离范围。

gl.LookAt代表了相机的位置,在OpenGL中的定义为

void gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez,GLdouble centerx, GLdouble centery, GLdouble centerz,GLdouble upx, GLdouble upy, GLdouble upz)

其中,eyex, eyey, eyez代表相机所在位置;centerx, centery, centerz则代表相机正对着的位置;upx, upy, upz表示相机平面的角度。

我们可以根据光斑图像的坐标范围来确定这些参数,由于像素点的值最大不超过255,而图片坐标的起始点为(0,0),所以我们选定(-10,-10,150)作为相机位置;相机正对着的点为图像中心处,即其z向坐标为0,x,y向坐标为图像长宽的一半;最后的视角,我们选择斜向下45度,即(1,1,-1)

gl.Color为设置点的颜色,需要注意的是,这里的输入值虽然可以是rgb,但其取值范围是0到1,所以我们先搜索出图像矩阵的最大值,然后根据当前值与最大值的比值来设置图像颜色。

根据我们的设置gl.Color(z/zMax,0.3,0),当像素的灰度值越大时,图像越红,否则越绿。

运行之后,拖动裁剪,然后转灰度,再绘制三维图,得到的结果为

在这里插入图片描述

5 MathNet拟合,OxyPlot作图

拟合曲线之前,我们需要找到一群可以被拟合的点。由于已经得到了光斑的灰度矩阵,所以我们可以从每一行选出一个最大值来代表这行光斑,从而得到一个一维的序列。

方法很简单

//private void btnFit_Click(object sender, EventArgs e)
double[] xArray = new double[facula.Height];
double[] pixArray = new double[facula.Height];for (int i = 0; i < facula.Height; i++)
{xArray[i] = i + 1;pixArray[i] = 0;for (int j = 0; j < facula.Width; j++)pixArray[i] = Math.Max(pixArray[i], matFacula[i, j]);
}

接下来就是问题之关键——如何将xArraypixArray逆合成一条高斯曲线。但在这个关键问题之前,我们还很好奇那些被选出来的点到底是什么样的,希望把这两组数先画出来看一看。

尽管SharpGL完全可以胜任这一工作,但相比之下,我们可以选择更适合的画图工具来完成,比如OxyPlot。那么接下来就是同样的套路

  1. 在NuGet包管理器中搜索OxyPlot,然后安装OxyPlot.Core以及OxyPlot.WindowsForms
  2. tabPages中添加一个选项卡,起个名字叫拟合
  3. 从工具箱中选择PlotView添加到拟合选项卡上,将其更名为curveView
  4. using OxyPlotusing OxyPlot.Series

然后在btnFit_Click函数中继续写

//接在这一行后面
//pixArray[i] = Math.Max(pixArray[i], matFacula[i, j]);
//}
curveView.Model = new PlotModel { };
var scatters = new ScatterSeries()
{Title = "原始数据",MarkerType = MarkerType.Circle,MarkerSize = 1
};
for (int i = 0; i < facula.Height; i++)scatters.Points.Add(new ScatterPoint(xArray[i], pixArray[i]));curveView.Model.Series.Add(scatters);
curveView.Model.InvalidatePlot(true);

运行结果如图所示

在这里插入图片描述

看上去的确有一点高斯的样子,所谓高斯函数,其表达形式为

y = a ⋅ exp ⁡ ( − ( x − b c ) 2 ​ ) y=a⋅\exp{(−(\frac{x−b}{c})^2​)} y=aexp((cxb)2)

其中,a的值表示该函数的最大值;b表示其中心值,c表示当y值降到 1 e 2 \frac{1}{e^2} e21分之一处时x距离中心的位置。

为了拟合这个函数,我们还需要再安装一个包,MathNet.Numerics,这个包里有一个可以对"任意"函数进行非线性拟合的工具,但悲催的是,目前只支持两个参数的拟合,而我们想要拟合的函数里有三个参数。

所以我们有两种方案,其一是做一些预处理,先消掉一个参数,例如对数据做归一化,从而消去强度项a,或者对数据取质心,从而将其移到原点,消去参数b。另一个方案则是通过某种变形,使得高斯函数变成某种多项式的形式。一个最直观的想法就是取对数。

ln ⁡ y = ln ⁡ a − ( x − b ) 2 c 2 ln ⁡ y = − x 2 c 2 + 2 b x c 2 + ln ⁡ a − b 2 c 2 \begin{aligned} \ln y&=\ln a-\frac{(x-b)^2}{c^2}\\ \ln y&=-\frac{x^2}{c^2}+\frac{2bx}{c^2}+\ln a-\frac{b^2}{c^2} \end{aligned} lnylny=lnac2(xb)2=c2x2+c22bx+lnac2b2

Y = ln ⁡ y , A = − 1 c 2 , B = 2 b c 2 , C = ln ⁡ a − b 2 c 2 Y=\ln y, A=-\frac{1}{c^2}, B = \frac{2b}{c^2}, C=\ln a-\frac{b^2}{c^2} Y=lny,A=c21,B=c22b,C=lnac2b2,则Gauss函数变为

Y = A x 2 + B x + C Y=Ax^2+Bx+C Y=Ax2+Bx+C

待拟合成功后,有 c = 1 − A , b = − B 2 A , a = exp ⁡ B 2 + 4 A C 4 A c=\frac{1}{\sqrt{-A}},b=-\frac{B}{2A},a=\exp\frac{B^2+4AC}{4A} c=A 1,b=2AB,a=exp4AB2+4AC

又考虑到我们截图的过程必然不会非常完美,于是会产生一些噪声,所以在正式做数据处理之前,需要先去下噪声,这里只用最简单的阈值方式,即只有大于阈值的点才可以参与到拟合中来。

最后将btnFit_Click函数分拆整理一下

private void btnFit_Click(object sender, EventArgs e)
{var data = showOrigin();curveFit(data);
}private double[] showOrigin()
{int pNum = facula.Height;            int[] xArray = new int[pNum];double[] pixArray = new double[pNum];for (int i = 0; i < pNum; i++){xArray[i] = i;pixArray[i] = 0;for (int j = 0; j < facula.Width; j++)pixArray[i] = Math.Max(pixArray[i], matFacula[i, j]);}curveView.Model = new PlotModel { };var scatters = new ScatterSeries(){Title = "原始数据",MarkerType = MarkerType.Circle,MarkerSize = 1};foreach (var item in xArray)scatters.Points.Add(new ScatterPoint(item, pixArray[item]));curveView.Model.Series.Add(scatters);curveView.Model.InvalidatePlot(true);return pixArray;
}private void curveFit(double[] yArray)
{int pNum = 0;int thres = 10;foreach (var item in yArray)if (item> thres)pNum += 1;double[] xFit = new double[pNum];double[] yFit = new double[pNum];int j = 0;for (int i = 0; i < yArray.Length; i++)if (yArray[i]>thres){xFit[j] = i;yFit[j++] = Math.Log(yArray[i]);}double[] fit = MathNet.Numerics.Fit.Polynomial(xFit, yFit, 2);var plotView = new LineSeries() { };plotView.Title = "拟合结果";plotView.Color = OxyColors.Red;for (int i = 0; i < yArray.Length; i++)plotView.Points.Add(new DataPoint(i, Math.Exp(fit[0] + fit[1] * i + fit[2] * Math.Pow(i, 2))));double c = -1 / Math.Sqrt(-fit[2]);double b = -fit[1] / fit[2] / 2;double a = Math.Exp((fit[1] * fit[1] + 4 * fit[0] * fit[2]) / fit[2] / 4);textMessage.AppendText(string.Format("y={0:F2}*exp(-((x-{1:F2})/{2:F2})^2)", a, b, c));curveView.Model.Series.Add(plotView);curveView.Model.InvalidatePlot(true);
}

结果为

在这里插入图片描述


http://chatgpt.dhexx.cn/article/rYmrSVm7.shtml

相关文章

(pytorch进阶之路)IDDPM之diffusion实现

文章目录 概述代码实现image_trian.pydef create_model_and_diffusion()def create_gaussian_diffusion()SpacedDiffusion类GaussianDiffusion类 ⭐ LOOK HERE ⭐ 边角料noise scheduling 概述 DM beat GANs作者改进了DDPM模型&#xff0c;提出了三个改进点&#xff0c;目的是…

【论文笔记】A Unified MRC Framework for Named Entity Recognition

香农科技 ACL 2020的论文笔记 代码和paper可见&#xff1a;https://github.com/ShannonAI/mrc-for-flat-nested-ner 文章提出了将ner看做MRC(machine reading comprehen- sion )任务&#xff0c;而不是当做序列标注看待。 文章认为。在序列标注的过程中&#xff0c;如ORG是被当…

在OpenCV中基于深度学习的边缘检测

点击上方“小白学视觉”&#xff0c;选择加"星标"或“置顶” 重磅干货&#xff0c;第一时间送达本文转自&#xff1a;AI算法与图像处理 导读 分析了Canny的优劣&#xff0c;并给出了OpenCV使用深度学习做边缘检测的流程&#xff0c;文末有代码链接。 在这篇文章中&am…

真实的产品案例:实现文档边缘检测

向AI转型的程序员都关注了这个号&#x1f447;&#x1f447;&#x1f447; 机器学习AI算法工程 公众号&#xff1a;datayx 什么是边缘检测&#xff1f; 边缘检测是计算机视觉中一个非常古老的问题&#xff0c;它涉及到检测图像中的边缘来确定目标的边界&#xff0c;从而分离感…

ConvLSTM官方示例

运行ConvLSTM官方例子记录&#xff08;包含逐行解释&#xff09;&#xff1a; """ This script demonstrates the use of a convolutional LSTM network. This network is used to predict the next frame of an artificially generated movie which contains …

一个卷积神经网络的python实现

这几天用numpy实现了卷积神经网络,并在mnist数据集上进行了0-5五个数字的训练,全连接层的前向和反向写的肯定是对的,但卷积层不能确定,可能是对的.以后发现有错再改,卷积层在cpu上训练速度很慢,还有把代码里的Flatten换成GlobalAveragePooling以后试过一次好像错了,以后有机会再…

斯坦福NLP名课带学详解 | CS224n 第16讲 - 指代消解问题与神经网络方法(NLP通关指南·完结)

作者&#xff1a;韩信子ShowMeAI&#xff0c;路遥ShowMeAI&#xff0c;奇异果ShowMeAI教程地址&#xff1a;https://www.showmeai.tech/tutorials/36本文地址&#xff1a;https://www.showmeai.tech/article-detail/253声明&#xff1a;版权所有&#xff0c;转载请联系平台与作…

tpl文件如何导入ps?tpl文件笔刷怎么安装?

tpl文件如何导入ps&#xff1f;tpl文件笔刷怎么安装&#xff1f;有些笔刷格式是TPL的&#xff0c;这类笔刷导入方法其实非常简单&#xff0c;轻松几个操作即可&#xff0c;下面小编为大家详细介绍如何载入TPL格式笔刷。 1、准备好 .tpl 文件&#xff0c;然后打开PS。 2、在PS顶…

vscode中将tpl文件高亮显示

打开vscode&#xff1a; file --> preferences --> settings 进入settings页面 打开后输入 "files.associations": {"*.tpl": "html"}保存就可以咯

VSCode 中支持 tpl 等文件高亮渲染方法

这里以 .tpl 结尾的文件为例&#xff0c;其他后缀皆是如此&#xff0c; 点击菜单 文件->首选项->设置 输入如下代码&#xff1a; "files.associations": {"*.tpl": "html" }

vscode解决不识别tpl后缀文件的解决方法

vscode解决不识别tpl后缀文件的解决方法 了解tpl文件 解释&#xff1a; 以前用过的前端页面都是.html格式的&#xff0c;现在出现了.tpl文件&#xff0c;是template的缩写&#xff0c;其实就是前端页面&#xff0c;写的也是html。 应该是前端模板Smarty的一个格式。可以在D…

.tpl 文件高亮配置

文件-》首选项-》设置 "files.associations": {​ "*.tpl": "html"}

webpack自定义loader--编译.tpl文件

一、初始化一个项目 1、npm 初始化 npm init -y2、安装需要的依赖 package.json文件&#xff1a;{"name": "webpack-plugin-test","version": "1.0.0","description": "","main": "main.js&quo…

EditPlus打开.tpl文件高亮显示代码

Tools——Preferences File——Settings&syntax 在HTML下增加&#xff1b;tpl

opencart html模板引擎,Opencart前台HTML、tpl文件的修改,附opencart文件目录

△问题和服务可以联系微信:yangtuo1991 △文章浏览次数: 20,008 很多时候有些同学有需要修改opencart前台的一小部分样式和文字,修改版权信息、顶部和底部文字等一系列的需求、这里介绍下前台的这些 tpl文件的位置和修改, 这些模板的主题文件都会在catalog/view/theme/ 下面…

goland中读取tpl文件

近来开始研究golang,使用国人做的beego框架做页面开发&#xff0c;以前用pycharm开发的&#xff0c;所以习惯了 就采用了goland&#xff0c;不过有个问题&#xff0c;就是在做页面模版时候采用tpl后缀&#xff0c;需要进行设置一下。&#xff08;mac系统&#xff0c;如果window…

让vscode编辑器支持smarty模版的TPL文件

如何让vscode支持 php的 smarty模版&#xff0c; 1、安装插件 该插件可以是的tpl格式的文件以html的方式显示&#xff0c;但是我在使用中发现安装此插件后电脑的cup会飙到很高&#xff0c;一会就会把vscode跑蹦掉。 2、其实我们就不用安装插件&#xff0c;直接在vscode中进行设…

软件安装管家

软件安装管家&#xff1a;&#xff08;更新时间&#xff1a;2021-11-04&#xff09; 原有安装管家链接失效&#xff0c;大家可通过下面CSDN博客链接进行下载。 https://blog.csdn.net/weixin_43729418/article/details/110307259 评价&#xff1a;常用UG、Core、Solidworks、…

HBuilder软件下载及安装教程

Hbuilder是由我国开发的一款开发网页的编辑器&#xff0c;使用起来及其方便容易上手&#xff0c;而且在Hbuilde全语法库中&#xff0c;可以清楚地看到对各个浏览器、各个版本的支持情况&#xff0c;集成了大量语法快&#xff0c;少敲多行代码&#xff0c;体验飞一般的感觉。 方…