1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
|
void LutOpimize(const cv::Mat& src, const float intensity, cv::Mat& result)
{
auto width = src.cols;
auto height = src.rows ;
result = src_img.clone();
int simd_step = cv::v_float32::nlanes;
#pragma omp parallel for
for(int i = 0; i < height; i++)
{
int j = 0;
const uchar* src_row_ptr = src_img.ptr(i);
for(; j < width - simd_step; j += simd_step)
{
cv::v_uint8 vb, vr, vg;
cv::v_load_deinterleave(src_row_ptr + j, vb, vg, vr);
cv::v_uint16 vb16_0, vb16_1, vg16_0, vg16_1, vr16_0, vr16_1;
cv::v_expand(vb, vb16_0, vb16_1);
cv::v_expand(vb, vg16_0, vg16_1);
cv::v_expand(vb, vr16_0, vr16_1);
std::vector<cv::v_uint32> vb32(4);
std::vector<cv::v_uint32> vg32(4);
std::vector<cv::v_uint32> vr32(4);
cv::v_expand(vb16_0, vb32[0], vb32[1]);
cv::v_expand(vb16_1, vb32[2], vb32[3]);
cv::v_expand(vg16_0, vg32[0], vg32[1]);
cv::v_expand(vg16_1, vg32[2], vg32[3]);
cv::v_expand(vr16_0, vr32[0], vr32[1]);
cv::v_expand(vr16_1, vr32[2], vr32[3]);
std::vector<cv::v_int32> v_block1(4);
std::vector<cv::v_int32> v_block2(4);
std::vector<cv::v_int32> v_block_x1(4);
std::vector<cv::v_int32> lut_x1(4);
std::vector<cv::v_int32> lut_x2(4);
std::vector<cv::v_int32> lut_y1(4);
std::vector<cv::v_int32> lut_y2(4);
cv::v_float32 v_8 = cv::v_setall_f32(8.0f);
cv::v_float32 v_4 = cv::v_setall_f32(4.0f);
for(int v = 0; v < 4; v++)
{
v_block1[v] = cv::v_floor(cv::v_reinterpret_as_f32(vb32[v]) / v_4);
v_block2[v] = cv::v_ceil(cv::v_reinterpret_as_f32(vb32[v]) / v_4);
auto v_block_x1 = cv::v_reinterpret_as_f32(v_block1[v]) - cv::v_reinterpret_as_f32(v_block1[v]) / v_8;
auto v_block_x2 = cv::v_reinterpret_as_f32(v_block2[v]) - cv::v_reinterpret_as_f32(v_block2[v]) / v_8;
auto v_block_y1 = cv::v_reinterpret_as_f32(v_block1[v]) / v_8;
auto v_block_y2 = cv::v_reinterpret_as_f32(v_block2[v]) / v_8;
auto v_lut_x1 = v_block_x1 * cv::v_setall_f32(64.0f) + cv::v_reinterpret_as_f32(vr32[v]) / v_4;
auto v_lut_x2 = v_block_x2 * cv::v_setall_f32(64.0f) + cv::v_reinterpret_as_f32(vr32[v]) / v_4;
auto v_lut_y1 = v_block_y1 * cv::v_setall_f32(64.0f) + cv::v_reinterpret_as_f32(vg32[v]) / v_4;
auto v_lut_y2 = v_block_y2 * cv::v_setall_f32(64.0f) + cv::v_reinterpret_as_f32(vg32[v]) / v_4;
//lut图的x、y所以存在可能是不连续的情况,此时旧无法正常通过连续的simd机制去访问了
}
}
for(; j < width; j++)
{
auto r = src_row_ptr[3 * j + 2];
auto g = src_row_ptr[3 * j + 1];
auto b = src_row_ptr[3 * j + 0];
//计算从8x8里面的第几块方块取色
int block1 = std::floor(b / 4.0);
int block2 = std::ceil(b / 4.0);
int block_x1 = block1 % 8;
int block_x2 = block2 % 8;
int block_y1 = block1 / 8;
int block_y2 = block2 / 8;
//计算每块里面的具体index
int lut_x1 = block_x1 * 64 + r / 4.0;
int lut_x2 = block_x2 * 64 + r / 4.0;
int lut_y1 = block_y1 * 64 + g / 4.0;
int lut_y2 = block_y2 * 64 + g / 4.0;
auto color1 = lut_img.at<cv::Vec3b>(lut_y1, lut_x1);
auto color2 = lut_img.at<cv::Vec3b>(lut_y2, lut_x2);
result.at<cv::Vec3b>(i, j)[0] = std::clamp((int)std::round((color1[0] + color2[0]) / 2.0), 0, 255);
result.at<cv::Vec3b>(i, j)[1] = std::clamp((int)std::round((color1[1] + color2[1]) / 2.0), 0, 255);
result.at<cv::Vec3b>(i, j)[2] = std::clamp((int)std::round((color1[2] + color2[2]) / 2.0), 0, 255);
}
}
//依照强度进行混合
cv::addWeighted(src_img,1.0 - intensity, result, intensity, 0.0, result);
}
|