c#联合halcon的基础教程(案例:亮度计算、角度计算和缺陷检测)(含halcon代码)

目录

1.环境配置

2.案例一:亮度计算

halcon代码:

主界面代码:

3.案例二: 角度计算

halcon代码:

主界面代码:

4.案例三:缺陷检测

halcon代码:

主界面代码:


通过网盘分享的文件:halcon-25.05.0.0-x64-win64
链接: 百度网盘 请输入提取码

提取码: whek

1.环境配置

A.创建新c# winform 项目,点击添加引用。

(halcon安装目录"D:\halcon\HALCON-25.05-Progress\bin\dotnet35\halcondotnet.dll")

B.把halcondotnet.dll拖到工具箱。

C.把"D:\halcon\HALCON-25.05-Progress\bin\x64-win64\halcon.dll"复制到项目的Debug文件夹中

D.项目属性生成中:取消勾选 首选32

2.案例一:亮度计算

                                            如图,计算 选框区域的亮度。

c#上添加几个控件

添加openfiledialog控件

点击选择文件后把地址放在textbox1

        private void button2_Click(object sender, EventArgs e)
        {

            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.Filter = "所有文件|*.*";
                openFileDialog.Title = "选择文件";

                if (openFileDialog.ShowDialog() == DialogResult.OK)
                {
                    string filePath = openFileDialog.FileName;
                    textBox1.Text = filePath;

                }
            }
        }
 

打开halcon软件,完成项目功能

halcon代码:

read_image (Heibai, 'C:/Users/86957/Desktop/heibai.png')rgb1_to_gray(Heibai, GrayImage)
get_image_size(GrayImage, Width, Height)
dev_open_window(0, 0, Width, Height, 'white', WindowHandle)
dev_display(GrayImage)* 交互式绘制矩形(轴对齐)
draw_rectangle1(WindowHandle, Row1, Column1, Row2, Column2)
* 参数说明:
* Row1, Column1: 矩形左上角坐标
* Row2, Column2: 矩形右下角坐标* 生成矩形区域
gen_rectangle1(Rectangle, Row1, Column1, Row2, Column2)* 显示结果
dev_set_color('red')
dev_display(Rectangle)*计算选框内的像素平均值
intensity(Rectangle, GrayImage, Mean, Deviation)
* 输出结果:
* Mean: 平均灰度值
* Deviation: 标准差(可选)* 在窗口显示计算结果
set_tposition(WindowHandle, 20, 20)
write_string(WindowHandle, 'Mean Intensity: ' + Mean$'.2f')

点击文件,导出程序。

把导出的.cs文件,复制到项目中。并进行修改。

我们只需要action();并把他放入项目的命名空间;还需要增加输入str filepath。

原来的hd.cs:

修改后的hd.cs如下:
 

