Coverage Report

Created: 2024-08-19 11:27

/home/liu/actions-runner/_work/ccv/ccv/lib/ccv_transform.c
Line
Count
Source (jump to first uncovered line)
1
#include "ccv.h"
2
#include "ccv_internal.h"
3
4
void ccv_decimal_slice(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, float y, float x, int rows, int cols)
5
1
{
6
1
  ccv_declare_derived_signature(sig, a->sig != 0, ccv_sign_with_format(128, "ccv_decimal_slice(%a,%a,%d,%d)", y, x, rows, cols), a->sig, CCV_EOF_SIGN);
7
1
  type = (type == 0) ? CCV_GET_DATA_TYPE(a->type) | CCV_GET_CHANNEL(a->type) : 
CCV_GET_DATA_TYPE0
(type) | 0
CCV_GET_CHANNEL0
(a->type);
8
1
  ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, rows, cols, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(a->type), type, sig);
9
1
  ccv_object_return_if_cached(, db);
10
1
  int i, j, ch = CCV_GET_CHANNEL(a->type);
11
1
  int ix = (int)x, iy = (int)y;
12
1
  float xd = x - ix, yd = y - iy;
13
1
  float w00 = (1 - xd) * (1 - yd);
14
1
  float w01 = xd * (1 - yd);
15
1
  float w10 = (1 - xd) * yd;
16
1
  float w11 = xd * yd;
17
1
  int dx = 0, dy = 0;
18
1
  int rows_1 = 0, cols_1 = 0;
19
  // it is going to be hard to deal with border efficiently, since this is used for tld, will ignore border for now
20
1
  if (!(iy >= 0 && iy + rows < a->rows && ix >= 0 && ix + cols < a->cols))
21
0
  {
22
0
    ccv_zero(db);
23
0
    if (iy < 0) { rows += iy; dy = -iy; iy = 0; }
24
0
    if (iy + rows >= a->rows)
25
0
    {
26
0
      rows = a->rows - iy - 1;
27
0
      if (iy + rows > a->rows)
28
0
        rows_1 = 1; // we need to do our best to padding the last row
29
0
    }
30
0
    if (ix < 0) { cols += ix; dx = -ix; ix = 0; }
31
0
    if (x + cols >= a->cols)
32
0
    {
33
0
      cols = a->cols - ix - 1;
34
0
      if (x + cols > a->cols)
35
0
        cols_1 = 1; // we need to do our best to padding the last col
36
0
    }
37
0
  }
38
1
  unsigned char* a_ptr = (unsigned char*)ccv_get_dense_matrix_cell(a, iy, ix, 0);
39
1
  unsigned char* b_ptr = (unsigned char*)ccv_get_dense_matrix_cell(db, dy, dx, 0);
40
1
#define for_block(_for_set, _for_get) \
41
112
  
for (i = 0; 1
i < rows;
i++111
) \
42
111
  { \
43
30.4k
    for (j = 0; j < cols * ch; 
j++30.3k
) \
44
30.3k
    { \
45
30.3k
      _for_set(b_ptr, j, (_for_get(a_ptr, j) * G00 + _for_get(a_ptr, j + ch) * G01 + _for_get(a_ptr + a->step, j) * G10 + _for_get(a_ptr + a->step, j + ch) * G11) / GALL); \
46
30.3k
    } \
47
111
    if (cols_1) \
48
111
      _for_set(b_ptr, j, (_for_get(a_ptr, j) * (G00 + G01) + _for_get(a_ptr + a->step, j) * G10 + _for_get(a_ptr + a->step, j + ch) * G11) / GALL); \
49
111
    a_ptr += a->step; \
50
111
    b_ptr += db->step; \
51
111
  } \
52
1
  if (rows_1) \
53
1
  { \
54
0
    for (j = 0; j < cols * ch; j++) \
55
0
    { \
56
0
      _for_set(b_ptr, j, (_for_get(a_ptr, j) * (G00 + G10) + _for_get(a_ptr, j + ch) * (G01 + G11)) / GALL); \
57
0
    } \
58
0
    if (cols_1) \
59
0
      _for_set(b_ptr, j, _for_get(a_ptr, j)); \
60
0
  }
