Browse Source

20251106002 添加了图像根据ROI进行切割的算法,使用LockBits的高性能方案。

向羽 孟 2 weeks ago
parent
commit
aa324af320

+ 90 - 0
MvvmScaffoldFrame48.DLL/ImageAlgorithm/ImageAlgorithmTools.cs

@@ -0,0 +1,90 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows.Media.Imaging;
+
+namespace MvvmScaffoldFrame48.DLL.ImageAlgorithm
+{
+    public static class ImageAlgorithmTools
+    {
+        public static Bitmap CropBitmap(Bitmap sourceBitmap, Rectangle roi)
+        {
+            // 检查边界
+            if (roi.X < 0 || roi.Y < 0 ||
+                roi.Right > sourceBitmap.Width ||
+                roi.Bottom > sourceBitmap.Height)
+            {
+                throw new ArgumentException("ROI区域超出源图像边界");
+            }
+
+            // 创建目标位图
+            Bitmap result = new Bitmap(roi.Width, roi.Height, sourceBitmap.PixelFormat);
+
+            // 锁定位图数据
+            BitmapData sourceData = sourceBitmap.LockBits(
+                new Rectangle(0, 0, sourceBitmap.Width, sourceBitmap.Height),
+                ImageLockMode.ReadOnly,
+                sourceBitmap.PixelFormat);
+
+            BitmapData resultData = result.LockBits(
+                new Rectangle(0, 0, result.Width, result.Height),
+                ImageLockMode.WriteOnly,
+                result.PixelFormat);
+
+            try
+            {
+                unsafe
+                {
+                    byte* sourcePtr = (byte*)sourceData.Scan0;
+                    byte* resultPtr = (byte*)resultData.Scan0;
+
+                    int pixelSize = Image.GetPixelFormatSize(sourceBitmap.PixelFormat) / 8;
+                    int sourceStride = sourceData.Stride;
+                    int resultStride = resultData.Stride;
+
+                    for (int y = 0; y < roi.Height; y++)
+                    {
+                        byte* srcRow = sourcePtr + (roi.Y + y) * sourceStride + roi.X * pixelSize;
+                        byte* dstRow = resultPtr + y * resultStride;
+
+                        // 复制一行像素数据
+                        for (int x = 0; x < roi.Width * pixelSize; x++)
+                        {
+                            dstRow[x] = srcRow[x];
+                        }
+                    }
+                }
+            }
+            finally
+            {
+                sourceBitmap.UnlockBits(sourceData);
+                result.UnlockBits(resultData);
+            }
+
+            return result;
+        }
+
+        // Bitmap 转 BitmapImage 的辅助方法
+        public static BitmapImage ConvertToBitmapImage(Bitmap bitmap)
+        {
+            using (MemoryStream memory = new MemoryStream())
+            {
+                bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Png);
+                memory.Position = 0;
+                var bitmapImage = new BitmapImage();
+                bitmapImage.BeginInit();
+                bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
+                bitmapImage.DecodePixelWidth = 1440; // 设置目标分辨率宽度
+                bitmapImage.DecodePixelHeight = 1080; // 保持宽高比
+                bitmapImage.StreamSource = memory;
+                bitmapImage.EndInit();
+                return bitmapImage;
+            }
+        }
+    }
+}

+ 7 - 0
MvvmScaffoldFrame48.DLL/MvvmScaffoldFrame48.Dll.csproj

@@ -22,6 +22,7 @@
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <PlatformTarget>x64</PlatformTarget>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <DebugType>pdbonly</DebugType>
@@ -30,6 +31,7 @@
     <DefineConstants>TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
     <DebugSymbols>true</DebugSymbols>
@@ -39,6 +41,7 @@
     <PlatformTarget>x64</PlatformTarget>
     <LangVersion>7.3</LangVersion>
     <ErrorReport>prompt</ErrorReport>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
     <OutputPath>bin\x64\Release\</OutputPath>
@@ -48,6 +51,7 @@
     <PlatformTarget>x64</PlatformTarget>
     <LangVersion>7.3</LangVersion>
     <ErrorReport>prompt</ErrorReport>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="MvCameraControl.Net, Version=4.5.0.2, Culture=neutral, PublicKeyToken=a3c7c5e3a730cd12, processorArchitecture=MSIL">
@@ -78,6 +82,7 @@
       <SpecificVersion>False</SpecificVersion>
       <HintPath>DLL\MvFGCtrlC.Net.dll</HintPath>
     </Reference>
+    <Reference Include="PresentationCore" />
     <Reference Include="System" />
     <Reference Include="System.Core" />
     <Reference Include="System.Drawing" />
@@ -87,6 +92,7 @@
     <Reference Include="System.Data" />
     <Reference Include="System.Net.Http" />
     <Reference Include="System.Xml" />
+    <Reference Include="WindowsBase" />
   </ItemGroup>
   <ItemGroup>
     <Compile Include="AlarmTools\AlarmMessageList.cs" />
