AvicScalar avic_mat_add_square(const AvicMat* src)
{
    int src_cn = AVICCV_MAT_CN(src->type);
    int depth = AVICCV_MAT_DEPTH(src->type);
    int elem_size = AVICCV_ELEM_SIZE(src->type);
    int size = elem_size / src_cn;
    int i, j, k, size_multi_cn = 0;
    double sum = 0;
    AvicScalar add_square_value;
    switch (depth)
    {
    case AVICCV_8U:
    {
        for (k = 0; k < src_cn; k++)
        {
            size_multi_cn = k * size;
            sum = 0;
            for (i = 0; i < src->rows; i++)
            {
                for (j = 0; j < src->cols; j++)
                {
                    sum += AVIC_CV_SQR(*(unsigned char*)(src->data.ptr + (i * src->cols + j) * elem_size + size_multi_cn));
                }
            }
            add_square_value.val[k] = sum;
        }
        break;
    }
    case AVICCV_32F:
    {
        if (src_cn == 3)
        {
            float* src_ptr = src->data.fl;
            for (k = 0; k < src_cn; k++)
            {
                size_multi_cn = k * size;
                sum = 0;
                for (i = 0; i < src->rows; i++)
                {
                    for (j = 0; j < src->cols; j++)
                    {
                        sum += AVIC_CV_SQR(*(float*)(src->data.ptr + (i * src->cols + j) * elem_size + size_multi_cn));
                    }
                }
                add_square_value.val[k] = sum;
            }
        }
        else
        {
            float* src_ptr = src->data.fl;
            float add[4] = {0};
            float* add_ptr = add;
#ifdef WITH_NEON
            #ifdef WITH_OMP
                #pragma omp parallel for private(j)
            #endif
            for (i = 0; i < src->rows; i++)
            {
                src_ptr = src->data.fl + i * src->cols * elem_size;
                float32x4_t re1 = vld1q_f32(add_ptr);
                for (j = 0; j < src->cols * src_cn - 3; j += 4)
                {
                    float32x4_t temp = vld1q_f32(src_ptr + j * size_multi_cn);
                    float32x4_t re = vmulq_f32(temp, temp);
                    re1 = vaddq_f32(re, re1);
                }
                add_square_value.val[0] += add[0];
                add_square_value.val[0] += add[1];
                add_square_value.val[0] += add[2];
                add_square_value.val[0] += add[3];
            }
#else
            #ifdef WITH_OMP
                #pragma omp parallel for private(j)
            #endif
            for (k = 0; k < src_cn; k++)
            {
                size_multi_cn = k * size;
                sum = 0;
                for (i = 0; i < src->rows; i++)
                {
                    for (j = 0; j < src->cols; j++)
                    {
                        sum += AVIC_CV_SQR(*(float*)(src->data.ptr + (i * src->cols + j) * elem_size + size_multi_cn));
                    }
                }
                add_square_value.val[k] = sum;
            }
#endif
        }
        break;
    }
    }
    return(add_square_value);
}

该函数使用循环遍历矩阵的每个元素,并计算其平方值。对于每个通道,将所有元素的平方值累加,最终得到每个通道的平方和。该函数支持8位无符号整型和32位浮点数两种数据类型。

优化部分:

该函数使用NEON和OpenMP进行优化,以提高计算效率。

  • NEON优化:当数据类型为32位浮点数时,使用NEON指令集进行向量化计算,可以显著提高计算速度。
  • OpenMP优化:使用OpenMP并行化循环,可以充分利用多核CPU的计算能力,进一步提高计算速度。

使用方法:

该函数接受一个指向AvicMat结构体的指针作为参数,该结构体包含矩阵数据和相关信息。函数返回一个AvicScalar结构体,包含每个通道的平方和结果。

示例:

// 创建一个3x3的矩阵
AvicMat mat = avic_mat_create(3, 3, AVICCV_32F, 3);

// 填充矩阵数据
float* data = mat.data.fl;
for (int i = 0; i < 9; i++)
{
    data[i] = i + 1;
}

// 计算矩阵元素平方和
AvicScalar sum = avic_mat_add_square(&mat);

// 打印结果
printf("通道0的平方和:%.2f\n", sum.val[0]);
printf("通道1的平方和:%.2f\n", sum.val[1]);
printf("通道2的平方和:%.2f\n", sum.val[2]);
AvicScalar avic_mat_add_square(const AvicMat* src) - 计算矩阵元素平方和

原文地址: http://www.cveoy.top/t/topic/qA9x 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录