61
  /* unswitch in the manual way so that we can use integer interpolation */
62
1
  if ((a->type & CCV_8U) || 
(a->type & CCV_32S)0
||
(a->type & CCV_64S)0
)
63
1
  {
64
1
    const int W_BITS14 = 14;
65
1
    int iw00 = (int)(w00 * (1 << W_BITS14) + 0.5);
66
1
    int iw01 = (int)(w01 * (1 << W_BITS14) + 0.5);
67
1
    int iw10 = (int)(w10 * (1 << W_BITS14) + 0.5);
68
1
    int iw11 = (1 << W_BITS14) - iw00 - iw01 - iw10;
69
1
#define G00 (iw00)
70
1
#define G01 (iw01)
71
1
#define G10 (iw10)
72
1
#define G11 (iw11)
73
1
#define GCOM (1 << (W_BITS14 - 1))
74
1
#define GALL (1 << (W_BITS14))
75
1
    ccv_matrix_setter(db->type, ccv_matrix_getter_integer_only, a->type, for_block);
76
1
#undef G00
77
1
#undef G01
78
1
#undef G10
79
1
#undef G11
80
1
#undef GCOM
81
1
#undef GALL
82
1
  } else {
83
0
#define G00 (w00)
84
0
#define G01 (w01)
85
0
#define G10 (w10)
86
0
#define G11 (w11)
87
0
#define GCOM (0)
88
0
#define GALL (1)
89
0
    ccv_matrix_setter(db->type, ccv_matrix_getter_float_only, a->type, for_block);
90
0
#undef G00
91
0
#undef G01
92
0
#undef G10
93
0
#undef G11
94
0
#undef GCOM
95
0
#undef GALL
96
0
  }
