From 6fa9d80f6f517fb97cd11f3158262070b52bbf8c Mon Sep 17 00:00:00 2001 From: pinb Date: Mon, 27 Nov 2023 15:01:42 +0900 Subject: [PATCH] update --- BlazorApp/Pages/OpenCvSharpSample.razor | 355 +++++++++++++++--------- 1 file changed, 229 insertions(+), 126 deletions(-) diff --git a/BlazorApp/Pages/OpenCvSharpSample.razor b/BlazorApp/Pages/OpenCvSharpSample.razor index 900bbfd..c548bb7 100644 --- a/BlazorApp/Pages/OpenCvSharpSample.razor +++ b/BlazorApp/Pages/OpenCvSharpSample.razor @@ -19,8 +19,8 @@ gaborfilter



함수 원형

-
-        
+    
+    
   cv::Mat cv::getGaborKernel(cv::Size ksize, double sigma, double theta, double lambd, double gamma, double psi = CV_PI*0.5, int ktype = CV_64F)  
         
     

@@ -84,12 +84,12 @@
- - Your browser does not support the HTML5 canvas tag. - - - Your browser does not support the HTML5 canvas tag. - + + Your browser does not support the HTML5 canvas tag. + + + Your browser does not support the HTML5 canvas tag. +

Threshold (0 ~ 255)

