WPF+Emgucv实现在图像上画出感兴趣的区域 并进行掩膜获取 得到图像均值 和简单的 漫水填充
<Grid.RowDefinitions>
</Grid.RowDefinitions>
<Grid>
<UniformGrid Columns="2">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<InkCanvas Name="ink" Background="Transparent" Cursor="Pen" ForceCursor="True">
<Image Name="ImgShow" Source="/temp.png" IsHitTestVisible="False">
</Image>
</InkCanvas>
</ScrollViewer>
<UniformGrid Rows="2">
<GroupBox Header="Mask" >
<Image x:Name="imgMask"></Image>
</GroupBox>
<GroupBox Header="Result">
<Image x:Name="imgResult"></Image>
</GroupBox>
</UniformGrid>
</UniformGrid>
</Grid>
<StackPanel Grid.Row="1" Margin="20">
<DockPanel >
<Grid Grid.Row="1" VerticalAlignment="Center" >
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<RadioButton Grid.Column="0" VerticalAlignment="Center" Content="绘制墨迹" Click="RadioButton_Click" IsChecked="True"/>
<RadioButton Grid.Column="1" Content="按点擦除" Click="RadioButton_Click"/>
<RadioButton Grid.Column="2" Content="按线擦除" Click="RadioButton_Click"/>
<RadioButton Grid.Column="3" Content="选中墨迹" Click="RadioButton_Click"/>
<RadioButton Grid.Column="4" Content="停止操作" Click="RadioButton_Click"/>
</Grid>
<TextBlock HorizontalAlignment="Left" VerticalAlignment="Center" Margin="20 0 0 0">颜色选择:</TextBlock>
<Border CornerRadius="5" x:Name="colorchk" Background="Black" Width="50" HorizontalAlignment="Left" MouseLeftButtonDown="Grid_MouseLeftButtonDown" ></Border>
</DockPanel>
<DockPanel>
<Button Margin="20 0 0 0" Width="100" Height="30" Click="Button_Click">Roi截取</Button>
<TextBlock HorizontalAlignment="Left" VerticalAlignment="Center" Margin="20 0 0 0">兴趣区域平均值:<Run Foreground="#e03997" Name="txt_meanValue"></Run></TextBlock>
<Slider Value="120" x:Name="threshould_slider" Width="200" TickPlacement="Both" TickFrequency="1" Maximum="255" IsSnapToTickEnabled="True"></Slider>
<TextBlock HorizontalAlignment="Center" VerticalAlignment="Center">阈值<Run Text="{Binding ElementName=threshould_slider,Path=Value}"></Run></TextBlock>
<Button Margin="20 0 0 0" Width="100" HorizontalAlignment="Left" Height="30" Click="floodfill_Click">漫水填充</Button>
</DockPanel>
</StackPanel>
</Grid>
</Grid>
//cs代码
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.UI;
using Emgu.CV.Util;
using Color = System.Drawing.Color;
using Point = System.Drawing.Point;
using Rectangle = System.Drawing.Rectangle;
namespace MaskGetMean
{
///
/// MainWindow.xaml 的交互逻辑
///
public partial class MainWindow : Window
{
//声明一个 DrawingAttributes 类型的变量
DrawingAttributes drawingAttributes;
///
/// 默认图像路径。可拖拽图像进窗体
///
string imgpath = (AppDomain.CurrentDomain.BaseDirectory + "temp.png");
public MainWindow()
{
InitializeComponent();
//创建 DrawingAttributes 类的一个实例
drawingAttributes = new DrawingAttributes();
//将 InkCanvas 的 DefaultDrawingAttributes 属性的值赋成创建的 DrawingAttributes 类的对象的引用
//InkCanvas 通过 DefaultDrawingAttributes 属性来获取墨迹的各种设置,该属性的类型为 DrawingAttributes 型
ink.DefaultDrawingAttributes = drawingAttributes;
//设置 DrawingAttributes 的 Color 属性设置颜色
}
/// <summary>
/// 拖拽
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void MainWindow_DragEnter(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effects = DragDropEffects.Link; //WinForm中为e.Effect = DragDropEffects.Link
else e.Effects = DragDropEffects.None; //WinFrom中为e.Effect = DragDropEffects.None
}
private void MainWindow_Drop(object sender, DragEventArgs e)
{
string fileName = ((System.Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(0).ToString();
if (fileName.EndsWith(".jpg") || fileName.EndsWith(".png") || fileName.EndsWith(".bmp"))
{
imgpath = fileName;
ImgShow.Source = new BitmapImage(new Uri(imgpath));
//The Imageviewer 直接弹出新的窗口
Image<Bgr, byte> loadImg = new Image<Bgr, byte>(imgpath);
ImageViewer viewer = new ImageViewer(loadImg, "Loaded Image");
viewer.Show();
//1.使用HistogramViewer不需要事先拉到设计窗口中,他是弹出窗口,你只需要直接使用便可以
HistogramViewer.Show(loadImg[0], 32); //image[0] 显示Blue,bin = 32
HistogramViewer.Show(loadImg, 32); //显示所有信道
//获得文件名后的操作...
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
//原始图像
var OldImage = CvInvoke.Imread(imgpath);
//获取图像原始大小和显示大小的比例
double a = OldImage.Width / ImgShow.Source.Width;
//获取画的坐标线集合
var list = ink.Strokes;
//装轮廓集合
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
//获取画的坐标点集合
foreach (var item in list)
{ //单个轮廓坐标集合
VectorOfPoint vectorOfPoint = new VectorOfPoint();
foreach (var stylusPoint in item.StylusPoints)
{
vectorOfPoint.Push(new System.Drawing.Point[] { new System.Drawing.Point((int)(stylusPoint.X * a), (int)(stylusPoint.Y * a)) });
}
if (vectorOfPoint.Size <= 0)
break;
contours.Push(vectorOfPoint);
}
//准备掩膜图像
Image<Gray, byte> mask = new Image<Gray, byte>(OldImage.Width, OldImage.Height);
//设置全黑
mask.SetZero();
//把轮廓全部绘制成白色在mask上变成感兴趣的区域 类似roi
for (int i = 0; i < contours.Size; i++)
{
CvInvoke.DrawContours(mask, contours, i, new MCvScalar(255, 255, 255), -1, LineType.AntiAlias, null, int.MaxValue);
}
//准备结果图像
Image<Bgr, byte> Result = new Image<Bgr, byte>(OldImage.Width, OldImage.Height);
//显示
imgMask.Source = BitmapToBitmapImage(mask.ToBitmap());
//CvInvoke.Imshow("DrawContours", mask);
//获取感兴趣的区域到结果图
OldImage.CopyTo(Result, mask);
//显示
//CvInvoke.Imshow("mask", Result);
imgResult.Source = BitmapToBitmapImage(Result.ToBitmap());
txt_meanValue.Text = CvInvoke.Mean(Result).V0.ToString();
}
/// <summary>
/// 左键选择画笔颜色
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
System.Windows.Forms.ColorDialog colorDialog = new System.Windows.Forms.ColorDialog();
if (colorDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
System.Drawing.SolidBrush sb = new System.Drawing.SolidBrush(colorDialog.Color);
SolidColorBrush solidColorBrush = new SolidColorBrush(System.Windows.Media.Color.FromArgb(sb.Color.A, sb.Color.R, sb.Color.G, sb.Color.B));
colorchk.Background = solidColorBrush;
drawingAttributes.Color = new System.Windows.Media.Color() { A = sb.Color.A, B = sb.Color.B, G = sb.Color.G, R = sb.Color.R };
}
}
/// <summary>
/// Bitmap转BitmapImage 用于Image控件成像
/// </summary>
/// <param name="bitmap"></param>
/// <returns></returns>
public static BitmapSource BitmapToBitmapImage(System.Drawing.Bitmap bitmap)
{
if (bitmap == null)
return null;
try
{
using (System.Drawing.Bitmap source = bitmap)
{
IntPtr ptr = source.GetHbitmap(); //obtain the Hbitmap
BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
ptr,
IntPtr.Zero,
System.Windows.Int32Rect.Empty,
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
DeleteObject(ptr); //release the HBitmap
return bs;
}
}
catch (Exception)
{
return null;
}
}
[DllImport("gdi32")]
private static extern int DeleteObject(IntPtr o);
/// <summary>
/// ink画板事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void RadioButton_Click(object sender, RoutedEventArgs e)
{
if ((sender as RadioButton).Content.ToString() == "绘制墨迹")
{
ink.ForceCursor = true;
ink.EditingMode = InkCanvasEditingMode.Ink;
}
else
{
ink.ForceCursor = false;
if ((sender as RadioButton).Content.ToString() == "按点擦除")
{
ink.EditingMode = InkCanvasEditingMode.EraseByPoint;
}
else if ((sender as RadioButton).Content.ToString() == "按线擦除")
{
ink.EditingMode = InkCanvasEditingMode.EraseByStroke;
}
else if ((sender as RadioButton).Content.ToString() == "选中墨迹")
{
ink.EditingMode = InkCanvasEditingMode.Select;
}
else if ((sender as RadioButton).Content.ToString() == "停止操作")
{
ink.EditingMode = InkCanvasEditingMode.None;
}
}
}
/// <summary>
/// 漫水填充
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void floodfill_Click(object sender, RoutedEventArgs e)
{
int threshould = (int)threshould_slider.Value;
var color = System.Drawing.Color.White;
//原始图像
var OldImage = CvInvoke.Imread(imgpath);
//获取图像原始大小和显示大小的比例
double a = OldImage.Width / ImgShow.Source.Width;
//获取画的坐标线集合
var list = ink.Strokes;
//装轮廓集合
VectorOfVectorOfPoint contours = new VectorOfVectorOfPoint();
//获取画的坐标点集合
foreach (var item in list)
{ //单个轮廓坐标集合
VectorOfPoint vectorOfPoint = new VectorOfPoint();
foreach (var stylusPoint in item.StylusPoints)
{
vectorOfPoint.Push(new System.Drawing.Point[] { new System.Drawing.Point((int)(stylusPoint.X * a), (int)(stylusPoint.Y * a)) });
}
if (vectorOfPoint.Size <= 0)
break;
contours.Push(vectorOfPoint);
}
if (contours.Size == 0) return;
//清空点
ink.Strokes.Clear();
//计算点的阈值平均值(不太好用 也就是没写好)
//var GrayOldImage = OldImage.Clone();
//if (GrayOldImage.NumberOfChannels == 3)
// CvInvoke.CvtColor(GrayOldImage, GrayOldImage, ColorConversion.Rgb2Gray);
//int rows = GrayOldImage.Rows, cols = GrayOldImage.Cols, step = GrayOldImage.Step;
//threshould = 0;
//long count = 0;
//for (int i = 0; i < contours.Size; i++)
//{
// for (int j = 0; j < contours[i].Size; j++)
// {
// unsafe
// {
// byte* dataptr = (byte*)GrayOldImage.DataPointer;
// ///单通道图像遍历方式
// int index = contours[i][j].X * step + contours[i][j].Y;
// value += dataptr[index];
// }
// }
// count += contours[i].Size;
//}
//value = value / count;
var data = FloodFill(OldImage.ToBitmap(), contours[0][0], color, threshould);
if (data != null)
{
VectorOfVectorOfPoint NewVec = new VectorOfVectorOfPoint();
CvInvoke.FindContours(data.ToImage<Gray, byte>(), NewVec, null, Emgu.CV.CvEnum.RetrType.External, Emgu.CV.CvEnum.ChainApproxMethod.ChainApproxTc89Kcos);
CvInvoke.DrawContours(OldImage, NewVec, 0, new MCvScalar(0, 255, 0), 1, LineType.AntiAlias, null, 1);
//显示
imgMask.Source = BitmapToBitmapImage(OldImage.ToBitmap());
//显示
imgResult.Source = BitmapToBitmapImage(OldImage.ToBitmap());
txt_meanValue.Text = CvInvoke.Mean(OldImage).V0.ToString();
//-----------获取roi---------------
//准备掩膜图像
Image<Gray, byte> mask = new Image<Gray, byte>(OldImage.Width, OldImage.Height);
//设置全黑
mask.SetZero();
//把轮廓全部绘制成白色在mask上变成感兴趣的区域 类似roi
for (int i = 0; i < NewVec.Size; i++)
{
CvInvoke.DrawContours(mask, NewVec, i, new MCvScalar(255, 255, 255), -1, LineType.AntiAlias, null, int.MaxValue);
}
//准备结果图像
Image<Bgr, byte> Result = new Image<Bgr, byte>(OldImage.Width, OldImage.Height);
//获取感兴趣的区域到结果图
OldImage.CopyTo(Result, mask);
//显示
//CvInvoke.Imshow("mask", Result);
imgResult.Source = BitmapToBitmapImage(Result.ToBitmap());
}
}
/// <summary>
///
/// </summary>
/// <param name="src">原图</param>
/// <param name="location">检测点</param>
/// <param name="fillColor">填充颜色</param>
/// <param name="threshould"阈值></param>
/// <returns>填充图,非填充部分为默认值</returns>
unsafe public Bitmap FloodFill(Bitmap src, Point location, Color fillColor, int threshould)
{
try
{
Bitmap srcbmp = src;
Color backColor = srcbmp.GetPixel(location.X, location.Y);
Bitmap dstbmp = new Bitmap(src.Width, src.Height);
int w = srcbmp.Width; int h = srcbmp.Height;
Stack<Point> fillPoints = new Stack<Point>(w * h);
System.Drawing.Imaging.BitmapData bmpData = srcbmp.LockBits(new Rectangle(0, 0, srcbmp.Width, srcbmp.Height), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
System.Drawing.Imaging.BitmapData dstbmpData = dstbmp.LockBits(new Rectangle(0, 0, dstbmp.Width, dstbmp.Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
int stride = bmpData.Stride; int stridedst = dstbmpData.Stride; byte* srcbuf = (byte*)bmpData.Scan0.ToPointer();
int* dstbuf = (int*)dstbmpData.Scan0.ToPointer();
int cr = backColor.R, cg = backColor.G, cb = backColor.B, ca = backColor.A;
byte fcr = fillColor.R, fcg = fillColor.G, fcb = fillColor.B; int fc = fillColor.ToArgb();
if (location.X < 0 || location.X >= w || location.Y < 0 || location.Y >= h) return null; fillPoints.Push(new Point(location.X, location.Y)); int[,] mask = new int[w, h];
while (fillPoints.Count > 0)
{
Point p = fillPoints.Pop();
mask[p.X, p.Y] = 1;
dstbuf[p.X + p.Y * w] = fc;
if (p.X > 0 && (mask[p.X - 1, p.Y] != 1) && Math.Abs(cb - srcbuf[4 * (p.X - 1) + p.Y * stride]) + Math.Abs(cg - srcbuf[4 * (p.X - 1) + 1 + p.Y * stride]) + Math.Abs(cr - srcbuf[4 * (p.X - 1) + 2 + p.Y * stride]) < threshould && Math.Abs(ca - srcbuf[4 * (p.X - 1) + 3 + p.Y * stride]) < threshould)
{
dstbuf[(p.X - 1) + p.Y * w] = fc;
fillPoints.Push(new Point(p.X - 1, p.Y)); mask[p.X - 1, p.Y] = 1;
}
if (p.X < w - 1 && (mask[p.X + 1, p.Y] != 1) && Math.Abs(cb - srcbuf[4 * (p.X + 1) + p.Y * stride]) + Math.Abs(cg - srcbuf[4 * (p.X + 1) + 1 + p.Y * stride]) + Math.Abs(cr - srcbuf[4 * (p.X + 1) + 2 + p.Y * stride]) < threshould && Math.Abs(ca - srcbuf[4 * (p.X + 1) + 3 + p.Y * stride]) < threshould)
{ dstbuf[(p.X + 1) + p.Y * w] = fc; fillPoints.Push(new Point(p.X + 1, p.Y)); mask[p.X + 1, p.Y] = 1; }
if (p.Y > 0 && (mask[p.X, p.Y - 1] != 1) && Math.Abs(cb - srcbuf[4 * p.X + (p.Y - 1) * stride]) + Math.Abs(cg - srcbuf[4 * p.X + 1 + (p.Y - 1) * stride]) + Math.Abs(cr - srcbuf[4 * p.X + 2 + (p.Y - 1) * stride]) < threshould && Math.Abs(ca - srcbuf[4 * p.X + 3 + (p.Y - 1) * stride]) < threshould)
{ dstbuf[p.X + (p.Y - 1) * w] = fc; fillPoints.Push(new Point(p.X, p.Y - 1)); mask[p.X, p.Y - 1] = 1; }
if (p.Y < h - 1 && (mask[p.X, p.Y + 1] != 1) && Math.Abs(cb - srcbuf[4 * p.X + (p.Y + 1) * stride]) + Math.Abs(cg - srcbuf[4 * p.X + 1 + (p.Y + 1) * stride]) + Math.Abs(cr - srcbuf[4 * p.X + 2 + (p.Y + 1) * stride]) < threshould && Math.Abs(ca - srcbuf[4 * p.X + 3 + (p.Y + 1) * stride]) < threshould)
{ dstbuf[p.X + (p.Y + 1) * w] = fc; fillPoints.Push(new Point(p.X, p.Y + 1)); mask[p.X, p.Y + 1] = 1; }
}
fillPoints.Clear(); srcbmp.UnlockBits(bmpData); dstbmp.UnlockBits(dstbmpData); return dstbmp;
}
catch
{
return null;
}
}
}
}
WPF+Emgucv实现在图像上画出感兴趣的区域 并进行掩膜获取 得到图像均值 和简单的 漫水填充的更多相关文章
- Android中Google地图路径导航,使用mapfragment地图上画出线路(google map api v2)详解
在这篇里我们只聊怎么在android中google map api v2地图上画出路径导航,用mapfragment而不是mapview,至于怎么去申请key,manifest.xml中加入的权限,系 ...
- 使用JavaScript在Canvas上画出一片星空
随着Html5的迅猛发展,画布也变得越来越重要.下面我就写一个关于在canvas上画出一片星空的简单的代码的示例. 理论基础 初始化一个canvas,获得一个用于绘制图形的上下文环境context.并 ...
- 【wpf】在win10系统上弹出toast和notification
原文:[wpf]在win10系统上弹出toast和notification 老规矩,先看效果 右下角的notification: 操作中心的notification: 整体效果: 前提条件 1.需要在 ...
- Python 图像处理 OpenCV (3):图像属性、图像感兴趣 ROI 区域及通道处理
前文传送门: 「Python 图像处理 OpenCV (1):入门」 「Python 图像处理 OpenCV (2):像素处理与 Numpy 操作以及 Matplotlib 显示图像」 图像属性 图像 ...
- WPF在圆上画出刻度线
思路 我们可以使用Ellipse先画出一个圆当背景,然后用Canvas再叠加画上刻度线,就能得到如下的效果 我们先用Ellipse画一个橙色的圆,然后将Canvas的宽度和高度绑定到Ellipse的宽 ...
- OpenCV之响应鼠标(四):在图像上绘制出矩形并标出起点的坐标
涉及到两方面的内容:1. 用鼠标画出矩形.2.在图像上绘制出点的坐标 用鼠标绘制矩形,涉及到鼠标的操作,opencv中有鼠标事件的介绍.需要用到两个函数:回调函数CvMouseCallback和注册回 ...
- Android教程:在百度地图上画出轨迹
[日期:2013-04-14] 来源:Linux社区 作者:crazyxin1988 [字体:大 中 小] 接着上面的项目<Android访问webservice.客户端登录注册> ...
- canvas上画出坐标集合,并标记新坐标,背景支持放大缩小拖动功能
写在前面:项目需求,用户上传一个区位的平面图片,用户可以在图片上添加新的相机位置,并且展示之前已绑定的相机坐标位置,图片支持放大缩小&拖动的功能.新增坐标,页面展示相对canvas定位,保存时 ...
- 还没被玩坏的robobrowser(4)——从页面上抓取感兴趣的内容
背景 本节的知识实际上是属于Beautiful Soup的内容. robobrowser支持Beautiful Soup,一般来说通过下面3个方法获取页面上感兴趣的内容 find find_all s ...
- [Java]在窗口界面上画出硬盘中图片文件
利用类javax.swing.JPanel来在窗口界面上画图.图片文件通过javax.imageio.ImageIO类来获取. import java.awt.Graphics; import jav ...
随机推荐
- 实时 3D 深度多摄像头跟踪 Real-time 3D Deep Multi-Camera Tracking
实时 3D 深度多摄像头跟踪 Real-time 3D Deep Multi-Camera Tracking 论文url https://arxiv.org/abs/2003.11753 论文简述: ...
- k8s 深入篇———— pod 深入实战[七]
前言 深入一下pod 实战. 正文 在 Kubernetes 中,有几种特殊的 Volume,它们存在的意义不是为了存放容器里的数据,也不是用来进行容器和宿主机之间的数据交换. 这些特殊 Volume ...
- k8s 深入篇———— docker 是什么[一]
前言 简单的整理一下一些基本概念. 正文 简单运行一个容器: 创建一个容器: docker run -it busybox /bin/bash 然后看下进程: ps -ef 做了一个障眼法,使用的是p ...
- gitlib配置
第1步:下载Java并安装Java.一般来说下载jdk对应的版本就行. 第2步:配置Java环境变量,具体如下: 1. 新建:变量名:JAVA_HOME:变量值:C:\Program Files\Ja ...
- 力扣686(java)-重复叠加字符串匹配(中等)
题目: 给定两个字符串 a 和 b,寻找重复叠加字符串 a 的最小次数,使得字符串 b 成为叠加后的字符串 a 的子串,如果不存在则返回 -1. 注意:字符串 "abc" 重复叠加 ...
- 阿里巴巴云数据仓库 MaxCompute 数据安全最佳实践
简介:MaxCompute作为企业级SaaS模式云数据仓库,正在为客户业务及其数据提供持续的安全保护. MaxCompute 近期对产品的安全能力进行了全面升级 ,结合数据生命周期,针对数据误用.数 ...
- 即学即会 Serverless | 初识 Serverless
简介:Serverless 架构被越来越多的业务所采纳,成为其技术选型,大多数开发者已经跨越对 Serverless 概念了解,切实向落地实践出发.本文带大家一探究竟,为什么说 Serverless ...
- 技术干货 | mPaaS 小程序高玩带你起飞:客户端预置小程序无视网络质量
简介: 弱网拉包无障碍,深度提升用户体验 传统的小程序技术容易受到网络环境影响,当网络质量不佳时可能导致拉取不到小程序包的情况.通过预置小程序,即可规避该问题.本文介绍了预置小程序的原理和预置小程序的 ...
- Springboot+Prometheus+grafana 制作自己的业务监控
目录 知识储备 系统架构 开始实现 生成业务指标 经典实现方法 自己的实现方案 引入依赖 配置文件 注册自己的指标[我这里用的是guaua格式数据] 写入指标 效果展示 配置prometheus 抓取 ...
- 003_Orcad菜单讲解与偏好设置
003_Orcad菜单讲解与偏好设置 菜单栏用的比较多的是File和Options项. 网格建议用lines,比较方便对齐. Auto Reference和Intertool Commuication ...