97
1
#undef for_block
98
1
}
99
100
ccv_decimal_point_t ccv_perspective_transform_apply(ccv_decimal_point_t point, ccv_size_t size, float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22)
101
0
{
102
0
  m00 *= 1.0 / ccv_max(size.width, size.height);
103
0
  m01 *= 1.0 / ccv_max(size.width, size.height);
104
0
  m02 *= 1.0 / ccv_max(size.width, size.height);
105
0
  m10 *= 1.0 / ccv_max(size.width, size.height);
106
0
  m11 *= 1.0 / ccv_max(size.width, size.height);
107
0
  m12 *= 1.0 / ccv_max(size.width, size.height);
108
0
  m20 *= 1.0 / (ccv_max(size.width, size.height) * ccv_max(size.width, size.height));
109
0
  m21 *= 1.0 / (ccv_max(size.width, size.height) * ccv_max(size.width, size.height));
110
0
  m22 *= 1.0 / ccv_max(size.width, size.height);
111
0
  point.x -= size.width * 0.5;
112
0
  point.y -= size.height * 0.5;
113
0
  float wz = 1.0 / (point.x * m20 + point.y * m21 + m22);
114
0
  float wx = size.width * 0.5 + (point.x * m00 + point.y * m01 + m02) * wz;
115
0
  float wy = size.height * 0.5 + (point.x * m10 + point.y * m11 + m12) * wz;
116
0
  return ccv_decimal_point(wx, wy);
117
0
}
118
119
// this method is a merely baseline implementation and has no optimization effort ever put into it, if at all
120
void ccv_perspective_transform(ccv_dense_matrix_t* a, ccv_dense_matrix_t** b, int type, float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22)
121
1
{
122
1
  ccv_declare_derived_signature(sig, a->sig != 0, ccv_sign_with_format(128, "ccv_perspective_transform(%a,%a,%a,%a,%a,%a,%a,%a,%a)", m00, m01, m02, m10, m11, m12, m20, m21, m22), a->sig, CCV_EOF_SIGN);
123
1
  type = (type == 0) ? CCV_GET_DATA_TYPE(a->type) | CCV_GET_CHANNEL(a->type) : 
CCV_GET_DATA_TYPE0
(type) | 0
CCV_GET_CHANNEL0
(a->type);
124
1
  ccv_dense_matrix_t* db = *b = ccv_dense_matrix_renew(*b, a->rows, a->cols, CCV_ALL_DATA_TYPE | CCV_GET_CHANNEL(a->type), type, sig);
125
1
  ccv_object_return_if_cached(, db);
126
  // with default of bilinear interpolation
127
1
  int i, j, k, ch = CCV_GET_CHANNEL(a->type);
128
1
  unsigned char* a_ptr = a->data.u8;
129
1
  unsigned char* b_ptr = db->data.u8;
130
  // assume field of view is 60, modify the matrix value to reflect that
131
  // (basically, apply x / ccv_max(a->rows, a->cols), y / ccv_max(a->rows, a->cols) before hand
132
1
  m00 *= 1.0 / ccv_max(a->rows, a->cols);
133
1
  m01 *= 1.0 / ccv_max(a->rows, a->cols);
134
1
  m02 *= 1.0 / ccv_max(a->rows, a->cols);
135
1
  m10 *= 1.0 / ccv_max(a->rows, a->cols);
136
1
  m11 *= 1.0 / ccv_max(a->rows, a->cols);
137
1
  m12 *= 1.0 / ccv_max(a->rows, a->cols);
138
1
  m20 *= 1.0 / (ccv_max(a->rows, a->cols) * ccv_max(a->rows, a->cols));
139
1
  m21 *= 1.0 / (ccv_max(a->rows, a->cols) * ccv_max(a->rows, a->cols));
140
1
  m22 *= 1.0 / ccv_max(a->rows, a->cols);
141
1
#define for_block(_for_set, _for_get) \
142
501
  
for (i = 0; 1
i < db->rows;
i++500
) \
143
500
  { \
144
500
    float cy = i - db->rows * 0.5; \
145
500
    float crx = cy * m01 + m02; \
146
500
    float cry = cy * m11 + m12; \
147
500
    float crz = cy * m21 + m22; \
148
250k
    for (j = 0; j < db->cols; 
j++250k
) \
149
250k
    { \
150
250k
      float cx = j - db->cols * 0.5; \
151
250k
      float wz = 1.0 / (cx * m20 + crz); \
152
250k
      float wx = a->cols * 0.5 + (cx * m00 + crx) * wz; \
153
250k
      float wy = a->rows * 0.5 + (cx * m10 + cry) * wz; \
154
250k
      int iwx = (int)wx; \
155
250k
      int iwy = (int)wy; \
156
250k
      wx = wx - iwx; \
157
250k
      wy = wy - iwy; \
158
250k
      int iwx1 = ccv_min(iwx + 1, a->cols - 1); \
159
250k
      int iwy1 = ccv_min(iwy + 1, a->rows - 1); \
160
250k
      if (iwx >= 0 && iwx < a->cols && 
iwy >= 0222k
&&
iwy < a->rows208k
) \
161
781k
        
for (k = 0; 195k
k < ch;
k++586k
) \
162
586k
          _for_set(b_ptr, j * ch + k, _for_get(a_ptr + iwy * a->step, iwx * ch + k) * (1 - wx) * (1 - wy) + \
163
250k
                        _for_get(a_ptr + iwy * a->step, iwx1 * ch + k) * wx * (1 - wy) + \
164
250k
                        _for_get(a_ptr + iwy1 * a->step, iwx * ch + k) * (1 - wx) * wy + \
165
250k
                        _for_get(a_ptr + iwy1 * a->step, iwx1 * ch + k) * wx * wy); \
166
250k
      else \
167
250k
        
for (k = 0; 54.5k
k < ch218k
;
k++163k
) \
168
163k
          _for_set(b_ptr, j * ch + k, 0); \
169
250k
    } \
170
500
    b_ptr += db->step; \
171
500
  }
172
1
  ccv_matrix_setter(db->type, ccv_matrix_getter, a->type, for_block);
173
1
#undef for_block
174
1
}