Merge MKDT_0002
This commit is contained in:
450
MarketData/MarketDataLib/CNNProcessing/ImageHelper.cs
Normal file
450
MarketData/MarketDataLib/CNNProcessing/ImageHelper.cs
Normal file
@@ -0,0 +1,450 @@
|
||||
using SkiaSharp;
|
||||
|
||||
namespace MarketData.CNNProcessing
|
||||
{
|
||||
public class ImageHelper : IDisposable
|
||||
{
|
||||
private SKBitmap bitmap = null;
|
||||
private PointMapping pointMapping;
|
||||
|
||||
public ImageHelper()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy constructor
|
||||
/// </summary>
|
||||
/// <param name="imageHelper"></param>
|
||||
public ImageHelper(ImageHelper imageHelper)
|
||||
{
|
||||
this.bitmap=Copy(imageHelper.bitmap);
|
||||
pointMapping = new PointMapping(Width,Height,Width,0,Height,0);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
DisposeAll();
|
||||
}
|
||||
|
||||
private void DisposeAll()
|
||||
{
|
||||
if(null!=bitmap)
|
||||
{
|
||||
bitmap.Dispose();
|
||||
bitmap=null;
|
||||
}
|
||||
}
|
||||
|
||||
private SKBitmap Copy(SKBitmap bitmap)
|
||||
{
|
||||
return bitmap.Copy(bitmap.ColorType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load image from file
|
||||
/// </summary>
|
||||
/// <param name="pathFileName"></param>
|
||||
/// <returns></returns>
|
||||
public bool LoadImage(string pathFileName)
|
||||
{
|
||||
FileStream stream = new FileStream(pathFileName, FileMode.Open);
|
||||
return LoadImage(stream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Load image from stream retaining the color space and pixel depth of the source image
|
||||
/// </summary>
|
||||
/// <param name="stream"></param>
|
||||
/// <returns></returns>
|
||||
public bool LoadImage(Stream stream)
|
||||
{
|
||||
try
|
||||
{
|
||||
DisposeAll();
|
||||
using SKImage image=SKImage.FromEncodedData(stream);
|
||||
SKImageInfo imageInfo = image.Info;
|
||||
bitmap = new SKBitmap(image.Info);
|
||||
if(!image.ReadPixels (imageInfo, bitmap.GetPixels (), imageInfo.RowBytes,0, 0))
|
||||
{
|
||||
bitmap.Dispose ();
|
||||
bitmap = null;
|
||||
return false;
|
||||
}
|
||||
pointMapping = new PointMapping(Width,Height,Width,0,Height,0);
|
||||
return true;
|
||||
}
|
||||
catch(Exception exception)
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resize image to given width maintaining aspect ration for height.
|
||||
/// If aspect ration is used for CNN then you will need to introduce padding. For instance 640,640 image and then paste the aspect
|
||||
/// mainained image onto that. The CNN will then have to learn that black means nothing. Resizing is the recommended way to go.
|
||||
/// </summary>
|
||||
/// <param name="newWidth"></param>
|
||||
/// <returns></returns>
|
||||
///
|
||||
public bool Resize(int newWidth)
|
||||
{
|
||||
double aspectRatio=(double)bitmap.Width/(double)bitmap.Height;
|
||||
int newHeight=(int)(((double)newWidth)/aspectRatio);
|
||||
if(0!=newHeight%2)newHeight++;
|
||||
return Resize(newWidth,newHeight);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resize image to given width and height. The documenation on CNN's indicates that resizing will work better than maintaining apsect
|
||||
/// ration with padding
|
||||
/// </summary>
|
||||
public bool Resize(int newWidth, int newHeight)
|
||||
{
|
||||
try
|
||||
{
|
||||
Validate();
|
||||
SKImageInfo imageInfo = new SKImageInfo(newWidth, newHeight);
|
||||
SKBitmap newBitmap = bitmap.Resize(imageInfo,SKSamplingOptions.Default);
|
||||
bitmap.Dispose();
|
||||
bitmap = newBitmap;
|
||||
pointMapping = new PointMapping(Width,Height,Width,0,Height,0);
|
||||
return true;
|
||||
}
|
||||
catch(Exception exception)
|
||||
{
|
||||
MDTrace.WriteLine(LogLevel.DEBUG,exception.ToString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new 32 bit bitmap with 8 bits per channel which includes 8 bits for the alpha channel where 0 = fully transparent and 255 = fully opaque
|
||||
/// </summary>
|
||||
/// <param name="width"></param>
|
||||
/// <param name="height"></param>
|
||||
/// <param name="pointMapping"></param>
|
||||
public void CreateImage(int width, int height,PointMapping pointMapping)
|
||||
{
|
||||
DisposeAll();
|
||||
this.pointMapping=pointMapping;
|
||||
bitmap=new SKBitmap(width,height,SKColorType.Rgba8888, SKAlphaType.Premul);
|
||||
Validate();
|
||||
}
|
||||
|
||||
// This is the method that is currently being used in the CNNClient.Predict to send the image stream to Flask
|
||||
public Stream SaveBlackAndWhiteJPG()
|
||||
{
|
||||
Validate();
|
||||
SKBitmap bwBitmap=ToBlackAndWhite(bitmap);
|
||||
Stream memoryStream=new MemoryStream();
|
||||
BitmapExtensions.SaveJPG100(bwBitmap,memoryStream);
|
||||
memoryStream.Position=0;
|
||||
bwBitmap.Dispose();
|
||||
return memoryStream;
|
||||
}
|
||||
|
||||
// Convert bitmap to stream for use in CNNClient
|
||||
public Stream ToStream()
|
||||
{
|
||||
Validate();
|
||||
Stream memoryStream=new MemoryStream();
|
||||
BitmapExtensions.SaveJPG100(bitmap,memoryStream);
|
||||
memoryStream.Position=0;
|
||||
return memoryStream;
|
||||
}
|
||||
|
||||
public bool SaveGrayScaleJPG(String pathFileName)
|
||||
{
|
||||
Validate();
|
||||
SKBitmap bwBitmap=ToGrayScale(bitmap);
|
||||
BitmapExtensions.SaveJPG100(bwBitmap,pathFileName);
|
||||
bwBitmap.Dispose();
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool SaveBlackAndWhiteJPG(String pathFileName)
|
||||
{
|
||||
Validate();
|
||||
SKBitmap bwBitmap=ToBlackAndWhite(bitmap);
|
||||
BitmapExtensions.SaveJPG100(bwBitmap,pathFileName);
|
||||
bwBitmap.Dispose();
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Save(String pathFileName)
|
||||
{
|
||||
Save(pathFileName,null);
|
||||
}
|
||||
|
||||
private void Save(String pathFileName,SKBitmap altBitmap=null)
|
||||
{
|
||||
Validate();
|
||||
if(null==altBitmap)BitmapExtensions.SaveJPG100(bitmap,pathFileName);
|
||||
else BitmapExtensions.SaveJPG100(altBitmap,pathFileName);
|
||||
}
|
||||
|
||||
// Convert to 8 bits per pixel black and white
|
||||
private SKBitmap ToBlackAndWhite(SKBitmap bitmap)
|
||||
{
|
||||
float n = 1.0f/3.0f;
|
||||
SKColorFilter bwColorFilter = SKColorFilter.CreateColorMatrix(new float[]
|
||||
{
|
||||
n, n, n, 0, 0,
|
||||
n, n, n, 0, 0,
|
||||
n, n, n, 0, 0,
|
||||
0, 0, 0, 1, 0
|
||||
});
|
||||
|
||||
SKBitmap dstBitmap = new SKBitmap(bitmap.Width, bitmap.Height,SKColorType.Gray8, SKAlphaType.Premul);
|
||||
using SKCanvas canvas = new SKCanvas(dstBitmap);
|
||||
using SKPaint paint = new SKPaint();
|
||||
paint.ColorFilter = bwColorFilter;
|
||||
canvas.DrawBitmap(bitmap, new SKPoint(0,0), paint);
|
||||
return dstBitmap;
|
||||
}
|
||||
|
||||
public bool RotateRight()
|
||||
{
|
||||
Validate();
|
||||
SKBitmap rotated = Rotate(bitmap, 90);
|
||||
bitmap.Dispose();
|
||||
bitmap=rotated;
|
||||
pointMapping = new PointMapping(Width,Height,Width,0,Height,0);
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool RotateLeft()
|
||||
{
|
||||
Validate();
|
||||
SKBitmap rotated = Rotate(bitmap, -90);
|
||||
bitmap.Dispose();
|
||||
bitmap=rotated;
|
||||
pointMapping = new PointMapping(Width,Height,Width,0,Height,0);
|
||||
return true;
|
||||
}
|
||||
|
||||
private SKBitmap Rotate(SKBitmap bitmap, double angle)
|
||||
{
|
||||
double radians = Math.PI * angle / 180;
|
||||
float sine = (float)Math.Abs(Math.Sin(radians));
|
||||
float cosine = (float)Math.Abs(Math.Cos(radians));
|
||||
int originalWidth = bitmap.Width;
|
||||
int originalHeight = bitmap.Height;
|
||||
int rotatedWidth = (int)(cosine * originalWidth + sine * originalHeight);
|
||||
int rotatedHeight = (int)(cosine * originalHeight + sine * originalWidth);
|
||||
|
||||
SKBitmap rotatedBitmap = new SKBitmap(rotatedWidth, rotatedHeight);
|
||||
|
||||
using (SKCanvas surface = new SKCanvas(rotatedBitmap))
|
||||
{
|
||||
surface.Clear();
|
||||
surface.Translate(rotatedWidth / 2, rotatedHeight / 2);
|
||||
surface.RotateDegrees((float)angle);
|
||||
surface.Translate(-originalWidth / 2, -originalHeight / 2);
|
||||
surface.DrawBitmap(bitmap, new SKPoint());
|
||||
}
|
||||
return rotatedBitmap;
|
||||
}
|
||||
|
||||
public void ToGrayScale()
|
||||
{
|
||||
Validate();
|
||||
SKBitmap grayScaleBitmap = ToGrayScale(bitmap);
|
||||
bitmap.Dispose();
|
||||
bitmap=grayScaleBitmap;
|
||||
}
|
||||
|
||||
// Convert to 8 bits per pixel black and white
|
||||
private SKBitmap ToGrayScale(SKBitmap bitmap)
|
||||
{
|
||||
SKColorFilter grayScaleColorFilter = SKColorFilter.CreateColorMatrix(new float[]
|
||||
{
|
||||
0.2126f, 0.7152f, 0.0722f, 0, 0,
|
||||
0.2126f, 0.7152f, 0.0722f, 0, 0,
|
||||
0.2126f, 0.7152f, 0.0722f, 0, 0,
|
||||
0, 0, 0, 1, 0
|
||||
});
|
||||
|
||||
SKBitmap dstBitmap = new SKBitmap(bitmap.Width, bitmap.Height,SKColorType.Gray8, SKAlphaType.Premul);
|
||||
using SKCanvas canvas = new SKCanvas(dstBitmap);
|
||||
using SKPaint paint = new SKPaint();
|
||||
paint.ColorFilter = grayScaleColorFilter;
|
||||
canvas.DrawBitmap(bitmap, new SKPoint(0,0), paint);
|
||||
return dstBitmap;
|
||||
}
|
||||
|
||||
public bool Blur(float sigmaX)
|
||||
{
|
||||
Validate();
|
||||
SKBitmap blurredBitmap = Blur(bitmap, sigmaX);
|
||||
bitmap.Dispose();
|
||||
bitmap = blurredBitmap;
|
||||
return true;
|
||||
}
|
||||
|
||||
private SKBitmap Blur(SKBitmap image, float sigmaX=5.0f, float sigmaY=5.0f)
|
||||
{
|
||||
SKImageFilter imageFilter = SKImageFilter.CreateBlur(sigmaX, sigmaY);
|
||||
SKBitmap blurredBitmap = new SKBitmap(image.Width, image.Height);
|
||||
using SKCanvas canvas = new SKCanvas(blurredBitmap);
|
||||
using SKPaint paint = new SKPaint()
|
||||
{
|
||||
ImageFilter = imageFilter
|
||||
};
|
||||
canvas.DrawBitmap(bitmap, new SKPoint(0,0), paint);
|
||||
return blurredBitmap;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// GetPixel - No point translation
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <returns></returns>
|
||||
public SKColor GetPixel(int x,int y)
|
||||
{
|
||||
Validate();
|
||||
return bitmap.GetPixel(x, y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// SetPixel - No point translation
|
||||
/// </summary>
|
||||
/// <param name="x"></param>
|
||||
/// <param name="y"></param>
|
||||
/// <param name="color"></param>
|
||||
public void SetPixel(int x, int y,SKColor color)
|
||||
{
|
||||
Validate();
|
||||
bitmap.SetPixel(x, y, color);
|
||||
}
|
||||
|
||||
public SKPoint TranslatePoint(SKPoint point)
|
||||
{
|
||||
return pointMapping.TranslatePoint(point);
|
||||
}
|
||||
|
||||
public void Validate()
|
||||
{
|
||||
if(null==bitmap)throw new InvalidDataException("The image has not been initialized");
|
||||
}
|
||||
|
||||
public int Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return bitmap.Width;
|
||||
}
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return bitmap.Height;
|
||||
}
|
||||
}
|
||||
|
||||
public void Fill(SKColor color)
|
||||
{
|
||||
SKRectI rect = new SKRectI(0, 0, Width, Height); // x, y, width, height
|
||||
bitmap.Erase(color, rect);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DrawPoint - With translation
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <param name="drawPoint"></param>
|
||||
public void DrawPoint(SKColor color,SKPoint drawPoint)
|
||||
{
|
||||
Validate();
|
||||
using SKCanvas canvas = new SKCanvas(bitmap);
|
||||
canvas.Clear();
|
||||
SKPoint txPoint = pointMapping.MapPoint(drawPoint);
|
||||
canvas.DrawPoint(drawPoint, color);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DrawPoint - with given strokeWidth and translation
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <param name="strokeWidth"></param>
|
||||
/// <param name="drawPoint"></param>
|
||||
public void DrawPoint(SKColor color, float strokeWidth, SKPoint drawPoint)
|
||||
{
|
||||
Validate();
|
||||
SKPoint txPoint = pointMapping.MapPoint(drawPoint);
|
||||
using SKCanvas canvas = new SKCanvas(bitmap);
|
||||
using SKPaint paint = new SKPaint();
|
||||
paint.Style = SKPaintStyle.Stroke;
|
||||
paint.StrokeWidth = strokeWidth; // Set the desired stroke width
|
||||
paint.Color = SKColors.Black;
|
||||
|
||||
SKPoint[] points = new SKPoint[] { txPoint};
|
||||
|
||||
canvas.DrawPoints(SKPointMode.Points, points, paint);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add noise to the image
|
||||
/// </summary>
|
||||
/// <param name="color"></param>
|
||||
/// <param name="percentDecimal"></param>
|
||||
public void AddNoise(SKColor color,double percentDecimal)
|
||||
{
|
||||
Random random=new Random();
|
||||
int amount=(int)(percentDecimal*(Width*Height));
|
||||
for(int index=0;index<amount;index++)
|
||||
{
|
||||
int x=random.Next(Width-1);
|
||||
int y=random.Next(Height-1);
|
||||
SetPixel(x, y,color);
|
||||
}
|
||||
}
|
||||
|
||||
public void DrawLine(SKColor color, float strokeWidth, SKPoint srcPoint,SKPoint dstPoint)
|
||||
{
|
||||
Validate();
|
||||
SKPoint txSrcPoint=pointMapping.MapPoint(srcPoint);
|
||||
SKPoint txDstPoint=pointMapping.MapPoint(dstPoint);
|
||||
using SKCanvas canvas = new SKCanvas(bitmap);
|
||||
using SKPaint paint = new SKPaint();
|
||||
paint.Style = SKPaintStyle.Stroke;
|
||||
paint.StrokeWidth = strokeWidth; // Set the desired stroke width
|
||||
paint.Color = SKColors.Black;
|
||||
canvas.DrawLine(txSrcPoint, txDstPoint, paint);
|
||||
}
|
||||
|
||||
public void DrawPath(SKColor color, float strokeWidth, LineSegments lineSegments)
|
||||
{
|
||||
Validate();
|
||||
|
||||
using SKCanvas canvas = new SKCanvas(bitmap);
|
||||
using SKPaint paint = new SKPaint();
|
||||
paint.Style = SKPaintStyle.Stroke;
|
||||
paint.StrokeWidth = strokeWidth; // Set the desired stroke width
|
||||
paint.Color = SKColors.Black;
|
||||
foreach(LineSegment lineSegment in lineSegments)
|
||||
{
|
||||
SKPoint txSrcPoint=pointMapping.MapPoint(lineSegment.P1);
|
||||
SKPoint txDstPoint=pointMapping.MapPoint(lineSegment.P2);
|
||||
canvas.DrawLine(txSrcPoint, txDstPoint, paint);
|
||||
}
|
||||
}
|
||||
|
||||
public bool DrawCircle(SKColor color, SKPoint center, float radius=1.00f)
|
||||
{
|
||||
Validate();
|
||||
SKPoint txPointCenter=pointMapping.MapPoint(center);
|
||||
using SKPaint paint = new SKPaint();
|
||||
paint.Color = color;
|
||||
paint.Style = SKPaintStyle.Fill;
|
||||
using SKCanvas canvas = new SKCanvas(bitmap);
|
||||
canvas.DrawCircle(txPointCenter, radius, paint);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user