美文网首页
对比几种图像处理方式的性能(浮点乘法,整形乘法,1D查表,3D查

对比几种图像处理方式的性能(浮点乘法,整形乘法,1D查表,3D查

作者: 罗引杰 | 来源:发表于2020-10-09 16:35 被阅读0次

以处理图像的亮度为例 (乘以1.3),我们采用如下几种方式对图像进行遍历-处理-写内存, 以分析其性能
方法1 Opencv自带Mat乘法
方法2 整形乘法
方法3 浮点数乘法
方法4 1D查表法
方法5 3D查表法

以下是程序输出的性能
(CPU=I7-8700 大小=4K 图像格式=BGR32)

Lightness1:
FPS=233.90 throutput=5.42GB/s
Lightness2:
FPS=55.40 throutput=1.28GB/s
Lightness3:
FPS=34.75 throutput=0.81GB/s
lighness_1D_table:
FPS=66.50 throutput=1.54GB/s
lighness_3D_table:
FPS=56.36 throutput=1.31GB/s

从以上输出可以看出来, 使用Opencv自带乘法最快, 可能是内部使用了指令集优化,浮点乘法最慢,最好不要使用

附上代码:

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <cv/cv_tools.h>

using namespace cv;
using namespace std;
using namespace oop;

static int loops = 100;
static int w = 3840;
static int h = 2160;

class TableLutLightness
{
public:
   static TableLutLightness table_lightness;

   static TableLutLightness& getTable() {
       return table_lightness;
   }

   uchar table1d[256];
   uchar table2d[256*256*2];
   uchar* table3d;
private:

   TableLutLightness(double factor) {
       table3d = new uchar[256 * 256 * 256 * 3];

       for (int i = 0; i != 256;++i) {
           table1d[i] = static_cast<uchar>(i * factor+0.5);
       }
       for (int i = 0; i != 256; ++i) {
           for (int j = 0; j != 256; ++j) {
               int offset = (i * 256 + j) * 2;
               table2d[offset  ] = static_cast<uchar>(i * factor + 0.5);
               table2d[offset+1] = static_cast<uchar>(j * factor + 0.5); 
           }
       }
       for (int i = 0; i != 256; ++i) {
           for (int j = 0; j != 256; ++j) {
               for (int k = 0; k != 256; ++k) {
                   int offset = ((i * 256 + j) *256 + k)*3;
                   table3d[offset    ] = static_cast<uchar>(i * factor + 0.5);
                   table3d[offset + 1] = static_cast<uchar>(j * factor + 0.5);
                   table3d[offset + 2] = static_cast<uchar>(k * factor + 0.5);
               }
           }
       }
   }
   ~TableLutLightness() {
       delete[] table3d;
   }
};

TableLutLightness TableLutLightness::table_lightness(1.75);

int lighness1(cv::Mat& src, cv::Mat& dst, double factor)
{
   dst = src * factor;
   return 0;
}

int lighness2(cv::Mat& src, cv::Mat& dst, double factor)
{
   int sz = src.cols* src.rows * 3;

   const int shift = 10;

   int fac_int =  factor * (1<< shift);

   for (int i = 0; i != sz; ++i) {
       int val = (src.data[i] * fac_int) >> shift;
       dst.data[i] = val > 255 ? 255 : val;
   }
   return 0;
}

int lighness_1D_table(cv::Mat& src, cv::Mat& dst, double factor)
{
   TableLutLightness& table = TableLutLightness::getTable();
   int sz = src.cols* src.rows * 3;

   for (int i = 0; i != sz; ++i) {
       dst.data[i] = table.table1d[src.data[i]];
   }
   return 0;
}

int lighness_3D_table(cv::Mat& src, cv::Mat& dst, double factor)
{
   TableLutLightness& table = TableLutLightness::getTable();
   int sz = src.cols* src.rows;

   for (int i = 0; i != sz; ++i) {
       int of3 = i * 3;
       int b = src.data[of3];
       int g = src.data[of3 +1];
       int r = src.data[of3 +2];

       int offset = (256 * (b * 256 + g) + r)*3;
       dst.data[of3] = table.table3d[offset  ];
       dst.data[of3 +1] = table.table3d[offset+1];
       dst.data[of3 +2] = table.table3d[offset+2];
   }
   return 0;
}



int lighness3(cv::Mat& src, cv::Mat& dst, double factor)
{
   int sz = src.cols* src.rows * 3;
   for (int i = 0; i != sz; ++i) {
       int val = (src.data[i] * factor + 0.5);
       dst.data[i] = val > 255 ? 255 : val;
   }
   return 0;
}



int saturation(cv::Mat& src, cv::Mat& dst, float factor)
{
   Mat lab_pic;
   Mat lab_pic1 = src.clone();
   cv::cvtColor(src, lab_pic, cv::COLOR_BGR2Lab);


   int sz = src.cols* src.rows ;
   for (int i = 0; i != sz; ++i) {
       int of3 = i * 3;
       float l = lab_pic.data[of3    ];
       float a = lab_pic.data[of3 + 1];
       float b = lab_pic.data[of3 + 2];

       lab_pic1.data[of3] = l;

       float a_val = (a - 128)*factor + 128;
       float b_val = (b - 128)*factor + 128;

       lab_pic1.data[of3+1] = CLAMP(a_val);
       lab_pic1.data[of3+2] = CLAMP(b_val);
   }

   cv::cvtColor(lab_pic1, dst, cv::COLOR_Lab2BGR);
   return 0;
}

int doLcsh(std::function<int(cv::Mat& src, cv::Mat& dst, double factor) > func, std::string filter_name, float factor=1.75)
{
   Mat src = imread("img/nlm.jpg");

   resize(src, src, cv::Size(w, h));
   Mat dst = src.clone();
   long long t1 = _getTickCount();
   for (int i = 0; i != loops; ++i) {
       func(src, dst, factor);
   }
   long long t2 = _getTickCount();


   myShow(dst, filter_name);

   double second_per_frame = ((t2 - t1)/loops) / _getTickFrequency();

   printf("%s:\nFPS=%.2f throutput=%.2fGB/s\n", filter_name.c_str(),  1.0 / second_per_frame,  (w*h * 3 / (1024 * 1024 * 1024.0))/ second_per_frame);
   //waitKey(0);
   return 0;
}




int main()
{
   float factor = 1.75;
   doLcsh(lighness1, "Lightness1");
   doLcsh(lighness2, "Lightness2");
   doLcsh(lighness3, "Lightness3");
   doLcsh(lighness_1D_table, "lighness_1D_table");
   doLcsh(lighness_3D_table, "lighness_3D_table");
   factor = 1.3;
   //doLcsh(saturation, "saturation-lab", factor);

   waitKey(0);
}

相关文章

  • 对比几种图像处理方式的性能(浮点乘法,整形乘法,1D查表,3D查

    以处理图像的亮度为例,我们采用如下几种方式对图像进行遍历-处理-写内存, 以分析其性能方法1 Opencv自带Ma...

  • 大数乘法(Multiply Strings)

    大数乘法的算法 大数乘法的关键在于如何用字符串来模拟大数乘法。方法有如下几种:模拟普通的手算乘法、利用代数方法优化...

  • Lecture 5

    2.6 浮点运算方法和浮点运算器 2.6.1 浮点加法、减法运算 2.6.2 浮点乘法、除法运算规则 2.6.3 ...

  • 浮点数乘法

    定义 浮点数乘法 性质 浮点数乘法性质 满足封闭性; 满足交换律; 单位元是; 不满足结合律;比如表达式的值是,表...

  • 几种矩阵乘法

    https://blog.csdn.net/weixin_40955254/article/details/809...

  • ROM乘法器

    基本算法 ROM乘法器的算法比较简单,即使用一个ROM保存乘法的结果,在需要运算的时候直接到相应的地址去查表即可。...

  • 【PY】小语法

    计算 / 表示 浮点数除法,返回浮点结果;// 表示整数除法。 * 表示乘法;** 表示乘方,符号后面的数字表示指...

  • 乘法

    埃及乘法 铺地锦 画线乘法 格子乘法‘

  • 17-12-8版子

    高精度加法 高精度乘法 快速乘法 二分匹配 阶乘长度(Stirling公式) 并查集 树状数组 树状数组的逆序数 ...

  • 神奇的乘法(二)

    乘法的种类已经多到计数困难了。 第六种乘法 难产的乘法:复数的乘法 因为复数出生的时候,难产,所以,这种乘法难产。...

网友评论

      本文标题:对比几种图像处理方式的性能(浮点乘法,整形乘法,1D查表,3D查

      本文链接:https://www.haomeiwen.com/subject/gxglpktx.html