Last active
May 24, 2017 12:58
-
-
Save ollewelin/dd94fc45a99b3fb34a1479270716dc23 to your computer and use it in GitHub Desktop.
Autoencoder neural network raspberry pi
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//Autoencoder learning test with raspicam | |
//press <Y> at start It's tested with 0..9 28x28 pixel digits pattern mnist.png filname 289x289 orginal | |
//orginal image taken from | |
// https://blog.webkid.io/datasets-for-machine-learning/ | |
//#define USE_RASPICAM_INPUT //If you want to use raspicam input data | |
#include <opencv2/highgui/highgui.hpp> // OpenCV window I/O | |
#include <opencv2/imgproc/imgproc.hpp> // Gaussian Blur | |
#include <stdio.h> | |
#include <raspicam/raspicam_cv.h> | |
#include <opencv2/opencv.hpp> | |
#include <opencv2/core/core.hpp> // Basic OpenCV structures (cv::Mat, Scalar) | |
#include <cstdlib> | |
#include <ctime> | |
#include <math.h> // exp | |
#include <stdlib.h>// exit(0); | |
//#include <iostream> | |
char filename[100]; | |
char filename2[100]; | |
char filename_dst[100]; | |
using namespace std; | |
using namespace cv; | |
//const float LearningRate =0.05; | |
//const float Momentum = 0.025; | |
const float LearningRate =0.02; | |
const float Momentum = 0.04; | |
// float noise_percent =50.0f; | |
float noise_percent =30.0f; | |
void sigmoid_mat(Mat image) | |
{ | |
float* ptr_src_index; | |
ptr_src_index = image.ptr<float>(0); | |
int nRows = image.rows; | |
int nCols = image.cols; | |
for(int i=0;i<nRows;i++) | |
{ | |
for(int j=0;j<nCols;j++) | |
{ | |
*ptr_src_index = 1.0/(1.0 + exp(-(*ptr_src_index)));//Sigmoid function | |
ptr_src_index++; | |
} | |
} | |
} | |
#include <termios.h> | |
#include <unistd.h> | |
#include <fcntl.h> | |
int kbhit(void) | |
{ | |
struct termios oldt, newt; | |
int ch; | |
int oldf; | |
tcgetattr(STDIN_FILENO, &oldt); | |
newt = oldt; | |
newt.c_lflag &= ~(ICANON | ECHO); | |
tcsetattr(STDIN_FILENO, TCSANOW, &newt); | |
oldf = fcntl(STDIN_FILENO, F_GETFL, 0); | |
fcntl(STDIN_FILENO, F_SETFL, oldf | O_NONBLOCK); | |
ch = getchar(); | |
tcsetattr(STDIN_FILENO, TCSANOW, &oldt); | |
fcntl(STDIN_FILENO, F_SETFL, oldf); | |
if(ch != EOF) | |
{ | |
ungetc(ch, stdin); | |
return 1; | |
} | |
return 0; | |
} | |
void local_normalizing(Mat gray) | |
{ | |
#define BLUR_FLT_NUMERATOR 2 | |
#define BLUR_FLT_DENOMINATOR 20 | |
Mat float_gray, blur, num, den, store_gray; | |
store_gray = gray;//Initialize size | |
// convert to floating-point image | |
gray.convertTo(float_gray, CV_32F, 1.0/255.0); | |
// numerator = img - gauss_blur(img) | |
cv::GaussianBlur(float_gray, blur, Size(0,0), BLUR_FLT_NUMERATOR, BLUR_FLT_NUMERATOR); | |
num = float_gray - blur; | |
// denominator = sqrt(gauss_blur(img^2)) | |
cv::GaussianBlur(num.mul(num), blur, Size(0,0), BLUR_FLT_DENOMINATOR, BLUR_FLT_DENOMINATOR); | |
cv::pow(blur, 0.5, den); | |
// output = numerator / denominator | |
gray = num / den; | |
// normalize output into [0,1] | |
cv::normalize(gray, gray, 0.0, 1.0, NORM_MINMAX, -1); | |
// Display | |
//namedWindow("demo", CV_WINDOW_AUTOSIZE ); | |
gray.convertTo(store_gray, CV_8U, 255); | |
//imshow("demo", gray); | |
} | |
//attach_weight_2_mat(ptr_M_matrix, i, visual_all_feature, sqr_of_H_nod_plus1, Hidden_nodes, Height, Width); | |
void attach_weight_2_mat(float* ptr_M_matrix, int i, Mat src, int sqr_of_H_nod_plus1, int Hidden_nodes, int Height, int Width) | |
{ | |
float *start_corner_offset = src.ptr<float>(0); | |
int start_offset=0; | |
float *src_zero_ptr = src.ptr<float>(0); | |
float *src_ptr = src.ptr<float>(0); | |
for(int j=0; j<Hidden_nodes ; j++) | |
{ | |
start_offset = (j/sqr_of_H_nod_plus1)*Height*src.cols + (j%sqr_of_H_nod_plus1)*Width; | |
start_corner_offset = start_offset + src_zero_ptr; | |
src_ptr = start_corner_offset + (i/Width)*src.cols + (i%Width); | |
*src_ptr = *ptr_M_matrix; | |
ptr_M_matrix++; | |
} | |
} | |
int main() | |
{ | |
float Rando=0.0f; | |
// float start_noise_range = 0.25f;//+/- start weight noise range | |
float start_noise_range = 0.025f;//+/- start weight noise range | |
printf("Auto encoder test program\n"); | |
//int get_data =0; | |
int Height=0; | |
int Width=0; | |
int nr_of_pixels=0; | |
int Hidden_nodes=0; | |
int nr_of_pictures=0; | |
int training_image=0; | |
char answer_character; | |
printf("Do you want default settings <Y>/<N> ? \n"); | |
answer_character = getchar(); | |
if(answer_character == 'Y' || answer_character == 'y') | |
{ | |
// Height = 48; | |
// Width = 64; | |
Height = 28; | |
Width = 28; | |
Hidden_nodes = 40; | |
nr_of_pictures = 80; | |
} | |
else | |
{ | |
printf("Enter number of pixel Height of input pictures\n"); | |
scanf("%d", &Height); | |
printf("Enter number of pixel Width of input pictures\n"); | |
scanf("%d", &Width); | |
printf("Enter number of hidden nodes of input pictures\n"); | |
scanf("%d", &Hidden_nodes); | |
printf("Enter number of hidden training pictures posXXX.JPG \n"); | |
scanf("%d", &nr_of_pictures); | |
} | |
nr_of_pixels = Height * Width; | |
printf("Number of pixels = %d\n", nr_of_pixels); | |
Mat src, image, mnist,m_gray; | |
///************** Raspicam ************** | |
#ifdef USE_RASPICAM_INPUT | |
raspicam::RaspiCam_Cv Camera; | |
Camera.set( CV_CAP_PROP_FRAME_WIDTH, Width); | |
Camera.set( CV_CAP_PROP_FRAME_HEIGHT, Height); | |
Camera.set( CV_CAP_PROP_FORMAT, CV_8UC1 ); | |
//Camera.set( CV_CAP_PROP_FORMAT, CV_8U ); | |
//Open camera | |
cout<<"Opening Camera..."<<endl; | |
if (!Camera.open()) {cerr<<"Error opening the camera"<<endl;return -1;} | |
Camera.grab(); | |
Camera.retrieve (src); | |
waitKey(1); | |
src.convertTo(image, CV_32F, 1.0/255.0);//Convert pixels from 0..255 char to float 0..1 | |
#endif // USE_RASPICAM_INPUT | |
///*************************************** | |
#ifndef USE_RASPICAM_INPUT | |
///************Open mnist image ******** | |
sprintf(filename2, "mnist_480_360.jpg");//Assigne a filename "pos" with index number added | |
sprintf(filename2, "mnist.png");//Assigne a filename "pos" with index number added | |
mnist = imread( filename2, 1 ); | |
if ( !mnist.data ) | |
{ | |
printf("\n"); | |
printf("==================================================\n"); | |
printf("No image data Error! Probably not find mnist_480_360.jpg \n"); | |
printf("==================================================\n"); | |
printf("\n"); | |
//return -1; | |
} | |
cvtColor(mnist,m_gray,CV_BGR2GRAY); | |
imshow("m_gray", m_gray); | |
waitKey(1); | |
int mnist_h1 = 28; | |
int mnist_w1 = 28; | |
int mnh=0; | |
int mnw=0; | |
int pos = 0; | |
int ret; | |
// Mat m1; | |
for(int j=0;j<8;j++) | |
{ | |
for(int i=0;i<10;i++) | |
{ | |
// Mat m1(image, Rect(0, 0, T0_FRAME_WIDTH, T0_FRAME_HEIGHT));// Rect(<start_x>, <start_y>, <width>, <hight>) | |
//48 x 45 | |
mnh = j*mnist_h1+j*1; | |
mnw = i*mnist_w1+i*1; | |
Mat m1(m_gray, Rect(mnw, mnh, mnist_w1, mnist_h1));// Rect(<start_x>, <start_y>, <width>, <hight>) | |
cv::imwrite("temporary_file.JPG",m1); | |
sprintf(filename_dst, "pos%d.JPG", pos); | |
ret = rename("temporary_file.JPG", filename_dst); | |
if(ret == 0) | |
{ | |
printf("File renamed successfully"); | |
} | |
else | |
{ | |
printf("Error: unable to rename the file"); | |
} | |
pos++; | |
} | |
} | |
///************************************* | |
#endif // USE_RASPICAM_INPUT | |
// mat_H = | |
float *input_node; | |
input_node = new float[nr_of_pixels]; | |
float *hidden_node; | |
hidden_node = new float[Hidden_nodes]; | |
float *output_node; | |
output_node = new float[nr_of_pixels]; | |
float **weight_matrix_M;//Pointer fo a dynamic array. This weight_matrix_M will then have a size of rows = nr_of_pixels, colums = Hidden_nodes. | |
float **change_weight_M;//Pointer fo a dynamic array. This weight_matrix_M will then have a size of rows = nr_of_pixels, colums = Hidden_nodes. | |
weight_matrix_M = new float *[nr_of_pixels]; | |
change_weight_M = new float *[nr_of_pixels]; | |
for(int i=0; i < nr_of_pixels; i++) | |
{ | |
weight_matrix_M[i] = new float[Hidden_nodes]; | |
change_weight_M[i] = new float[Hidden_nodes]; | |
} | |
printf("size of weight_matrix_M[2][0] =%d\n", sizeof weight_matrix_M[2][0]); | |
int sqr_of_H_nod_plus1=0; | |
sqr_of_H_nod_plus1 = sqrt(Hidden_nodes); | |
sqr_of_H_nod_plus1 += 1; | |
printf("sqr_of_H_nod_plus1 %d\n", sqr_of_H_nod_plus1); | |
float* ptr_M_matrix; | |
Mat visual_all_feature, outimg; | |
visual_all_feature.create(Height * sqr_of_H_nod_plus1, Width * sqr_of_H_nod_plus1,CV_32F); | |
outimg.create(Height, Width, CV_32F); | |
srand (static_cast <unsigned> (time(0)));//Seed the randomizer | |
for(int i=0;i<nr_of_pixels;i++) | |
{ | |
ptr_M_matrix = &weight_matrix_M[i][0]; | |
for(int j=0;j<(Hidden_nodes);j++) | |
{ | |
Rando = (float) (rand() % 65535) / 65536;//0..1.0 range | |
Rando -= 0.5f; | |
Rando *= start_noise_range; | |
*ptr_M_matrix = Rando; | |
ptr_M_matrix++; | |
change_weight_M[i][j] = 0.0f; | |
} | |
} | |
for(int i=0;i<nr_of_pixels;i++) | |
{ | |
ptr_M_matrix = &weight_matrix_M[i][0]; | |
attach_weight_2_mat(ptr_M_matrix, i, visual_all_feature, sqr_of_H_nod_plus1, Hidden_nodes, Height, Width); | |
} | |
// local_normalizing(visual_all_feature); | |
//test on | |
visual_all_feature += 0.5f; | |
Mat color_img, gray; | |
srand (static_cast <unsigned> (time(0)));//Seed the randomizer | |
float error=0.0; | |
float *zero_ptr_gray = gray.ptr<float>(0); | |
float *ptr_gray = gray.ptr<float>(0); | |
ptr_gray = zero_ptr_gray + (gray.cols * (gray.rows/2)) + gray.cols/2; | |
float test_pixel_value = *ptr_gray; | |
int *noise_pixels; | |
noise_pixels = new int[nr_of_pixels]; | |
int noise_p_counter=0; | |
float noise_ratio=0.0f; | |
int nr_of_noise_rand_ittr=0; | |
int rand_pix_pos=0; | |
char keyboard; | |
int started = 1; | |
while(1) | |
{ | |
#ifdef USE_RASPICAM_INPUT | |
Camera.grab(); | |
Camera.retrieve (src); | |
waitKey(1); | |
src.convertTo(image, CV_32F, 1.0/255.0);//Convert pixels from 0..255 char to float 0..1 | |
imshow("image", image); | |
gray = image;//Connect raspberry camera instead of posXXX.jpg image | |
#else | |
training_image = rand() % nr_of_pictures; | |
// printf("training_image %d\n", training_image); | |
sprintf(filename, "pos%d.JPG", training_image);//Assigne a filename "pos" with index number added | |
color_img = imread( filename, 1 ); | |
if ( !color_img.data ) | |
{ | |
printf("\n"); | |
printf("==================================================\n"); | |
printf("No image data Error! Probably not find pos%d.JPG \n", training_image); | |
printf("==================================================\n"); | |
printf("\n"); | |
//return -1; | |
} | |
cvtColor(color_img,gray,CV_BGR2GRAY); | |
imshow("color_img", color_img); | |
gray.convertTo(gray, CV_32F, 1.0/255.0);//Convert pixels from 0..255 char to float 0..1 | |
#endif // USE_RASPICAM_INPUT | |
// local_normalizing(gray); | |
sigmoid_mat(gray); | |
zero_ptr_gray = gray.ptr<float>(0); | |
ptr_gray = gray.ptr<float>(0); | |
///****************************************************** | |
///************ Select noise pixels positions *********** | |
///****************************************************** | |
noise_p_counter=0; | |
noise_ratio=0.0f; | |
nr_of_noise_rand_ittr=0; | |
rand_pix_pos=0; | |
for(int n=0;n<nr_of_pixels;n++) | |
{ | |
noise_pixels[n] = 0; | |
} | |
while(noise_ratio < (noise_percent*0.01f)) | |
{ | |
rand_pix_pos = (int) (rand() % nr_of_pixels); | |
if(noise_pixels[rand_pix_pos] == 0) | |
{ | |
noise_p_counter++; | |
} | |
noise_pixels[rand_pix_pos] = 1; | |
noise_ratio = ((float)noise_p_counter) / ((float)nr_of_pixels); | |
nr_of_noise_rand_ittr++; | |
if(nr_of_noise_rand_ittr > 2*nr_of_pixels) | |
{ | |
printf("give up fill random up noise this turn\n"); | |
printf("noise_ratio %f\n", noise_ratio); | |
break; | |
} | |
} | |
///**************************************************** | |
///**************** Feed forward ********************** | |
///**************************************************** | |
///Connect image pixel and also insert noise to input_node[] | |
for(int n=0;n<nr_of_pixels;n++) | |
{ | |
if(noise_pixels[n] == 1 && started == 1) | |
{ | |
input_node[n] = 0.5f;///Insert noise 0.5f instead of real pixel value | |
} | |
else | |
{ | |
ptr_gray = zero_ptr_gray + n; | |
input_node[n] = *ptr_gray;///Insert pixel value | |
} | |
} | |
///*********** Forward to hidden nodes **************** | |
for(int j=0;j<Hidden_nodes;j++) | |
{ | |
hidden_node[j] = 0; | |
for(int i=0;i<nr_of_pixels;i++) | |
{ | |
hidden_node[j] += input_node[i] * weight_matrix_M[i][j];///Sum up values from input gained with weight | |
} | |
///*** Sigmoid this node *** | |
hidden_node[j] = 1.0/(1.0 + exp(-(hidden_node[j])));///Sigmoid function | |
} | |
///********** Forward to output nodes ******************* | |
for(int i=0;i<nr_of_pixels;i++) | |
{ | |
output_node[i] = 0.0f; | |
for(int j=0;j<Hidden_nodes;j++) | |
{ | |
output_node[i] += hidden_node[j] * weight_matrix_M[i][j];///Sum up values from hidden gained with weight | |
} | |
output_node[i] = 1.0/(1.0 + exp(-(output_node[i])));///Sigmoid function | |
} | |
float input_pixel =0.0f; | |
///**************************************************** | |
///************* Calculate total loss ***************** | |
///**************************************************** | |
/// k = nr_of_pixel | |
/// loss = -SUM k (output[k] * log(input[k]) + (1.0 - output[k]) * log(1.0 - input[k])) | |
/// or | |
/// loss = 1/2 SUM k (input[k] - ouput[k])² | |
float loss=0.0f; | |
loss=0.0f; | |
for(int i=0;i<nr_of_pixels;i++) | |
{ | |
ptr_gray = zero_ptr_gray + i;///pick real input pixel | |
input_pixel = *ptr_gray;///Insert pixel value | |
loss += (input_pixel - output_node[i]) * (input_pixel - output_node[i]);/// loss = 1/2 SUM k (input[k] - ouput[k])² | |
} | |
static int print_loss=0; | |
if(print_loss<10) | |
{ | |
print_loss++; | |
} | |
else | |
{ | |
printf("loss error = %f\n", loss); | |
print_loss=0; | |
} | |
///**************************************************** | |
///**************** Backpropagation ******************* | |
///**************************************************** | |
/// **** make Delta value for backpropagation and loss calculation **** | |
float delta_pixel=0.0f; | |
for(int i=0;i<nr_of_pixels;i++) | |
{ | |
ptr_gray = zero_ptr_gray + i;///pick real input pixel | |
input_pixel = *ptr_gray;///Insert pixel value | |
delta_pixel = input_pixel - output_node[i] ;/// detal calculus | |
/// **** update tied weight regarding delta | |
for(int j=0;j<Hidden_nodes;j++) | |
{ | |
if(started == 1) | |
{ | |
change_weight_M[i][j] = LearningRate * hidden_node[j] * delta_pixel + Momentum * change_weight_M[i][j]; | |
weight_matrix_M[i][j] += change_weight_M[i][j]; | |
} | |
} | |
} | |
float *zero_ptr_outimg = outimg.ptr<float>(0); | |
float *ptr_outimg = outimg.ptr<float>(0); | |
for(int i=0;i<nr_of_pixels;i++) | |
{ | |
ptr_outimg = zero_ptr_outimg + i; | |
*ptr_outimg = output_node[i]; | |
} | |
gray -= 0.5; | |
outimg -= 0.5; | |
visual_all_feature -= 0.5; | |
gray *= 2; | |
outimg *= 2; | |
visual_all_feature *= 2; | |
gray += 0.5; | |
outimg += 0.5; | |
visual_all_feature += 0.5; | |
for(int i=0;i<nr_of_pixels;i++) | |
{ | |
ptr_M_matrix = &weight_matrix_M[i][0]; | |
attach_weight_2_mat(ptr_M_matrix, i, visual_all_feature, sqr_of_H_nod_plus1, Hidden_nodes, Height, Width); | |
} | |
visual_all_feature += 0.5f; | |
imshow("visual_all_feature", visual_all_feature); | |
imshow("gray", gray); | |
imshow("outimg", outimg); | |
waitKey(1); | |
///******** start stop | |
if(kbhit()){ | |
keyboard = getchar(); | |
if(keyboard== ' ') | |
{ | |
if(started == 1) | |
{ | |
started = 0; | |
printf("Stop training\n"); | |
} | |
else | |
{ | |
started = 1; | |
printf("Start training\n"); | |
} | |
} | |
} | |
///*************** | |
if(started == 0) | |
{ | |
waitKey(2000); | |
} | |
} | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment