以处理图像的亮度为例 (乘以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);
}
网友评论