Commit e586bf4e authored by Théophile BORNON's avatar Théophile BORNON

ML on conv filter

parent 98996813
...@@ -11,16 +11,40 @@ namespace ImageProcessing_Benchmark ...@@ -11,16 +11,40 @@ namespace ImageProcessing_Benchmark
Stopwatch sw = new Stopwatch(); Stopwatch sw = new Stopwatch();
System.Console.WriteLine("Benchmarking"); System.Console.WriteLine("Benchmarking");
for (int i = 0; i < 10; i++) for (int i = 0; i < 50; i++)
{ {
sw.Restart(); sw.Restart();
ProcessStartInfo processStartInfo = new ProcessStartInfo(); ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.Arguments = "--input flocon.bmp --multithreading"; processStartInfo.Arguments = "--input flocon.bmp --output flocon_o.bmp";
processStartInfo.FileName = "S04_Projet.exe"; processStartInfo.FileName = "S04_Projet.exe";
Process.Start(processStartInfo); Process.Start(processStartInfo);
while (Process.GetProcessesByName("S04_Projet").Length != 0) System.Threading.Thread.Sleep(20); while (Process.GetProcessesByName("S04_Projet").Length != 0) System.Threading.Thread.Sleep(20);
sw.Stop(); sw.Stop();
results += sw.ElapsedMilliseconds + "\n"; results += sw.ElapsedMilliseconds + ";";
}
results += "\n";
for (int i = 0; i < 50; i++)
{
sw.Restart();
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.Arguments = "--input flocon.bmp --filter --output flocon_o.bmp";
processStartInfo.FileName = "S04_Projet.exe";
Process.Start(processStartInfo);
while (Process.GetProcessesByName("S04_Projet").Length != 0) System.Threading.Thread.Sleep(20);
sw.Stop();
results += sw.ElapsedMilliseconds + ";";
}
results += "\n";
for (int i = 0; i < 50; i++)
{
sw.Restart();
ProcessStartInfo processStartInfo = new ProcessStartInfo();
processStartInfo.Arguments = "--input flocon.bmp --filter --multithreading --output flocon_o.bmp";
processStartInfo.FileName = "S04_Projet.exe";
Process.Start(processStartInfo);
while (Process.GetProcessesByName("S04_Projet").Length != 0) System.Threading.Thread.Sleep(20);
sw.Stop();
results += sw.ElapsedMilliseconds + ";";
} }
File.WriteAllText("bench.csv", results); File.WriteAllText("bench.csv", results);
......
...@@ -45,6 +45,7 @@ ...@@ -45,6 +45,7 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="MultiThreadedTask.cs" />
<Compile Include="MyImage.cs" /> <Compile Include="MyImage.cs" />
<Compile Include="Display.cs" /> <Compile Include="Display.cs" />
<Compile Include="Options.cs" /> <Compile Include="Options.cs" />
......
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace S04_Projet
{
class MultiThreadedTask
{
#region Attributs
public enum Operation
{
Load,
Filter
}
private enum RGB
{
R,
G,
B
}
private byte[] file;
private int nbPixel;
private int nbProcessors;
private Pixel[,] Pixels;
private Pixel[,] NewPixels;
private Options opt;
private short[,] filter;
private double factor;
private int size;
#endregion
public void setNbPixel(int nbPixel) => this.nbPixel = nbPixel;
public void setFile(byte[] file) => this.file = file;
private Operation ToDo;
public MultiThreadedTask(Operation ToDo, byte[] file, Options opt)
{
this.ToDo = ToDo;
this.opt = opt;
this.file = file;
nbPixel = opt.width * opt.height;
nbProcessors = Environment.ProcessorCount;
}
public MultiThreadedTask(Operation ToDo, Pixel[,] Pixels, Options opt, short[,] filter, double factor)
{
this.ToDo = ToDo;
this.opt = opt;
this.Pixels = Pixels;
this.filter = filter;
this.factor = factor;
size = filter.GetLength(0);
}
public void Start()
{
if (ToDo == Operation.Load) LoadImage();
else if (ToDo == Operation.Filter) ApplyFilter();
}
#region LoadImage
public void LoadImage()
{
Pixels = new Pixel[opt.width, opt.height];
Thread[] threads = new Thread[nbProcessors];
for (int i = 0; i < nbProcessors; i++)
{
threads[i] = new Thread(new ParameterizedThreadStart(LoadImageTask));
threads[i].Start(i);
}
for (int i = 0; i < nbProcessors; i++)
threads[i].Join();
}
public void LoadImageTask(object i)
{
if (file != null && Pixels != null)
{
int start = nbPixel / nbProcessors * (int)i;
int end = nbPixel / nbProcessors * ((int)i + 1);
int x, y;
byte r, g, b;
for (int j = start; j < end; j++)
{
x = j % opt.width;
y = j / opt.width;
b = file[j * 3 + opt.padding * y + opt.offset];
g = file[j * 3 + opt.padding * y + opt.offset + 1];
r = file[j * 3 + opt.padding * y + opt.offset + 2];
Pixels[x, y] = new Pixel(r, g, b);
}
}
}
#endregion
#region Filter
public void ApplyFilter()
{
NewPixels = new Pixel[opt.width, opt.height];
int pixelNumber = opt.width * opt.height;
nbProcessors = Environment.ProcessorCount;
int pixelPerThread = pixelNumber / nbProcessors;
Thread[] threads = new Thread[nbProcessors];
Console.WriteLine("Génération de {0} threads", nbProcessors);
for (int i = 0; i < nbProcessors; i++)
{
threads[i] = new Thread(new ParameterizedThreadStart(ApplyFilterTask));
threads[i].Start(i);
}
for (int i = 0; i < nbProcessors; i++)
{
threads[i].Join();
Console.WriteLine("Thread {0} done", i);
}
}
public void ApplyFilterTask(object i)
{
int x, y;
int start = opt.width * opt.height / nbProcessors * (int)i;
int end = opt.width * opt.height / nbProcessors * ((int)i + 1);
byte[,] rMatrix, gMatrix, bMatrix;
byte r, g, b;
for (int j = start; j < end; j++)
{
x = j % opt.width;
y = j / opt.width;
rMatrix = GetMatrix(x, y, size, RGB.R);
gMatrix = GetMatrix(x, y, size, RGB.G);
bMatrix = GetMatrix(x, y, size, RGB.B);
r = ConvolutionalResult(rMatrix, filter, size, factor);
g = ConvolutionalResult(gMatrix, filter, size, factor);
b = ConvolutionalResult(bMatrix, filter, size, factor);
NewPixels[x, y] = new Pixel(r, g, b);
}
}
/// <summary>
/// Retourne la matrice de pixels de taille size ,de milieu (x0,y0) et de couleur RGB
/// </summary>
/// <param name="x0">Coordonnée verticale du pixel milieu</param>
/// <param name="y0">Coordonnée horizontale du pixel milieu</param>
/// <param name="size">Taille de la matrice de pixel désirée</param>
/// <param name="rgb">Couleur souhaitée</param>
/// <returns>Matrice de pixels de taille size ,de milieu (x0,y0) et de couleur RGB</returns>
private byte[,] GetMatrix(int x0, int y0, int size, RGB rgb)
{
byte[,] matrix = new byte[size, size];
for (int i = 0; i < size * size; i++)
{
int x = x0 + (i % size) - ((size - 1) / 2);
int y = y0 + (i / size) - ((size - 1) / 2);
if (x < 0) x = 0;
else if (x >= opt.width) x = opt.width - 1;
if (y < 0) y = 0;
else if (y >= opt.height) y = opt.height - 1;
if (rgb == RGB.R)
matrix[(i % size), (i / size)] = Pixels[x, y].r;
else if (rgb == RGB.G)
matrix[(i % size), (i / size)] = Pixels[x, y].g;
else if (rgb == RGB.B)
matrix[(i % size), (i / size)] = Pixels[x, y].b;
}
return matrix;
}
/// <summary>
/// Calcul convolutionnel
/// </summary>
/// <param name="matrix">Matrice</param>
/// <param name="conv">Convolution</param>
/// <param name="size">Taille du filtre</param>
/// <param name="factor">Factor de normalisation</param>
/// <returns>Résultat du calcul convolutinnel</returns>
public static byte ConvolutionalResult(byte[,] matrix, short[,] conv, int size, double factor)
{
short r = 0; ;
for (int x = 0; x < size; x++)
for (int y = 0; y < size; y++)
r += (short)(matrix[x, y] * conv[x, y]);
r = (short)Math.Round(r * factor);
if (r > 255) return 255;
else if (r < 0) return 0;
else return (byte)r;
}
#endregion
public Pixel[,] getPixelMatrix()
{
return Pixels;
}
public Pixel[,] getFilteredMatrix()
{
return NewPixels;
}
}
}
...@@ -10,7 +10,6 @@ namespace S04_Projet ...@@ -10,7 +10,6 @@ namespace S04_Projet
{ {
private Options opt; private Options opt;
private Pixel[,] Pixels; private Pixel[,] Pixels;
private int nbProcessors;
byte[] file; byte[] file;
public enum GrayFilterType public enum GrayFilterType
...@@ -26,6 +25,11 @@ namespace S04_Projet ...@@ -26,6 +25,11 @@ namespace S04_Projet
B B
} }
public Options getOptions()
{
return opt;
}
/// <summary> /// <summary>
/// Constructeur prenant en paramètre un chemin vers un fichier BMP 24 bits /// Constructeur prenant en paramètre un chemin vers un fichier BMP 24 bits
/// </summary> /// </summary>
...@@ -106,7 +110,7 @@ namespace S04_Projet ...@@ -106,7 +110,7 @@ namespace S04_Projet
#region Mono #region Mono
if (!Program.MULTITHREADING) if (!Program.MULTITHREADING_LOAD)
{ {
int x, y; int x, y;
byte r, g, b; byte r, g, b;
...@@ -124,19 +128,11 @@ namespace S04_Projet ...@@ -124,19 +128,11 @@ namespace S04_Projet
#endregion #endregion
#region Multithreading #region Multithreading
if (Program.MULTITHREADING) else
{
nbProcessors = Environment.ProcessorCount;
int pixelPerThread = pixelNumber / nbProcessors;
Thread[] threads = new Thread[nbProcessors];
for (int i = 0; i < nbProcessors; i++)
{ {
threads[i] = new Thread(new ParameterizedThreadStart(LoadImage)); MultiThreadedTask LoadImageTask = new MultiThreadedTask(MultiThreadedTask.Operation.Load, file, opt);
threads[i].Start(i); LoadImageTask.Start();
} Pixels = LoadImageTask.getPixelMatrix();
for (int i = 0; i < nbProcessors; i++) threads[i].Join();
} }
#endregion #endregion
...@@ -145,37 +141,6 @@ namespace S04_Projet ...@@ -145,37 +141,6 @@ namespace S04_Projet
#endregion #endregion
} }
/// <summary>
/// Fonction utilisée par FromImageToFile() pour le multithreading. Parcours le fichier pour en extraire
/// la matrice de pixels
/// </summary>
/// <param name="i">Numero du thread</param>
private void LoadImage(object i)
{
int start = opt.width * opt.height / nbProcessors * (int)i;
int end = opt.width * opt.height / nbProcessors * ((int)i + 1);
int x, y;
byte r, g, b;
Pixel _pix;
for (int j = start; j < end; j++)
{
x = j % opt.width;
y = j / opt.width;
b = file[j * 3 + opt.padding * y + opt.offset];
g = file[j * 3 + opt.padding * y + opt.offset + 1];
r = file[j * 3 + opt.padding * y + opt.offset + 2];
_pix = new Pixel(r, g, b);
lock (Pixels){
Pixels[x, y] = _pix;
}
}
}
/// <summary> /// <summary>
/// Sauvegarde l'image vers le chemin passé en paramètres /// Sauvegarde l'image vers le chemin passé en paramètres
/// </summary> /// </summary>
...@@ -404,6 +369,8 @@ namespace S04_Projet ...@@ -404,6 +369,8 @@ namespace S04_Projet
int nbPixel = options.height * options.width; int nbPixel = options.height * options.width;
Pixel[,] PixelArr = new Pixel[options.width, options.height]; Pixel[,] PixelArr = new Pixel[options.width, options.height];
if (!Program.MULTITHREADING)
{
int x, y; int x, y;
byte[,] rMatrix, gMatrix, bMatrix; byte[,] rMatrix, gMatrix, bMatrix;
byte r, g, b; byte r, g, b;
...@@ -423,6 +390,15 @@ namespace S04_Projet ...@@ -423,6 +390,15 @@ namespace S04_Projet
PixelArr[x, y] = new Pixel(r, g, b); PixelArr[x, y] = new Pixel(r, g, b);
} }
}
else
{
MultiThreadedTask FilterImageTask =
new MultiThreadedTask(MultiThreadedTask.Operation.Filter, Pixels, opt, filter, factor);
FilterImageTask.Start();
Pixel[,] _Pixels = FilterImageTask.getFilteredMatrix();
return new MyImage(opt, _Pixels);
}
return new MyImage(options, PixelArr); return new MyImage(options, PixelArr);
} }
......
...@@ -11,6 +11,7 @@ namespace S04_Projet ...@@ -11,6 +11,7 @@ namespace S04_Projet
{ {
class Program class Program
{ {
public static bool MULTITHREADING_LOAD = false;
public static bool MULTITHREADING = true; public static bool MULTITHREADING = true;
static void Main(string[] args) static void Main(string[] args)
{ {
...@@ -56,9 +57,22 @@ namespace S04_Projet ...@@ -56,9 +57,22 @@ namespace S04_Projet
{ 0, -1, 0 } { 0, -1, 0 }
}; };
#endregion #endregion
MyImage imgg = new MyImage("flocon.bmp");
Stopwatch sw = new Stopwatch();
Console.WriteLine("Loading done");
sw.Start();
imgg.ApplyConvFilter(edgeDetect1Filter, 1);
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
Console.Read();
/*
#region Arguments
if (args.Length > 0) if (args.Length > 0)
{ {
MULTITHREADING = false; MULTITHREADING = false;
bool filter = false;
string inputPath = ""; string inputPath = "";
string outputPath = ""; string outputPath = "";
for (int i = 0; i < args.Length; i++) for (int i = 0; i < args.Length; i++)
...@@ -74,10 +88,12 @@ namespace S04_Projet ...@@ -74,10 +88,12 @@ namespace S04_Projet
i++; i++;
} }
else if (args[i].Equals("--multithreading")) MULTITHREADING = true; else if (args[i].Equals("--multithreading")) MULTITHREADING = true;
else if (args[i].Equals("--filter")) filter = true;
} }
if(inputPath != "") if(inputPath != "")
{ {
MyImage img = new MyImage(inputPath); MyImage img = new MyImage(inputPath);
if (filter) img = img.ApplyConvFilter(edgeDetect1Filter, 1);
if (outputPath != "") if (outputPath != "")
{ {
img.Save(outputPath); img.Save(outputPath);
...@@ -85,11 +101,16 @@ namespace S04_Projet ...@@ -85,11 +101,16 @@ namespace S04_Projet
{ {
Console.WriteLine("No output specified, program will only load image in memory and stop"); Console.WriteLine("No output specified, program will only load image in memory and stop");
} }
} else } else
{ {
Console.WriteLine("--input argument required"); Console.WriteLine("--input argument required");
} }
} }
#endregion
#region Display
else else
{ {
Console.ForegroundColor = ConsoleColor.White; Console.ForegroundColor = ConsoleColor.White;
...@@ -113,6 +134,8 @@ namespace S04_Projet ...@@ -113,6 +134,8 @@ namespace S04_Projet
Console.Read(); Console.Read();
} }
#endregion
*/
} }
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment