main
pinb 1 year ago
parent 694b6abceb
commit 6fa9d80f6f

@ -19,8 +19,8 @@
<img src="images/gaborfilter3.png" alt="gaborfilter"><br />
</p><br /><br />
<h3 id="-parameters-"><strong>함수 원형</strong></h3>
<pre style ="background-color: #f8f8f8;">
<code class="lang-cpp">
<pre style="background-color: #f8f8f8;">
<code class="lang-cpp">
cv::Mat cv::getGaborKernel(cv::Size ksize, <span class="hljs-keyword">double</span> sigma, <span class="hljs-keyword">double</span> theta, <span class="hljs-keyword">double</span> lambd, <span class="hljs-keyword">double</span> gamma, <span class="hljs-keyword">double</span> psi = CV_PI*<span class="hljs-number">0.5</span>, <span class="hljs-keyword">int</span> ktype = CV_64F)
</code>
</pre><br />
@ -84,12 +84,12 @@
</div>
<br />
<div>
<canvas @ref="srcCanvas" width="256" height="256" style="border:1px solid gray;">
Your browser does not support the HTML5 canvas tag.
</canvas>
<canvas @ref="dstCanvas" width="256" height="256" style="border:1px solid gray;">
Your browser does not support the HTML5 canvas tag.
</canvas>
<canvas @ref="srcCanvas" width="256" height="256" style="border:1px solid gray;">
Your browser does not support the HTML5 canvas tag.
</canvas>
<canvas @ref="dstCanvas" width="256" height="256" style="border:1px solid gray;">
Your browser does not support the HTML5 canvas tag.
</canvas>
</div>
<div>
<p>Threshold (0 ~ 255)</p>
@ -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<grayMat.Rows; i++)
{
for(int j=0; j<grayMat.Cols; j++)
{
byte pixelValue = grayMat.At<byte>(i, j);
byte newValue = (Convert.ToInt32(pixelValue) > valthreshold) ? (byte)255 : (byte)0;
dstMat.Set<byte>(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<byte>(i, j);
// byte newValue = (Convert.ToInt32(pixelValue) > valthreshold) ? (byte)255 : (byte)0;
// dstMat.Set<byte>(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<float>(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<byte>(yy, xx);
// double kernelValue = kernel.At<double>(kRow, kCol);
// sum += Convert.ToDouble(pixelValue) * kernelValue;
// }
// }
// }
//
// byte resultValue = dst.At<byte>(y, x);
// resultValue = (byte)Math.Clamp(sum, 0, 255);
// dst.Set<byte>(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<double>(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);
}
}
}
Loading…
Cancel
Save