LuJiaYi/MainForm.cs
2024-08-17 18:00:59 +08:00

780 lines
28 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using OpenCvSharp;
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 GuideGraspSys;
using System.IO;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;
using OpenCvSharp.Extensions;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ProgressBar;
using Point = System.Drawing.Point;
using System.Data.SQLite;
using Google.Protobuf;
using System.Drawing.Imaging;
//using Microsoft.Data.Sqlite;
using HalconDotNet;
using System.Diagnostics;
using System.Data.SqlClient;
using Org.BouncyCastle.Ocsp;
using Google.Protobuf.WellKnownTypes;
//using System.Diagnostics.Metrics;
namespace WindowsFormsApp1
{
public partial class MainForm : Form
{
private MGSCameraDriver cam1;//
private WriteLog writeLog1;//主界面日志
private WriteLog writeLog2;//插入日志
string preproduct = "";
private int count = 0;//每种型号插入模板计数
string Resultpath = "D:\\Lujiayi\\Result";
string OKpath= "D:\\Lujiayi\\OKNG\\OK.png";
string NGpath = "D:\\Lujiayi\\OKNG\\NG.png";
string LablePath = "";
string cam1path = "D:\\Lujiayi\\cam1";
string cam2path = "D:\\Lujiayi\\cam2";
string cam3path = "D:\\Lujiayi\\cam3";
string cam4path = "D:\\Lujiayi\\cam4";
private bool isDrawing = false;
private Point startPoint;
private Rectangle rectangle;
SimboObjectDetection simboObjectDetection = new SimboObjectDetection();
private readonly List<CameraThread> _cameraThreads;
private readonly List<PictureBox> _imageDisplays;
Mat originalImage = new Mat();
public volatile int AllDsums = 0;
public volatile int NGDsums = 0;
public volatile int OKDsums = 0;
private CameraManager cameraManager;
public MainForm()
{
InitializeComponent();
writeLog1 = new WriteLog(richTextBox1);
writeLog2 = new WriteLog(richTextBox2);
cam1 = new MGSCameraDriver();
cameraManager = new CameraManager();
Control.CheckForIllegalCrossThreadCalls = false;
ShowData();
}
private void checkedListBox1_SelectedIndexChanged(object sender, EventArgs e)
{
}
// <summary>
/// 主窗口
/// </summary>
private void Form1_Load(object sender, EventArgs e)
{
x = this.Width;
y = this.Height;
SetTag(this);
string LablePathstr = "D:\\Lujiayi\\Yolov5\\class.txt";
string ModelPath = "D:\\Lujiayi\\Yolov5\\best.onnx";
if (File.Exists(LablePathstr) && File.Exists(ModelPath))
{
LablePath = LablePathstr;
}
else
{
MessageBox.Show("检测" + ModelPath + " " + LablePathstr + "模型有无");
return;
}
//初始化驱动
simboObjectDetection.Load(ModelPath, "CPU", "images", 640, 640);
}
private float x;//定义当前窗体的宽度
private float y;//定义当前窗体的高度
private void SetTag(Control control)
{
foreach (Control con in control.Controls)
{
con.Tag = con.Width + ";" + con.Height + ";" + con.Left + ";" + con.Top + ";" + con.Font.Size;
if (con.Controls.Count > 0)
{
SetTag(con);
}
}
}
private void SetControls(float newx, float newy, Control cons)
{
//遍历窗体中的控件,重新设置控件的值
foreach (Control con in cons.Controls)
{
//获取控件的Tag属性值并分割后存储字符串数组
if (con.Tag != null)
{
string[] mytag = con.Tag.ToString().Split(new char[] { ';' });
//根据窗体缩放的比例确定控件的值
con.Width = Convert.ToInt32(System.Convert.ToSingle(mytag[0]) * newx);//宽度
con.Height = Convert.ToInt32(System.Convert.ToSingle(mytag[1]) * newy);//高度
con.Left = Convert.ToInt32(System.Convert.ToSingle(mytag[2]) * newx);//左边距
con.Top = Convert.ToInt32(System.Convert.ToSingle(mytag[3]) * newy);//顶边距
Single currentSize = System.Convert.ToSingle(mytag[4]) * newy;//字体大小
con.Font = new Font(con.Font.Name, currentSize, con.Font.Style, con.Font.Unit);
if (con.Controls.Count > 0)
{
SetControls(newx, newy, con);
}
}
}
}
//private void Form1_Resize(object sender, EventArgs e)
//{
// float newx = (this.Width) / x;
// float newy = (this.Height) / y;
// SetControls(newx, newy, this);
//}
// <summary>
/// NG图片路径按钮
/// </summary>
private void checkBox1_CheckedChanged(object sender, EventArgs e)
{
}
private void MainForm_Resize(object sender, EventArgs e)
{
float newx = (this.Width) / x;
float newy = (this.Height) / y;
SetControls(newx, newy, this);
}
// <summary>
/// 拍摄照片按钮
/// </summary>
private void button5_Click(object sender, EventArgs e)
{
cam1.Snapshot();
writeLog2.LogAppendMsg("采集图像成功!");
}
public void OnCameraMatOutPut(DateTime dt, Mat cameraMat)
{
originalImage = cameraMat;
string fitImageFolder = "D:\\Lujiayi\\Module";
if (!Directory.Exists(fitImageFolder))
{
Directory.CreateDirectory(fitImageFolder);
}
// string nameCam = fitImageFolder + dt.Year.ToString() + dt.Month.ToString() + dt.Day.ToString() + dt.Hour.ToString() + dt.Minute.ToString() + dt.Millisecond.ToString() + "1.jpg";
//string nameCam = fitImageFolder + "111.jpg";
//cameraMat.ImWrite(nameCam);
userControl11._mat = cameraMat;
}
// <summary>
/// 启动相机(插入)
/// </summary>
private void button6_Click(object sender, EventArgs e)
{
cam1.Start("Cam2");
if (cam1.IfSuccess)
{
writeLog2.LogAppendMsg("相机1启动成功");
}
else { writeLog2.LogAppendMsg("相机1启动失败"); }
cam1.OnHImageOutput -= OnCameraMatOutPut;
cam1.OnHImageOutput += OnCameraMatOutPut;
}
// <summary>
/// 窗体关闭事件
/// </summary>
private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
DialogResult result = MessageBox.Show("你确定要关闭吗!", "提示信息", MessageBoxButtons.OKCancel, MessageBoxIcon.Information);
if (result == DialogResult.OK)
{
cam1.Stop();
e.Cancel = false; //点击OK
}
else
{
e.Cancel = true;
}
}
private void label11_Click(object sender, EventArgs e)
{
}
// <summary>
/// 保存模板
/// </summary>
private void button4_Click(object sender, EventArgs e)
{
string folderName = textBox7.Text;
// 构建完整的路径
string basePath = @"D:\Lujiayi\Module";
string fullPath = Path.Combine(basePath, folderName);
try
{
LuJiaYi xkword = new LuJiaYi
{
Product = textBox7.Text,
Num = int.TryParse(textBox9.Text, out int num) ? num : 0, // 转换文本框中的文本为整数
Distance = double.TryParse(textBox8.Text, out double distance) ? distance : 0.0, // 转换文本框中的文本为浮点数
Load = fullPath
};
// 设置 Hole 属性
if (checkBox1.CheckState == CheckState.Checked)
{
xkword.Hole = 0;
}
else if (checkBox1.CheckState == CheckState.Unchecked)
{
xkword.Hole = 1;
}
else
{
xkword.Hole = 1;
}
// 检查文件夹是否存在
if (!Directory.Exists(fullPath))
{
try
{
// 如果文件夹不存在,则创建它
Directory.CreateDirectory(fullPath);
writeLog2.LogAppendMsg($"文件夹 {fullPath} 已创建。");
}
catch (Exception ex)
{
// 捕获并显示异常
writeLog2.LogAppendMsg("创建文件夹错误!");
}
}
string Product = xkword.Product; // 从 xkword 获取 Product
if (!string.IsNullOrEmpty(Product) && num != 0 && distance != 0.0)
{
if (Product == preproduct)
{
count++;
}
else
{
count = 1;
preproduct = Product;
InsertData(xkword);
}
int count2 = CountPhotos(fullPath);
SaveCroppedImage(fullPath, count2); // 在绘制完成后保存裁剪区域
textBox10.Text=count.ToString();
writeLog2.LogAppendMsg("模板已保存至数据库!");
ShowData();
}
else
{
MessageBox.Show("插入的数据不能为NULL");
}
}
catch (Exception es)
{
MessageBox.Show(es.Message);
}
}
private void userControl11_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left)
{
if (isDrawing)
{
// 完成绘制矩形框
isDrawing = false;
}
else
{
// 开始绘制矩形框
isDrawing = true;
startPoint = e.Location;
}
}
}
private void userControl11_MouseMove(object sender, MouseEventArgs e)
{
if (isDrawing)
{
// 更新矩形框的大小
int width = e.X - startPoint.X;
int height = e.Y - startPoint.Y;
rectangle = new Rectangle(startPoint.X, startPoint.Y, width, height);
userControl11.Invalidate(); // 刷新控件以显示矩形框
}
}
private void userControl11_Paint(object sender, PaintEventArgs e)
{
if (rectangle != null && rectangle.Width > 0 && rectangle.Height > 0)
{
// 绘制矩形框
using (Pen pen = new Pen(Color.Red, 2))
{
e.Graphics.DrawRectangle(pen, rectangle);
}
}
}
private Bitmap MatToBitmap(Mat mat)
{
// 将 Mat 转换为 Bitmap
using (var stream = new MemoryStream(mat.ToBytes()))
{
return new Bitmap(stream);
}
}
private void SaveCroppedImage(string savePath, int count)
{
if (originalImage.Empty() || rectangle.Width <= 0 || rectangle.Height <= 0)
{
MessageBox.Show("原始图像为空或矩形框无效");
return;
}
// 将原始 Mat 图像转换为 Bitmap
Bitmap bitmap = MatToBitmap(originalImage);
// 确保矩形框在原始图像的范围内
Rectangle cropRect = new Rectangle(
(int)(rectangle.X * originalImage.Width / userControl11.Width),
(int)(rectangle.Y * originalImage.Height / userControl11.Height),
(int)(rectangle.Width * originalImage.Width / userControl11.Width),
(int)(rectangle.Height * originalImage.Height / userControl11.Height)
);
// 确保裁剪矩形在原始图像范围内
cropRect.Intersect(new Rectangle(0, 0, bitmap.Width, bitmap.Height));
if (cropRect.Width > 0 && cropRect.Height > 0)
{
using (Bitmap croppedImage = new Bitmap(cropRect.Width, cropRect.Height))
{
using (Graphics g = Graphics.FromImage(croppedImage))
{
g.DrawImage(bitmap, new Rectangle(0, 0, croppedImage.Width, croppedImage.Height),
cropRect, GraphicsUnit.Pixel);
}
// 确保保存路径存在
if (!Directory.Exists(savePath))
{
try
{
Directory.CreateDirectory(savePath);
}
catch (Exception ex)
{
MessageBox.Show($"创建文件夹时发生错误: {ex.Message}");
return;
}
}
int num = count + 1;
// 构建文件名和保存路径
string fileName = $"{num}.png";
string filePath = Path.Combine(savePath, fileName);
try
{
croppedImage.Save(filePath, ImageFormat.Png);
writeLog2.LogAppendMsg($"裁剪区域已保存到 {filePath}");
}
catch (Exception ex)
{
MessageBox.Show($"保存图像时发生错误: {ex.Message}");
}
}
}
}
private void groupBox7_Enter(object sender, EventArgs e)
{
}
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
public static int CountPhotos(string folderPath)
{
// 图片文件扩展名列表
string[] imageExtensions = { ".jpg", ".jpeg", ".png", ".bmp", ".gif" };
// 获取所有图片文件
var photoFiles = Directory.GetFiles(folderPath)
.Where(file => imageExtensions.Contains(Path.GetExtension(file).ToLower()))
.ToArray();
return photoFiles.Length;
}
private bool IsProductExists(string product)//用于型号是否已经插入到数据库中,避免数据重复插入导致信息更改
{
string query = "SELECT COUNT(*) FROM LuJiaYi WHERE Product = @Product";
string connectionString = "Data Source = D:\\Lujiayi\\DataBase\\JianZhenQi1.db;BinaryGUID=False;";
using (var connection = new SQLiteConnection(connectionString))
{
connection.Open();
using (var command = new SQLiteCommand(query, connection))
{
command.Parameters.AddWithValue("@Product", product);
int count = Convert.ToInt32(command.ExecuteScalar());
return count > 0;
}
}
}
public void InsertData(LuJiaYi xkWord)//插入模板数据到数据库中
{
if (IsProductExists(xkWord.Product))
{
writeLog2.LogAppendMsg("产品型号已在数据库中,请勿重复插入!");
return;
}
StringBuilder strSql = new StringBuilder();
strSql.Append("insert into LuJiaYi(");
strSql.Append("Product,Num,Distance,Hole,Load)");
strSql.Append(" values (");
strSql.Append("@Product,@Num,@Distance,@Hole,@Load)");
SQLiteParameter[] parameters = {
new SQLiteParameter("@Product", DbType.String),
new SQLiteParameter("@Num", DbType.String),
new SQLiteParameter("@Distance", DbType.String),
new SQLiteParameter("@Hole", DbType.String),
new SQLiteParameter("@Load",DbType.String) };
parameters[0].Value = xkWord.Product;
parameters[1].Value = xkWord.Num;
parameters[2].Value = xkWord.Distance;
parameters[3].Value = xkWord.Hole;
parameters[4].Value = xkWord.Load;
int iv = SQLiteHelper.ExecuteSql(strSql.ToString(), parameters);
if (iv == 1)
{
writeLog2.LogAppendMsg($"型号:{xkWord.Product}的相关信息已插入!");
}
}
public void ShowData()//展示数据库结果
{
string query = "SELECT * FROM LuJiaYi";
DataSet ds = SQLiteHelper.Query(query);
if (ds.Tables.Count == 0)
{
writeLog2.LogAppendMsg("没有找到相关数据!");
return;
}
// 获取DataTable
DataTable dt = ds.Tables[0];
// 创建列名映射表(示例映射)
Dictionary<string, string> columnMappings = new Dictionary<string, string>
{
{ "Product", "产品号" },
{ "Num", "金属圈数量" },
{ "Distance", "距离" },
{ "Hole", "孔" },
{ "Load", "路径" }
};
// 遍历DataTable的列并修改列名
foreach (DataColumn column in dt.Columns)
{
if (columnMappings.TryGetValue(column.ColumnName, out string newName))
{
column.ColumnName = newName;
}
}
// 绑定DataTable到DataGridView
dataGridView1.DataSource = dt;
dataGridView1.DefaultCellStyle.WrapMode = DataGridViewTriState.False;
dataGridView1.ColumnHeadersDefaultCellStyle.WrapMode = DataGridViewTriState.False;//列名不换行
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;//自适应填充
foreach (DataGridViewColumn column in dataGridView1.Columns)
{
column.DefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;//列内容居中
}
dataGridView1.ColumnHeadersDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCenter;//列名居中
}
private void tabPage2_Click(object sender, EventArgs e)
{
}
private void label6_Click(object sender, EventArgs e)
{
}
private void groupBox5_Enter(object sender, EventArgs e)
{
}
private void button1_Click_1(object sender, EventArgs e)
{
cameraManager.StartAllCameras();
SQLiteHelper.DataToComboBox(comboBox1, "LuJiaYi","Product");//数据库型号信息传入选框中
SQLiteHelper.DataToComboBox(comboBox2, "LuJiaYi", "Product");
}
private void button2_Click_1(object sender, EventArgs e)
{
textBox4.Text = comboBox1.SelectedItem.ToString();//产线1型号
textBox15.Text = comboBox1.SelectedItem.ToString();//产线2型号
textBox19.Text = comboBox2.SelectedItem.ToString();//产线3型号
textBox23.Text = comboBox2.SelectedItem.ToString();//产线4型号
cameraManager.takepic1();
cameraManager.takepic2();
cameraManager.takepic3();
cameraManager.takepic4();
}
public void TriggerCam()//触发相机拍照
{
}
public void AddRect(string ImgPath, string templatePath,PictureBox pictureBox1, PictureBox pictureBox2,System.Windows.Forms.TextBox textBox, System.Windows.Forms.TextBox Num, System.Windows.Forms.TextBox Hole, System.Windows.Forms.TextBox Distance)
{
string Type = textBox.Text;
MLRequest req = new MLRequest();
req.ResizeWidth = 640;
req.ResizeHeight = 640;
req.Score = 0.3f;
req.in_lable_path = LablePath;//标签路径
req.confThreshold = 0.3f;//模型置信度
req.iouThreshold = 0.4f;//检测IOU
req.out_node_name = "output0";
int countPhotos = CountPhotos(templatePath);
string SavePath = $"{templatePath}\\Result";
SaveCroppedImage(SavePath, countPhotos);
string ResPath = $"{SavePath}\\{countPhotos}.jpg";
req.currentMat = Cv2.ImRead(ImgPath);
MLResult mL = simboObjectDetection.RunInferenceFixed(req);
Rect rect = ProcessImg.ProcessImagesInFolder(templatePath, ImgPath, SavePath, ResPath);
string JsonStr = mL.JsonString;
Bitmap ResPic = new Bitmap(ResPath);
Bitmap OKPic = new Bitmap(OKpath);
Bitmap NGPic = new Bitmap(NGpath);
if (mL.ResultMap != null)
{
mL.ResultMap.Save(ResPath);
pictureBox1.Image = ResPic;
writeLog1.LogAppendMsg("模型运行成功!");
bool IsNot= ResultOut(rect, JsonStr,Type,Num,Hole,Distance);//结果
if (IsNot == true)
{
pictureBox2.Image = OKPic;
}
else
{
pictureBox2.Image = NGPic;
}
}
else
{
writeLog1.LogAppendMsg("模板或相机照片不存在!");
}
}
public bool ResultOut(Rect rect, string JsonStr,string Type, System.Windows.Forms.TextBox Num,System.Windows.Forms.TextBox Hole,System.Windows.Forms.TextBox Distance)
{
int MetalCount = SimboObjectDetection.LableCount(JsonStr, "Metal");//金属圈个数
int SQLMetal = SQLiteHelper.GetNum("LuJiaYi", "Product", Type, "Num");//数据库金属圈个数
Num.Text = MetalCount.ToString();
int ScrewholeCount = SimboObjectDetection.LableCount(JsonStr, "Screwhole");//螺丝孔个数
int SQLScrewhole = SQLiteHelper.GetNum("LuJiaYi", "Product", Type, "Hole");//数据库螺丝孔个数
Hole.Text = ScrewholeCount.ToString();
double DistanceCount = 0;
Distance.Text = DistanceCount.ToString();
double SQLDistance= SQLiteHelper.GetNum("LuJiaYi", "Product", Type, "Distance");//数据库距离
Rect DenseRect = SimboObjectDetection.RectMes(JsonStr, "Dense");
int Dense_Top = DenseRect.Y;
int Dense_Bottom=DenseRect.Y+DenseRect.Height;
int Template_Top=rect.Y;
int Template_Bottom=rect.Y+rect.Height;
// if dense_point_top_y < template_point_top_y:
// if template_point_top_y - dense_point_bottom_y > 100:
// cv2.putText(result_img, 'Shock absorbers:NG', (10, 100), font, 1, (0, 0, 255), 5, cv2.LINE_AA)
// else:
// cv2.putText(result_img, 'Shock absorbers:OK', (10, 100), font, 1, (0, 255, 0), 5, cv2.LINE_AA)
//elif dense_point_top_y > template_point_top_y:
// if dense_point_top_y - template_point_bottom_y > 100:
// cv2.putText(result_img, 'Shock absorbers:NG', (10, 100), font, 1, (0, 0, 255), 5, cv2.LINE_AA)
// else:
// cv2.putText(result_img, 'Shock absorbers:OK', (10, 100), font, 1, (0, 255, 0), 5, cv2.LINE_AA)
if (MetalCount== SQLMetal&& ScrewholeCount== SQLScrewhole&& DistanceCount==SQLDistance)
{
return true;
}
else
{
return false;
}
}
public void AddRectTest( )//YOLO标框测试
{
string imagePath = "D:\\Lujiayi\\Yolov5\\test.jpg";
// 图像文件夹路径
string templatePath = "D:\\Lujiayi\\Yolov5\\test";
// 结果图像输出文件夹路径
string outputFolderPath = @"D:\Lujiayi\Yolov5";
string respic = "D:\\Lujiayi\\Cam1\\1.jpg";//框后结果
MLRequest req =new MLRequest();
req.ResizeWidth = 640;
req.ResizeHeight = 640;
req.Score = 0.3f;
req.in_lable_path = LablePath;//标签路径
req.confThreshold = 0.3f;//模型置信度
req.iouThreshold = 0.4f;//检测IOU
req.out_node_name = "output0";
req.currentMat = Cv2.ImRead(imagePath);
DateTime dt = DateTime.Now;
Stopwatch sw = new Stopwatch();
sw.Start();
MLResult mL = simboObjectDetection.RunInferenceFixed(req);//将模型训练后的框标出
//Rect rect = ProcessImg.ProcessImagesInFolder(templatePath, imagePath, outputFolderPath, respic);
sw.Stop();
//if (mL.ResultMap != null)
//{
// mL.ResultMap.Save(respic);
// pictureBox1.Image = mL.ResultMap;
// int MetalCount = SimboObjectDetection.LableCount(mL.JsonString, "Metal");//金属圈个数
// string Type1=textBox4.Text;
// int SQLMetal = SQLiteHelper.GetNum("LuJiaYi","Product", Type1, "Num");
// textBox5.Text = MetalCount.ToString();
// int ScrewholeCount = SimboObjectDetection.LableCount(mL.JsonString, "Screwhole");//螺丝孔个数
// textBox11.Text = ScrewholeCount.ToString();
// string numberAsString = SQLMetal.ToString();
// writeLog1.LogMessage(numberAsString);
// writeLog1.LogAppendMsg("模板匹配标识成功!" + sw.ElapsedMilliseconds);
//}
//else if (mL.ResultMap == null)//如果标框失败,结果返回原图
//{
// Mat res_yolo = Cv2.ImRead(NGpath);
// pictureBox1.Image = res_yolo.ToBitmap();
// writeLog1.LogAppendMsg("无法定位矩形框,图像为原图!");
//}
}
private void groupBox4_Enter(object sender, EventArgs e)
{
}
private void button3_Click(object sender, EventArgs e)
{
textBox4.Text = comboBox1.SelectedItem.ToString();//产线1型号
textBox15.Text = comboBox1.SelectedItem.ToString();//产线2型号
textBox19.Text = comboBox2.SelectedItem.ToString();//产线3型号
textBox23.Text = comboBox2.SelectedItem.ToString();//产线4型号
}
}
}