//
// File generated by HDevelop for HALCON/.NET (C#) Version 25.05.0.0
// Non-ASCII strings in this file are encoded in local-8-bit encoding (cp936).
// 
// Please note that non-ASCII characters in string constants are exported
// as octal codes in order to guarantee that the strings are correctly
// created on all systems, independent on any compiler settings.
// 
// Source files with different encoding should not be mixed in one project.
//using HalconDotNet;
namespace halcon_cs
{public partial class HDevelopExport{// Main procedure public void action(string filepath){// Local iconic variables HObject ho_Heibai, ho_GrayImage, ho_Rectangle;// Local control variables HTuple hv_Width = new HTuple(), hv_Height = new HTuple();HTuple hv_WindowHandle = new HTuple(), hv_Row1 = new HTuple();HTuple hv_Column1 = new HTuple(), hv_Row2 = new HTuple();HTuple hv_Column2 = new HTuple(), hv_Mean = new HTuple();HTuple hv_Deviation = new HTuple();// Initialize local and output iconic variables HOperatorSet.GenEmptyObj(out ho_Heibai);HOperatorSet.GenEmptyObj(out ho_GrayImage);HOperatorSet.GenEmptyObj(out ho_Rectangle);ho_Heibai.Dispose();HOperatorSet.ReadImage(out ho_Heibai, filepath);ho_GrayImage.Dispose();HOperatorSet.Rgb1ToGray(ho_Heibai, out ho_GrayImage);hv_Width.Dispose(); hv_Height.Dispose();HOperatorSet.GetImageSize(ho_GrayImage, out hv_Width, out hv_Height);HOperatorSet.SetWindowAttr("background_color", "white");HOperatorSet.OpenWindow(0, 0, hv_Width, hv_Height, 0, "visible", "", out hv_WindowHandle);HDevWindowStack.Push(hv_WindowHandle);if (HDevWindowStack.IsOpen()){HOperatorSet.DispObj(ho_GrayImage, HDevWindowStack.GetActive());}//交互式绘制矩形(轴对齐)hv_Row1.Dispose(); hv_Column1.Dispose(); hv_Row2.Dispose(); hv_Column2.Dispose();HOperatorSet.DrawRectangle1(hv_WindowHandle, out hv_Row1, out hv_Column1, out hv_Row2,out hv_Column2);//参数说明://Row1, Column1: 矩形左上角坐标//Row2, Column2: 矩形右下角坐标//生成矩形区域ho_Rectangle.Dispose();HOperatorSet.GenRectangle1(out ho_Rectangle, hv_Row1, hv_Column1, hv_Row2, hv_Column2);//显示结果if (HDevWindowStack.IsOpen()){HOperatorSet.SetColor(HDevWindowStack.GetActive(), "red");}if (HDevWindowStack.IsOpen()){HOperatorSet.DispObj(ho_Rectangle, HDevWindowStack.GetActive());}//计算选框内的像素平均值hv_Mean.Dispose(); hv_Deviation.Dispose();HOperatorSet.Intensity(ho_Rectangle, ho_GrayImage, out hv_Mean, out hv_Deviation);//输出结果://Mean: 平均灰度值//Deviation: 标准差(可选)//在窗口显示计算结果HOperatorSet.SetTposition(hv_WindowHandle, 20, 20);using (HDevDisposeHelper dh = new HDevDisposeHelper()){HOperatorSet.WriteString(hv_WindowHandle, "Mean Intensity: " + (hv_Mean.TupleString(".2f")));}ho_Heibai.Dispose();ho_GrayImage.Dispose();ho_Rectangle.Dispose();hv_Width.Dispose();hv_Height.Dispose();hv_WindowHandle.Dispose();hv_Row1.Dispose();hv_Column1.Dispose();hv_Row2.Dispose();hv_Column2.Dispose();hv_Mean.Dispose();hv_Deviation.Dispose();}}
}

主界面代码:

如下:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using HalconDotNet;
namespace halcon_cs
{public partial class Form1 : Form{public Form1(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){string filepath = textBox1.Text;HDevelopExport hd = new HDevelopExport();hd.action(filepath);}private void button2_Click(object sender, EventArgs e){using (OpenFileDialog openFileDialog = new OpenFileDialog()){openFileDialog.Filter = "所有文件|*.*";openFileDialog.Title = "选择文件";if (openFileDialog.ShowDialog() == DialogResult.OK){string filePath = openFileDialog.FileName;textBox1.Text = filePath;}}}}
}

设计器代码如下:

using HalconDotNet;namespace halcon_cs
{partial class Form1{/// <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.button1 = new System.Windows.Forms.Button();this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();this.button2 = new System.Windows.Forms.Button();this.textBox1 = new System.Windows.Forms.TextBox();this.SuspendLayout();// // button1// this.button1.Location = new System.Drawing.Point(374, 594);this.button1.Name = "button1";this.button1.Size = new System.Drawing.Size(430, 101);this.button1.TabIndex = 1;this.button1.Text = "start";this.button1.UseVisualStyleBackColor = true;this.button1.Click += new System.EventHandler(this.button1_Click);// // openFileDialog1// this.openFileDialog1.FileName = "openFileDialog1";// // button2// this.button2.Location = new System.Drawing.Point(779, 41);this.button2.Name = "button2";this.button2.Size = new System.Drawing.Size(116, 43);this.button2.TabIndex = 4;this.button2.Text = "选择文件";this.button2.UseVisualStyleBackColor = true;this.button2.Click += new System.EventHandler(this.button2_Click);// // textBox1// this.textBox1.Location = new System.Drawing.Point(314, 50);this.textBox1.Name = "textBox1";this.textBox1.Size = new System.Drawing.Size(459, 28);this.textBox1.TabIndex = 5;// // Form1// this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F);this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;this.ClientSize = new System.Drawing.Size(1176, 821);this.Controls.Add(this.textBox1);this.Controls.Add(this.button2);this.Controls.Add(this.button1);this.Name = "Form1";this.Text = "Form1";this.ResumeLayout(false);this.PerformLayout();}#endregionprivate System.Windows.Forms.Button button1;private System.Windows.Forms.OpenFileDialog openFileDialog1;private System.Windows.Forms.Button button2;private System.Windows.Forms.TextBox textBox1;}
}

运行后;

运行后,弹窗无法关闭,后续添加halcon控件来显示图像。

3.案例二: 角度计算

如图,计算三角形 三个角的角度。

在案例一的基础上,增加HWindowcontrol

显示图像按钮:
 

        private void button1_Click(object sender, EventArgs e){//读取文件HOperatorSet.ReadImage(out TestImage, textBox1.Text);//获取图片大小HTuple Width, Height;HOperatorSet.GetImageSize(TestImage, out Width, out Height);//设置图片显示范围 hWindowControl1.HalconWindow获得窗体句柄HOperatorSet.SetPart(hWindowControl1.HalconWindow, 0, 0, (Height - 1), (Width - 1)); //0,0, (Height - 1), (Width - 1)代表从0,0坐标到图片的宽高坐标,达到全屏显示//将图片投射到窗体上HOperatorSet.DispObj(TestImage, hWindowControl1.HalconWindow);//将TestImage变量投射到句柄窗口上}

计算角度按钮:

        private void button3_Click(object sender, EventArgs e){double[] result;HDevelopExport hDevelopExport = new HDevelopExport();result = hDevelopExport.action(textBox1.Text);foreach (double indexer in result) { textBox2.AppendText(indexer.ToString()+"\r\n");}}

使用halcon代码转换成的action,计算角度。

主要方法为:

A获取区域轮廓

B将轮廓分割为线段

C得到线段的终点和起点

D计算线段交点

E根据三角形三个顶点,计算三个内角

运行后:

halcon代码:

read_image (Image, 'C:/Users/86957/Desktop/sanjiao.png')
rgb1_to_gray (Image, GrayImage)
threshold(GrayImage, TriangleRegion, 0, 128)
gen_contour_region_xld(TriangleRegion, Contour, 'border')
segment_contours_xld(Contour, Segments, 'lines_circles', 5, 4, 2)count_obj(Segments, NumSegments)
Angles := []for i := 1 to 3 by 1select_obj(Segments, Segment, i)fit_line_contour_xld(Segment, 'tukey', -1, 0, 5, 2, RowBegin, ColBegin, RowEnd, ColEnd, _, _, _)* 存储线段端点if (i == 1)Line1 := [RowBegin, ColBegin, RowEnd, ColEnd]elseif (i == 2)Line2 := [RowBegin, ColBegin, RowEnd, ColEnd]elseLine3 := [RowBegin, ColBegin, RowEnd, ColEnd]endifendforintersection_lines(Line1[0], Line1[1], Line1[2], Line1[3], Line2[0], Line2[1], Line2[2], Line2[3], RowV1, ColV1, IsOverlapping1)
intersection_lines(Line2[0], Line2[1], Line2[2], Line2[3], Line3[0], Line3[1], Line3[2], Line3[3], RowV2, ColV2, IsOverlapping2)
intersection_lines(Line3[0], Line3[1], Line3[2], Line3[3], Line1[0], Line1[1], Line1[2], Line1[3], RowV3, ColV3, IsOverlapping3) * 1. 计算三条边的长度
distance_pp(RowV1, ColV1, RowV2, ColV2, AB)
distance_pp(RowV1, ColV1, RowV3, ColV3, AC) 
distance_pp(RowV2, ColV2, RowV3, ColV3, BC)* 2. 使用余弦定理计算角度
* 顶点A的角度 (对边BC)
cosAngleA := (AC*AC + AB*AB - BC*BC) / (2 * AC * AB)
AngleA := acos(cosAngleA) * 180 / 3.1415926535* 顶点B的角度 (对边AC)
cosAngleB := (AB*AB + BC*BC - AC*AC) / (2 * AB * BC)
AngleB := acos(cosAngleB) * 180 / 3.1415926535* 顶点C的角度 (对边AB)
cosAngleC := (AC*AC + BC*BC - AB*AB) / (2 * AC * BC)
AngleC := acos(cosAngleC) * 180 / 3.1415926535

转成c#程序,并修改 输入输出。

//
// File generated by HDevelop for HALCON/.NET (C#) Version 25.05.0.0
// Non-ASCII strings in this file are encoded in local-8-bit encoding (cp936).
// 
// Please note that non-ASCII characters in string constants are exported
// as octal codes in order to guarantee that the strings are correctly
// created on all systems, independent on any compiler settings.
// 
// Source files with different encoding should not be mixed in one project.
//using HalconDotNet;
namespace halcon_cs
{public partial class HDevelopExport{public double[] action(string imgpath ){// Local iconic variables HObject ho_Image, ho_GrayImage, ho_TriangleRegion;HObject ho_Contour, ho_Segments, ho_Segment = null;// Local control variables HTuple hv_NumSegments = new HTuple(), hv_Angles = new HTuple();HTuple hv_i = new HTuple(), hv_RowBegin = new HTuple();HTuple hv_ColBegin = new HTuple(), hv_RowEnd = new HTuple();HTuple hv_ColEnd = new HTuple(), hv__ = new HTuple(), hv_Line1 = new HTuple();HTuple hv_Line2 = new HTuple(), hv_Line3 = new HTuple();HTuple hv_RowV1 = new HTuple(), hv_ColV1 = new HTuple();HTuple hv_IsOverlapping1 = new HTuple(), hv_RowV2 = new HTuple();HTuple hv_ColV2 = new HTuple(), hv_IsOverlapping2 = new HTuple();HTuple hv_RowV3 = new HTuple(), hv_ColV3 = new HTuple();HTuple hv_IsOverlapping3 = new HTuple(), hv_AB = new HTuple();HTuple hv_AC = new HTuple(), hv_BC = new HTuple(), hv_cosAngleA = new HTuple();HTuple hv_AngleA = new HTuple(), hv_cosAngleB = new HTuple();HTuple hv_AngleB = new HTuple(), hv_cosAngleC = new HTuple();HTuple hv_AngleC = new HTuple(), hv___Tmp_Ctrl_0_5 = new HTuple();HTuple hv___Tmp_Ctrl_0_6 = new HTuple();// Initialize local and output iconic variables HOperatorSet.GenEmptyObj(out ho_Image);HOperatorSet.GenEmptyObj(out ho_GrayImage);HOperatorSet.GenEmptyObj(out ho_TriangleRegion);HOperatorSet.GenEmptyObj(out ho_Contour);HOperatorSet.GenEmptyObj(out ho_Segments);HOperatorSet.GenEmptyObj(out ho_Segment);ho_Image.Dispose();HOperatorSet.ReadImage(out ho_Image, imgpath);ho_GrayImage.Dispose();HOperatorSet.Rgb1ToGray(ho_Image, out ho_GrayImage);ho_TriangleRegion.Dispose();HOperatorSet.Threshold(ho_GrayImage, out ho_TriangleRegion, 0, 128);ho_Contour.Dispose();HOperatorSet.GenContourRegionXld(ho_TriangleRegion, out ho_Contour, "border");ho_Segments.Dispose();HOperatorSet.SegmentContoursXld(ho_Contour, out ho_Segments, "lines_circles",5, 4, 2);hv_NumSegments.Dispose();HOperatorSet.CountObj(ho_Segments, out hv_NumSegments);hv_Angles.Dispose();hv_Angles = new HTuple();for (hv_i = 1; (int)hv_i <= 3; hv_i = (int)hv_i + 1){ho_Segment.Dispose();HOperatorSet.SelectObj(ho_Segments, out ho_Segment, hv_i);hv_RowBegin.Dispose(); hv_ColBegin.Dispose(); hv_RowEnd.Dispose(); hv_ColEnd.Dispose(); hv__.Dispose(); hv___Tmp_Ctrl_0_5.Dispose(); hv___Tmp_Ctrl_0_6.Dispose();HOperatorSet.FitLineContourXld(ho_Segment, "tukey", -1, 0, 5, 2, out hv_RowBegin,out hv_ColBegin, out hv_RowEnd, out hv_ColEnd, out hv__, out hv___Tmp_Ctrl_0_5,out hv___Tmp_Ctrl_0_6);//存储线段端点if ((int)(new HTuple(hv_i.TupleEqual(1))) != 0){hv_Line1.Dispose();using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_Line1 = new HTuple();hv_Line1 = hv_Line1.TupleConcat(hv_RowBegin, hv_ColBegin, hv_RowEnd, hv_ColEnd);}}else if ((int)(new HTuple(hv_i.TupleEqual(2))) != 0){hv_Line2.Dispose();using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_Line2 = new HTuple();hv_Line2 = hv_Line2.TupleConcat(hv_RowBegin, hv_ColBegin, hv_RowEnd, hv_ColEnd);}}else{hv_Line3.Dispose();using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_Line3 = new HTuple();hv_Line3 = hv_Line3.TupleConcat(hv_RowBegin, hv_ColBegin, hv_RowEnd, hv_ColEnd);}}}using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_RowV1.Dispose(); hv_ColV1.Dispose(); hv_IsOverlapping1.Dispose();HOperatorSet.IntersectionLines(hv_Line1.TupleSelect(0), hv_Line1.TupleSelect(1), hv_Line1.TupleSelect(2), hv_Line1.TupleSelect(3), hv_Line2.TupleSelect(0), hv_Line2.TupleSelect(1), hv_Line2.TupleSelect(2), hv_Line2.TupleSelect(3), out hv_RowV1, out hv_ColV1, out hv_IsOverlapping1);}using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_RowV2.Dispose(); hv_ColV2.Dispose(); hv_IsOverlapping2.Dispose();HOperatorSet.IntersectionLines(hv_Line2.TupleSelect(0), hv_Line2.TupleSelect(1), hv_Line2.TupleSelect(2), hv_Line2.TupleSelect(3), hv_Line3.TupleSelect(0), hv_Line3.TupleSelect(1), hv_Line3.TupleSelect(2), hv_Line3.TupleSelect(3), out hv_RowV2, out hv_ColV2, out hv_IsOverlapping2);}using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_RowV3.Dispose(); hv_ColV3.Dispose(); hv_IsOverlapping3.Dispose();HOperatorSet.IntersectionLines(hv_Line3.TupleSelect(0), hv_Line3.TupleSelect(1), hv_Line3.TupleSelect(2), hv_Line3.TupleSelect(3), hv_Line1.TupleSelect(0), hv_Line1.TupleSelect(1), hv_Line1.TupleSelect(2), hv_Line1.TupleSelect(3), out hv_RowV3, out hv_ColV3, out hv_IsOverlapping3);}//1. 计算三条边的长度hv_AB.Dispose();HOperatorSet.DistancePp(hv_RowV1, hv_ColV1, hv_RowV2, hv_ColV2, out hv_AB);hv_AC.Dispose();HOperatorSet.DistancePp(hv_RowV1, hv_ColV1, hv_RowV3, hv_ColV3, out hv_AC);hv_BC.Dispose();HOperatorSet.DistancePp(hv_RowV2, hv_ColV2, hv_RowV3, hv_ColV3, out hv_BC);//2. 使用余弦定理计算角度//顶点A的角度 (对边BC)hv_cosAngleA.Dispose();using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_cosAngleA = (((hv_AC * hv_AC) + (hv_AB * hv_AB)) - (hv_BC * hv_BC)) / ((2 * hv_AC) * hv_AB);}hv_AngleA.Dispose();using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_AngleA = ((hv_cosAngleA.TupleAcos()) * 180) / 3.1415926535;}//顶点B的角度 (对边AC)hv_cosAngleB.Dispose();using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_cosAngleB = (((hv_AB * hv_AB) + (hv_BC * hv_BC)) - (hv_AC * hv_AC)) / ((2 * hv_AB) * hv_BC);}hv_AngleB.Dispose();using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_AngleB = ((hv_cosAngleB.TupleAcos()) * 180) / 3.1415926535;}//顶点C的角度 (对边AB)hv_cosAngleC.Dispose();using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_cosAngleC = (((hv_AC * hv_AC) + (hv_BC * hv_BC)) - (hv_AB * hv_AB)) / ((2 * hv_AC) * hv_BC);}hv_AngleC.Dispose();using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_AngleC = ((hv_cosAngleC.TupleAcos()) * 180) / 3.1415926535;}ho_Image.Dispose();ho_GrayImage.Dispose();ho_TriangleRegion.Dispose();ho_Contour.Dispose();ho_Segments.Dispose();ho_Segment.Dispose();hv_NumSegments.Dispose();hv_Angles.Dispose();hv_i.Dispose();hv_RowBegin.Dispose();hv_ColBegin.Dispose();hv_RowEnd.Dispose();hv_ColEnd.Dispose();hv__.Dispose();hv_Line1.Dispose();hv_Line2.Dispose();hv_Line3.Dispose();hv_RowV1.Dispose();hv_ColV1.Dispose();hv_IsOverlapping1.Dispose();hv_RowV2.Dispose();hv_ColV2.Dispose();hv_IsOverlapping2.Dispose();hv_RowV3.Dispose();hv_ColV3.Dispose();hv_IsOverlapping3.Dispose();hv_AB.Dispose();hv_AC.Dispose();hv_BC.Dispose();hv_cosAngleA.Dispose();hv_AngleA.Dispose();hv_cosAngleB.Dispose();hv_AngleB.Dispose();hv_cosAngleC.Dispose();hv_AngleC.Dispose();hv___Tmp_Ctrl_0_5.Dispose();hv___Tmp_Ctrl_0_6.Dispose();return new double[] { hv_AngleA,hv_AngleB,hv_AngleC };}}
}

主界面程序form1.cs

主界面代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using HalconDotNet;
namespace halcon_cs
{public partial class Form1 : Form{HObject TestImage;public Form1(){InitializeComponent();}private void button2_Click(object sender, EventArgs e){using (OpenFileDialog openFileDialog = new OpenFileDialog()){openFileDialog.Filter = "所有文件|*.*";openFileDialog.Title = "选择文件";if (openFileDialog.ShowDialog() == DialogResult.OK){string filePath = openFileDialog.FileName;textBox1.Text = filePath;}}}private void button1_Click(object sender, EventArgs e){//读取文件HOperatorSet.ReadImage(out TestImage, textBox1.Text);//获取图片大小HTuple Width, Height;HOperatorSet.GetImageSize(TestImage, out Width, out Height);//设置图片显示范围 hWindowControl1.HalconWindow获得窗体句柄HOperatorSet.SetPart(hWindowControl1.HalconWindow, 0, 0, (Height - 1), (Width - 1)); //0,0, (Height - 1), (Width - 1)代表从0,0坐标到图片的宽高坐标,达到全屏显示//将图片投射到窗体上HOperatorSet.DispObj(TestImage, hWindowControl1.HalconWindow);//将TestImage变量投射到句柄窗口上}private void button3_Click(object sender, EventArgs e){double[] result;HDevelopExport hDevelopExport = new HDevelopExport();result = hDevelopExport.action(textBox1.Text);foreach (double indexer in result) { textBox2.AppendText(indexer.ToString()+"\r\n");}}}
}

主界面设计:

using HalconDotNet;namespace halcon_cs
{partial class Form1{/// <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.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();this.button2 = new System.Windows.Forms.Button();this.textBox1 = new System.Windows.Forms.TextBox();this.hWindowControl1 = new HalconDotNet.HWindowControl();this.button1 = new System.Windows.Forms.Button();this.button3 = new System.Windows.Forms.Button();this.textBox2 = new System.Windows.Forms.TextBox();this.SuspendLayout();// // openFileDialog1// this.openFileDialog1.FileName = "openFileDialog1";// // button2// this.button2.Location = new System.Drawing.Point(779, 41);this.button2.Name = "button2";this.button2.Size = new System.Drawing.Size(116, 43);this.button2.TabIndex = 4;this.button2.Text = "选择文件";this.button2.UseVisualStyleBackColor = true;this.button2.Click += new System.EventHandler(this.button2_Click);// // textBox1// this.textBox1.Location = new System.Drawing.Point(314, 50);this.textBox1.Name = "textBox1";this.textBox1.Size = new System.Drawing.Size(459, 28);this.textBox1.TabIndex = 5;// // hWindowControl1// this.hWindowControl1.BackColor = System.Drawing.Color.Black;this.hWindowControl1.BorderColor = System.Drawing.Color.Black;this.hWindowControl1.ImagePart = new System.Drawing.Rectangle(0, 0, 640, 480);this.hWindowControl1.Location = new System.Drawing.Point(314, 110);this.hWindowControl1.Name = "hWindowControl1";this.hWindowControl1.Size = new System.Drawing.Size(555, 347);this.hWindowControl1.TabIndex = 6;this.hWindowControl1.WindowSize = new System.Drawing.Size(555, 347);// // button1// this.button1.Location = new System.Drawing.Point(229, 502);this.button1.Name = "button1";this.button1.Size = new System.Drawing.Size(177, 99);this.button1.TabIndex = 7;this.button1.Text = "显示图像";this.button1.UseVisualStyleBackColor = true;this.button1.Click += new System.EventHandler(this.button1_Click);// // button3// this.button3.Location = new System.Drawing.Point(722, 502);this.button3.Name = "button3";this.button3.Size = new System.Drawing.Size(183, 99);this.button3.TabIndex = 8;this.button3.Text = "计算角度";this.button3.UseVisualStyleBackColor = true;this.button3.Click += new System.EventHandler(this.button3_Click);// // textBox2// this.textBox2.Location = new System.Drawing.Point(280, 659);this.textBox2.Multiline = true;this.textBox2.Name = "textBox2";this.textBox2.Size = new System.Drawing.Size(588, 112);this.textBox2.TabIndex = 9;// // Form1// this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F);this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;this.ClientSize = new System.Drawing.Size(1176, 821);this.Controls.Add(this.textBox2);this.Controls.Add(this.button3);this.Controls.Add(this.button1);this.Controls.Add(this.hWindowControl1);this.Controls.Add(this.textBox1);this.Controls.Add(this.button2);this.Name = "Form1";this.Text = "Form1";this.ResumeLayout(false);this.PerformLayout();}#endregionprivate System.Windows.Forms.OpenFileDialog openFileDialog1;private System.Windows.Forms.Button button2;private System.Windows.Forms.TextBox textBox1;private HWindowControl hWindowControl1;private System.Windows.Forms.Button button1;private System.Windows.Forms.Button button3;private System.Windows.Forms.TextBox textBox2;}
}

4.案例三:缺陷检测

如图

一个四边形,边上有2个缺陷。要求:检查出缺陷所在。

方法:先找到整体的轮廓,然后基于轮廓曲率的变化,来判断缺陷。

halcon代码:

read_image(Image, 'C:/Users/86957/Desktop/txqx.png')
rgb1_to_gray(Image, GrayImage)
get_image_size (Image, Width, Height)
dev_open_window (0, 0, Width, Height, 'black', WindowHandle)threshold(GrayImage, Regions, 0, 127)
select_shape (Regions, SelectedRegions, 'area', 'and', 'min', 99999)
* 提取边界('inner' 表示内边界,'outer' 表示外边界)
boundary(SelectedRegions, RegionBorder, 'inner')* 设置绿色轮廓
dev_set_color('green')
dev_set_line_width(3)
* 显示原始图像
dev_display(GrayImage)
* 仅显示绿色轮廓(不填充)
dev_display(RegionBorder)
*绿色轮廓是一个标准的四边形。* 将区域边界转换为XLD轮廓
gen_contour_region_xld(RegionBorder, Contour, 'border')* 获取轮廓点坐标
get_contour_xld(Contour, Rows, Cols)* 计算轮廓点的方向角度 (使用5点平滑)
get_contour_angle_xld (Contour, 'abs', 'range', 3, AngleValues)* 计算相邻点的角度变化
tuple_length(AngleValues, NumPoints)
DiffAngles := []
for i := 1 to NumPoints-1 by 1* 处理角度跳变(π到-π)diff := abs(AngleValues[i] - AngleValues[i-1])if (diff > rad(180))diff := rad(360) - diffendifDiffAngles := [DiffAngles, diff]
endfor* 找出角度突变点 (阈值设为30度)
Threshold := rad(30)
DefectRows := []
DefectCols := []
for i := 1 to NumPoints-1 by 1if (DiffAngles[i-1] > Threshold)DefectRows := [DefectRows, Rows[i]]DefectCols := [DefectCols, Cols[i]]endif
endfor* 标记缺陷点
if (|DefectRows| > 0)gen_cross_contour_xld(Cross, DefectRows, DefectCols, 12, 0.785398)dev_set_color('red')dev_set_line_width(2)dev_display(Cross)
endif* 捕获窗口内容
dump_window_image(ResultImage, WindowHandle)
*保存
*write_image(ResultImage, 'png', 0, 'C:/Users/86957/Desktop/result_image.png')
dev_close_window()

效果如下:

将halcon代码输出为c#,并修改输入输出。

返回HObject类型。
在返回前,关闭窗口,避免弹窗一直存在。


using HalconDotNet;
namespace halcon_cs
{public partial class HDevelopExport{public HObject action(string imgpath){// Local iconic variables HObject ho_Image, ho_GrayImage, ho_Regions;HObject ho_SelectedRegions, ho_RegionBorder, ho_Contour;HObject ho_Cross = null, ho_ResultImage;// Local control variables HTuple hv_Width = new HTuple(), hv_Height = new HTuple();HTuple hv_WindowHandle = new HTuple(), hv_Rows = new HTuple();HTuple hv_Cols = new HTuple(), hv_AngleValues = new HTuple();HTuple hv_NumPoints = new HTuple(), hv_DiffAngles = new HTuple();HTuple hv_i = new HTuple(), hv_diff = new HTuple(), hv_Threshold = new HTuple();HTuple hv_DefectRows = new HTuple(), hv_DefectCols = new HTuple();// Initialize local and output iconic variables HOperatorSet.GenEmptyObj(out ho_Image);HOperatorSet.GenEmptyObj(out ho_GrayImage);HOperatorSet.GenEmptyObj(out ho_Regions);HOperatorSet.GenEmptyObj(out ho_SelectedRegions);HOperatorSet.GenEmptyObj(out ho_RegionBorder);HOperatorSet.GenEmptyObj(out ho_Contour);HOperatorSet.GenEmptyObj(out ho_Cross);HOperatorSet.GenEmptyObj(out ho_ResultImage);ho_Image.Dispose();HOperatorSet.ReadImage(out ho_Image, imgpath);ho_GrayImage.Dispose();HOperatorSet.Rgb1ToGray(ho_Image, out ho_GrayImage);hv_Width.Dispose(); hv_Height.Dispose();HOperatorSet.GetImageSize(ho_Image, out hv_Width, out hv_Height);HOperatorSet.SetWindowAttr("background_color", "black");HOperatorSet.OpenWindow(0, 0, hv_Width, hv_Height, 0, "visible", "", out hv_WindowHandle);HDevWindowStack.Push(hv_WindowHandle);ho_Regions.Dispose();HOperatorSet.Threshold(ho_GrayImage, out ho_Regions, 0, 127);ho_SelectedRegions.Dispose();HOperatorSet.SelectShape(ho_Regions, out ho_SelectedRegions, "area", "and", "min",99999);//提取边界('inner' 表示内边界,'outer' 表示外边界)ho_RegionBorder.Dispose();HOperatorSet.Boundary(ho_SelectedRegions, out ho_RegionBorder, "inner");//设置绿色轮廓if (HDevWindowStack.IsOpen()){HOperatorSet.SetColor(HDevWindowStack.GetActive(), "green");}if (HDevWindowStack.IsOpen()){HOperatorSet.SetLineWidth(HDevWindowStack.GetActive(), 3);}//显示原始图像if (HDevWindowStack.IsOpen()){HOperatorSet.DispObj(ho_GrayImage, HDevWindowStack.GetActive());}//仅显示绿色轮廓(不填充)if (HDevWindowStack.IsOpen()){HOperatorSet.DispObj(ho_RegionBorder, HDevWindowStack.GetActive());}//绿色轮廓是一个标准的四边形。//将区域边界转换为XLD轮廓ho_Contour.Dispose();HOperatorSet.GenContourRegionXld(ho_RegionBorder, out ho_Contour, "border");//获取轮廓点坐标hv_Rows.Dispose(); hv_Cols.Dispose();HOperatorSet.GetContourXld(ho_Contour, out hv_Rows, out hv_Cols);//计算轮廓点的方向角度 (使用5点平滑)hv_AngleValues.Dispose();HOperatorSet.GetContourAngleXld(ho_Contour, "abs", "range", 3, out hv_AngleValues);//计算相邻点的角度变化hv_NumPoints.Dispose();HOperatorSet.TupleLength(hv_AngleValues, out hv_NumPoints);hv_DiffAngles.Dispose();hv_DiffAngles = new HTuple();HTuple end_val34 = hv_NumPoints - 1;HTuple step_val34 = 1;for (hv_i = 1; hv_i.Continue(end_val34, step_val34); hv_i = hv_i.TupleAdd(step_val34)){//处理角度跳变(π到-π)hv_diff.Dispose();using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_diff = (((hv_AngleValues.TupleSelect(hv_i)) - (hv_AngleValues.TupleSelect(hv_i - 1)))).TupleAbs();}if ((int)(new HTuple(hv_diff.TupleGreater((new HTuple(180)).TupleRad()))) != 0){using (HDevDisposeHelper dh = new HDevDisposeHelper()){{HTupleExpTmpLocalVar_diff = ((new HTuple(360)).TupleRad()) - hv_diff;hv_diff.Dispose();hv_diff = ExpTmpLocalVar_diff;}}}using (HDevDisposeHelper dh = new HDevDisposeHelper()){{HTupleExpTmpLocalVar_DiffAngles = hv_DiffAngles.TupleConcat(hv_diff);hv_DiffAngles.Dispose();hv_DiffAngles = ExpTmpLocalVar_DiffAngles;}}}//找出角度突变点 (阈值设为30度)hv_Threshold.Dispose();using (HDevDisposeHelper dh = new HDevDisposeHelper()){hv_Threshold = (new HTuple(30)).TupleRad();}hv_DefectRows.Dispose();hv_DefectRows = new HTuple();hv_DefectCols.Dispose();hv_DefectCols = new HTuple();HTuple end_val47 = hv_NumPoints - 1;HTuple step_val47 = 1;for (hv_i = 1; hv_i.Continue(end_val47, step_val47); hv_i = hv_i.TupleAdd(step_val47)){if ((int)(new HTuple(((hv_DiffAngles.TupleSelect(hv_i - 1))).TupleGreater(hv_Threshold))) != 0){using (HDevDisposeHelper dh = new HDevDisposeHelper()){{HTupleExpTmpLocalVar_DefectRows = hv_DefectRows.TupleConcat(hv_Rows.TupleSelect(hv_i));hv_DefectRows.Dispose();hv_DefectRows = ExpTmpLocalVar_DefectRows;}}using (HDevDisposeHelper dh = new HDevDisposeHelper()){{HTupleExpTmpLocalVar_DefectCols = hv_DefectCols.TupleConcat(hv_Cols.TupleSelect(hv_i));hv_DefectCols.Dispose();hv_DefectCols = ExpTmpLocalVar_DefectCols;}}}}//标记缺陷点if ((int)(new HTuple((new HTuple(hv_DefectRows.TupleLength())).TupleGreater(0))) != 0){ho_Cross.Dispose();HOperatorSet.GenCrossContourXld(out ho_Cross, hv_DefectRows, hv_DefectCols,12, 0.785398);if (HDevWindowStack.IsOpen()){HOperatorSet.SetColor(HDevWindowStack.GetActive(), "red");}if (HDevWindowStack.IsOpen()){HOperatorSet.SetLineWidth(HDevWindowStack.GetActive(), 2);}if (HDevWindowStack.IsOpen()){HOperatorSet.DispObj(ho_Cross, HDevWindowStack.GetActive());}}//捕获窗口内容ho_ResultImage.Dispose();HOperatorSet.DumpWindowImage(out ho_ResultImage, hv_WindowHandle);//保存//write_image (ResultImage, 'png', 0, 'C:/Users/86957/Desktop/result_image.png')HOperatorSet.CloseWindow(hv_WindowHandle);return ho_ResultImage;      }}
}

使用 HOperatorSet.CloseWindow(hv_WindowHandle);直接关闭弹窗。

主界面代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using HalconDotNet;
namespace halcon_cs
{public partial class Form1 : Form{HObject TestImage;public Form1(){InitializeComponent();}private void button2_Click(object sender, EventArgs e){using (OpenFileDialog openFileDialog = new OpenFileDialog()){openFileDialog.Filter = "所有文件|*.*";openFileDialog.Title = "选择文件";if (openFileDialog.ShowDialog() == DialogResult.OK){string filePath = openFileDialog.FileName;textBox1.Text = filePath;}}}private void button1_Click(object sender, EventArgs e){HDevelopExport hDevelopExport = new HDevelopExport();HObject result = hDevelopExport.action(textBox1.Text);//获取图片大小HTuple Width, Height;HOperatorSet.GetImageSize(result, out Width, out Height);//设置图片显示范围 hWindowControl1.HalconWindow获得窗体句柄HOperatorSet.SetPart(hWindowControl1.HalconWindow, 0, 0, (Height - 1), (Width - 1)); //0,0, (Height - 1), (Width - 1)代表从0,0坐标到图片的宽高坐标,达到全屏显示//将图片投射到窗体上HOperatorSet.DispObj(result, hWindowControl1.HalconWindow);}}
}

运行后:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

大数据云原生是什么

"云原生"&#xff08;Cloud Native&#xff09;指的是‌利用云计算原生优势&#xff08;弹性、按需服务、自动化、分布式等&#xff09;来设计、构建、部署和运行大数据应用和工作负载的方法论与技术体系‌。它不是简单地“把大数据平台搬到云上”&#xff0c;而是从…

Pytest项目_day16(yaml和parametrize结合)

查询手机号归属地 我们首先可以在YAML文件中定义测试数据 方式一&#xff0c;使用- 注意&#xff1a;当我们需要一次传入两个参数时&#xff0c;需要定义两层迭代&#xff0c;即两层列表不够直观&#xff0c;容易写错 输出的结果为&#xff1a; 然后我们可以将测试数据传入test…

【Nginx指南】从核心原理到生产实践

目录Nginx指南&#xff1a;从核心原理到生产实践引言&#xff1a;Nginx在现代架构中的核心地位一、Nginx核心能力与应用场景1.1 多场景适配的全能型中间件1.2 技术优势&#xff1a;Nginx成为行业标准的关键二、Nginx安装部署&#xff1a;源码编译与包管理方案2.1 源码编译&…

物体检测

目录 1 目标定位 2 地标检测 3 目标检测 4 在卷积网络上实现滑动窗口 5 边界框预测 6 交并比 7 非极大值抑制 8 锚框 9 YOLO算法 10 用u-net进行语义分割 11 转置卷积 12 u-net 结构灵感 1 目标定位 你已经对图片分类有所了解。例如通过这张图片可以识…

es7.x es的高亮与solr高亮查询的对比对比说明

一 solr&es高亮1.1 solr与es高亮功能解释说明&#xff1a;1)高亮配置&#xff1a;fragmentSize(1000) 设置片段长度numOfFragments(1) 指定返回的片段数量preTags() 和 postTags() 设置高亮标记2)字段处理差异&#xff1a;在 ES 中&#xff0c;使用 matchQuery 而非 termQ…

DSP音频算法工程师技能2

一、核心知识准备1. 算法原理3A算法&#xff08;AGC自动增益控制/AEC回声消除/ANS降噪&#xff09;&#xff1a;掌握AEC的NLMS/双讲检测原理&#xff0c;ANS的谱减法/维纳滤波&#xff0c;AGC的压缩曲线设计。熟悉Speex/WebRTC等开源实现。EQ音效&#xff1a;IIR/FIR滤波器设计…

第4章-04-用WebDriver页面元素操作

🏆作者简介,黑夜开发者,CSDN领军人物,全栈领域优质创作者✌,CSDN博客专家,阿里云社区专家博主,2023年CSDN全站百大博主。 🏆数年电商行业从业经验,历任核心研发工程师,项目技术负责人。 🏆本文已收录于专栏:Web爬虫入门与实战精讲,后续完整更新内容如下。 文章…

【计算机视觉与深度学习实战】04基于K-Means聚类的图像分割系统设计与实现

摘要 图像分割作为计算机视觉领域的基础任务,在目标检测、医学影像分析、自动驾驶等众多应用中发挥着关键作用。本文基于K-Means聚类算法设计并实现了一个完整的图像分割系统,该系统集成了多种颜色空间转换、自定义初始化策略、空间特征融合等先进技术。通过Python和Tkinter…

Android Studio常用知识总结

一、运行方式1.运行 (Run)当您选择“运行”时&#xff0c;Android Studio 会编译您的应用并将其安装到目标设备或模拟器上。这通常用于&#xff1a;快速部署: 您只想看看应用是否能正常启动并运行&#xff0c;或者进行一些基础的用户界面测试。性能测试: 在正常运行模式下测试应…

设计模式笔记_行为型_访问者模式

1. 访问者模式介绍访问者模式&#xff08;Visitor Pattern&#xff09;是一种行为型设计模式&#xff0c;它允许你在不改变对象结构的前提下&#xff0c;定义作用于这些对象的新操作。访问者模式将操作的逻辑从对象结构中分离出来&#xff0c;使得你可以在运行时动态地添加新的…

数学建模 14 中心对数比变换

用途&#xff1a;是处理成分数据的核心预处理方法&#xff0c;核心目标是解决成分数据的和为常数100% &#xff0c; 导致的维度冗余&#xff0c;非线性相关问题。使得数据满足传统的统计/建模方法&#xff1b;举例子&#xff1a;食品比例中 面粉(50%),糖(30%),水(20%)原理&…

【C语言强化训练16天】--从基础到进阶的蜕变之旅:Day7

&#x1f525;个人主页&#xff1a;草莓熊Lotso &#x1f3ac;作者简介&#xff1a;C研发方向学习者 &#x1f4d6;个人专栏&#xff1a; 《C语言》 《数据结构与算法》《C语言刷题集》《Leetcode刷题指南》 ⭐️人生格言&#xff1a;生活是默默的坚持&#xff0c;毅力是永久的…

污水处理行业的 “智能革命”:边缘计算网关如何重塑传统运维模式?

污水处理行业的 “智能革命”&#xff1a;边缘计算网关如何重塑传统运维模式&#xff1f;在污水处理这一关乎生态环境与可持续发展的关键领域&#xff0c;蓝蜂网关正凭借其先进技术与强大功能&#xff0c;发挥着无可替代的重要作用。作为工业级物联网解决方案的核心组件&#x…

ASP.NET Core 中的多租户 SaaS 应用程序

介绍随着软件即服务 (SaaS) 持续主导技术领域&#xff0c;构建能够高效地从单一代码库服务于多位客户&#xff08;租户&#xff09;的应用程序变得至关重要。ASP.NET Core 凭借其模块化和可扩展的架构&#xff0c;是实现多租户 SaaS 应用程序的强大框架。本文将指导您了解构建多…

JUC之CompletableFuture【中】

文章目录四、CompletableFuture基本使用4.1 默认线程池、无返回值4.2 默认线程池、有返回值4.3 自定义线程池、有返回值4.4 CompletableFuture 获取结果五、对结果进行处理5.1 方法说明5.2 示例5.3 thenApply vs thenApplyAsync5.3.1 核心区别: 执行线程不同5.3.2 thenApply: 同…

环境变量不生效?

目录 添加环境变量 解决不生效 不生效场景 解决办法 大家都知道Windows系统对于开发者来说并不友好&#xff0c;尤其是新手&#xff0c;当然这是相比于linux和MacOS相比&#xff0c;因为开发工具、项目脚本等环境配置要为复杂&#xff0c;注意事项也更多一些。而这篇文章将…

小迪安全v2023学习笔记(六十六讲)—— Java安全SQL注入SSTISPELXXE

文章目录前记WEB攻防——第六十六天Java安全&SPEL表达式&SSTI模板注入&XXE&JDBC&MyBatis注入环境搭建Hello-Java-SecJavaSecJava安全 - SQL注入-JDBC&MyBatisJDBC注入原理语句拼接预编译的错误使用JdbcTemplate正则过滤MyBatis注入原理Like注入Order B…

把 AI 变成「图书馆管理员」——基于检索增强的离线图书语音导航小盒子

标签&#xff1a;检索增强、语音导航、离线 LLM、RAG、ESP32-S3、低功耗、TTS、BLE ---- 1. 背景&#xff1a;读者找不到书的痛苦 高校图书馆每天 5000 人次&#xff0c;高频问题&#xff1a; • “《深度学习》在哪个书架&#xff1f;” • “有没有类似《三体》的科幻&…

架构思维:在AI时代为产品“减负”的终极武器——用结构化智慧破解数字化复杂困局

摘要 数字化产品的复杂度飙升已成为企业发展的核心瓶颈。本文基于架构思维的本质&#xff08;元素、连接、演进&#xff09;&#xff0c;结合5A架构体系&#xff08;业务/信息/应用/技术/治理架构&#xff09;&#xff0c;系统阐述如何通过分而治之、共性沉淀、AI赋能三大策略降…

黎阳之光:以数字之力,筑牢流域防洪“智慧防线”

当洪水来袭&#xff0c;每一分精准的预报、每一次及时的预警、每一轮科学的预演、每一套完善的预案&#xff0c;都可能关系到江河安澜与万家平安。在水利现代化建设的浪潮中&#xff0c;黎阳之光凭借数字孪生、视频孪生等核心技术&#xff0c;打造流域防洪“四预”管理平台&…