#include <iostream>
#include <fstream>
#include <cstdlib>
#include <ctime>
#include <time.h>
using namespace std;
ofstream out("output.txt");
// Initilize a 3D array
double*** initialize_3DArray( int x, int y, int z)
{
double*** arr;
arr = new double**[z];
for(int i=0; i<z; i++)
{
arr[i] = new double*[x];
for(int ii=0; ii<x; ii++)
{
arr[i][ii] = new double[y];
for(int iii=0; iii<y; iii++)
{
arr[i][ii][iii] = (double)rand() / RAND_MAX;
}
}
}
return arr;
}
void free_3DArray(double*** arr, int x, int y, int z)
{
for(int i = 0; i < z; i++)
{
for(int ii =0; ii < x; ii++)
{
delete [] arr[i][ii];
arr[i][ii]=NULL;
}
delete [] arr[i];
arr[i] = NULL;
}
delete [] arr;
arr = NULL;
}
double** initialize_2DArray(int x, int y)
{
double** arr = new double*[x];
for(int i = 0; i < x; i++)
{
arr[i] = new double[y];
}
return arr;
}
void free_2DArray(double** arr, int x, int y)
{
for(int i = 0; i < x; i++)
{
delete [] arr[i];
arr[i] = NULL;
}
delete [] arr;
arr = NULL;
}
// Purpose: perform the convolution between convoluted matrix and convolutor kernel, both them are 2D
// convoluted: the matrix beconvoluted, x0: size of its X-dimension, y0: size of its Y-dimension
// convolutor: the convolution kernel, x1: size of its X-dimension, y1: size of its Y-dimension
// the function return a convolution resulting matrix, whose x-Dimension: x0-x1+1, Y-Dimension:
// y0-y1+1.
double** convolution_2D(double** convoluted, int x0, int y0, double** convolutor, int x1, int y1)
{
if(x0 < x1 || y0 < y1)
{
cout<<"Error: the kernel lager than convoluted matrix!"<<endl;
exit(1);
}
int stepsize = 1;
double** result;
int result_x = x0-x1+1;
int result_y = y0-y1+1;
result = initialize_2DArray(result_x, result_y);
for(int row = 0; row < result_x; row += stepsize)
{
for(int col = 0; col < result_y; col += stepsize)
{
double temp_sum = 0;
// k_x: index of the X-dimesnion of the kernel, k_y: index of the Y-dimension of the kernel
// row0: index of the X-dimesnion of the convoluted matrix, col0:index of the Y-dimension of the convoluted matrix
int k_x, k_y, row0, col0;
for(k_x = 0, row0 = row; k_x < x1, row0 < row+x1; k_x++, row0++)
{
for(k_y = 0, col0 = col; k_y < y1, col0 < col+y1; k_y++, col0++)
{
temp_sum += convoluted[row0][col0] * convolutor[k_x][k_y];
}
}
result[row][col] = temp_sum;
}
}
return result;
}
// pupose: add two 2D matrix together, both them have size of x by y
double** add_2D(double** matrix1, double** matrix2, int x, int y)
{
//double** tmp = initialize_2DArray(x,y);
for(int i = 0; i < x; i++)
{
for (int ii = 0; ii < y; ii++)
{
matrix1[i][ii] = matrix1[i][ii] + matrix2[i][ii];
}
}
return matrix1;
}
// In this version, we assume z0 = z1, but in general cases, the z0 can larger than z1.
double** convolution_3D(double*** convoluted, int x0, int y0, int z0, double*** convolutor, int x1, int y1, int z1)
{
// store the temp result of convolution
double** tmp_conv;
int conv_result_x = x0-x1+1;
int conv_result_y = y0-y1+1;
double** conv_result = initialize_2DArray(conv_result_x, conv_result_y);
// this loop summary the results of cube_z times convolution
for(int recep = 0; recep < z0; recep++)
{
tmp_conv = convolution_2D(convoluted[recep],x0,y0,convolutor[recep],x1,y1);
conv_result = add_2D(conv_result, tmp_conv, conv_result_x, conv_result_y);
}
return conv_result;
}
void show_2D(double** matrix, int x, int y)
{
for(int i = 0; i < x; i++)
{
for (int ii = 0; ii < y; ii++)
{
cout<<matrix[i][ii]<<" ";
}
cout<<endl;
}
}
void show_3D(double*** matrix, int x, int y, int z)
{
for(int i = 0; i < x; i++)
{
for(int ii = 0; ii < x; ii++)
{
for (int iii = 0; iii < y; iii++)
{
cout<<matrix[i][ii][ii]<<" ";
}
cout<<endl;
}
cout<<endl;
}
}
int main()
{
//设置随即数生成器的种子
srand( (unsigned)time(NULL) );
// length of receptive field
int recep_field = 3;
// cube: it formed by stacked multiple frames(feature maps)
double*** cube;
/*
sizes of three dimension of the cube
*/
int cube_x;
int cube_y;
int cube_z;
cube_x = 30;
cube_y = 10;
//cube_z = 7;
cube_z = 3;
cube = initialize_3DArray(cube_x,cube_y,cube_z);
//free_3DArray(cube,cube_x,cube_y,cube_z);
// Design the 3D-kernel
double*** kernel;
int kernel_x;
int kernel_y;
int kernel_z;
kernel_z = 3;
kernel_x = 7;
kernel_y = 7;
kernel = initialize_3DArray(kernel_x, kernel_y, kernel_z);
//free_3DArray(kernel, kernel_x, kernel_y, kernel_z);
// allocate space for convolutional result
double** conv_result;
int conv_result_x = cube_x-kernel_x+1;
int conv_result_y = cube_y-kernel_y+1;
// int conv_result_z = cube_z-kernel_z+1;
//conv_result = initialize_2DArray(conv_result_x, conv_result_y);
//free_2DArray(conv_result, conv_result_x, conv_result_y);
/*****************************************************
3D convolution
*****************************************************/
conv_result = convolution_3D(cube,cube_x,cube_y,cube_z,kernel,kernel_x,kernel_y,kernel_z);
show_2D(conv_result,conv_result_x,conv_result_y);
// // store the temp result of convolution
// double** tmp_conv;
// // this loop summary the results of cube_z times convolution
// for(int recep = 0; recep < cube_z; recep++)
// {
// tmp_conv = convolution_2D(cube[recep],cube_x,cube_y,kernel[recep],kernel_x,kernel_y);
// conv_result = add_2D(conv_result, tmp_conv, conv_result_x, conv_result_y);
// }
free_3DArray(cube,cube_x,cube_y,cube_z);
free_3DArray(kernel, kernel_x, kernel_y, kernel_z);
delete [] conv_result;
//free_2DArray(conv_result, conv_result_x, conv_result_y);
return 0;
}
模拟3维卷积的计算
最新推荐文章于 2024-07-03 17:41:54 发布