From c1efddde74673a675ea66e108fd7d9ab06210b7c Mon Sep 17 00:00:00 2001 From: zqm Date: Fri, 9 Jan 2026 16:27:42 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=9D=E5=AD=98=E6=97=B6=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E8=A3=81=E5=88=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CS/Framework4.0/Toprie/Toprie/Setting.cs | 269 ++++++++++++++---- 1 file changed, 213 insertions(+), 56 deletions(-) diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/Setting.cs b/Windows/CS/Framework4.0/Toprie/Toprie/Setting.cs index 0d6115a..692378e 100644 --- a/Windows/CS/Framework4.0/Toprie/Toprie/Setting.cs +++ b/Windows/CS/Framework4.0/Toprie/Toprie/Setting.cs @@ -4101,13 +4101,13 @@ namespace JoyD.Windows.CS // 写入CSV文件头部(使用中文标题) writer.WriteLine("索引,X坐标,Y坐标,宽度,高度,颜色"); - // 遍历所有测温区,将信息写入CSV文件 - foreach (RegionInfo region in _drawnRectangles) + // 遍历所有原始测温区,将相对坐标信息写入CSV文件 + foreach (RegionInfo region in _originalTemperatureZones) { // 获取颜色的十六进制表示 string colorHex = ColorTranslator.ToHtml(region.Color); - // 写入一行数据,格式:索引,X坐标,Y坐标,宽度,高度,颜色 + // 写入一行数据,格式:索引,X坐标,Y坐标,宽度,高度,颜色(相对坐标) writer.WriteLine($"{region.Index},{region.ImageRectangle.X},{region.ImageRectangle.Y},{region.ImageRectangle.Width},{region.ImageRectangle.Height},{colorHex}"); } } @@ -4185,11 +4185,212 @@ namespace JoyD.Windows.CS /// /// 窗口关闭时停止定时器并释放资源 /// + /// + /// 检查所有测温区是否在检测区内 + /// + /// 所有测温区都在检测区内返回true,否则返回false + private bool CheckTemperatureZonesInDetectionZone() + { + // 创建检测区矩形 + Rectangle detectionRect = new Rectangle( + _detectionZone.X, + _detectionZone.Y, + _detectionZone.Width, + _detectionZone.Height + ); + + // 遍历所有测温区 + foreach (RegionInfo region in _drawnRectangles) + { + // 检查测温区是否完全包含在检测区内 + if (!detectionRect.Contains(region.ImageRectangle)) + { + return false; + } + } + + return true; + } + + /// + /// 检查温差图是否在检测区内 + /// + /// 温差图完全在检测区内返回true,否则返回false + private bool CheckTempDiffInDetectionZone() + { + // 如果没有温差图,直接返回true + if (_tempDiffOverlayImage == null || !(_tempDiffOverlayImage is Bitmap)) + { + return true; + } + + Bitmap bitmap = (Bitmap)_tempDiffOverlayImage; + // 创建检测区矩形 + Rectangle detectionRect = new Rectangle( + _detectionZone.X, + _detectionZone.Y, + _detectionZone.Width, + _detectionZone.Height + ); + + // 检查温差图中是否有超出检测区的像素 + for (int y = 0; y < bitmap.Height; y++) + { + for (int x = 0; x < bitmap.Width; x++) + { + Color pixelColor = bitmap.GetPixel(x, y); + if (pixelColor.A > 0) // 只检查非透明像素 + { + Point pixelPoint = new Point(x, y); + if (!detectionRect.Contains(pixelPoint)) + { + return false; + } + } + } + } + + return true; + } + + /// + /// 裁切测温区到检测区内 + /// + private void CropTemperatureZonesToDetectionZone() + { + // 创建检测区矩形 + Rectangle detectionRect = new Rectangle( + _detectionZone.X, + _detectionZone.Y, + _detectionZone.Width, + _detectionZone.Height + ); + + // 遍历所有测温区 + for (int i = _drawnRectangles.Count - 1; i >= 0; i--) + { + RegionInfo region = _drawnRectangles[i]; + + // 如果测温区完全在检测区内,跳过 + if (detectionRect.Contains(region.ImageRectangle)) + { + continue; + } + + // 计算两个矩形的交集,确保结果完全在检测区内 + Rectangle newRect = Rectangle.Intersect(region.ImageRectangle, detectionRect); + + // 如果裁切后矩形仍然有大小(最小2x2像素),更新测温区 + if (newRect.Width > 2 && newRect.Height > 2) + { + region.ImageRectangle = newRect; + } + else + { + // 如果裁切后矩形太小,移除该测温区 + _drawnRectangles.RemoveAt(i); + } + } + + // 同步列表 + SyncTemperatureZonesFromDrawnRectangles(); + + // 更新叠加层 + CreateRectangleOverlayImage(); + } + + /// + /// 裁切温差图到检测区内 + /// + private void CropTempDiffToDetectionZone() + { + // 如果没有温差图,直接返回 + if (_tempDiffOverlayImage == null || !(_tempDiffOverlayImage is Bitmap)) + { + return; + } + + Bitmap bitmap = (Bitmap)_tempDiffOverlayImage; + // 创建检测区矩形 + Rectangle detectionRect = new Rectangle( + _detectionZone.X, + _detectionZone.Y, + _detectionZone.Width, + _detectionZone.Height + ); + + // 创建新的位图用于保存裁切后的温差图 + Bitmap croppedBitmap = new Bitmap(bitmap.Width, bitmap.Height); + + // 将超出检测区的像素设置为透明 + for (int y = 0; y < bitmap.Height; y++) + { + for (int x = 0; x < bitmap.Width; x++) + { + Color pixelColor = bitmap.GetPixel(x, y); + if (pixelColor.A > 0) // 只处理非透明像素 + { + Point pixelPoint = new Point(x, y); + if (!detectionRect.Contains(pixelPoint)) + { + // 设置为透明 + croppedBitmap.SetPixel(x, y, Color.Transparent); + } + else + { + // 保留原颜色 + croppedBitmap.SetPixel(x, y, pixelColor); + } + } + } + } + + // 释放旧的温差图并替换为裁切后的 + _tempDiffOverlayImage.Dispose(); + _tempDiffOverlayImage = croppedBitmap; + } + private void Setting_FormClosing(object sender, FormClosingEventArgs e) { // 当自动配置为true时,保存回加载时的文件 if (_autoConfig && !string.IsNullOrEmpty(_projectPath)) { + bool hasOutOfBounds = false; + string message = ""; + + // 检查测温区 + if (!CheckTemperatureZonesInDetectionZone()) + { + hasOutOfBounds = true; + message += "部分测温区超出检测区范围,"; + } + + // 检查温差图 + if (!CheckTempDiffInDetectionZone()) + { + hasOutOfBounds = true; + message += "部分温差图超出检测区范围,"; + } + + // 如果有超出部分,提示用户 + if (hasOutOfBounds) + { + message += "是否自动裁切并保存?"; + DialogResult result = MessageBox.Show(message, "保存确认", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning); + + if (result == DialogResult.Cancel) + { + e.Cancel = true; // 取消关闭窗口 + return; + } + else + { + // 裁切超出部分 + CropTemperatureZonesToDetectionZone(); + CropTempDiffToDetectionZone(); + } + } + // 自动保存测温区配置 SaveTempRegionToDefaultPath(); // 自动保存温差图配置 @@ -5367,8 +5568,8 @@ namespace JoyD.Windows.CS writer.WriteLine("像素温度数据"); writer.WriteLine("X坐标,Y坐标,温度值(°C)"); - // 从_tempDiffOverlayImage中获取真实温度数据 - if (_tempDiffOverlayImage != null && _tempDiffOverlayImage is Bitmap) + // 使用原始温差图数据(相对坐标)保存 + if (_originalTempDiffData.Count > 0) { Bitmap bitmap = (Bitmap)_tempDiffOverlayImage; @@ -5480,59 +5681,15 @@ namespace JoyD.Windows.CS writer.WriteLine("像素温度数据"); writer.WriteLine("X坐标,Y坐标,温度值(°C)"); - // 从_tempDiffOverlayImage中获取真实温度数据 - if (_tempDiffOverlayImage != null && _tempDiffOverlayImage is Bitmap) + // 使用_originalTempDiffData保存相对坐标的温差数据 + if (_originalTempDiffData.Count > 0) { - Bitmap bitmap = (Bitmap)_tempDiffOverlayImage; - - // 锁定位图以提高性能 - BitmapData bitmapData = bitmap.LockBits( - new Rectangle(0, 0, bitmap.Width, bitmap.Height), - ImageLockMode.ReadOnly, - PixelFormat.Format32bppArgb); - - try + // 遍历原始温差数据字典,保存相对坐标的温差数据 + foreach (KeyValuePair pair in _originalTempDiffData) { - int bytesPerPixel = 4; // 32bppArgb格式每像素4字节 - int byteCount = bitmapData.Stride * bitmapData.Height; - byte[] pixels = new byte[byteCount]; - - // 将图像数据复制到数组 - Marshal.Copy(bitmapData.Scan0, pixels, 0, byteCount); - - // 保存所有非透明像素 - for (int y = 0; y < bitmap.Height; y++) - { - for (int x = 0; x < bitmap.Width; x++) - { - // 计算当前像素在数组中的位置 - int pixelIndex = y * bitmapData.Stride + x * bytesPerPixel; - - // 获取像素颜色 - byte b = pixels[pixelIndex]; - byte g = pixels[pixelIndex + 1]; - byte r = pixels[pixelIndex + 2]; - byte a = pixels[pixelIndex + 3]; - - // 只处理非透明的像素 - if (a > 0) - { - Color pixelColor = Color.FromArgb(a, r, g, b); - double? temperature = GetTemperatureByColor(pixelColor); - - // 如果找到对应的温度值,则写入文件 - if (temperature.HasValue) - { - writer.WriteLine($"{x},{y},{temperature.Value:F1}"); - } - } - } - } - } - finally - { - // 解锁位图 - bitmap.UnlockBits(bitmapData); + Point relativePoint = pair.Key; + double temperature = pair.Value; + writer.WriteLine($"{relativePoint.X},{relativePoint.Y},{temperature:F1}"); } } else