From bf4bc32c5523a5d68de8fb45f23c512ad029fe4a Mon Sep 17 00:00:00 2001 From: OLDREDSTONE Date: Mon, 20 Oct 2025 07:39:42 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=A1=B9=E7=9B=AE=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DigitalImageProcessing.sln | 25 ++++++++ .../DigitalImageProcessing.csproj | 15 +++++ DigitalImageProcessing/Extensions.cs | 33 ++++++++++ DigitalImageProcessing/Program.cs | 61 +++++++++++++++++++ 4 files changed, 134 insertions(+) create mode 100644 DigitalImageProcessing.sln create mode 100644 DigitalImageProcessing/DigitalImageProcessing.csproj create mode 100644 DigitalImageProcessing/Extensions.cs create mode 100644 DigitalImageProcessing/Program.cs diff --git a/DigitalImageProcessing.sln b/DigitalImageProcessing.sln new file mode 100644 index 0000000..81bf366 --- /dev/null +++ b/DigitalImageProcessing.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.14.36408.4 d17.14 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DigitalImageProcessing", "DigitalImageProcessing\DigitalImageProcessing.csproj", "{CC16DC64-4AF5-4AA5-83CF-EC6C2C137450}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {CC16DC64-4AF5-4AA5-83CF-EC6C2C137450}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CC16DC64-4AF5-4AA5-83CF-EC6C2C137450}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CC16DC64-4AF5-4AA5-83CF-EC6C2C137450}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CC16DC64-4AF5-4AA5-83CF-EC6C2C137450}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {97DBED84-8E20-4363-B6B9-E5D9CBA483FB} + EndGlobalSection +EndGlobal diff --git a/DigitalImageProcessing/DigitalImageProcessing.csproj b/DigitalImageProcessing/DigitalImageProcessing.csproj new file mode 100644 index 0000000..5a6df2e --- /dev/null +++ b/DigitalImageProcessing/DigitalImageProcessing.csproj @@ -0,0 +1,15 @@ + + + + Exe + net8.0 + enable + enable + + + + + + + + diff --git a/DigitalImageProcessing/Extensions.cs b/DigitalImageProcessing/Extensions.cs new file mode 100644 index 0000000..1feacd6 --- /dev/null +++ b/DigitalImageProcessing/Extensions.cs @@ -0,0 +1,33 @@ +using SkiaSharp; + +namespace DigitalImageProcessing +{ + internal static class Extensions + { + public static void DrawTo(this float[,] values, string filename) + { + int width = values.GetLength(0); + int height = values.GetLength(1); + float min = float.MaxValue; + float max = float.MinValue; + for (int y = 0; y < height; y++) + for (int x = 0; x < width; x++) + { + if (values[x, y] < min) min = values[x, y]; + if (values[x, y] > max) max = values[x, y]; + } + using SKBitmap output = new(width, height); + using FileStream fs = new(filename, FileMode.Create, FileAccess.Write); + for (int y = 0; y < height; y++) + for (int x = 0; x < width; x++) + { + float color = (values[x, y] - min) / (max - min); + output.SetPixel(x, y, new SKColor( + (byte)(color * 128 + 128), + (byte)(color * 128 + 128), + (byte)(color * 128 + 128))); + } + output.Encode(fs, SKEncodedImageFormat.Png, 100); + } + } +} diff --git a/DigitalImageProcessing/Program.cs b/DigitalImageProcessing/Program.cs new file mode 100644 index 0000000..acba414 --- /dev/null +++ b/DigitalImageProcessing/Program.cs @@ -0,0 +1,61 @@ +using DigitalImageProcessing; +using SkiaSharp; + +string filename = @"E:\Download\a7522809e76767bec27db9650365c56a.jpeg"; + +int blockSize = 16; + +using SKBitmap bitmap = SKBitmap.Decode(filename); +using SKCanvas canvas = new(bitmap); + +using SKBitmap avgGraph = new(bitmap.Width, bitmap.Height); +using SKCanvas avgCanvas = new(avgGraph); + +float[,] gray = new float[bitmap.Width, bitmap.Height]; +float[,] xgradient = new float[bitmap.Width, bitmap.Height]; +float[,] ygradient = new float[bitmap.Width, bitmap.Height]; +float[,] fequency = new float[bitmap.Width, bitmap.Height]; +float[,] angle = new float[bitmap.Width, bitmap.Height]; +//float[,] direction = new float[bitmap.Width, bitmap.Height]; + +for (int y = 0; y < bitmap.Height; y++) + for (int x = 0; x < bitmap.Width; x++) + { + SKColor color = bitmap.GetPixel(x, y); + + // gray + gray[x, y] = (color.Red + color.Green + color.Blue) / 3f / 256f; + } + +for (int y = 0; y < bitmap.Height; y++) + for (int x = 0; x < bitmap.Width; x++) + { + // gradient + if (x > 0 && x < bitmap.Width - 1) + xgradient[x, y] = (gray[x + 1, y] - gray[x - 1, y]) / 2f; + if (y > 0 && y < bitmap.Height - 1) + ygradient[x, y] = (gray[x, y + 1] - gray[x, y - 1]) / 2f; + fequency[x, y] = float.Sqrt(xgradient[x, y] * xgradient[x, y] + ygradient[x, y] * ygradient[x, y]); + if (fequency[x, y] == 0) + continue; + angle[x, y] = float.Atan2(ygradient[x, y], xgradient[x, y]); + int blockx = x / blockSize; + int blocky = y / blockSize; + float dirx = float.Cos(angle[x, y]); + float diry = float.Sin(angle[x, y]); + avgCanvas.DrawLine( + (blockx + 0.5f - diry / 2) * blockSize, + (blocky + 0.5f - -dirx / 2) * blockSize, + (blockx + 0.5f + diry / 2) * blockSize, + (blocky + 0.5f + -dirx / 2) * blockSize, + new SKPaint { Color = SKColors.Red.WithAlpha((byte)(fequency[x, y] * 64)), StrokeWidth = 1 }); + } + +using FileStream fs = new(@"E:\Download\avgGraph.png", FileMode.Create, FileAccess.Write); +avgGraph.Encode(fs, SKEncodedImageFormat.Png, 100); + +xgradient.DrawTo(@"E:\Download\xgradient.png"); +ygradient.DrawTo(@"E:\Download\ygradient.png"); +fequency.DrawTo(@"E:\Download\fequency.png"); +angle.DrawTo(@"E:\Download\angle.png"); +