|
51 | 51 | #include "opencl_kernels_imgproc.hpp"
|
52 | 52 | #include "hal_replacement.hpp"
|
53 | 53 | #include "opencv2/core/hal/intrin.hpp"
|
| 54 | +#include "opencv2/core/utils/buffer_area.private.hpp" |
54 | 55 |
|
55 | 56 | #include "opencv2/core/openvx/ovx_defs.hpp"
|
56 | 57 | #include "resize.hpp"
|
@@ -1104,6 +1105,121 @@ resizeNN( const Mat& src, Mat& dst, double fx, double fy )
|
1104 | 1105 | }
|
1105 | 1106 | }
|
1106 | 1107 |
|
| 1108 | +class resizeNN_bitexactInvoker : public ParallelLoopBody |
| 1109 | +{ |
| 1110 | +public: |
| 1111 | + resizeNN_bitexactInvoker(const Mat& _src, Mat& _dst, int* _x_ofse, int _ify, int _ify0) |
| 1112 | + : src(_src), dst(_dst), x_ofse(_x_ofse), ify(_ify), ify0(_ify0) {} |
| 1113 | + |
| 1114 | + virtual void operator() (const Range& range) const CV_OVERRIDE |
| 1115 | + { |
| 1116 | + Size ssize = src.size(), dsize = dst.size(); |
| 1117 | + int pix_size = (int)src.elemSize(); |
| 1118 | + for( int y = range.start; y < range.end; y++ ) |
| 1119 | + { |
| 1120 | + uchar* D = dst.ptr(y); |
| 1121 | + int _sy = (ify * y + ify0) >> 16; |
| 1122 | + int sy = std::min(_sy, ssize.height-1); |
| 1123 | + const uchar* S = src.ptr(sy); |
| 1124 | + |
| 1125 | + int x = 0; |
| 1126 | + switch( pix_size ) |
| 1127 | + { |
| 1128 | + case 1: |
| 1129 | +#if CV_SIMD |
| 1130 | + for( ; x <= dsize.width - v_uint8::nlanes; x += v_uint8::nlanes ) |
| 1131 | + v_store(D + x, vx_lut(S, x_ofse + x)); |
| 1132 | +#endif |
| 1133 | + for( ; x < dsize.width; x++ ) |
| 1134 | + D[x] = S[x_ofse[x]]; |
| 1135 | + break; |
| 1136 | + case 2: |
| 1137 | +#if CV_SIMD |
| 1138 | + for( ; x <= dsize.width - v_uint16::nlanes; x += v_uint16::nlanes ) |
| 1139 | + v_store((ushort*)D + x, vx_lut((ushort*)S, x_ofse + x)); |
| 1140 | +#endif |
| 1141 | + for( ; x < dsize.width; x++ ) |
| 1142 | + *((ushort*)D + x) = *((ushort*)S + x_ofse[x]); |
| 1143 | + break; |
| 1144 | + case 3: |
| 1145 | + for( ; x < dsize.width; x++, D += 3 ) |
| 1146 | + { |
| 1147 | + const uchar* _tS = S + x_ofse[x] * 3; |
| 1148 | + D[0] = _tS[0]; D[1] = _tS[1]; D[2] = _tS[2]; |
| 1149 | + } |
| 1150 | + break; |
| 1151 | + case 4: |
| 1152 | +#if CV_SIMD |
| 1153 | + for( ; x <= dsize.width - v_uint32::nlanes; x += v_uint32::nlanes ) |
| 1154 | + v_store((uint32_t*)D + x, vx_lut((uint32_t*)S, x_ofse + x)); |
| 1155 | +#endif |
| 1156 | + for( ; x < dsize.width; x++ ) |
| 1157 | + *((uint32_t*)D + x) = *((uint32_t*)S + x_ofse[x]); |
| 1158 | + break; |
| 1159 | + case 6: |
| 1160 | + for( ; x < dsize.width; x++, D += 6 ) |
| 1161 | + { |
| 1162 | + const ushort* _tS = (const ushort*)(S + x_ofse[x]*6); |
| 1163 | + ushort* _tD = (ushort*)D; |
| 1164 | + _tD[0] = _tS[0]; _tD[1] = _tS[1]; _tD[2] = _tS[2]; |
| 1165 | + } |
| 1166 | + break; |
| 1167 | + case 8: |
| 1168 | +#if CV_SIMD |
| 1169 | + for( ; x <= dsize.width - v_uint64::nlanes; x += v_uint64::nlanes ) |
| 1170 | + v_store((uint64_t*)D + x, vx_lut((uint64_t*)S, x_ofse + x)); |
| 1171 | +#endif |
| 1172 | + for( ; x < dsize.width; x++ ) |
| 1173 | + *((uint64_t*)D + x) = *((uint64_t*)S + x_ofse[x]); |
| 1174 | + break; |
| 1175 | + case 12: |
| 1176 | + for( ; x < dsize.width; x++, D += 12 ) |
| 1177 | + { |
| 1178 | + const int* _tS = (const int*)(S + x_ofse[x]*12); |
| 1179 | + int* _tD = (int*)D; |
| 1180 | + _tD[0] = _tS[0]; _tD[1] = _tS[1]; _tD[2] = _tS[2]; |
| 1181 | + } |
| 1182 | + break; |
| 1183 | + default: |
| 1184 | + for( x = 0; x < dsize.width; x++, D += pix_size ) |
| 1185 | + { |
| 1186 | + const uchar* _tS = S + x_ofse[x] * pix_size; |
| 1187 | + for (int k = 0; k < pix_size; k++) |
| 1188 | + D[k] = _tS[k]; |
| 1189 | + } |
| 1190 | + } |
| 1191 | + } |
| 1192 | + } |
| 1193 | +private: |
| 1194 | + const Mat& src; |
| 1195 | + Mat& dst; |
| 1196 | + int* x_ofse; |
| 1197 | + const int ify; |
| 1198 | + const int ify0; |
| 1199 | +}; |
| 1200 | + |
| 1201 | +static void resizeNN_bitexact( const Mat& src, Mat& dst, double /*fx*/, double /*fy*/ ) |
| 1202 | +{ |
| 1203 | + Size ssize = src.size(), dsize = dst.size(); |
| 1204 | + int ifx = ((ssize.width << 16) + dsize.width / 2) / dsize.width; // 16bit fixed-point arithmetic |
| 1205 | + int ifx0 = ifx / 2 - 1; // This method uses center pixel coordinate as Pillow and scikit-images do. |
| 1206 | + int ify = ((ssize.height << 16) + dsize.height / 2) / dsize.height; |
| 1207 | + int ify0 = ify / 2 - 1; |
| 1208 | + |
| 1209 | + cv::utils::BufferArea area; |
| 1210 | + int* x_ofse = 0; |
| 1211 | + area.allocate(x_ofse, dsize.width, CV_SIMD_WIDTH); |
| 1212 | + area.commit(); |
| 1213 | + |
| 1214 | + for( int x = 0; x < dsize.width; x++ ) |
| 1215 | + { |
| 1216 | + int sx = (ifx * x + ifx0) >> 16; |
| 1217 | + x_ofse[x] = std::min(sx, ssize.width-1); // offset in element (not byte) |
| 1218 | + } |
| 1219 | + Range range(0, dsize.height); |
| 1220 | + resizeNN_bitexactInvoker invoker(src, dst, x_ofse, ify, ify0); |
| 1221 | + parallel_for_(range, invoker, dst.total()/(double)(1<<16)); |
| 1222 | +} |
1107 | 1223 |
|
1108 | 1224 | struct VResizeNoVec
|
1109 | 1225 | {
|
@@ -3723,6 +3839,12 @@ void resize(int src_type,
|
3723 | 3839 | return;
|
3724 | 3840 | }
|
3725 | 3841 |
|
| 3842 | + if( interpolation == INTER_NEAREST_EXACT ) |
| 3843 | + { |
| 3844 | + resizeNN_bitexact( src, dst, inv_scale_x, inv_scale_y ); |
| 3845 | + return; |
| 3846 | + } |
| 3847 | + |
3726 | 3848 | int k, sx, sy, dx, dy;
|
3727 | 3849 |
|
3728 | 3850 |
|
|
0 commit comments