@@ -102,8 +102,10 @@ @code { - private Mat? srcMat; - private Mat? srcMat2; + //private Mat? srcMat; + //private Mat? srcMat2; + private byte[] imageBytes_rgba = new byte[256 * 256 * 4]; + private byte[] imageBytes_rgba2 = new byte[256 * 256 * 4]; private ElementReference srcCanvas; private ElementReference dstCanvas; private ElementReference srcCanvas2; @@ -122,12 +124,12 @@ public void Dispose() { - srcMat?.Dispose(); - srcMat2?.Dispose(); + //srcMat?.Dispose(); + //srcMat2?.Dispose(); } protected override async Task OnInitializedAsync() - { + { await base.OnInitializedAsync(); } @@ -136,55 +138,120 @@ if (!firstRender) return; await base.OnAfterRenderAsync(firstRender); + int width = 256; + int height = 256; var imageBytes = await httpClient.GetByteArrayAsync("/images/mandrill.bmp"); - srcMat ??= Mat.FromImageData(imageBytes); - if(srcMat.Width < 256 || srcMat.Height < 256) - { - Cv2.PyrUp(srcMat, srcMat, new Size(256, 256)); - } + //srcMat ??= Mat.FromImageData(imageBytes); + //if(srcMat.Width < 256 || srcMat.Height < 256) + //{ + // Cv2.PyrUp(srcMat, srcMat, new Size(256, 256)); + //} srcCanvasClient ??= new CanvasClient(jsRuntime, srcCanvas); dstCanvasClient ??= new CanvasClient(jsRuntime, dstCanvas); - await srcCanvasClient.DrawMatAsync(srcMat); - + //await srcCanvasClient.DrawMatAsync(srcMat); - var imageBytes2 = await httpClient.GetByteArrayAsync("/images/lenna.bmp"); - srcMat2 ??= Mat.FromImageData(imageBytes2); - if(srcMat2.Width > 256 || srcMat2.Height > 256) + unsafe { - Cv2.PyrDown(srcMat2, srcMat2, new Size(256, 256)); + fixed (byte* pImageByte = imageBytes, pImageBytes_rgba = imageBytes_rgba) + { + var pRgb = pImageByte; + var pRgba = pImageBytes_rgba; + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + // RGB 채널 복사 + *(pRgba++) = *(pRgb++); // R + *(pRgba++) = *(pRgb++); // G + *(pRgba++) = *(pRgb++); // B + + // 알파 채널 추가 + *(pRgba++) = 255; // A + } + } + } } + imageBytes_rgba = FlipVertical(imageBytes_rgba, width, height); + ConvertBgrToRgba(imageBytes_rgba); + + await srcCanvasClient.DrawPixelsAsync(imageBytes_rgba); + + + var imageBytes2 = await httpClient.GetByteArrayAsync("/images/lenna256.bmp"); + //srcMat2 ??= Mat.FromImageData(imageBytes2); + //if(srcMat2.Width > 256 || srcMat2.Height > 256) + //{ + // Cv2.PyrDown(srcMat2, srcMat2, new Size(256, 256)); + //} srcCanvasClient2 ??= new CanvasClient(jsRuntime, srcCanvas2); dstCanvasClient2 ??= new CanvasClient(jsRuntime, dstCanvas2); - await srcCanvasClient2.DrawMatAsync(srcMat2); + //await srcCanvasClient2.DrawMatAsync(srcMat2); + + unsafe + { + fixed (byte* pImageByte = imageBytes2, pImageBytes_rgba = imageBytes_rgba2) + { + var pRgb = pImageByte; + var pRgba = pImageBytes_rgba; + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < width; x++) + { + // RGB 채널 복사 + *(pRgba++) = *(pRgb++); // R + *(pRgba++) = *(pRgb++); // G + *(pRgba++) = *(pRgb++); // B + + // 알파 채널 추가 + *(pRgba++) = 255; // A + } + } + } + } + imageBytes_rgba2 = FlipVertical(imageBytes_rgba2, width, height); + ConvertBgrToRgba(imageBytes_rgba2); + + //await srcCanvasClient2.DrawPixelsAsync(imageBytes2); + await srcCanvasClient2.DrawPixelsAsync(imageBytes_rgba2); } private async Task Grayscale() { - if (srcMat is null) - throw new InvalidOperationException($"{nameof(srcMat)} is null"); - if (dstCanvasClient is null) - throw new InvalidOperationException($"{nameof(dstCanvasClient)} is null"); + //if (srcMat is null) + // throw new InvalidOperationException($"{nameof(srcMat)} is null"); + //if (dstCanvasClient is null) + // throw new InvalidOperationException($"{nameof(dstCanvasClient)} is null"); - using var grayMat = new Mat(); - Cv2.CvtColor(srcMat, grayMat, ColorConversionCodes.BGR2GRAY); + //using var grayMat = new Mat(); + //Cv2.CvtColor(srcMat, grayMat, ColorConversionCodes.BGR2GRAY); + + byte[] gray = new byte[imageBytes_rgba.Length]; + imageBytes_rgba.CopyTo(gray, 0); + + ConvertRgbaToGray(gray); - await dstCanvasClient.DrawMatAsync(grayMat); + //await dstCanvasClient.DrawMatAsync(grayMat); + await dstCanvasClient.DrawPixelsAsync(gray); } private async Task PseudoColor() { - if (srcMat is null) - throw new InvalidOperationException($"{nameof(srcMat)} is null"); - if (dstCanvasClient is null) - throw new InvalidOperationException($"{nameof(dstCanvasClient)} is null"); + //if (srcMat is null) + // throw new InvalidOperationException($"{nameof(srcMat)} is null"); + //if (dstCanvasClient is null) + // throw new InvalidOperationException($"{nameof(dstCanvasClient)} is null"); + Mat srcMat = new Mat(256, 256, MatType.CV_8UC4, imageBytes_rgba); using var grayMat = new Mat(); using var dstMat = new Mat(); Cv2.CvtColor(srcMat, grayMat, ColorConversionCodes.BGR2GRAY); + //Cv2.CvtColor(srcMat, grayMat, ColorConversionCodes.BGR2GRAY); Cv2.ApplyColorMap(grayMat, dstMat, ColormapTypes.Jet); await dstCanvasClient.DrawMatAsync(dstMat); @@ -192,62 +259,76 @@ private async Task Threshold() { - if (srcMat is null) - throw new InvalidOperationException($"{nameof(srcMat)} is null"); - if (dstCanvasClient is null) - throw new InvalidOperationException($"{nameof(dstCanvasClient)} is null"); - - using var grayMat = new Mat(); - using var dstMat = new Mat(srcMat.Size(), MatType.CV_8UC1); - Cv2.CvtColor(srcMat, grayMat, ColorConversionCodes.BGR2GRAY); - //Cv2.Threshold(grayMat, dstMat, 127, 255, ThresholdTypes.Binary); - - for(int i=0; i(i, j); - byte newValue = (Convert.ToInt32(pixelValue) > valthreshold) ? (byte)255 : (byte)0; - dstMat.Set(i, j, newValue); - } - } - - await dstCanvasClient.DrawMatAsync(dstMat); + //if (srcMat is null) + // throw new InvalidOperationException($"{nameof(srcMat)} is null"); + //if (dstCanvasClient is null) + // throw new InvalidOperationException($"{nameof(dstCanvasClient)} is null"); + // + //using var grayMat = new Mat(); + //using var dstMat = new Mat(srcMat.Size(), MatType.CV_8UC1); + //Cv2.CvtColor(srcMat, grayMat, ColorConversionCodes.BGR2GRAY); + ////Cv2.Threshold(grayMat, dstMat, 127, 255, ThresholdTypes.Binary); + // + //for (int i = 0; i < grayMat.Rows; i++) + //{ + // for (int j = 0; j < grayMat.Cols; j++) + // { + // byte pixelValue = grayMat.At(i, j); + // byte newValue = (Convert.ToInt32(pixelValue) > valthreshold) ? (byte)255 : (byte)0; + // dstMat.Set(i, j, newValue); + // } + //} + // + //await dstCanvasClient.DrawMatAsync(dstMat); + + byte[] th = new byte[imageBytes_rgba.Length]; + imageBytes_rgba.CopyTo(th, 0); + + ConvertRgbaToGray(th); + Threshold(th, valthreshold); + + await dstCanvasClient.DrawPixelsAsync(th); } private async Task GaborFilter() { - if (srcMat2 is null) - throw new InvalidOperationException($"{nameof(srcMat2)} is null"); - if (dstCanvasClient2 is null) - throw new InvalidOperationException($"{nameof(dstCanvasClient2)} is null"); - - using var grayMat = new Mat(srcMat2.Size(), MatType.CV_32F); - Cv2.CvtColor(srcMat2, grayMat, ColorConversionCodes.BGR2GRAY); - + //if (srcMat2 is null) + // throw new InvalidOperationException($"{nameof(srcMat2)} is null"); + //if (dstCanvasClient2 is null) + // throw new InvalidOperationException($"{nameof(dstCanvasClient2)} is null"); + // + //using var grayMat = new Mat(srcMat2.Size(), MatType.CV_32F); + //Cv2.CvtColor(srcMat2, grayMat, ColorConversionCodes.BGR2GRAY); + // int kernel_size = valKernelSize; double sigma = valSigma; double theta = valTheta * Cv2.PI / 180.0; double lambd = valLambd; double gamma = valGamma; double psi = valPsi * Cv2.PI / 180.0; - - - Mat rst = new Mat(); - try - { - //Mat gabor_filter = Cv2.GetGaborKernel(new Size(kernel_size, kernel_size), sigma, theta, lambd, gamma, psi, ktype); - //Mat kenel = new Mat(5, 5, MatType.CV_8UC1); - //Cv2.Filter2D(grayMat, rst, grayMat.Type(), kenel); - - Mat gabor_filter = Gabor2DFilter.CreateGaborKernel(kernel_size, sigma, theta, lambd, gamma, psi); - rst = Gabor2DFilter.Filter2D(grayMat, gabor_filter); - } - catch(Exception e) - { - String log = e.Message; - } - await dstCanvasClient2.DrawMatAsync(rst); + // + // + //Mat rst = new Mat(); + //try + //{ + // //Mat gabor_filter = Cv2.GetGaborKernel(new Size(kernel_size, kernel_size), sigma, theta, lambd, gamma, psi, ktype); + // //Mat kenel = new Mat(5, 5, MatType.CV_8UC1); + // //Cv2.Filter2D(grayMat, rst, grayMat.Type(), kenel); + // + // Mat gabor_filter = Gabor2DFilter.CreateGaborKernel(kernel_size, sigma, theta, lambd, gamma, psi); + // rst = Gabor2DFilter.Filter2D(grayMat, gabor_filter); + //} + //catch (Exception e) + //{ + // String log = e.Message; + //} + //await dstCanvasClient2.DrawMatAsync(rst); + + Mat srcMat = new Mat(256, 256, MatType.CV_8UC4, imageBytes_rgba2); + Cv2.CvtColor(srcMat, srcMat, ColorConversionCodes.BGRA2GRAY); + Mat gaborfilter = Gabor2DFilter.CreateGaborKernel(kernel_size, sigma, theta, lambd, gamma, psi); + Mat rstMat = Gabor2DFilter.Filter2D(srcMat, gaborfilter); + await dstCanvasClient2.DrawMatAsync(rstMat); } public class Gabor2DFilter @@ -255,21 +336,10 @@ public static Mat CreateGaborKernel(int ksize, double sigma, double theta, double lambd, double gamma, double psi) { int center = ksize / 2; - Mat kernel = new Mat(ksize, ksize, MatType.CV_32F); + Mat kernel = new Mat(ksize, ksize, MatType.CV_32FC1); double sigmaX = sigma; double sigmaY = sigma / gamma; - //for (int y = -center; y <= center; y++) - //{ - // for (int x = -center; x <= center; x++) - // { - // double xPrime = x * Math.Cos(theta) + y * Math.Sin(theta); - // double yPrime = -x * Math.Sin(theta) + y * Math.Cos(theta); - // double value = Math.Exp(-0.5 * (xPrime * xPrime / (sigmaX * sigmaX) + yPrime * yPrime / (sigmaY * sigmaY))); - // value *= Math.Cos(2 * Math.PI * xPrime / lambd + psi); - // kernel.Set(center + y, center + x, Convert.ToSingle(value)); - // } - //} unsafe { for (int y = -center; y <= center; y++) @@ -300,36 +370,10 @@ try { - //for (int y = 0; y < src.Rows; y++) - //{ - // for (int x = 0; x < src.Cols; x++) - // { - // double sum = 0.0; - // - // for (int kRow = 0; kRow < kernelRows; kRow++) - // { - // int yy = y + kRow - kernelCenterY; - // - // for (int kCol = 0; kCol < kernelCols; kCol++) - // { - // int xx = x + kCol - kernelCenterX; - // - // if (xx >= 0 && xx < src.Cols && yy >= 0 && yy < src.Rows) - // { - // byte pixelValue = src.At(yy, xx); - // double kernelValue = kernel.At(kRow, kCol); - // sum += Convert.ToDouble(pixelValue) * kernelValue; - // } - // } - // } - // - // byte resultValue = dst.At(y, x); - // resultValue = (byte)Math.Clamp(sum, 0, 255); - // dst.Set(y, x, resultValue); - // } - //} unsafe { + double* kernelData = (double*)kernel.DataPointer; + for (int y = 0; y < src.Rows; y++) { for (int x = 0; x < src.Cols; x++) @@ -342,11 +386,11 @@ for (int kCol = 0; kCol < kernelCols; kCol++) { int xx = x + kCol - kernelCenterX; - + if (xx >= 0 && xx < src.Cols && yy >= 0 && yy < src.Rows) { byte* pixelValue = src.DataPointer + yy * src.Step() + xx * src.ElemSize(); - double kernelValue = kernel.At(kRow, kCol); + double kernelValue = *(kernelData + kRow * kernelCols + kCol); sum += Convert.ToDouble(*pixelValue) * kernelValue; } } @@ -357,16 +401,75 @@ } } } + } - catch(Exception ex) + catch (Exception ex) { String log = ex.Message; } return dst; } - + } + + public byte[] FlipVertical(byte[] pixels, int width, int height) + { + byte[] flippedPixels = new byte[pixels.Length]; + int rowBytes = width * 4; // 각 행의 바이트 수 (RGBA 채널) + + for (int y = 0; y < height; y++) + { + for (int x = 0; x < rowBytes; x++) + { + flippedPixels[(height - 1 - y) * rowBytes + x] = pixels[y * rowBytes + x]; + } + } + + return flippedPixels; + } + public void ConvertBgrToRgba(byte[] pixels) + { + for (int i = 0; i < pixels.Length; i += 4) + { + byte temp = pixels[i]; // B 채널 + pixels[i] = pixels[i + 2]; // R 채널 + pixels[i + 2] = temp; + } + } + + public void ConvertRgbaToGray(byte[] pixels) + { + for (int i = 0; i < pixels.Length; i += 4) + { + byte r = pixels[i]; + byte g = pixels[i + 1]; + byte b = pixels[i + 2]; + // byte a = pixels[i + 3]; // 알파 채널은 사용하지 않음 + + // 그레이스케일 값 계산 + byte grayValue = (byte)((r * 0.299) + (g * 0.587) + (b * 0.114)); + pixels[i] = grayValue; + pixels[i + 1] = grayValue; + pixels[i + 2] = grayValue; + } + } + + public void Threshold(byte[] pixels, int threshold) + { + for (int i = 0; i < pixels.Length; i += 4) + { + byte r = pixels[i]; + byte g = pixels[i + 1]; + byte b = pixels[i + 2]; + + if(r != g || r!= b) + { + return; + } + + pixels[i] = pixels[i + 1] = pixels[i + 2] = Convert.ToInt32(r) > threshold ? Convert.ToByte(255) : Convert.ToByte(0); + } } } \ No newline at end of file