/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 | } |