From e89767d97656acfb77290a979e262ca7dea2375c Mon Sep 17 00:00:00 2001 From: "zhengxuan.zhang" Date: Sat, 14 Mar 2026 21:35:30 +0800 Subject: [PATCH] =?UTF-8?q?#0019=20=E4=BF=AE=E5=A4=8DProcessImageAsync=20?= =?UTF-8?q?=E8=B7=A8=E7=BA=BF=E7=A8=8B=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- XplorePlane/Services/ImageConverter.cs | 20 +++++++++++++++++++ .../Services/ImageProcessingService.cs | 6 +++++- .../ViewModels/ImageProcessingViewModel.cs | 1 - 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/XplorePlane/Services/ImageConverter.cs b/XplorePlane/Services/ImageConverter.cs index 1e22b09..416e1e1 100644 --- a/XplorePlane/Services/ImageConverter.cs +++ b/XplorePlane/Services/ImageConverter.cs @@ -10,6 +10,19 @@ namespace XplorePlane.Services { public static class ImageConverter { + public static byte[] ExtractGray8Pixels(BitmapSource bitmapSource, out int width, out int height) + { + if (bitmapSource == null) throw new ArgumentNullException(nameof(bitmapSource)); + + var formatted = new FormatConvertedBitmap(bitmapSource, PixelFormats.Gray8, null, 0); + width = formatted.PixelWidth; + height = formatted.PixelHeight; + int stride = width; + byte[] pixels = new byte[height * stride]; + formatted.CopyPixels(pixels, stride, 0); + return pixels; + } + public static Image ToEmguCV(BitmapSource bitmapSource) { if (bitmapSource == null) throw new ArgumentNullException(nameof(bitmapSource)); @@ -26,6 +39,13 @@ namespace XplorePlane.Services return image; } + public static Image ToEmguCVFromPixels(byte[] pixels, int width, int height) + { + var image = new Image(width, height); + image.Bytes = pixels; + return image; + } + public static BitmapSource ToBitmapSource(Image emguImage) { if (emguImage == null) throw new ArgumentNullException(nameof(emguImage)); diff --git a/XplorePlane/Services/ImageProcessingService.cs b/XplorePlane/Services/ImageProcessingService.cs index c7f2799..18bba8d 100644 --- a/XplorePlane/Services/ImageProcessingService.cs +++ b/XplorePlane/Services/ImageProcessingService.cs @@ -99,13 +99,16 @@ namespace XplorePlane.Services if (!_processorRegistry.TryGetValue(processorName, out var processor)) throw new ArgumentException($"Processor not registered: {processorName}", nameof(processorName)); + // Extract pixels on the UI thread (BitmapSource / FormatConvertedBitmap are DependencyObjects) + var rawPixels = ImageConverter.ExtractGray8Pixels(source, out int imgWidth, out int imgHeight); + return await Task.Run(() => { cancellationToken.ThrowIfCancellationRequested(); try { - var emguImage = ImageConverter.ToEmguCV(source); + var emguImage = ImageConverter.ToEmguCVFromPixels(rawPixels, imgWidth, imgHeight); if (parameters != null) { @@ -118,6 +121,7 @@ namespace XplorePlane.Services progress?.Report(0.9); var result = ImageConverter.ToBitmapSource(processedEmgu); + result.Freeze(); // must freeze before crossing thread boundary progress?.Report(1.0); return result; diff --git a/XplorePlane/ViewModels/ImageProcessingViewModel.cs b/XplorePlane/ViewModels/ImageProcessingViewModel.cs index 1a4078d..09722b8 100644 --- a/XplorePlane/ViewModels/ImageProcessingViewModel.cs +++ b/XplorePlane/ViewModels/ImageProcessingViewModel.cs @@ -111,7 +111,6 @@ namespace XplorePlane.ViewModels try { - SelectedProcessor = processorName; var parameters = _imageProcessingService.GetProcessorParameters(processorName); CurrentParameters.Clear(); foreach (var param in parameters)