【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);

    }

    #endregion

    private 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;                //窗口ID
    private HTuple CurrentROIHandle = null;         //当前选中的ROI
    private 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;
            }
        }
    }
    //显示ROI
    private 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;
            }
        }
    }
    //绘制ROI
    public 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:    //矩形1
                paramValue = 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:    //矩形1
                roi.ShapeParamNames = ShapeParam.RECT1;
                roi.ShapeParamValues = ShapeParamValue.RECT1;
                break;
            case ROIType.RECTANGLE2:    //矩形2
                roi.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_width
            drawObj.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; }                     //ID
     public 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 pair
        for (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 point
                using (HDevDisposeHelper dh = new HDevDisposeHelper())
                {
                    ho_TempArrow.Dispose();
                    HOperatorSet.GenContourPolygonXld(out ho_TempArrow, 
                        hv_Row1.TupleSelect(hv_Index),
                        hv_Column1.TupleSelect(hv_Index));
                }
            }
            //Create arrow contour
            else
            {
                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;                         //图像窗口ID
    private HObject hImage = null;                  //图像
    private HTuple width = new HTuple();            //宽度
    private HTuple height = new HTuple();           //高度
    private Thread drawArrowThread = null;          //绘制线程
    private int pointX = -1;                        //点X
    private int pointY = -1;                        //点Y
    private 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();
        }
    }
}

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

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

相关文章

Visual Studio 使用 GitHub Copilot 与 IntelliCode 辅助编码 【AI辅助开发系列】

&#x1f380;&#x1f380;&#x1f380;【AI辅助编程系列】&#x1f380;&#x1f380;&#x1f380; Visual Studio 使用 GitHub Copilot 与 IntelliCode 辅助编码Visual Studio 安装和管理 GitHub CopilotVisual Studio 使用 GitHub Copilot 扩展Visual Studio 使用 GitHu…

4.FPGA如何实现设计

在前面分别引入了&#xff0c;LUT的知识&#xff0c;全局时钟网络&#xff0c;以及FPGA内部的资源。 LUT的知识&#xff1a; 在FPGA设计中实现的逻辑运算在不借用其他的硬核的基础上都是在LUT中通过查表的方式进行完成的&#xff0c;比如实现的c a & b;就是将a&b的所…

centos权限大集合,覆盖多种权限类型,解惑权限后有“. + t s”问题!

在 CentOS 系统中&#xff0c;权限管理是操作系统的核心功能之一&#xff0c;确保不同用户和进程对文件、目录以及设备的访问被合理控制。 权限系统主要包括传统的 Unix 权限模型、特殊权限&#xff08;SetUID、SetGID、Sticky 位&#xff09;和更精细的访问控制列表&#xff…

不良人系列-复兴数据结构(栈和队列)

个人主页&#xff1a;爱编程的小新☆ 不良人经典语录&#xff1a;“相呴相济 玉汝于成 勿念 心安” 目录 一. 栈(stack) 1. 栈的概念 2. 栈的常见方法 3.栈的模拟实现 ​编辑 二. 队列 1. 队列的概念 2. 队列的使用 2.1 队列的常见方法 2.2 队列的模拟实现 2.3 队列…

【动态规划篇】步步带你深入解答成功AC最优包含问题(通俗易懂版)

本篇小鸡汤&#xff1a;待到苦尽甘来时&#xff0c;我给你讲讲来时路。 欢迎拜访&#xff1a;羑悻的小杀马特.-CSDN博客 本篇主题&#xff1a;解答洛谷的最优包含问题 制作日期&#xff1a;2024.12.23 隶属专栏&#xff1a;C/C题海汇总 ​​ 目录 本篇简介&#xff1a; 一动态…

【大语言模型】ACL2024论文-29 答案即所需:通过回答问题实现指令跟随的文本嵌入

【大语言模型】ACL2024论文-29 答案即所需&#xff1a;通过回答问题实现指令跟随的文本嵌入 目录 文章目录 目录文章信息摘要研究背景问题与挑战如何解决创新点算法模型实验效果推荐阅读指数&#xff1a;★★★★☆ 后记 文章信息 答案即所需&#xff1a;通过回答问题实现指令…

模型的量化(Quantization)

文章目录 一、浮点数格式&#xff1a;FP64, FP32, FP16, BFLOAT16, TF32之间的相互区别1、关于浮点数2、常见的浮点数格式 二、量化&#xff08;Quantization&#xff09;1、基本概念2、量化的实现8bit量化4bit量化 三、QLora四、大语言模型量化方法对比&#xff1a;GPTQ、GGUF…

10. zynq应用开发--camke编译

使用SDK工具 如果只做 Linux 应用开发&#xff0c;只需要一个 sdk.sh 文件即可&#xff0c;可以脱离 Petalinux 和 Vitis&#xff0c;也可以编译其三方的应用&#xff0c;可以说一劳永逸。 配置根文件系统 petalinux-config -c rootfs 编译SDK petalinux-build --sdk Linux主…

CSS学习记录20

CSS 3D 转换 通过CSS transform 属性&#xff0c;您可以使用以下3D转换方法&#xff1a; rotateX()rotateY()rotateZ() rotateX() 方法 rotateX() 方法使元素绕其X轴旋转给定角度&#xff1a; #myDiv {transform: rotateX(150deg); } rotateY() 方法 rotateY() 方法使元…

开发微信小程序的过程与心得

起因 作为家长&#xff0c;我近期参与了学校的护学岗工作。在这个过程中&#xff0c;我发现需要使用水印相机来记录护学活动&#xff0c;但市面上大多数水印相机应用都要求开通会员才能使用完整功能。作为一名程序员&#xff0c;我决定利用自己的技术背景&#xff0c;开发一个…

【论文笔记】Visual Alignment Pre-training for Sign Language Translation

&#x1f34e;个人主页&#xff1a;小嗷犬的个人主页 &#x1f34a;个人网站&#xff1a;小嗷犬的技术小站 &#x1f96d;个人信条&#xff1a;为天地立心&#xff0c;为生民立命&#xff0c;为往圣继绝学&#xff0c;为万世开太平。 基本信息 标题: Visual Alignment Pre-tra…

数据可视化echarts学习笔记

目录&#xff0c;介绍 知识储备 一端操作&#xff0c;多端联动的效果&#xff08;开启了多个网页&#xff0c;操作一端&#xff0c;多个网页的效果会跟着改变&#xff09; cmd命令控制面板返回上一级或上上级 在当前目录打开文件&#xff1a; cd 文件名 在Windows命令提示符&am…

踏踏实实练SQLday1-1连续登录

踏踏实实练SQLday1 1连续登录1.1查询连续登录3天以上的用户第一步去重第二步-开窗rownumber&#xff0c;用date减一下&#xff0c;对结果进行分组 -- over()开窗函数知识图谱第三步 1.2查询连续登录最大天数用户1.3某个用户连续登录天数注意先where一下这个用户的数据过滤出来.…

Vue开发环境搭建上篇:安装NVM和NPM(cpnm、pnpm)

文章目录 引言I 安装NVM1.1 Windows系统安装NVM,实现Node.js多版本管理1.2 配置下载镜像1.3 NVM常用操作命令II NPM永久使用淘宝源安装 cnpm安装pnpm【推荐】see also: vscode常用插件引言 淘宝镜像:http://npm.taobao.org 和 http://registry.npm.taobao.org 已在 2022.06.3…

数据仓库工具箱—读书笔记02(Kimball维度建模技术概述03、维度表技术基础)

Kimball维度建模技术概述 记录一下读《数据仓库工具箱》时的思考&#xff0c;摘录一些书中关于维度建模比较重要的思想与大家分享&#x1f923;&#x1f923;&#x1f923; 第二章前言部分作者提到&#xff1a;技术的介绍应该通过涵盖各种行业的熟悉的用例展开&#xff08;赞同…

Postman接口测试02|执行接口测试、全局变量和环境变量、接口关联、动态参数、断言

目录 五、Postman 1、安装 2、postman的界面介绍 六、Postman执行接口测试 1、请求页签 3、响应页签 七、Postman的环境变量和全局变量 1、创建环境变量和全局变量可以解决的问题 2、postman中的操作 八、接口关联 1、第一种方式&#xff1a;Json提取器 2、第二种方…

Oracle 日常巡检

1. 检查服务器状态 1.1. CPU使用情况 1.1.1. top top 命令是 Linux 和 Unix 系统中用于显示实时系统状态的工具&#xff0c;特别是对于监控 CPU 和内存的使用非常有用。 在命令行中输入 top&#xff0c;top 会显示一个实时更新的界面&#xff0c;其中包含系统的关键指标&am…

计算机组成原理的学习笔记(8)-- 指令系统·其一 指令的组成以及数据寻址方式

学习笔记 前言 ​ 本文主要是对于b站尚硅谷的计算机组成原理的学习笔记&#xff0c;仅用于学习交流。 1. 指令 1.1 组成 操作码&#xff08;Opcode&#xff09;&#xff1a;指指令中执行特定操作的部分。地址码&#xff1a;指令中用于指定操作数位置的部分。 1.2 扩展操作…

JavaScript 标准内置对象——Array

1、构造函数 2、静态方法 // 从可迭代或类数组对象创建一个新的浅拷贝的数组实例 // arrayLike 想要转换成数组的类数组或可迭代对象 Array.from(arrayLike, mapFn, thisArg) Array.fromAsync(arrayLike, mapFn, thisArg) // 异步Array.isArray(value) // 判断传递的值是否是一…

IndexOf Apache Web For Liunx索引服务器部署及应用

Apache HTTP Server 是一款广泛使用的开源网页服务器软件,它支持多种协议,包括 HTTP、HTTPS、FTP 等 IndexOf 功能通常指的是在一个目录中自动生成一个索引页面的能力,这个页面会列出该目录下所有的文件和子目录。比如网上经常看到的下图展现的效果,那么接下来我们就讲一下…