Added Neural network code

This commit is contained in:
2017-12-20 12:21:17 +01:00
parent 8175417c23
commit 6c3eeac6fb
212 changed files with 5140 additions and 92 deletions
+335
View File
@@ -0,0 +1,335 @@
// avansvisionlib - Growing Visionlibrary of Avans based on OpenCV 2.4.10
// Goal: deep understanding of vision algorithms by means of developing own (new) algorithms.
// deep understanding of neural networks
//
// Copyright Jan Oostindie, version 2.0 dd 5-12-2016 (= Neural Network (BPN) added to version 1.0 dd 5-11-2016.)
// Contains basic functions to perform calculations on matrices/images of class Mat. Including BLOB labeling functions
// Contains a BPN neural network.
// Note: Students of Avans are free to use this library in projects and for own vision competence development. Others may ask permission to use it by means
// of sending an email to Jan Oostindie, i.e. jac.oostindie@avans.nl
#pragma once
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv/cv.h>
#include <iostream>
#include <string>
using namespace cv;
using namespace std;
// remark: a function call with a Mat-object parameter is a call by reference
/*********************** PROTOTYPES of the function library ************************/
// func: setup a specified entry (i,j) of a matrix m with a specific value
// pre: (i < m.rows) & (j < m.cols)
void setEntry(Mat m, int i, int j, double value);
// func: get the value of a specified entry (i,j) of a matrix m
// pre: (i < m.rows) & (j < m.cols)
// return: <return_value> == m(i,j)
double getEntry(Mat m, int i, int j);
// func: calculate product of a row and column of equal length
// pre: (row.cols == col.rows) & (row.rows == 1) & (col.cols == 1)
double inproduct(Mat row, Mat col);
// func: prints matrix m in the console
// pre: true
void printMatrix(Mat m);
// func: select and get a row of a matrix m. rowNr contains the row number
// pre: 0 < rowNr < m.rows
// return: <result matrix> contains the selected row
Mat getRow(Mat m, int rowNr);
// func: get a column of a matrix m. colNr contains the column number
// pre: 0 < colNr < m.cols
// return: <result matrix> contains the selected column
Mat getCol(Mat m, int colNr);
// func: multiply two matrices a and b
// pre: (a.cols == b.rows)
// return: <result matrix>.rows == b.rows & <result matrix>.cols == b.cols
Mat multiply(Mat a, Mat b);
// pre: matrices have equal dimensions i.e. (a.cols == b.cols) & (a.rows == b.rows)
// return: <result matrix>(i,j) == a(i,j) + b(i,j) for all (0,0) <= (i,j) < (a.rows,a.cols)
Mat add(Mat a, Mat b);
// func: transposes a matrix
// return: <return_matrix>(i,j) = m(j,i) & <return_matrix>.rows = m.cols & <return_matrix>.cols = m.rows
Mat transpose(Mat m);
// func: sets all entries of a matrix to a certain value
// pre: true
void setValue(Mat m, double value);
// func: generates a randomvalue between min and max
// pre: true
double generateRandomValue(double min, double max);
// func: sets all entries of a matrix to a random value
// pre: true
void setRandomValue(Mat m, double min, double max);
/*********************************** Image operaties ****************************************/
// NB images are supposed to have 1 channel (B/W image) and depth 16 bits signed (CV_16S)
/********************************************************************************************/
// func: setup a specified entry (i,j) of a matrix m with a specific value
// pre: (i < m.rows) & (j < m.cols)
void setEntryImage(Mat m, int i, int j, _int16 value);
// func: get the value of a specified entry (i,j) of a matrix m
// pre: (i < m.rows) & (j < m.cols)
// return: <return_value> == m(i,j)
_int16 getEntryImage(Mat m, int i, int j);
// func: calculate product of a row and column of equal length
// pre: (row.cols == col.rows) & (row.rows == 1) & (col.cols == 1)
_int16 inproductImage(Mat row, Mat col);
// func: select and get a row of a matrix m. rowNr contains the row number
// pre: 0 < rowNr < m.rows
// return: <result matrix> contains the selected row
Mat getRowImage(Mat m, int rowNr);
// func: get a column of a matrix m. colNr contains the column number
// pre: 0 < colNr < m.cols
// return: <result matrix> contains the selected column
Mat getColImage(Mat m, int colNr);
// func: multiply two matrices a and b
// pre: (a.cols == b.rows)
// return: <result matrix>.rows == b.rows & <result matrix>.cols == b.cols
Mat multiplyImage(Mat a, Mat b);
// pre: matrices have equal dimensions i.e. (a.cols == b.cols) & (a.rows == b.rows)
// return: <result matrix>(i,j) == a(i,j) + b(i,j) for all (0,0) <= (i,j) < (a.rows,a.cols)
Mat addImage(Mat a, Mat b);
// func: searches the maximum pixel value in the image
// return: maximum pixel value
_int16 maxPixelImage(Mat m);
// func: searches the minimum pixel value in the image
// return: minimum pixel value
_int16 minPixelImage(Mat m);
// func: determines the range of the image, i.e. the minimum
// and maximum pixel value in the image
// post: range = minPixelValue, maxPixelValue
void getPixelRangeImage(Mat m, _int16 &minPixelValue, _int16 &maxPixelValue);
// func: transform scale the image
// return: maximum pixel value
void stretchImage(Mat m, _int16 minPixelValue, _int16 maxPixelValue);
// func: shows a 16S image on the screen. All values mapped on the interval 0-255
/// pre: m is a 16S image (depth 16 bits, signed)
void show16SImageStretch(Mat m, string windowTitle = "show16SImageStretch");
// func: shows a 16S image on the screen. All values clipped to the interval 0-255
// i.e. value < 0 => 0; 0 <= value <= 255 => value ; value > 255 => 255
/// pre: m is a 16S image (depth 16 bits, signed)
void show16SImageClip(Mat m, string windowTitle = "show16SImageClip");
// func: histogram gamma correction
// pre: image has depth 8 bits unsigned and 1 or 3 channels
// post: entry(i,j) = 255*power(entry@pre(i,j)/255)^gamma
void gammaCorrection(Mat image, float gamma);
// func: makes a administration used for labeling blobs.
// the function adds a edge of 1 pixel wide tot a binary image, all with value 0.
// All 1's are made -1. The result is returned.
// This function is used by function labelBLOBs
// pre : binaryImage has depth 16 bits signed int. Contains only values 0 and 1.
// return_matrix: All "1" are made "-1" meaning value 1 and unvisited.
Mat makeAdmin(Mat binaryImage);
// func: Searches the next blob after position (row,col)
// post: if return_value == 1 then (row,col) contains the position
// where the next blob starts.
// return_value: true => blob found ; starting position is (row,col)
// false => no blob found ; (row, col) == (-1, -1)
bool findNextBlob(Mat admin, int & row, int & col);
// func: searches the first 1 when rotating around the pixel (currX,currY),
// starting at position 0. Definition of relative positions:
// 7 0 1
// 6 X 2
// 5 4 3
void findNext1(Mat admin, int & currX, int & currY, int & next1);
// func: gets the entry of a neighbour pixel with relative position nr.
// Definition of relative positions nr:
// 7 0 1
// 6 X 2
// 5 4 3
_int16 getEntryNeighbour(const Mat & admin, int x, int y, int nr);
// func: determines if there are more than 1 adjacent 1's
bool moreNext1(const Mat & admin, int x, int y);
// func: labels all pixels of one blob which starts at position (row,col) with blobNr.
// This function is used by function labelBLOB's which labels all blobs.
// return_value: area of the blob
// Evaluation: This function uses a iterative algorithm in which a special labeling technique is
// is used which gives the opportunity to trace all individiual pixels. This makes it
// possible for example to save only these pixels on disk or to translate the object in
// in the image.
// The disadvantagae however is that the algorithm is more complicated an maybe a little bit
// slower than the recursive variant.
int labelIter(Mat & admin, int row, int col, int blobNr);
// func: labels all pixels of one blob which starts at position (row,col) with blobNr.
// return_value: area of the blob
// Evaluation: This function uses a recursive algorithm which has the advantage that it is easy and trasparent.
// The disadvantagae however is that it claims a lot of spacee on the stack. I.e. every found
// pixel results in a function call which in case of large blobs causes a stack overflow.
int labelRecursive(Mat & admin, int row, int col, int blobNr);
// func: retrieves a labeledImage from the labeling administration
// pre : admin is contains labeled pixels with neighbour number information.
// post: labeledImage: binary 8-connected pixels with value 1 in binaryImage are
// labeled with the number of the object they belong to.
void retrieveLabeledImage(const Mat & admin, Mat & labeledImage);
// func: labeling of all blobs in a binary image
// pre : binaryImage has depth 16 bits signed int. Contains only values 0 and 1.
// post: labeledImage: binary 8-connected pixels with value 1 in binaryImage are
// labeled with the number of the object they belong to.
// return_value: the total number of objects.
int labelBLOBs(Mat binaryImage, Mat & labeledImage);
// func: labeling of all blobs in a binary image with a area in [threshAreaMin,threshAreaMax]. Default
// threshold is [1,INT_MAX]. Alle gathered data during the labeling proces is returned,
// i.e. the positions of the firstpixel of each blob, the position of the blobs (i.e. the
// centres of gravity) and the area's of all blobs.
// pre : binaryImage has depth 16 bits signed int. Contains only values 0 and 1.
// post: labeledImage: binary 8-connected pixels with value 1 in binaryImage are
// labeled with the number of the object they belong to.
// areaVec: contains all area's of the blobs. The index corresponds to the number
// of the blobs. Index 0 has no meaning.
// return_value: the total number of objects.
int labelBLOBsInfo(Mat binaryImage, Mat & labeledImage,
vector<Point2d *> & firstpixelVec, vector<Point2d *> & posVec,
vector<int> & areaVec,
int threshAreaMin = 1, int threshAreaMax = INT_MAX);
/*****************************************************************************************************************************************************/
/*BEGIN********************************************** BACK PROPAGATION NEURAL NETWORK ****************************************************************/
/*****************************************************************************************************************************************************/
// func: loads an example of a training set
// pre: true
// post: ITset input training set. Each row contains a number of features.
// OTset output training set. Each row contains the expected output belonging to the corresponding row of features in the input training set.
//
// TRAININGSET: I0 because of bias V0
//
// setnr I0 I1 I2 I3 I4 O1 O2
// 1 1.0 0.4 -0.7 0.1 0.71 0.0 0.0
// 2 1.0 0.3 -0.5 0.05 0.34 0.0 0.0
// 3 1.0 0.6 0.1 0.3 0.12 0.0 1.0
// 4 1.0 0.2 0.4 0.25 0.34 0.0 1.0
// 5 1.0 -0.2 0.12 0.56 1.0 1.0 0.0
// 6 1.0 0.1 -0.34 0.12 0.56 1.0 0.0
// 7 1.0 -0.6 0.12 0.56 1.0 1.0 1.0
// 8 1.0 0.56 -0.2 0.12 0.56 1.0 1.0
void loadTrainingSet1(Mat & ITset, Mat & OTset);
// func: loads an example of a training set in which only binary numbers are used.
// pre: true
// post: ITset input training set. Each row contains a number of binary numbers.
// OTset output training set. Each row contains the expected output belonging to the corresponding row of binary numbers in the input training set.
//
// TRAININGSET binary function O1 = (I1 OR I2) AND I3
// without bias
// setnr I1 I2 I3 O1
// 1 0 0 0 0
// 2 0 0 1 0
// 3 0 1 0 0
// 4 0 1 1 1
// 5 1 0 0 0
// 6 1 0 1 1
// 7 1 1 0 0
// 8 1 1 1 1
void loadBinaryTrainingSet1(Mat & ITset, Mat & OTset);
// func: Initialization of the (1) weigthmatrices V0 and W0 and (2) of the delta matrices dV0 and dW0.
// pre: inputNeurons, hiddenNeurons and outputNeurons define the Neural Network.
// (from these numbers the dimensions of the weightmatrices can be determined)
// post: V0 and W0 have random values between 0.1 and 0.9
void initializeBPN(int inputNeurons, int hiddenNeurons, int outputNeurons,
Mat & V0, Mat & dV0, Mat & W0, Mat & dW0);
// Test of a BPN with all values defined explicitly.
// pre: true
// post: IT is the input training set ; OT is the corresponding output training set. ; V0, W0 are the weight matrices of a BPN with 1 hidden layer;
// dV0, dW0 are the initial delta matrices of the weight factor matrices.
void testBPN(Mat & IT, Mat & OT, Mat & V0, Mat & dV0, Mat & W0, Mat & dW0);
// func: Given an inputvector of the inputlayer and a weightmatrix V calculates the outputvector of the hiddenlayer
// pre: II is input of the inputlayer. V = matrix with weightfactors between inputlayer and the hiddenlayer.
// post: OH is the outputvector of the hidden layer
void calculateOutputHiddenLayer(Mat II, Mat V, Mat & OH);
// func: Given the outputvector of the hiddenlayer and a weigthmatrix W calculates the outputvector of the outputlayer
// pre: OH is the outputvector of the hiddenlayer. W = matrix with weightfactors between hiddenlayer and the outputlayer.
// post: OO is the outputvector of the output layer
void calculateOutputBPN(Mat OH, Mat W, Mat & OO);
// func: Calculates the total error Error = 1/2*Sigma(OTi-OOi)^2.
// OTi is the expected output according to the trainingvector i
// OOi is the calculated output from the current neural network of the traininngvector i
// pre: OO is the outputvector of the outputlayer. OT is the expected outputvector from the trainingset
// post: OO is the outputvector of the output layer
void calculateOutputBPNError(Mat OO, Mat OT, double & outputError);
// func: calculates the updates of the weight factor matrices V0 and W0 on basics of the calculated output matrix and the expected output matrix.
// A back propagation algorithm is used.
// pre: OT is the expected outputvector from the trainingset ; OO is the calculated outputvector of the outputlayer ;
// OH is the calculated output of the hiddenlayer ; OI is the output of the inputlayer (normaly equal to the input of the inputlayer)
// V0 is the weight matrix between the input layer and the hidden layer ; W0 is the weight matrix between the hiddenlayer and the output layer.
// dV0, dW0 are the correction matrices.
// post: V is the adapted weight matrix between the inputlayer and the hidden layer ; W is the weight matrix between the hiddenlayer and the output layer.
void adaptVW(Mat OT, Mat OO, Mat OH, Mat OI, Mat W0, Mat dW0, Mat V0, Mat dV0, Mat & W, Mat & V,
double ALPHA = 1.0, double ETHA = 0.6);
// func: given an inputvector calculates the output of a BPN with weigth matrices V and W.
// pre: II is the input vector of the BPN ;
// V is the weight factor matrix between the input layer and the hidden layer
// W is the weight factor matrix between the hidden layer and the output layer
// return: output vector
Mat BPN(Mat II, Mat V, Mat W);
/*****************************************************************************************************************************************************/
/*END********************************************** BACK PROPAGATION NEURAL NETWORK ******************************************************************/
/*****************************************************************************************************************************************************/