LuJiaYi/MainForm.cs

780 lines
28 KiB
C#
Raw Normal View History

2024-08-17 18:00:59 +08:00
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型号
}
}
}