用C语言实现单通道的卷积(conv )、池化(max and average pooling、填充(Padding)

一、单通道的卷积 conv

#include <stdio.h>

//单卷积
//IMG:5x5    kernel:3x3    out:3x3   
//计算公式:(f-w+2p)/s + 1       
//其中f是矩阵的大小  w是卷积核的大小 p是padding填充 s是步长(默认为1)
#define IMG_SIZE 5
#define W_SIZE 3
#define OUT_SIZE 3   // 根据计算公式: (5-3+2*0)/1 +1 = 3
int conv(float img[IMG_SIZE][IMG_SIZE],float w[W_SIZE][W_SIZE],float out[OUT_SIZE][OUT_SIZE])
{
    int i,j,k,r;

    float tmp;
    // 步长s=1滑动 进行 行卷积核列卷积
    for(k=0;k<=IMG_SIZE-W_SIZE;k++)  //行卷积
    {
        for(r=0;r<=IMG_SIZE-W_SIZE;r++)  //列卷积
        {
            tmp = 0.0f;  //每次计算时需要将tmp清零  来存放下一次的值(避免计算叠加)
            //单点卷积计算
            for(i=0;i<W_SIZE;i++)
            {
                for(j=0;j<W_SIZE;j++)
                {
                    tmp = tmp + img[i+k][j+r]*w[i][j];
                }
            }
            out[k][r] = tmp;
        }
    } 
    return 0;
}

void conv_test()
{
    
    //输入图片
    float img[IMG_SIZE][IMG_SIZE] = { 
                    1,1,1,0,0,
                    0,1,1,1,0,
                    0,0,1,1,1,
                    0,0,1,1,0,
                    0,1,1,0,0};

    //输入权重
    float conv_w[W_SIZE][W_SIZE] = {
                        1,0,1,
                        0,1,0,
                        1,0,1};
    
    //存放输出的结果
    float img_out[OUT_SIZE][OUT_SIZE];

    int i,j; 
    //打印输入图片数据
    printf("input picture data:\n");
    for(i=0;i<IMG_SIZE;i++)
    {
        for(j=0;j<IMG_SIZE;j++)
        {
            printf("%.1f ",img[i][j]);
        }
        printf("\n");
    }
    //打印输入权重数据
    printf("input weight data:\n");
    for(i=0;i<W_SIZE;i++)
    {
        for(j=0;j<W_SIZE;j++)
        {
            printf("%.1f ",conv_w[i][j]);
        }
        printf("\n");
    }

    //调用卷积函数
    conv(img,conv_w,img_out);

    //打印输出权重数据
    printf("output picture data:\n");
    for(i=0;i<OUT_SIZE;i++)
    {
        for(j=0;j<OUT_SIZE;j++)
        {
            printf("%.1f ",img_out[i][j]);
        }
        printf("\n");
    }

}

int main()
{
    conv_test();  
    return 0;
}

运行结果:
在这里插入图片描述

二、单通道池化pooling

1.max_pooling 最大池化

//单通道最大池化 max_pooling
#define IMG_POOL_SIZE 4
#define OUT_POOL_SIZE 2 
int max_pooling(float img[IMG_POOL_SIZE][IMG_POOL_SIZE],float out[OUT_POOL_SIZE][OUT_POOL_SIZE])
{
    int i,j,k,r;
    float tmp1,tmp2,tmp3;
    for(i=0,k=0;i<IMG_POOL_SIZE,k<OUT_POOL_SIZE;i=i+2,k++)
    {
         
        for(j=0,r=0;j<IMG_POOL_SIZE,r<OUT_POOL_SIZE;j=j+2,r++)
        {
           
            tmp1 = 0.0f;
            tmp2 = 0.0f;
            tmp3 = 0.0f;
            tmp1 = img[i][j] > img[i][j+1] ? img[i][j]:img[i][j+1];
            tmp2 = img[i+1][j] > img[i+1][j+1] ? img[i+1][j] : img[i+1][j+1];
            tmp3 = tmp1 > tmp2 ? tmp1:tmp2;
            out[k][r] = tmp3;
        } 
         
    }
    
    return 0;
}

void max_pooling_test()
{
    //输入图片
    float img[IMG_POOL_SIZE][IMG_POOL_SIZE] = { 
                    5,6,1,0,
                    3,2,3,8,
                    5,6,9,1,
                    7,8,6,7
                    };
    
    //存放输出的结果
    float img_out[OUT_POOL_SIZE][OUT_POOL_SIZE];

    int i,j; 
    //打印输入图片数据
    printf("input picture data:\n");
    for(i=0;i<IMG_POOL_SIZE;i++)
    {
        for(j=0;j<IMG_POOL_SIZE;j++)
        {
            printf("%.1f ",img[i][j]);
        }
        printf("\n");
    }

    //调用最大池化函数
    max_pooling(img,img_out);

    //打印输出图像数据
    printf("output picture data:\n");
    for(i=0;i<OUT_POOL_SIZE;i++)
    {
        for(j=0;j<OUT_POOL_SIZE;j++)
        {
            printf("%.1f ",img_out[i][j]);
        }
        printf("\n");
    }
}
int main()
{
    //conv_test();  
    max_pooling_test();
    //average_pooling_test();
    //padding_test();
    return 0;
}

在这里插入图片描述

2.average_pooling 平均池化

//单通道平均池化maxpooling
#define IMG_POOL_SIZE 4
#define OUT_POOL_SIZE 2 

int average_pooling(float img[IMG_POOL_SIZE][IMG_POOL_SIZE],float out[OUT_POOL_SIZE][OUT_POOL_SIZE])
{
    int i,j,k,r;
    float tmp1,tmp2,tmp3;
    for(i=0,k=0;i<IMG_POOL_SIZE,k<OUT_POOL_SIZE;i=i+2,k++)
    {
         
        for(j=0,r=0;j<IMG_POOL_SIZE,r<OUT_POOL_SIZE;j=j+2,r++)
        {
           
            tmp1 = 0.0f;
            tmp2 = 0.0f;
            tmp3 = 0.0f;
            tmp1 = img[i][j] + img[i][j+1];
            tmp2 = img[i+1][j] + img[i+1][j+1];
            tmp3 = tmp1 + tmp2 ;
            out[k][r] = tmp3/4;
        } 
         
    }
}

void average_pooling_test()
{
    //输入图片
    float img[IMG_POOL_SIZE][IMG_POOL_SIZE] = { 
                    5,6,1,0,
                    3,2,3,8,
                    5,6,9,1,
                    7,8,6,7
                    };
    
    //存放输出的结果
    float img_out[OUT_POOL_SIZE][OUT_POOL_SIZE];

    int i,j; 
    //打印输入图片数据
    printf("input picture data:\n");
    for(i=0;i<IMG_POOL_SIZE;i++)
    {
        for(j=0;j<IMG_POOL_SIZE;j++)
        {
            printf("%.1f ",img[i][j]);
        }
        printf("\n");
    }

    //调用池化函数
    average_pooling(img,img_out);

    //打印输出图像数据
    printf("output picture data:\n");
    for(i=0;i<OUT_POOL_SIZE;i++)
    {
        for(j=0;j<OUT_POOL_SIZE;j++)
        {
            printf("%.1f ",img_out[i][j]);
        }
        printf("\n");
    }
}
int main()
{
    //conv_test();  
    //max_pooling_test();
    average_pooling_test();
    //padding_test();
    return 0;
}

在这里插入图片描述

三、填充(Padding)

//padding  使得图像卷积后的输入和输出不变   
// 根据计算公式: (4-3+2*p)/1 +1 = 4  ->p=1
//
#define IMG_P_SIZE 4
#define Padding 1  
#define OUT_P_SIZE (Padding*2 + IMG_P_SIZE)

int padding(float img[IMG_P_SIZE][IMG_P_SIZE],float out[OUT_P_SIZE][OUT_P_SIZE])
{
    int i,j;
    //先全部填充为0 
     for(i=0;i<OUT_P_SIZE;i++)
    {
        for(j=0;j<OUT_P_SIZE;j++)
        {
            out[i][j] = 0.0f;
        }
    }

    for(i=1;i<OUT_P_SIZE-1;i++)
    {
        for(j=1;j<OUT_P_SIZE-1;j++)
        {
            out[i][j] = img[i-1][j-1];
        }
    }
}

void padding_test()
{
    //输入图片
    float img[IMG_P_SIZE][IMG_P_SIZE] = { 
                    5,6,1,0,
                    3,2,3,8,
                    5,6,9,1,
                    7,8,6,7
                    };
    
    //存放输出的结果
    float img_out[OUT_P_SIZE][OUT_P_SIZE];

    int i,j; 
    //打印输入图片数据
    printf("input picture data:\n");
    for(i=0;i<IMG_P_SIZE;i++)
    {
        for(j=0;j<IMG_P_SIZE;j++)
        {
            printf("%.1f ",img[i][j]);
        }
        printf("\n");
    }

    //调用padding函数
    padding(img,img_out);

    //打印输出图像数据
    printf("output picture data:\n");
    for(i=0;i<OUT_P_SIZE;i++)
    {
        for(j=0;j<OUT_P_SIZE;j++)
        {
            printf("%.1f ",img_out[i][j]);
        }
        printf("\n");
    }
}
 


int main()
{
    //conv_test();  
    //max_pooling_test();
    //average_pooling_test();
    padding_test();
    return 0;
}

在这里插入图片描述

  • 7
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值