@@ -101,6 +107,7 @@
     <Compile Include="ImageAlgorithm\BoundRectangleClass.cs" />
     <Compile Include="ImageAlgorithm\CPUDeepObjectDetectClass.cs" />
     <Compile Include="ImageAlgorithm\HikVisionAlgorithmRelated.cs" />
+    <Compile Include="ImageAlgorithm\ImageAlgorithmTools.cs" />
     <Compile Include="LogTools\TxtLog.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="UserManager.cs" />

+ 4 - 0
MvvmScaffoldFrame48.VIEWMODEL/MvvmScaffoldFrame48.ViewModel.csproj

@@ -22,6 +22,7 @@
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
     <PlatformTarget>x64</PlatformTarget>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
     <DebugType>pdbonly</DebugType>
@@ -30,6 +31,7 @@
     <DefineConstants>TRACE</DefineConstants>
     <ErrorReport>prompt</ErrorReport>
     <WarningLevel>4</WarningLevel>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
     <DebugSymbols>true</DebugSymbols>
@@ -39,6 +41,7 @@
     <PlatformTarget>x64</PlatformTarget>
     <LangVersion>7.3</LangVersion>
     <ErrorReport>prompt</ErrorReport>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
     <OutputPath>bin\x64\Release\</OutputPath>
@@ -48,6 +51,7 @@
     <PlatformTarget>x64</PlatformTarget>
     <LangVersion>7.3</LangVersion>
     <ErrorReport>prompt</ErrorReport>
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
   </PropertyGroup>
   <ItemGroup>
     <Reference Include="MVDCNNDetect.Net, Version=4.2.1.4, Culture=neutral, PublicKeyToken=f4e2bfa0ac20f5c4" />

+ 15 - 19
MvvmScaffoldFrame48.VIEWMODEL/ViewModel/DeepObjectDetectClass.cs

@@ -2,6 +2,7 @@
 using System;
 using System.Collections.Generic;
 using System.Drawing;
+using System.Drawing.Imaging;
 using System.IO;
 using System.Linq;
 using System.Text;
@@ -42,18 +43,27 @@ namespace MvvmScaffoldFrame48.ViewModel.ViewModel
         #region 绑定用Action方法
         public void Test(object obj)
         {
+            List<Bitmap> bitmaps = new List<Bitmap>();
             // 创建一个 Bitmap 对象
             Bitmap bitmap = new Bitmap("D:\\work\\MvvmScaffoldFrame48\\MvvmScaffoldFrame48\\MvvmScaffoldFrame48\\testfile\\testimage\\2025-08-04-13-28-45-807.jpg");
 
             cPUDeepObject.LoadImage(bitmap);
             cPUDeepObject.LoadDeepModel("D:\\work\\MvvmScaffoldFrame48\\MvvmScaffoldFrame48\\MvvmScaffoldFrame48\\testfile\\model\\Detect_20250818T1328175385.bin");
             var result = cPUDeepObject.RunDetect();
+            foreach (var item in result) 
+            {
+                if (item.LabelName == "A好药")
+                {
+                    continue;
+                }
+                Rectangle rectangle = new Rectangle(Convert.ToInt32(item.Box.CenterX - (item.Box.Width / 2)), Convert.ToInt32(item.Box.CenterY - (item.Box.Height / 2)), Convert.ToInt32(item.Box.Width), Convert.ToInt32(item.Box.Height));
+                bitmaps.Add(ImageAlgorithmTools.CropBitmap(bitmap, rectangle));
+            }
             PrintRectToBitmap(result, ref bitmap);
             // 将 Bitmap 转换为 BitmapImage
-            BitmapImage bitmapImage = ConvertToBitmapImage(bitmap);
+            BitmapImage bitmapImage = ImageAlgorithmTools.ConvertToBitmapImage(bitmap);
 
             ShowImage = bitmapImage;
-
         }
         #endregion
 
@@ -75,23 +85,7 @@ namespace MvvmScaffoldFrame48.ViewModel.ViewModel
             TestCommand = new RelayCommand(Test, CanTrue);
         }
 
-        // Bitmap 转 BitmapImage 的辅助方法
-        private BitmapImage ConvertToBitmapImage(Bitmap bitmap)
-        {
-            using (MemoryStream memory = new MemoryStream())
-            {
-                bitmap.Save(memory, System.Drawing.Imaging.ImageFormat.Png);
-                memory.Position = 0;
-                var bitmapImage = new BitmapImage();
-                bitmapImage.BeginInit();
-                bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
-                bitmapImage.DecodePixelWidth = 1440; // 设置目标分辨率宽度
-                bitmapImage.DecodePixelHeight = 1080; // 保持宽高比
-                bitmapImage.StreamSource = memory;
-                bitmapImage.EndInit();
-                return bitmapImage;
-            }
-        }
+
 
         public void PrintRectToBitmap(List<CNNDetectPredInfo> RectData , ref Bitmap bitmap)
         {
@@ -108,6 +102,8 @@ namespace MvvmScaffoldFrame48.ViewModel.ViewModel
                 }
             }
         }
+
+
         #endregion
     }
 }