I am trying to implement image noise reduction using MRF. I used this article. It also provides this code in matlab. I tried to rewrite it in c# to work with noised images with only blue channel like this
But after using my code I got only darker image. What am I doing wrong? Is it something in matlab that I didn't include in my code?
My code is:
public static Bitmap Process(Bitmap src, double covar, double max_diff, double weight_diff, int iterations)
{
var buffer = new Bitmap[2];
var b = new Bitmap(src.Width, src.Height, src.PixelFormat);
for (var i = 0; i < src.Width; i++)
for (var j = 0; j < src.Height; j++)
{
b.SetPixel(i, j, Color.FromArgb(src.GetPixel(i, j).A, 0, 0, 0));
}
buffer[0] = src;
buffer[1] = b;
var s = 1;
var d = 0;
var vMax = (src.Width * src.Height) * (Math.Pow(256, 2) / (2 * covar) + 4 * weight_diff * max_diff);
for (var i = 0; i < iterations; i++)
{
Console.WriteLine("Iteration: " + i.ToString());
if (s == 0) { s = 1; d = 0; }
else { s = 0; d = 1; }
for (var r = 0; r < src.Height - 1; r++)
for (var c = 0; c < src.Width - 1; c++)
{
//val = red
var vLocal = vMax;
var minVal = -1;
for (var val = 0; val < 255; val+=1)
{
var V_Data = Math.Pow((val - src.GetPixel(r, c).B), 2) / (2 * covar); //r
var V_diff = 0;
if (r > 1)
{
V_diff = V_diff + (int)Math.Min((val - Math.Pow(buffer[s].GetPixel(r - 1, c).B, 2)), max_diff);
}
if (r < src.Height)
{
V_diff = V_diff + (int)Math.Min((val - Math.Pow(buffer[s].GetPixel(r + 1, c).B, 2)), max_diff);
}
if (c > 1)
{
V_diff = V_diff + (int)Math.Min((val - Math.Pow(buffer[s].GetPixel(r, c - 1).B, 2)), max_diff);
}
if (c < src.Height)
{
V_diff = V_diff + (int)Math.Min((val - Math.Pow(buffer[s].GetPixel(r, c + 1).B, 2)), max_diff);
}
var V_current = V_Data + weight_diff * V_diff;
if (V_current < vLocal)
{
minVal = val;
vLocal = V_current;
}
}
Color color = buffer[d].GetPixel(r, c);
var e = Color.FromArgb(color.A, color.R, color.G, minVal);
buffer[d].SetPixel(r, c, e);
}
}
return buffer[d];
}
Related
I got an array of data voltages and I want to get the RMS value from the FFT that has been applied before to that data. I've seen that RMS in time domain should be equal to RMS(fft) / sqrt(nFFT) from Parseval's Theorem, but gives me different results. I'm using these functions:
1)FFT
public static VectorDPoint FFT(double[] trama, double samplingFreq)
{
double fs = samplingFreq; // Sampling frequency
double t1 = 1 / fs; // Sample time
int l = trama.Length; // Length of signal
// Time vector
//Vector t = Normal(0, l, 1) * t1;
//// Values vector
//Vector y = new Vector(trama);
// We just use half of the data as the other half is simetric. The middle is found in NFFT/2 + 1
int nFFT = (int)Math.Pow(2, NextPow2(l));
if (nFFT > 655600)
{ }
// Create complex array for FFT transformation. Use 0s for imaginary part
Complex[] samples = new Complex[nFFT];
for (int i = 0; i < nFFT; i++)
{
if (i >= trama.Length)
{
samples[i] = new MathNet.Numerics.Complex(0, 0);
}
else
{
samples[i] = new MathNet.Numerics.Complex(trama[i], 0);
}
}
ComplexFourierTransformation fft = new ComplexFourierTransformation(TransformationConvention.Matlab);
fft.TransformForward(samples);
ComplexVector s = new ComplexVector(samples);
s = s / l;
Vector f = (fs / 2.0) * Linspace(0, 1, (nFFT / 2) + 1);
VectorDPoint result = new VectorDPoint();
for (int i = 0; i < (nFFT / 2) + 1; i++)
{
result.Add(new DPoint(f[i], 2 * s[i].Modulus));
}
s = null;
f = null;
samples = null;
return result;
2) RMS
public static double RMSCalculate(double[] channelValues, int samplesNumber, double sampleRate, DateTime currentDate)
{
double[] times = new double[channelValues.Length];
double sampleTime = 0.0;
double period = 0;
times[0] = currentDate.Second + currentDate.Millisecond / 1000.0;
sampleTime = 1 / sampleRate; //s
// Limited samples
for (int i = 1; i < channelValues.Length; i++)
{
times[i] = times[i - 1] + sampleTime;
}
DPoint RMSValues = new DPoint();
RMSValues.Y = 0;
if (channelValues.Length == 1)
{
double x = channelValues[0];
double y = channelValues[0];
RMSValues = new DPoint(x, Math.Abs(y));
}
else
{
for (int i = 0; i < times.Length - 1; i++)
{
period = 0;
if (i + 1 < times.Length)
{
RMSValues.Y += channelValues[i + 1] * channelValues[i + 1] * (times[i + 1] - times[i]);
}
}
period = times[times.Length - 1] - times[0];
RMSValues.Y = RMSValues.Y / period;
RMSValues.Y = Math.Sqrt(RMSValues.Y);
}
return RMSValues.Y;
}
For example, I have set up a formula to find my Xnew[k+1], Ynew[k+1] and Anew[k+1].
How do I pass the value to a 3 by 1 matrix if I want my
index 1,1 be Xnew[k+1],
index 1,2 be Ynew[k+1],
index 1,3 be Anew[k+1].
Here's what I got so far.
for (k = 0; k < 5; k++)
{
Xnew[k+1] = cX + (T * MPCV[k]) * Math.Cos(cA);
Ynew[k+1] = cY + (T * MPCV[k]) * Math.Sin(cA);
Anew[k+1] = cA + (T * MPCW[k]);
double[,] qK = new double[3, 1];
int i, j;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 1; j++)
{
qK[i, j] = 1;
}
}
}
Thank you for the help.
Suposing Xnew[k+1], Ynew[k+1] and Anew[k+1] are doubles:
for ( k = 0; k < 5; k++ ) {
Xnew[k + 1] = cX + (T * MPCV[k]) * Math.Cos(cA);
Ynew[k + 1] = cY + (T * MPCV[k]) * Math.Sin(cA);
Anew[k + 1] = cA + (T * MPCW[k]);
double[,] qk = { { Xnew[k + 1] , Ynew[k + 1] , Anew[k + 1] } };
}
This will make you a 1x3 matrix (arrays start in 0) with:
qk[0,0] = Xnew[k+1]
qk[0,1] = Ynew[k+1]
qk[0,2] = Anew[k+1]
But if you want a 3x1 matrix use instead.
double[,] qk = { { Xnew[k + 1] }, {Ynew[k + 1] }, {Anew[k + 1] } };
That will give you:
qk[0,0] = Xnew[k+1]
qk[1,0] = Ynew[k+1]
qk[2,0] = Anew[k+1]
I have a weird problem. I have been searching the internet for a good and fast Gaussian blur algorithm. And I finally found one!
So what I did was to try it in a new project - it worked just fine.
When I then was going to import the class into my main project and then tried it, I got a System.OverflowException. I'm finding this really weird that it works in one project, but not in another.
Here's the algorithm:
(I am calling the function almost the same. I tried calling it the exact same way, but I still got an exception)
public static void FastBlur(Bitmap SourceImage, int radius)
{
var rct = new Rectangle(0, 0, SourceImage.Width, SourceImage.Height);
var dest = new int[rct.Width * rct.Height];
var source = new int[rct.Width * rct.Height];
var bits = SourceImage.LockBits(rct, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
Marshal.Copy(bits.Scan0, source, 0, source.Length);
SourceImage.UnlockBits(bits);
if (radius < 1) return;
int w = rct.Width;
int h = rct.Height;
int wm = w - 1;
int hm = h - 1;
int wh = w * h;
int div = radius + radius + 1;
var r = new int[wh];
var g = new int[wh];
var b = new int[wh];
int rsum, gsum, bsum, x, y, i, p1, p2, yi;
var vmin = new int[max(w, h)];
var vmax = new int[max(w, h)];
var dv = new int[256 * div];
for (i = 0; i < 256 * div; i++)
{
dv[i] = (i / div);
}
int yw = yi = 0;
for (y = 0; y < h; y++)
{ // blur horizontal
rsum = gsum = bsum = 0;
for (i = -radius; i <= radius; i++)
{
int p = source[yi + min(wm, max(i, 0))];
rsum += (p & 0xff0000) >> 16;
gsum += (p & 0x00ff00) >> 8;
bsum += p & 0x0000ff;
}
for (x = 0; x < w; x++)
{
r[yi] = dv[rsum];
g[yi] = dv[gsum];
b[yi] = dv[bsum];
if (y == 0)
{
vmin[x] = min(x + radius + 1, wm);
vmax[x] = max(x - radius, 0);
}
p1 = source[yw + vmin[x]];
p2 = source[yw + vmax[x]];
rsum += ((p1 & 0xff0000) - (p2 & 0xff0000)) >> 16;
gsum += ((p1 & 0x00ff00) - (p2 & 0x00ff00)) >> 8;
bsum += (p1 & 0x0000ff) - (p2 & 0x0000ff);
yi++;
}
yw += w;
}
for (x = 0; x < w; x++)
{ // blur vertical
rsum = gsum = bsum = 0;
int yp = -radius * w;
for (i = -radius; i <= radius; i++)
{
yi = max(0, yp) + x;
rsum += r[yi];
gsum += g[yi];
bsum += b[yi];
yp += w;
}
yi = x;
for (y = 0; y < h; y++)
{
dest[yi] = (int)(0xff000000u | (uint)(dv[rsum] << 16) | (uint)(dv[gsum] << 8) | (uint)dv[bsum]); // <--- Here's where I get the exception
if (x == 0)
{
vmin[y] = min(y + radius + 1, hm) * w;
vmax[y] = max(y - radius, 0) * w;
}
p1 = x + vmin[y];
p2 = x + vmax[y];
rsum += r[p1] - r[p2];
gsum += g[p1] - g[p2];
bsum += b[p1] - b[p2];
yi += w;
}
}
// copy back to image
var bits2 = SourceImage.LockBits(rct, ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
Marshal.Copy(dest, 0, bits2.Scan0, dest.Length);
SourceImage.UnlockBits(bits);
}
Here's how I call the function:
public Bitmap DownloadBlurredImage(List<string> uris, int blurradius)
{
Uri urlUri = new Uri(uris.ElementAt(0));
if (RandomSelect == true)
{
Random r = new Random();
urlUri = new Uri(uris.ElementAt(r.Next(0, uris.Count - 1)));
}
WebRequest webRequest = WebRequest.CreateDefault(urlUri);
webRequest.ContentType = "image/jpeg";
WebResponse webResponse = webRequest.GetResponse();
Stream mystream;
if ((mystream = webResponse.GetResponseStream()) != null)
{
Bitmap b = new Bitmap(mystream);
imageFilters.FastBlur(b, 10); //<--- here's where I'm calling
return b;
}
else
{
return null;
}
}
Does anyone know why this is acting up? I myself have NO clue..
You're using signed 'ints' to hold unsigned data - if the MSB is set, the overflow will occur. Use unsigned ints (for example for dest), or surround in an unchecked { } directive.
im tryn to add a new adaptive threshold method to the AForge.Imaging.Filters
I have added the new cs file under
Sources\Imaging\Filters\Adaptive Binarization
Below is the code for the thresholding methods
namespace AForge.Imaging.Filters
{
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using AForge.Imaging;
class SauvolaAdaptiveThresholding : BaseInPlacePartialFilter
{
private const float DEFAULT_WeightingFactor = 0.3f;
private const short DEFAULT_WindowSize = 40;
private float weightingFactor ;
private short windowSize ;
// private format translation dictionary
private Dictionary<PixelFormat, PixelFormat> formatTranslations = new Dictionary<PixelFormat, PixelFormat>();
/// <summary>
/// Format translations dictionary.
/// </summary>
public override Dictionary<PixelFormat,PixelFormat> FormatTranslations
{
get { return formatTranslations; }
}
public float WeightingFactor
{
get{return this.weightingFactor;}
set{this.weightingFactor = value;}
}
public short WindowSize
{
get{return this.windowSize;}
set{this.windowSize = value;}
}
public SauvolaAdaptiveThresholding() :
this(DEFAULT_WeightingFactor,DEFAULT_WindowSize) { }
public SauvolaAdaptiveThresholding(float _weightFact , short _wsize)
{
this.WeightingFactor = _weightFact;
this.WindowSize =_wsize;
// initialize format translation dictionary
formatTranslations[PixelFormat.Format8bppIndexed] = PixelFormat.Format8bppIndexed;
formatTranslations[PixelFormat.Format16bppGrayScale] = PixelFormat.Format16bppGrayScale;
}
protected override unsafe void ProcessFilter(UnmanagedImage image, Rectangle rect)
{
int whalf = windowSize >> 1; //half of windowsize
whalf = windowSize >> 1;
byte* ptr = (byte*)image.ImageData.ToPointer(); //input
// Calculate the integral image, and integral of the squared image
ulong[,] integral_image = new ulong[image.Width , image.Height];
ulong[,] rowsum_image = new ulong[image.Width , image.Height];
ulong[,] integral_sqimg = new ulong[image.Width , image.Height];
ulong[,] rowsum_sqimg = new ulong[image.Width , image.Height];
int xmin, ymin, xmax, ymax, index;
double diagsum, idiagsum, diff, sqdiagsum, sqidiagsum, sqdiff, area;
double mean, std, threshold;
for (int j = 0; j < image.Height; j++)
{
rowsum_image[0, j] = (ulong)*(ptr + j);
rowsum_sqimg[0, j] = rowsum_image[0, j] * rowsum_image[0, j];
}
for (int i = 1; i < image.Width; i++)
{
for (int j = 0; j < image.Height; j++)
{
index = j * image.Width + i;
rowsum_image[i, j] = rowsum_image[i - 1, j] + (ulong)*(ptr + index);
rowsum_sqimg[i, j] = rowsum_sqimg[i - 1, j] + (ulong)(*(ptr + index) * *(ptr + index));
}
}
for (int i = 0; i < image.Width; i++)
{
integral_image[i, 0] = rowsum_image[i, 0];
integral_sqimg[i, 0] = rowsum_sqimg[i, 0];
}
for (int i = 0; i < image.Width; i++)
{
for (int j = 1; j < image.Height; j++)
{
integral_image[i, j] = integral_image[i, j - 1] + rowsum_image[i, j];
integral_sqimg[i, j] = integral_sqimg[i, j - 1] + rowsum_sqimg[i, j];
}
}
//Calculate the mean and standard deviation using the integral image
for (int i = 0; i < image.Width; i++)
{
for (int j = 0; j < image.Height; j++)
{
xmin = Math.Max(0, i - whalf);//max(0, i - whalf);
ymin = Math.Max(0, j - whalf);
xmax = Math.Min(image.Width - 1, i + whalf);
ymax = Math.Min(image.Height - 1, j + whalf);
area = (xmax - xmin + 1) * (ymax - ymin + 1);
if (xmin == 0 && ymin == 0)
{ // Point at origin
diff = integral_image[xmax, ymax];
sqdiff = integral_sqimg[xmax, ymax];
}
else if (xmin == 0 && ymin != 0)
{ // first column
diff = integral_image[xmax, ymax] - integral_image[xmax, ymin - 1];
sqdiff = integral_sqimg[xmax, ymax] - integral_sqimg[xmax, ymin - 1];
}
else if (xmin != 0 && ymin == 0)
{ // first row
diff = integral_image[xmax, ymax] - integral_image[xmin - 1, ymax];
sqdiff = integral_sqimg[xmax, ymax] - integral_sqimg[xmin - 1, ymax];
}
else
{ // rest of the image
diagsum = integral_image[xmax, ymax] + integral_image[xmin - 1, ymin - 1];
idiagsum = integral_image[xmax, ymin - 1] + integral_image[xmin - 1, ymax];
diff = diagsum - idiagsum;
sqdiagsum = integral_sqimg[xmax, ymax] + integral_sqimg[xmin - 1, ymin - 1];
sqidiagsum = integral_sqimg[xmax, ymin - 1] + integral_sqimg[xmin - 1, ymax];
sqdiff = sqdiagsum - sqidiagsum;
}
mean = diff / area;
std = Math.Sqrt((sqdiff - diff * diff / area) / (area - 1));
threshold = mean * (1 + WeightingFactor * ((std / 128) - 1));
if ((double)*(ptr + (j * image.Width + i)) < threshold)//if (gray_image[i, j] < threshold)
*(ptr + (j * image.Width + i)) = 0;
else
*(ptr + (j * image.Width + i)) = 255;
}
}
}
}
}
but when i build the project and use the AForge.Imaging.dll, the above class isn't available. When i try to use the object browser i see all the other classes except for the one i added newly.
Can someone please tell me what am i doing wrong?
It needs to be public
public class SauvolaAdaptiveThresholding : BaseInPlacePartialFilter
You can find more info about the C# access modifiers here: http://msdn.microsoft.com/en-us/library/ms173121.aspx
I have encountered some difficulties while training my nn. When I use, lets say, 10 training sets, at the end of training procces neural network is trained just for the last two. I'm entering same values that I have used to train network and I am getting wrong results save for the last two. It seems to me that new nn memory suppresses older memory. I'm using 64 input neurons, 42 neurons in hidden layer and one output neuron. Sigmoid function is used for activating neurons. Training inputs and expected outputs are in 0 to 1 range. Does anyone have any clue what might be causing the problem?
Neuron b = new Neuron();
Fft f = new Fft();
float e = 2.71828f;
float eta = 0.05f;
float alpha = 0.05f;
float[] saw = new float[42];
float[] dh = new float[42];
float error = 0;
float dto = 0;
Random broj = new Random();
TextReader br = new StreamReader("d:/trening.txt");
TextReader ir = new StreamReader("d:\\input.txt");
float NextFloat(Random rng, float min, float max)
{
return (float)(min + (rng.NextDouble() * (max - min)));
}
public void load()//load memory
{
int i, j;
byte[] floatBytes;
BinaryReader br = new BinaryReader(File.Open("d:/memorija.txt", FileMode.Open));
for (j = 0; j <= 41; j++)
{
for (i = 0; i <= 64; i++)
{
floatBytes = br.ReadBytes(4);
b.w12[i][j] = BitConverter.ToSingle(floatBytes, 0);
}
}
for (j = 0; j <= 1; j++)
{
for (i = 0; i <= 41; i++)
{
floatBytes = br.ReadBytes(4);
b.w23[i][j] = BitConverter.ToSingle(floatBytes, 0);
}
}
br.Close();
}
public void trening()//Get training inputs and expected outputs
{ //Calls process methode
int i, n,ct=0;
using (TextReader tr = new StreamReader("d:/trening.txt"))
{
do
{
ct++;
} while (tr.ReadLine() != null);
tr.Close();
}
for (n = 0; n < (ct-1)/65; n++)
{
for (i = 1; i <= 65; i++)
b.input[i] = Convert.ToSingle(br.ReadLine());
process(b.input[65]);
target.Text = ((b.input[65]).ToString());
}
}
public void process(double t)//Trains nn using backpropagation
{
error = 0;
do
{
int i, j, k;
BinaryWriter bw = new BinaryWriter(File.Open("d:\\memorija.txt", FileMode.Create));
i = k = j = 0;
for (j = 1; j <= 41; j++)
{
b.ulaz2[j] = b.w12[0][j];
for (i = 1; i <= 64; i++)
{
b.ulaz2[j] += b.input[i] * b.w12[i][j];
} b.izlaz2[j] = (float)(1.0 / (1.0 + Math.Pow(e, -b.ulaz2[j])));
if (b.izlaz2[j] < 0)
MessageBox.Show(b.izlaz2[j].ToString());
}
for (k = 1; k <= 1; k++)
{
b.ulaz3 = b.w23[0][k];
for (j = 1; j <= 41; j++)
{
b.ulaz3 += b.izlaz2[j] * b.w23[j][k];
} b.izlaz = (float)(1.0 / (1.0 + Math.Pow(e, -b.ulaz3)));
error += (float)(0.5 * (t - b.izlaz) * (t - b.izlaz));
dto = (float)(t - b.izlaz) * b.izlaz * (1 - b.izlaz);
}
for (j = 1; j <= 41; j++)
{
saw[j] = 0;
for (k = 1; k <= 1; k++)
{
saw[j] += dto * b.izlaz2[j];
} dh[j] = saw[j] * b.izlaz2[j] * (1 - b.izlaz2[j]);
}
for (j = 1; j <= 41; j++)
{
b.w12d[0][j] = eta * dh[j] + alpha * b.w12d[0][j];
b.w12[0][j] += b.w12d[0][j];
for (i = 1; i <= 64; i++)
{
b.w12d[i][j] = eta * b.input[i] * dh[j] + alpha * b.w12d[i][j];
b.w12[i][j] += b.w12d[i][j];
}
}
for (k = 1; k <= 1; k++)
{
b.w23d[0][k] = eta * dto + alpha * b.w23d[0][k];
b.w23[0][k] += b.w23d[0][k];
for (j = 1; j <= 41; j++)
{
b.w23d[j][k] = eta * b.izlaz2[j] * dto + alpha * b.w23d[j][k];
b.w23[j][k] += b.w23d[j][k];
}
}
for (j = 0; j <= 41; j++)
{
for (i = 0; i <= 64; i++)
bw.Write(b.w12[i][j]);
}
for (j = 0; j <= 1; j++)
{
for (i = 0; i <= 41; i++)
bw.Write(b.w23[i][j]);
}
bw.Close();
izlazb.Text = Convert.ToString(b.izlaz);
errorl.Text = Convert.ToString(Math.Abs(b.izlaz - b.input[64]));
} while (Math.Abs(b.izlaz - t) > 0.03);
}
public void test()//This methode gets input values and gives output based on previous training
{
int i = 0, j = 0, k = 0;
for (i = 1; i < 65; i++)
b.input[i] = (float)Convert.ToDouble(ir.ReadLine());
for (j = 1; j <= 41; j++)
{
b.ulaz2[j] = b.w12[0][j];
for (i = 1; i <= 64; i++)
{
b.ulaz2[j] += b.input[i] * b.w12[i][j];
} b.izlaz2[j] = (float)(1.0 / (1.0 + Math.Pow(e, -b.ulaz2[j])));
}
for (k = 1; k <= 1; k++)
{
b.ulaz3 = b.w23[0][k];
for (j = 1; j <= 41; j++)
{
b.ulaz3 += b.izlaz2[j] * b.w23[j][k];
} b.izlaz = (float)(1.0 / (1.0 + Math.Pow(e, -b.ulaz3)));
} izlazb.Text = Convert.ToString(b.izlaz);
target.Text = "/";
errorl.Text = "/";
}
public void reset()//Resets memory
{
BinaryWriter fw = new BinaryWriter(File.Open("d:\\memorija.txt", FileMode.Create));
int i = 0;
int j = 0;
Random broj = new Random();
for (j = 0; j <= 41; j++)
{
for (i = 0; i <= 64; i++)
{
b.w12[i][j] = 0;
b.w12[i][j] = 2 * (NextFloat(broj, -0.5f, 0.5f));
fw.Write(b.w12[i][j]);
}
}
for (j = 0; j <= 1; j++)
{
for (i = 0; i <= 41; i++)
{
b.w23[i][j] = 0;
b.w23[i][j] = 2 * (NextFloat(broj, -0.5f, 0.5f));
fw.Write(b.w23[i][j]);
}
}
fw.Close();
}
}
}
And neuron class
public class Neuron
{
public float[][] w12 = new float[65][];//(65, 42);
public float[][] w12d = new float[65][];//(65, 42);
public float[][] w23 = new float[42][];//(42,2);
public float[][] w23d = new float[42][];//(42, 2);
public float[] ulaz2 = new float[42];
public float[] izlaz2 = new float[42];
public float ulaz3;
public float[] input =new float[66];
public static float[] ioutput;
public float izlaz;
public void arrayInit()
{
int i, j;
for (i = 0; i <=64; i++)
{
w12[i] = new float[42];
w12d[i] = new float[42];
}
for (i = 0; i <42; i++)
{
w23[i] = new float[2];
w23d[i] = new float[2];
}
for (j = 0; j < 42; j++)
for (i = 0; i <=64; i++)
{
w12[i][j] = 0;
w12d[i][j] = 0;
}
for (j = 0; j < 2; j++)
for (i = 0; i < 42; i++)
{
w23[i][j] = 0;
w23d[i][j] = 0;
}
}
}
I found out what the problem was. I didn't mix training arrays, I was introducing one array to nn until it was trained for it, instead of introducing all arrays in cyclic manner. I hope this will be useful for someone.