【C#联合halcon实现绘制ROI功能】
前言
C#联合halcon实现绘制ROI功能:
C#联合Halcon,使用HDrawingObject、HDrawingObjectXld,绘制矩形、方向矩形、圆形、椭圆、自定义ROI。支持拖动、重设大小、选中,右键复制、粘贴、删除功能。
运行结果
代码
代码结构
MainForm 视图
MainViewModel 视图模型
ROI ROI模型
GenArrow 生成带箭头的点
GrawArrowViewModel 绘制箭头视图模型
MainForm
public partial class MainForm : Form{DrawArrowViewModel drawArrowViewModel;MainViewModel viewModel;public MainForm(){InitializeComponent();drawArrowViewModel = new DrawArrowViewModel(this);viewModel = new MainViewModel(this);}}
MainForm 设计器
partial class MainForm
{/// <summary>/// 必需的设计器变量。/// </summary>private System.ComponentModel.IContainer components = null;/// <summary>/// 清理所有正在使用的资源。/// </summary>/// <param name="disposing">如果应释放托管资源,为 true;否则为 false。</param>protected override void Dispose(bool disposing){if (disposing && (components != null)){components.Dispose();}base.Dispose(disposing);}#region Windows 窗体设计器生成的代码/// <summary>/// 设计器支持所需的方法 - 不要修改/// 使用代码编辑器修改此方法的内容。/// </summary>private void InitializeComponent(){this.panel_Top = new System.Windows.Forms.Panel();this.checkBox_ShowROI = new System.Windows.Forms.CheckBox();this.Btn_LoadImage = new System.Windows.Forms.Button();this.panel_Bottom = new System.Windows.Forms.Panel();this.panel_Left = new System.Windows.Forms.Panel();this.Lbx_ROIList = new System.Windows.Forms.ListBox();this.Cbx_ROIType = new System.Windows.Forms.ComboBox();this.Btn_CreateROI = new System.Windows.Forms.Button();this.Btn_DrawArrow = new System.Windows.Forms.Button();this.panel_ImageWin = new System.Windows.Forms.Panel();this.HSImageWindow = new HalconDotNet.HSmartWindowControl();this.panel_ImageInfo = new System.Windows.Forms.Panel();this.Tbx_ImageInfo = new System.Windows.Forms.TextBox();this.panel_Top.SuspendLayout();this.panel_Left.SuspendLayout();this.panel_ImageWin.SuspendLayout();this.panel_ImageInfo.SuspendLayout();this.SuspendLayout();// // panel_Top// this.panel_Top.Controls.Add(this.checkBox_ShowROI);this.panel_Top.Controls.Add(this.Btn_LoadImage);this.panel_Top.Dock = System.Windows.Forms.DockStyle.Top;this.panel_Top.Location = new System.Drawing.Point(0, 0);this.panel_Top.Name = "panel_Top";this.panel_Top.Size = new System.Drawing.Size(1449, 100);this.panel_Top.TabIndex = 0;// // checkBox_ShowROI// this.checkBox_ShowROI.AutoSize = true;this.checkBox_ShowROI.Font = new System.Drawing.Font("宋体", 12F);this.checkBox_ShowROI.Location = new System.Drawing.Point(281, 44);this.checkBox_ShowROI.Name = "checkBox_ShowROI";this.checkBox_ShowROI.Size = new System.Drawing.Size(120, 28);this.checkBox_ShowROI.TabIndex = 2;this.checkBox_ShowROI.Text = "显示ROI";this.checkBox_ShowROI.UseVisualStyleBackColor = true;// // Btn_LoadImage// this.Btn_LoadImage.Location = new System.Drawing.Point(53, 31);this.Btn_LoadImage.Name = "Btn_LoadImage";this.Btn_LoadImage.Size = new System.Drawing.Size(136, 46);this.Btn_LoadImage.TabIndex = 1;this.Btn_LoadImage.Text = "加载图像";this.Btn_LoadImage.UseVisualStyleBackColor = true;// // panel_Bottom// this.panel_Bottom.Dock = System.Windows.Forms.DockStyle.Bottom;this.panel_Bottom.Location = new System.Drawing.Point(0, 804);this.panel_Bottom.Name = "panel_Bottom";this.panel_Bottom.Size = new System.Drawing.Size(1449, 113);this.panel_Bottom.TabIndex = 1;// // panel_Left// this.panel_Left.Controls.Add(this.Lbx_ROIList);this.panel_Left.Controls.Add(this.Cbx_ROIType);this.panel_Left.Controls.Add(this.Btn_CreateROI);this.panel_Left.Controls.Add(this.Btn_DrawArrow);this.panel_Left.Dock = System.Windows.Forms.DockStyle.Left;this.panel_Left.Location = new System.Drawing.Point(0, 100);this.panel_Left.Name = "panel_Left";this.panel_Left.Size = new System.Drawing.Size(411, 704);this.panel_Left.TabIndex = 1;// // Lbx_ROIList// this.Lbx_ROIList.Font = new System.Drawing.Font("宋体", 14F);this.Lbx_ROIList.FormattingEnabled = true;this.Lbx_ROIList.ItemHeight = 28;this.Lbx_ROIList.Location = new System.Drawing.Point(13, 221);this.Lbx_ROIList.Name = "Lbx_ROIList";this.Lbx_ROIList.ScrollAlwaysVisible = true;this.Lbx_ROIList.Size = new System.Drawing.Size(358, 340);this.Lbx_ROIList.TabIndex = 3;// // Cbx_ROIType// this.Cbx_ROIType.Font = new System.Drawing.Font("宋体", 16F);this.Cbx_ROIType.FormattingEnabled = true;this.Cbx_ROIType.Location = new System.Drawing.Point(13, 157);this.Cbx_ROIType.Name = "Cbx_ROIType";this.Cbx_ROIType.Size = new System.Drawing.Size(358, 41);this.Cbx_ROIType.TabIndex = 2;// // Btn_CreateROI// this.Btn_CreateROI.Location = new System.Drawing.Point(12, 78);this.Btn_CreateROI.Name = "Btn_CreateROI";this.Btn_CreateROI.Size = new System.Drawing.Size(359, 57);this.Btn_CreateROI.TabIndex = 1;this.Btn_CreateROI.Text = "创建ROI";this.Btn_CreateROI.UseVisualStyleBackColor = true;// // Btn_DrawArrow// this.Btn_DrawArrow.Location = new System.Drawing.Point(12, 6);this.Btn_DrawArrow.Name = "Btn_DrawArrow";this.Btn_DrawArrow.Size = new System.Drawing.Size(359, 57);this.Btn_DrawArrow.TabIndex = 0;this.Btn_DrawArrow.Text = "绘制箭头";this.Btn_DrawArrow.UseVisualStyleBackColor = true;// // panel_ImageWin// this.panel_ImageWin.Controls.Add(this.HSImageWindow);this.panel_ImageWin.Controls.Add(this.panel_ImageInfo);this.panel_ImageWin.Dock = System.Windows.Forms.DockStyle.Fill;this.panel_ImageWin.Location = new System.Drawing.Point(411, 100);this.panel_ImageWin.Name = "panel_ImageWin";this.panel_ImageWin.Size = new System.Drawing.Size(1038, 704);this.panel_ImageWin.TabIndex = 2;// // HSImageWindow// this.HSImageWindow.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;this.HSImageWindow.AutoValidate = System.Windows.Forms.AutoValidate.EnableAllowFocusChange;this.HSImageWindow.Dock = System.Windows.Forms.DockStyle.Fill;this.HSImageWindow.HDoubleClickToFitContent = true;this.HSImageWindow.HDrawingObjectsModifier = HalconDotNet.HSmartWindowControl.DrawingObjectsModifier.None;this.HSImageWindow.HImagePart = new System.Drawing.Rectangle(0, 0, 640, 480);this.HSImageWindow.HKeepAspectRatio = true;this.HSImageWindow.HMoveContent = true;this.HSImageWindow.HZoomContent = HalconDotNet.HSmartWindowControl.ZoomContent.WheelForwardZoomsIn;this.HSImageWindow.Location = new System.Drawing.Point(0, 0);this.HSImageWindow.Margin = new System.Windows.Forms.Padding(0);this.HSImageWindow.Name = "HSImageWindow";this.HSImageWindow.Size = new System.Drawing.Size(1038, 666);this.HSImageWindow.TabIndex = 1;this.HSImageWindow.WindowSize = new System.Drawing.Size(1038, 666);// // panel_ImageInfo// this.panel_ImageInfo.BackColor = System.Drawing.SystemColors.ControlDarkDark;this.panel_ImageInfo.Controls.Add(this.Tbx_ImageInfo);this.panel_ImageInfo.Dock = System.Windows.Forms.DockStyle.Bottom;this.panel_ImageInfo.Location = new System.Drawing.Point(0, 666);this.panel_ImageInfo.Name = "panel_ImageInfo";this.panel_ImageInfo.Size = new System.Drawing.Size(1038, 38);this.panel_ImageInfo.TabIndex = 0;// // Tbx_ImageInfo// this.Tbx_ImageInfo.BackColor = System.Drawing.SystemColors.ButtonShadow;this.Tbx_ImageInfo.Dock = System.Windows.Forms.DockStyle.Fill;this.Tbx_ImageInfo.Font = new System.Drawing.Font("宋体", 14F);this.Tbx_ImageInfo.Location = new System.Drawing.Point(0, 0);this.Tbx_ImageInfo.Name = "Tbx_ImageInfo";this.Tbx_ImageInfo.Size = new System.Drawing.Size(1038, 39);this.Tbx_ImageInfo.TabIndex = 0;// // MainForm// this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F);this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;this.ClientSize = new System.Drawing.Size(1449, 917);this.Controls.Add(this.panel_ImageWin);this.Controls.Add(this.panel_Left);this.Controls.Add(this.panel_Bottom);this.Controls.Add(this.panel_Top);this.DoubleBuffered = true;this.Name = "MainForm";this.Text = "MainForm";this.panel_Top.ResumeLayout(false);this.panel_Top.PerformLayout();this.panel_Left.ResumeLayout(false);this.panel_ImageWin.ResumeLayout(false);this.panel_ImageInfo.ResumeLayout(false);this.panel_ImageInfo.PerformLayout();this.ResumeLayout(false);}#endregionprivate System.Windows.Forms.Panel panel_Top;private System.Windows.Forms.Panel panel_Bottom;private System.Windows.Forms.Panel panel_Left;private System.Windows.Forms.Panel panel_ImageWin;private System.Windows.Forms.Panel panel_ImageInfo;public HalconDotNet.HSmartWindowControl HSImageWindow;public System.Windows.Forms.Button Btn_DrawArrow;public System.Windows.Forms.Button Btn_LoadImage;public System.Windows.Forms.TextBox Tbx_ImageInfo;public System.Windows.Forms.Button Btn_CreateROI;public System.Windows.Forms.ComboBox Cbx_ROIType;public System.Windows.Forms.ListBox Lbx_ROIList;public System.Windows.Forms.CheckBox checkBox_ShowROI;
}
MainViewModel
public class MainViewModel
{#region 集合//ROI类型字典private Dictionary<string, ROIType> _roiTypeDictionary = new Dictionary<string, ROIType>();//ROI类型字典public Dictionary<string, ROIType> RoiTypeDictionary { get => _roiTypeDictionary; }//ROI类型字典键public List<string> ROITypeNameList { get => RoiTypeDictionary.Keys.ToList(); }//ROI字典private Dictionary<ROI, DrawingObject> _roiDictionary = new Dictionary<ROI, DrawingObject>();//ROI字典public Dictionary<ROI, DrawingObject> ROIDictionary { get => _roiDictionary; }//ROI字典 - 值public List<DrawingObject> ROIValues { get => ROIDictionary.Values.ToList(); }#endregion#region 字段private MainForm mainForm; //操作窗体private string currentRoiType = string.Empty; //当前ROI类型private int ImageChannel = 0; //图像通道private ContextMenuStrip RoiRightMenu; //右键菜单private HWindow windowID = null; //窗口IDprivate HTuple CurrentROIHandle = null; //当前选中的ROIprivate ROI copyROI = null; //当前ROI对象public event EventHandler<ROIOperator> NotifyROIOperation; //ROI操作事件#endregion//构造函数public MainViewModel(MainForm mainForm){this.mainForm = mainForm;this.windowID = this.mainForm.HSImageWindow.HalconWindow;//事件绑定this.mainForm.HSImageWindow.HMouseDown += HSImageWindow_HMouseDown;this.mainForm.Btn_CreateROI.Click += Btn_CreateROI_Click;this.mainForm.Cbx_ROIType.SelectedIndexChanged += Cbx_ROIType_SelectedIndexChanged;this.mainForm.Lbx_ROIList.SelectedIndexChanged += Lbx_ROIList_SelectedIndexChanged;this.mainForm.checkBox_ShowROI.CheckedChanged += CheckBox_ShowROI_CheckedChanged;Initialize();//数据绑定,ROI类型集合this.mainForm.Cbx_ROIType.DataSource = ROITypeNameList;this.mainForm.Cbx_ROIType.SelectedIndex = 0;}//ROI-列表索引变更private void Lbx_ROIList_SelectedIndexChanged(object sender, EventArgs e){if (sender is ListBox item){string handler = item.SelectedItem?.ToString();var tempDrawObj = ROIDictionary.FirstOrDefault(roi =>roi.Key.Name.ToString().Equals(handler)).Value;if (tempDrawObj != null){Debug.WriteLine($"{CurrentROIHandle} => {tempDrawObj.Obj.ID}");HOperatorSet.DetachDrawingObjectFromWindow(windowID, tempDrawObj.Obj);foreach ( var draw in ROIValues){if (draw.Obj.ID != tempDrawObj.Obj.ID)HOperatorSet.AttachDrawingObjectToWindow(windowID, draw.Obj);}foreach (var draw in ROIValues){if (draw.Obj.ID != tempDrawObj.Obj.ID)HOperatorSet.DetachDrawingObjectFromWindow(windowID, draw.Obj);}HOperatorSet.AttachDrawingObjectToWindow(windowID, tempDrawObj.Obj);CurrentROIHandle = tempDrawObj.Obj.ID;}}}//显示ROIprivate void CheckBox_ShowROI_CheckedChanged(object sender, EventArgs e){if (this.mainForm.checkBox_ShowROI.Checked){foreach (var item in ROIDictionary.Values){HOperatorSet.AttachDrawingObjectToWindow(windowID, item.Obj);}}else{foreach (var item in ROIDictionary.Values){HOperatorSet.DetachDrawingObjectFromWindow(windowID, item.Obj);}}}//初始化方法:初始化ROI类型public void Initialize(){//初始化ROI列表RoiTypeDictionary.Add("矩形1", ROIType.RECTANGLE1);RoiTypeDictionary.Add("矩形2", ROIType.RECTANGLE2);RoiTypeDictionary.Add("圆形", ROIType.CIRCLE);RoiTypeDictionary.Add("椭圆", ROIType.ELLIPSE);RoiTypeDictionary.Add("半圆", ROIType.CIRCLE_SECTOR);RoiTypeDictionary.Add("半椭圆", ROIType.ELLIPSE_SECTOR);RoiTypeDictionary.Add("线条", ROIType.LINE);RoiTypeDictionary.Add("轮廓", ROIType.XLD_CONTOUR);RoiTypeDictionary.Add("文本", ROIType.TEXT);//初始化ROI右键菜单RoiRightMenu = new ContextMenuStrip();ToolStripMenuItem menuItem1 = new ToolStripMenuItem("复制");ToolStripMenuItem menuItem2 = new ToolStripMenuItem("粘贴");ToolStripMenuItem menuItem3 = new ToolStripMenuItem("删除");menuItem1.Click += ROIOperation_CopyEvent;menuItem2.Click += ROIOperation_PasterEvent;menuItem3.Click += ROIOperation_RemoveEvent;RoiRightMenu.Items.Add(menuItem1);RoiRightMenu.Items.Add(menuItem2);RoiRightMenu.Items.Add(menuItem3);}//析构函数~MainViewModel(){CurrentROIHandle?.Dispose();copyROI = null;}//ROI右键操作-复制private void ROIOperation_CopyEvent(object sender, EventArgs e){ROI roiObj = ROIDictionary.FirstOrDefault(roi => roi.Value.Obj.ID.Equals(CurrentROIHandle)).Key;if (roiObj!=null){copyROI = roiObj.DeepCopy<ROI>(roiObj); ;Debug.WriteLine($"复制ROI{roiObj.Handle},新ROI{copyROI.Handle}");}}//ROI右键操作-删除private void ROIOperation_RemoveEvent(object sender, EventArgs e){Debug.WriteLine("移除ROI");ROI roi = ROIDictionary.FirstOrDefault(roiObj => roiObj.Value.Obj.ID.Equals(CurrentROIHandle)).Key;if (roi != null){OnNotifyROIOperation(new ROIOperator(roi.Name, ROIOperation.Remove), null);HDrawingObject drawObj = ROIDictionary[roi].Obj;ROIDictionary.Remove(roi);HOperatorSet.DetachDrawingObjectFromWindow(windowID, drawObj);Debug.WriteLine($"移除ROI{roi.Handle}");}}//ROI右键操作-粘贴private void ROIOperation_PasterEvent(object sender, EventArgs e){Debug.WriteLine("粘贴ROI");if (copyROI != null){ROI roi = new ROI();roi.ID = ROIDictionary.Count;roi.Name = $"{currentRoiType}{ROIDictionary.Count}";roi.Type = copyROI.Type;roi.ShapeParamNames = copyROI.ShapeParamNames;roi.ShapeParamValues = copyROI.ShapeParamValues;for (int i = 0; i < copyROI.ShapeParamValues.Length; i++)roi.ShapeParamValues[i] = roi.ShapeParamValues[i] + 20;DrawingObject drawObj = null;CreateROIDrawingObject(roi, out drawObj );drawObj.Obj.SetDrawingObjectParams("color", "blue");if (drawObj!=null){ROIDictionary.Add(roi, drawObj);roi.Handle = drawObj.Obj.ID;copyROI = roi;OnNotifyROIOperation(new ROIOperator(roi.Name, ROIOperation.Add), null);HOperatorSet.AttachDrawingObjectToWindow(windowID, drawObj.Obj);Debug.WriteLine($"粘贴ROI{copyROI.Handle}");}}}//鼠标按下弹出右键菜单private void HSImageWindow_HMouseDown(object sender, HMouseEventArgs e){if (e.Button == MouseButtons.Left){// 检查鼠标点击位置是否在绘图对象内foreach(DrawingObject drawingObject in ROIValues){GetDrawingObjectShapeParameter(drawingObject,out HObject shape ,out HTuple results);}}if (e.Button == MouseButtons.Right)if (CurrentROIHandle != null)if (sender is HSmartWindowControl control)RoiRightMenu.Show(Control.MousePosition.X, Control.MousePosition.Y);}//ROI类型列表索引变更private void Cbx_ROIType_SelectedIndexChanged(object sender, EventArgs e){currentRoiType = this.mainForm.Cbx_ROIType.SelectedItem.ToString();}//创建ROI按钮按下private void Btn_CreateROI_Click(object sender, EventArgs e){DrawROI(currentRoiType);}//通知ROI变更private void OnNotifyROIOperation(object sender, EventArgs e){if (sender is ROIOperator roiOperator){switch(roiOperator.Operation){//this.mainForm.Lbx_ROIList.Items.Add(sender);case ROIOperation.Add:this.mainForm.Lbx_ROIList.Items.Add(roiOperator.Name);break;case ROIOperation.Remove:this.mainForm.Lbx_ROIList.Items.Remove(roiOperator.Name);break;case ROIOperation.Update:break;case ROIOperation.Search:break;}}}//绘制ROIpublic void DrawROI(string typeName){ROI roi = new ROI();roi.ID = ROIDictionary.Count;roi.Name = $"{typeName}_{roi.ID}";roi.Type = RoiTypeDictionary[typeName];//获取ROI类型DrawingObject drawObj = null;SetROIParam(roi, roi.Type);CreateROIDrawingObject(roi, out drawObj);if (drawObj != null){HOperatorSet.AttachDrawingObjectToWindow(windowID, drawObj.Obj);roi.Handle = drawObj.Obj.ID;ROIDictionary.Add(roi, drawObj);CurrentROIHandle = drawObj.Obj.ID;OnNotifyROIOperation(new ROIOperator(roi.Name,ROIOperation.Add),null);}}/// <summary>/// 获取绘制对象参数: input: 自定义DrawingObject对象,/// output: 形状对象,/// output: 输出结果参数/// </summary>public void GetDrawingObjectShapeParameter(DrawingObject drawObj,out HObject shape ,out HTuple resultParam){HTuple paramValue = new HTuple();HObject roiTypeObj = new HObject();shape = roiTypeObj;resultParam = paramValue;switch (drawObj.Type){case ROIType.RECTANGLE1: //矩形1paramValue = drawObj.Obj.GetDrawingObjectParams(drawObj.ShapeParamNames);HOperatorSet.GenRectangle1(out roiTypeObj, paramValue.DArr[0], paramValue.DArr[1], paramValue.DArr[2], paramValue.DArr[3]);shape = roiTypeObj;resultParam = paramValue;break;case ROIType.RECTANGLE2: //方向矩形paramValue = drawObj.Obj.GetDrawingObjectParams(drawObj.ShapeParamNames);HOperatorSet.GenRectangle2(out roiTypeObj, paramValue.DArr[0], paramValue.DArr[1], paramValue.DArr[2], paramValue.DArr[3], paramValue.DArr[4]);shape = roiTypeObj;resultParam = paramValue;break;case ROIType.CIRCLE: //圆形paramValue = drawObj.Obj.GetDrawingObjectParams(drawObj.ShapeParamNames);HOperatorSet.GenCircle(out roiTypeObj, paramValue.DArr[0], paramValue.DArr[1], paramValue.DArr[2]);shape = roiTypeObj;resultParam = paramValue;break;case ROIType.ELLIPSE: //椭圆paramValue = drawObj.Obj.GetDrawingObjectParams(drawObj.ShapeParamNames);HOperatorSet.GenEllipse(out roiTypeObj, paramValue.DArr[0], paramValue.DArr[1], paramValue.DArr[2], paramValue.DArr[3], paramValue.DArr[4]);shape = roiTypeObj;resultParam = paramValue;break;case ROIType.XLD_CONTOUR: //xld轮廓paramValue = drawObj.Obj.GetDrawingObjectParams(drawObj.ShapeParamNames);shape = roiTypeObj;resultParam = paramValue;break;default: //其他shape = null;resultParam = null;break;}}/// <summary>/// 设置ROI参数/// </summary>public void SetROIParam(ROI roi, ROIType type){switch (type){case ROIType.RECTANGLE1: //矩形1roi.ShapeParamNames = ShapeParam.RECT1;roi.ShapeParamValues = ShapeParamValue.RECT1;break;case ROIType.RECTANGLE2: //矩形2roi.ShapeParamNames = ShapeParam.RECT2;roi.ShapeParamValues = ShapeParamValue.RECT2;break;case ROIType.CIRCLE: //圆形roi.ShapeParamNames = ShapeParam.CIRCLE;roi.ShapeParamValues = ShapeParamValue.CIRCLE;break;case ROIType.ELLIPSE: //椭圆roi.ShapeParamNames = ShapeParam.ELLIPSE;roi.ShapeParamValues = ShapeParamValue.ELLIPSE;break;case ROIType.LINE: //线型break;case ROIType.XLD_CONTOUR: //轮廓roi.ShapeParamNames = ShapeParam.XLD_COUTOUR;roi.ShapeParamValues = ShapeParamValue.XLD_COUTOUR;break;case ROIType.TEXT:break;}}/// <summary>/// 创建ROI对象:根据ROI类型和ROI参数,在指定窗体中生成ROI/// </summary>public void CreateROIDrawingObject(ROI roi,out DrawingObject drawObj){drawObj = new DrawingObject();if (ROIDictionary.Count < 10){drawObj.Type = roi.Type;drawObj.ShapeParamNames = roi.ShapeParamNames;drawObj.ShapeParamValues = roi.ShapeParamValues;if (roi.Type == ROIType.XLD_CONTOUR){HOperatorSet.CreateDrawingObjectXld(drawObj.ShapeParamValues[0], drawObj.ShapeParamValues[1], out HTuple drawID);drawObj.Obj = new HDrawingObject(drawID.H);}else{drawObj.Obj = CreateROIObject(drawObj.Type, drawObj.ShapeParamValues);}//line_widthdrawObj.Obj.SetDrawingObjectParams("color", "blue");///绑定事件:ROI:拖拽、调整大小、解除附加、选中drawObj.Obj.OnDrag(OnDragDrawObjectCallback);drawObj.Obj.OnResize(OnResizeDrawObjectCallback);drawObj.Obj.OnDetach(OnDetachDrawObjectCallback);drawObj.Obj.OnSelect(OnSelectDrawObjectCallback);drawObj.Obj.OnAttach(OnAttachDrawObjectCallback);}else{drawObj = null;}}#region 绘制对象的事件绑定 :ROI信息变更回调(拖拽、调整大小、选择...)/// <summary>/// 附加ROI时触发/// </summary>private void OnAttachDrawObjectCallback(HDrawingObject drawid, HWindow window, string type){Debug.WriteLine($"附加ROI:ID = [{drawid}]");CurrentROIHandle = drawid.ID;}/// <summary>/// 移除ROI时触发/// </summary>private void OnDetachDrawObjectCallback(HDrawingObject drawid, HWindow window, string type){CurrentROIHandle = null ;Debug.WriteLine($"移除ROI:ID = [{drawid.ID}]");}/// <summary>/// 选中ROI时触发/// </summary>private void OnSelectDrawObjectCallback(HDrawingObject drawid, HWindow window, string type){var drawObj = ROIDictionary.FirstOrDefault(obj => obj.Value.Obj.ID == drawid.ID).Value;if (drawObj != null){Debug.WriteLine($"选中ROI:ID = [{drawid.ID}]");}CurrentROIHandle = drawid.ID;}/// <summary>/// 拖拽ROI时触发/// </summary>private void OnDragDrawObjectCallback(HDrawingObject drawid, HWindow window, string type){Debug.WriteLine($"拖拽ROI:ID = [{drawid.ID}]");CurrentROIHandle = drawid.ID;}/// <summary>/// 调整ROI大小时触发/// </summary>private void OnResizeDrawObjectCallback(HDrawingObject drawid, HWindow window, string type){Debug.WriteLine($"调整ROI大小:ID = [{drawid.ID}]");CurrentROIHandle = drawid.ID;}#endregion#region 类型转换、对象创建//创建ROI对象public HDrawingObject CreateROIObject(ROIType type, HTuple[] param){return HDrawingObject.CreateDrawingObject(ROITypeConvert(type), param);}//ROI类型转换private HDrawingObject.HDrawingObjectType ROITypeConvert(ROIType type){return (HDrawingObject.HDrawingObjectType)type;}#endregion
}
ROI
[Serializable]public class ROI{public int ID { get; set; } //IDpublic string Name { get; set; } //名称public ROIType Type { get; set; } //形状类型public HTuple Handle { get; set; } //绘制对象public HTuple ShapeParamNames { get; set; } //创建参数名:row1 ,column1,row2 ,column2...public HTuple[] ShapeParamValues { get; set; } //创建参数值:100,100,200,200...public HObject Contour { get; set; } //结果轮廓public T DeepCopy<T>(T obj){object retval = null;try{using (MemoryStream ms = new MemoryStream()){BinaryFormatter bf = new BinaryFormatter();//序列化成流bf.Serialize(ms, obj);ms.Seek(0, SeekOrigin.Begin);//反序列化成对象retval = bf.Deserialize(ms);}}catch (Exception ex) { MessageBox.Show(new Form { TopMost = true }, ex.ToString()); }return (T)retval;}}public enum ROIType{RECTANGLE1,RECTANGLE2,CIRCLE,ELLIPSE,CIRCLE_SECTOR,ELLIPSE_SECTOR,LINE,XLD_CONTOUR,TEXT}/// <summary>/// ROI绘制形状参数模型:获取对应形状的参数值时使用/// </summary>public class ShapeParam{/// <summary>/// 圆形参数/// </summary>public readonly static HTuple CIRCLE = new string[] { "row", "column", "radius" };/// <summary>/// 椭圆参数/// </summary>public readonly static HTuple ELLIPSE = new string[] { "row", "column", "phi", "radius1", "radius2" };/// <summary>/// 矩形1参数/// </summary>public readonly static HTuple RECT1 = new string[] { "row1", "column1", "row2", "column2" };/// <summary>/// 矩形2参数/// </summary>public readonly static HTuple RECT2 = new string[] { "row", "column", "phi", "length1", "length2" };/// <summary>/// /// </summary>public readonly static HTuple XLD_COUTOUR = new string[] { "row", "column" };}public class ShapeParamValue{public readonly static HTuple[] CIRCLE = new HTuple[] { 100, 100, 100 };public readonly static HTuple[] ELLIPSE = new HTuple[] { 100, 100, 50, 50, 50 };public readonly static HTuple[] RECT1 = new HTuple[] { 100, 100, 200, 200 }; public readonly static HTuple[] RECT2 = new HTuple[] { 200, 200, 0, 100, 100 }; public readonly static HTuple[] XLD_COUTOUR = new HTuple[] { (new HTuple(200, 250)), (new HTuple(300, 350)) };}/// <summary>/// 绘制对象/// </summary> public class DrawingObject{public HDrawingObject Obj { get; set; }public HTuple ShapeParamNames { get; set; }public HTuple[] ShapeParamValues { get; set; }public ROIType Type { get; set; }}public class ROIOperator{public ROIOperator(string name, ROIOperation operation){this.Name = name;this.Operation = operation;}public HTuple ID { get; set; }public string Name { get; set; }public ROIOperation Operation { get; set; }}public enum ROIOperation{Add,Remove,Update,Search}
GenArrow
public class GenArrow
{/// <summary>/// 生成箭头轮廓/// </summary>public static void Gen_arrow_contour_xld(out HObject ho_Arrow, HTuple hv_Row1, HTuple hv_Column1,HTuple hv_Row2, HTuple hv_Column2, HTuple hv_HeadLength, HTuple hv_HeadWidth){HObject ho_TempArrow = null;HTuple hv_Length = new HTuple(); HTuple hv_ZeroLengthIndices = new HTuple();HTuple hv_DR = new HTuple(); HTuple hv_DC = new HTuple(); HTuple hv_HalfHeadWidth = new HTuple();HTuple hv_RowP1 = new HTuple(); HTuple hv_ColP1 = new HTuple();HTuple hv_RowP2 = new HTuple(); HTuple hv_ColP2 = new HTuple();HTuple hv_Index = new HTuple();HOperatorSet.GenEmptyObj(out ho_Arrow);HOperatorSet.GenEmptyObj(out ho_TempArrow);ho_Arrow.Dispose();HOperatorSet.GenEmptyObj(out ho_Arrow);//计算箭头长度hv_Length.Dispose();HOperatorSet.DistancePp(hv_Row1, hv_Column1, hv_Row2, hv_Column2, out hv_Length);////Mark arrows with identical start and end point//(set Length to -1 to avoid division-by-zero exception)hv_ZeroLengthIndices.Dispose();using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_ZeroLengthIndices = hv_Length.TupleFind(0);}if ((int)(new HTuple(hv_ZeroLengthIndices.TupleNotEqual(-1))) != 0){if (hv_Length == null)hv_Length = new HTuple();hv_Length[hv_ZeroLengthIndices] = -1;}////Calculate auxiliary variables.hv_DR.Dispose();using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_DR = (1.0 * (hv_Row2 - hv_Row1)) / hv_Length;}hv_DC.Dispose();using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_DC = (1.0 * (hv_Column2 - hv_Column1)) / hv_Length;}hv_HalfHeadWidth.Dispose();using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_HalfHeadWidth = hv_HeadWidth / 2.0;}////Calculate end points of the arrow head.hv_RowP1.Dispose();using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_RowP1 = (hv_Row1 + ((hv_Length - hv_HeadLength) * hv_DR)) + (hv_HalfHeadWidth * hv_DC);}hv_ColP1.Dispose();using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_ColP1 = (hv_Column1 + ((hv_Length - hv_HeadLength) * hv_DC)) - (hv_HalfHeadWidth * hv_DR);}hv_RowP2.Dispose();using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_RowP2 = (hv_Row1 + ((hv_Length - hv_HeadLength) * hv_DR)) - (hv_HalfHeadWidth * hv_DC);}hv_ColP2.Dispose();using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_ColP2 = (hv_Column1 + ((hv_Length - hv_HeadLength) * hv_DC)) + (hv_HalfHeadWidth * hv_DR);}//Finally create output XLD contour for each input point pairfor (hv_Index = 0; (int)hv_Index <= (int)((new HTuple(hv_Length.TupleLength())) - 1); hv_Index = (int)hv_Index + 1){if ((int)(new HTuple(((hv_Length.TupleSelect(hv_Index))).TupleEqual(-1))) != 0){//Create_ single points for arrows with identical start and end pointusing (HDevDisposeHelper dh = new HDevDisposeHelper()){ho_TempArrow.Dispose();HOperatorSet.GenContourPolygonXld(out ho_TempArrow, hv_Row1.TupleSelect(hv_Index),hv_Column1.TupleSelect(hv_Index));}}//Create arrow contourelse{using (HDevDisposeHelper dh = new HDevDisposeHelper()){ho_TempArrow.Dispose();HOperatorSet.GenContourPolygonXld(out ho_TempArrow, ((((((((((hv_Row1.TupleSelect(hv_Index))).TupleConcat(hv_Row2.TupleSelect(hv_Index)))).TupleConcat(hv_RowP1.TupleSelect(hv_Index)))).TupleConcat(hv_Row2.TupleSelect(hv_Index)))).TupleConcat(hv_RowP2.TupleSelect(hv_Index)))).TupleConcat(hv_Row2.TupleSelect(hv_Index)),((((((((((hv_Column1.TupleSelect(hv_Index))).TupleConcat(hv_Column2.TupleSelect(hv_Index)))).TupleConcat(hv_ColP1.TupleSelect(hv_Index)))).TupleConcat(hv_Column2.TupleSelect(hv_Index)))).TupleConcat(hv_ColP2.TupleSelect(hv_Index)))).TupleConcat(hv_Column2.TupleSelect(hv_Index)));}}{HObject ExpTmpOutVar_0;HOperatorSet.ConcatObj(ho_Arrow, ho_TempArrow, out ExpTmpOutVar_0);ho_Arrow.Dispose();ho_Arrow = ExpTmpOutVar_0;}}ho_TempArrow.Dispose();hv_Length.Dispose();hv_ZeroLengthIndices.Dispose();hv_DR.Dispose();hv_DC.Dispose();hv_HalfHeadWidth.Dispose();hv_RowP1.Dispose();hv_ColP1.Dispose();hv_RowP2.Dispose();hv_ColP2.Dispose();hv_Index.Dispose();}
}
DrawArrowViewModel
public class DrawArrowViewModel
{#region 字段private MainForm mainForm; //操作的窗体private HSmartWindowControl HSImageWindow; //操作的图像窗口private HWindow window; //图像窗口IDprivate HObject hImage = null; //图像private HTuple width = new HTuple(); //宽度private HTuple height = new HTuple(); //高度private Thread drawArrowThread = null; //绘制线程private int pointX = -1; //点Xprivate int pointY = -1; //点Yprivate string context = string.Empty; //内容public event EventHandler<string> ContextChanged; //内容变更事件#endregion/// <summary>/// 构造函数/// </summary>public DrawArrowViewModel(MainForm form){this.mainForm = form;HSImageWindow = form.HSImageWindow;window = HSImageWindow.HalconWindow;mainForm.Btn_DrawArrow.Click += Btn_DrawArrow_Click;mainForm.Btn_LoadImage.Click += Btn_LoadImage_Click;mainForm.MouseWheel += CustomMouseWheel;mainForm.HSImageWindow.HMouseMove += HSImageWindow_HMouseMove;drawArrowThread = new Thread(DrawArrowThreadMethod);}//析构函数、释放资源~ DrawArrowViewModel(){drawArrowThread = null ;window?.Dispose();hImage?.Dispose();width?.Dispose();height?.Dispose();HSImageWindow?.Dispose();}/// <summary>/// 鼠标滚轮缩放图像/// </summary>private void CustomMouseWheel(object sender, MouseEventArgs e){System.Drawing.Point pt = mainForm.Location;int leftBorder = HSImageWindow.Location.X;int rightBorder = HSImageWindow.Location.X + HSImageWindow.Size.Width;int topBorder = HSImageWindow.Location.Y;int bottomBorder = HSImageWindow.Location.Y + HSImageWindow.Size.Height;//判断鼠标指针是否在控件内部if (e.X > leftBorder && e.X < rightBorder && e.Y > topBorder && e.Y < bottomBorder){MouseEventArgs newe = new MouseEventArgs(e.Button, e.Clicks, e.X - pt.X, e.Y - pt.Y, e.Delta);HSImageWindow.HSmartWindowControl_MouseWheel(sender, newe);}}/// <summary>/// 绘制箭头线程方法/// </summary>public void DrawArrowThreadMethod(){HObject ho_Arrow = new HObject();HTuple hv_Row = new HTuple();HTuple hv_Column = new HTuple();try{HOperatorSet.SetColor(window, "blue");HOperatorSet.DrawPoint(window, out hv_Row, out hv_Column);HOperatorSet.SetColor(window, (new HTuple("red")).TupleConcat("green"));GenArrow.Gen_arrow_contour_xld(out ho_Arrow,hv_Row.TupleConcat(hv_Row), hv_Column.TupleConcat(hv_Column),((hv_Row + 200)).TupleConcat(hv_Row),hv_Column.TupleConcat(hv_Column + 200), 5, 5);HOperatorSet.DispObj(ho_Arrow, window);}catch (Exception ex){Debug.Write(ex.ToString());}finally{ho_Arrow.Dispose();hv_Row.Dispose();hv_Column.Dispose();}}/// <summary>/// 鼠标移动显示坐标及所在点的灰度值。/// </summary>private void HSImageWindow_HMouseMove(object sender, HMouseEventArgs e){if (hImage != null){HOperatorSet.CountChannels(hImage, out HTuple hChannels);HTuple grayValue = new HTuple();pointX = Convert.ToInt32(e.X);pointY = Convert.ToInt32(e.Y);if (pointX >= 0 && pointY >= 0&& pointX < width && pointY < height){HOperatorSet.GetGrayval(hImage, pointY, pointX, out grayValue);if (hChannels != null && hChannels == 1){context = $"[X = {pointX},Y = {pointY},Gray = {grayValue.D.ToString("F0")}]";Debug.WriteLine(context);mainForm.Tbx_ImageInfo.Text = context;}else if (hChannels != null && hChannels == 3){context = $"[X = {pointX},Y = {pointY},Gray = {grayValue.D.ToString("F0")}]";Debug.WriteLine(context);mainForm.Tbx_ImageInfo.Text = context;}}}else{context = $"[X = {(int)e.X},Y = {(int)e.Y}]";Debug.WriteLine(context);mainForm.Tbx_ImageInfo.Text = context;}}/// <summary>/// 加载图像的方法/// </summary>private void Btn_LoadImage_Click(object sender, EventArgs e){OpenFileDialog openFile = new OpenFileDialog();openFile.InitialDirectory = "F:\\Image";if (openFile.ShowDialog() == DialogResult.OK){HOperatorSet.ReadImage(out hImage, openFile.FileName);HOperatorSet.DispObj(hImage, window);HOperatorSet.GetImageSize(hImage, out width, out height);}}/// <summary>/// 绘制箭头/// </summary>private void Btn_DrawArrow_Click(object sender, EventArgs e){if (!drawArrowThread.IsAlive){drawArrowThread = new Thread(DrawArrowThreadMethod);drawArrowThread?.Start();}else{drawArrowThread?.Start();}}
}
相关文章:
【C#联合halcon实现绘制ROI功能】
前言 C#联合halcon实现绘制ROI功能: C#联合Halcon,使用HDrawingObject、HDrawingObjectXld,绘制矩形、方向矩形、圆形、椭圆、自定义ROI。支持拖动、重设大小、选中,右键复制、粘贴、删除功能。 运行结果 代码 代码结构 MainFo…...
语言模型的革命:大型概念模型(LCM)的崛起
在人工智能领域,Meta最近推出的一项重大突破正在引起研究人员和开发者的广泛关注:大型概念模型(Large Concept Models,简称LCM)。这一创新彻底改变了我们对语言模型的理解,并为未来AI技术的进展指明了新的方…...
在C#中获取程序的命令行参数
实现此目的的一种方法是重写程序的Main方法并赋予其一个字符串数组参数,如下面的代码所示。 static void Main(string[] args) {foreach (string arg in args){lstArguments.Items.Add(arg);} } 这种方法是从 C 编程语言继承而来的。 我更喜欢下面的方法…...
R基于贝叶斯加法回归树BART、MCMC的DLNM分布滞后非线性模型分析母婴PM2.5暴露与出生体重数据及GAM模型对比、关键窗口识别
全文链接:https://tecdat.cn/?p38667 摘要:在母婴暴露于空气污染对儿童健康影响的研究中,常需对孕期暴露情况与健康结果进行回归分析。分布滞后非线性模型(DLNM)是一种常用于估计暴露 - 时间 - 响应函数的统计方法&am…...
小程序基础 —— 08 文件和目录结构
文件和目录结构 一个完整的小程序项目由两部分组成:主体文件、页面文件: 主体文件:全局文件,能够作用于整个小程序,影响小程序的每个页面,主体文件必须放到项目的根目录下; 主体文件由三部分组…...
bishengjdk-8
title: 深入探索 BishengJDK-8:技术魅力与优势尽显 date: 2024-12-29 category: blog tags:- BishengJDK-8- Java 开发- 性能优化- 技术剖析 sig: BishengJDK archives: 2024-12 author:- way_back summary: BishengJDK-8 作为一款备受瞩目的 JDK 版本,以…...
Android9.x SurfaceView源码分析
前言 本文是继Android 深入理解SurfaceView再次对SurfaceView进行源码分析。 看了下代码,上篇文章是基于Android7.x的,本篇基于Android9.x再次进行分析, Android从7.0开始支持SurfaceView动画,并建议7.0之后使用SurfaceView替代TextureView,这里主要在Android9.0上分析Su…...
分布式 IO 模块助力冲压机械臂产线实现智能控制
在当今制造业蓬勃发展的浪潮中,冲压机械臂产线的智能化控制已然成为提升生产效率、保障产品质量以及增强企业竞争力的关键所在。而分布式 IO 模块的应用,正如同为这条产线注入了一股强大的智能动力,开启了全新的高效生产篇章。 传统挑战 冲压…...
解决VMware的ubuntu22虚拟机没有网络
解决步骤 1.在 Windows 系统中,按 “WinR” 键,输入 “services.msc” 并回车,在服务列表中找到 “VMware DHCP Service” 和 “VMware NAT Service”,确保这两个服务已启动,若未启动则右键点击选择 “启动”…...
Linux arm 编译安装glibc-2.29
重要的话说三遍: !!!!!不要轻易自己去安装glibc!!!!! !!!!!不要轻易自己去安装glibc&a…...
Docker-构建自己的Web-Linux系统-镜像webtop:ubuntu-kde
介绍 安装自己的linux-server,可以作为学习使用,web方式访问,基于ubuntu构建开源项目 https://github.com/linuxserver/docker-webtop安装 docker run -d -p 1336:3000 -e PASSWORD123456 --name webtop lscr.io/linuxserver/webtop:ubuntu-kde登录 …...
linux 7.6安装mysql 8.0步骤如下
linux 7.6安装mysql 8.0步骤如下: 注意:在导入密钥的时候这个不行,可更换为 rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2023...
meshy的文本到3d的使用
Meshy官方网站: 中文官网: Meshy官网中文站 编辑 Opens in a new window 编辑www.meshycn.com Meshy AI 中文官网首页 英文官网: Meshy目前似乎还没有单独的英文官网,但您可以在中文官网上找到英文界面或相关英文资料。 链…...
抓取手机HCI日志
荣耀手机 1、打开开发者模式 2、开启HCI、ADB调试 3、开启AP LOG 拨号界面输入*##2846579##* 4、蓝牙配对 5、抓取log adb pull /data/log/bt ./...
如果你的网站是h5网站,如何将h5网站变成小程序-除开完整重做方法如何快速h5转小程序-h5网站转小程序的办法-优雅草央千澈
如果你的网站是h5网站,如何将h5网站变成小程序-除开完整重做方法如何快速h5转小程序-h5网站转小程序的办法-优雅草央千澈 h5如何转小程序 如果当年你们开发网站是用的h5但是没有开发小程序,也没有使用uniapp这样的混开框架,但是目前根据业务需…...
2024:踏平坎坷成大道,斗罢艰险又出发!
一、开篇 12月今年最后一个月了,相逢的人已走散,Q4的OKR已经定型了,很平淡无味、闲的无聊,提前写个年终总结吧。25年,再过一个月就35岁了,一个人来北京也已经11年了。年近末尾,思绪良多。回顾过…...
Qt For Android之环境搭建(Qt 5.12.11 Qt下载SDK的处理方案)
文章目录 一、Qt For Android运行示例二、个人理解及情况解析三、配置Android相关配置项3.1 安装简述3.2 安装Qt1.安装Qt第一步:启动Qt安装包程序2.Qt账号(注册)登录3.了解Qt开源使用义务4.指定Qt安装目录5.选择Qt安装内容6.接受“许可协议”…...
LLaMA详解
LLaMA 进化史 大规模语言模型(Large Language Model, LLM)的快速发展正在以前所未有的速度推动人工智能(AI)技术的进步。 作为这一领域的先行者, Meta在其LLaMA(Large Language Model Meta AI)系列模型上取得了一系列重大突破。 近日, Meta官方正式宣布推出LLaMA-3, 作为继LL…...
【学生管理系统】权限管理之用户管理
目录 6. 权限管理 6.1 环境搭建 6.1.1 数据库 6.1.2 后端环境 6.2 用户管理 6.2.1 查询所有用户(关联角色) 6.2.2 核心1:给用户授予角色 6. 权限管理 6.1 环境搭建 6.1.1 数据库 权限管理的5张表的关系 添加4张表 # 权限表&…...
基于Java+Springboot+Vue开发的旅游景区管理系统,实习作品
项目简介 该项目是基于JavaSpringbootVue开发的旅游景区管理系统(前后端分离),这是一项为大学生课程设计作业而开发的项目。该系统旨在帮助大学生学习并掌握Java编程技能,同时锻炼他们的项目设计与开发能力。通过学习基于Java的旅…...
人工智能及深度学习的一些题目
1、一个含有2个隐藏层的多层感知机(MLP),神经元个数都为20,输入和输出节点分别由8和5个节点,这个网络有多少权重值? 答:在MLP中,权重是连接神经元的参数,每个连接都有一…...
JavaFX FXML模式下的布局
常见布局方式概述 在 JavaFX FXML 模式下,有多种布局方式可供选择。这些布局方式可以帮助您有效地组织和排列 UI 组件,以创建出美观且功能良好的用户界面。常用布局容器及布局方式 BorderPane 布局 特点:BorderPane 将空间划分为五个区域&…...
在 Windows 11 下的 WSL - Ubuntu 24.04 中安装 CUDA 的记录
#记录工作 以下是基于CUDA官网给定命令在 Windows 11 下的 WSL - Ubuntu 24.04 中安装 CUDA 的记录: 一、准备工作 确保你的 Windows 11 系统已经成功启用 WSL 功能,并且已经安装了 Ubuntu 24.04 操作系统。同时,确保系统处于联网状态&#…...
Qt 12.28 day3
作业: 1】 思维导图 2】 在登录界面的登录取消按钮进行以下设置: 使用手动连接,将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中,在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中&a…...
AISuite:提供了统一的跨 LLM API的开源 Python 库
1. 简介: AISuite是一个开源的Python库,旨在提供一个统一的接口来调用不同的大型语言模型(LLM)API。这个工具由吴恩达(Andrew Ng)领导开发,目的是简化AI模型的调用过程,使得开发者能…...
springMVC-请求响应
springmvc——一 站式web框架,核心是处理http请求响应。 前后端分离:需要序列化,服务端把数据序列化成字符串或者流给前端,前端又把json转成对象,前端的叫反序列化。前端把数据序列化转成字符串给服务器,服…...
【代码分析】Unet-Pytorch
1:unet_parts.py 主要包含: 【1】double conv,双层卷积 【2】down,下采样 【3】up,上采样 【4】out conv,输出卷积 """ Parts of the U-Net model """import torch im…...
uni-app开发-识图小程序-个人中心页面
目录 一:功能描述 二:代码实现 一:功能描述 个人中心中心主要包含用户登录信息,退出登录,图像识别记录,分类识别记录,分享记录以及小程序介绍信息。用户登录状态下可以看到图形识别记录,分类识别记录和分享记录,未登录状态只能看到介绍信息,点击未登录文字会触发…...
C++小游戏
【欢迎关注编码小哥,学习更多实用的编程方法和技巧】 设计一个桌面游戏是一个有趣且富有挑战性的项目。下面是一个简单的C桌面游戏的设计思路和示例代码。我们将创建一个简单的“猜数字”游戏,玩家需要在有限的尝试次数内猜测一个随机生成的数字。 游戏…...
Flutter封装一个三方ViewPager学习
Flutter如何实现一个增强的 PageView,支持自定义页面切换动画。 前置知识点学习 CrossAxisAlignment CrossAxisAlignment 是 Flutter 中用于控制布局子组件在交叉轴(cross axis)方向上的对齐方式的一个枚举类。它主要在 Flex 布局模型中使…...
【算法】复杂性理论初步
六、算法复杂性初步 重要的复杂性类 P P P 的定义 多项式时间内可解的问题 若 L ∈ P L∈P L∈P,则存在确定性多项式时间的图灵机 M M M,使得 M ( x ) 1 ⟺ x ∈ L M(x)1⟺x∈L M(x)1⟺x∈L N P NP NP 的定义 多项式时间内可验证验证解的正确性 &…...
vscode实用插件(持续更新)
目录 Git History Diff Git Graph Error Lens Git History Diff 用于将当前分支的某个文件夹与远程分支的相同文件夹做对比,方便代码评审!解决了为了一个问题而多次commit,导致代码不好评审,即不晓得和远程分支相比࿰…...
使用Lodash工具库的orderby和sortby进行排序的区别
简介 _.orderBy 和 _.sortBy 是 Lodash 库中用于排序数组的两个函数。 区别 _.orderBy 允许你指定一个或多个属性来排序,并为每个属性指定排序方向(升序或降序)。默认所有值为升序排,指定为"desc" 降序,…...
胡闹厨房练习(三)
ScriptableObject 一、初步了解 1、实质:是一种特殊类型的Unity对象, 2、作用:用于存储大量数据,而不必依附于游戏场景中的某个GameObject。 3、特点: 可以在不增加场景中对象数量的情况下,管理和存储复杂的数据结构、配置信息、游戏状态等。 4、适用:非常适合用来…...
Postman接口测试01|接口测试基础概念、http协议、RESTful风格、接口文档
目录 一、接口测试基础概念 1、什么是接口 2、接口的类型 3、什么是接口测试 4、为什么要做接口测试 5、接口测试的实现方式 6、什么是自动化接口测试? 二、接口返回的数据格式 1、三种格式 2、Json 三、接口协议 1、webservice协议 2、dubbo协议 3、…...
算法进阶:贪心算法
贪心算法是一种简单而直观的算法思想,它在每一步选择中都采取在当前状态下最优的选择,以期望最终得到全局最优解。贪心算法通常适用于一些具有最优子结构的问题,即问题的最优解可以通过一系列局部最优解的选择得到。 贪心算法的基本思路是&a…...
深度学习笔记(6)——循环神经网络RNN
循环神经网络 RNN 核心思想:RNN内部有一个“内部状态”,随着序列处理而更新 h t f W ( h t − 1 , x t ) h_tf_W(h_{t-1},x_t) htfW(ht−1,xt) 一般来说 h t t a n h ( W h h h t − 1 W x h x t ) h_ttanh(W_{hh}h_{t-1}W_{xh}x_t) httanh(Whhht−1Wxhxt…...
电商项目高级篇07-redisson分布式锁
redisson分布式锁 1、引入maven依赖2、config类3、可重入锁设计 1、引入maven依赖 <!--引入redisson--><dependency><groupId>org.redisson</groupId><artifactId>redisson</artifactId><version>3.12.0</version></depend…...
STM32中断详解
STM32中断详解 NVIC 中断系统中断向量表相关寄存器中断优先级中断配置 外部中断实验EXTI框图外部中断/事件线映射中断步骤初始化代码实现 定时器中断通用定时器相关功能标号1:时钟源标号 2:控制器标号 3:时基单元 代码实现 NVIC 中断系统 STM…...
KNN分类算法 HNUST【数据分析技术】(2025)
1.理论知识 KNN(K-Nearest Neighbor)算法是机器学习算法中最基础、最简单的算法之一。它既能用于分类,也能用于回归。KNN通过测量不同特征值之间的距离来进行分类。 KNN算法的思想: 对于任意n维输入向量,分别对应于特征…...
【Win11】安装 VMware17 和 Ubuntu
【Win11】安装 VMware17 和 Ubuntu 15 版本和 Win11 家庭版间的兼容应该有 BUG,请直接跳至【VMware 17】 安装【VMware 15】 本来是按如下资源链接安装的,但发现 15 版本和 Win11 家庭版间的兼容应该有 BUG,在安装并关闭 Hyper-Vÿ…...
Jmeter快速入门
目录 1.安装Jmeter 1.1.下载 1.2.解压 1.3.运行 2.快速入门 2.1.设置中文语言 2.2.基本用法 1.安装Jmeter Jmeter依赖于JDK,所以必须确保当前计算机上已经安装了JDK,并且配置了环境变量。 1.1.下载 可以Apache Jmeter官网下载,地址…...
Android Studio2024版本安装环境SDK、Gradle配置
一、软件版本,安装包附上 👉android-studio-2024.1.2.12-windows.exe👈 👉百度网盘Android Studio安装包👈 (若下载连链接失效可去百度网盘链接下载) 二、软件安装过程 三、准备运行…...
嵌入式单片机窗口看门狗控制与实现
窗口看门狗 注意:WWDG外设没有独立的时钟源,而是挂载在APB1总线下,APB1总线外设时钟为42MHZ。 了解WWDG外设的使用流程,可以参考stm32f4xx_wwdg.c的开头注释,具体流程如下图所示...
[单master节点k8s部署]43.全链路监控(二)
部署pinpoint服务端 这里安装的是pinpoint-docker,可以从GitHub - pinpoint-apm/pinpoint-docker: Officix 下载。通过readme可以看到,该项目提供的镜像: Pinpoint-Web ServerPinpoint-CollectorPinpoint-AgentPinpoint-FlinkPinpoint-Hba…...
Apache Doris 创始人:何为“现代化”的数据仓库?
在 12 月 14 日的 Doris Summit Asia 2024 上,Apache Doris 创始人 & PMC 成员马如悦在开场演讲中,围绕“现代化数据仓库”这一主题,指出 3.0 版本是 Apache Doris 研发路程中的重要里程碑,他将这一进展总结为“实时之路”、“…...
json的作用?
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,具有简洁、易读、易于解析和生成等特点,在前后端数据交互、配置文件、数据存储等多个领域发挥着重要作用,以下是具体介绍: JSON 的作用 数据…...
ChatGPT是如何生成长文的
说实话,现在我们对chatGPT的最深的印象就是他是一个各方面知识都比较全面的机器助手,我们的问题他都能生成答案,不过大家发现没有,它生成相对应的长文的时候,都是一个词一个词蹦出来的,有的时候是一个个词组…...
微服务——部署与运维
1、你是否有将 Java 微服务部署到容器(如 Docker)中的经验?请描述一下部署过程和相关注意事项。 部署过程: 编写 Dockerfile,定义基础镜像(如 openjdk)、应用 JAR 包路径和启动命令。构建镜像…...
json笔记
1、json的组成 JSON是一个标记符序列。这套标记符包括:构造字符、字符串、数字和字面值(false, true, null)。 1.1 构造字符 六个构造字符: 左方括号 [ 右方括号 ] 左大括号 { 右大括号 } 冒号 : 逗号 , 1.2 JSON值 json值包括:对象…...