1
0
mirror of https://github.com/opencv/opencv.git synced 2026-07-29 23:33:05 +04:00

Merge pull request #24301 from hanliutong:rewrite-stereo-sift

Rewrite Universal Intrinsic code: features2d and calib3d module. #24301

The goal of this series of PRs is to modify the SIMD code blocks guarded by CV_SIMD macro: rewrite them by using the new Universal Intrinsic API.

This is the modification to the features2d module and calib3d module.

Test with clang 16 and QEMU v7.0.0. `AP3P.ctheta1p_nan_23607` failed beacuse of a small calculation error. But this patch does not touch the relevant code, and this error always reproduce on QEMU, regardless of whether the patch is applied or not. I think we can ignore it
```
[ RUN      ] AP3P.ctheta1p_nan_23607
/home/hanliutong/project/opencv/modules/calib3d/test/test_solvepnp_ransac.cpp:2319: Failure
Expected: (cvtest::norm(res.colRange(0, 2), expected, NORM_INF)) <= (3e-16), actual: 3.33067e-16 vs 3e-16
[  FAILED  ] AP3P.ctheta1p_nan_23607 (26 ms)

...

[==========] 148 tests from 64 test cases ran. (1147114 ms total)
[  PASSED  ] 147 tests.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] AP3P.ctheta1p_nan_23607
```

Note: There are 2 test cases failed with GCC 13.2.1 without this patch, seems like there are someting wrong with RVV part on GCC.
```
[----------] Global test environment tear-down
[==========] 148 tests from 64 test cases ran. (1511399 ms total)
[  PASSED  ] 146 tests.
[  FAILED  ] 2 tests, listed below:
[  FAILED  ] Calib3d_StereoSGBM.regression
[  FAILED  ] Calib3d_StereoSGBM_HH4.regression
```

The patch is partially auto-generated by using the [rewriter](https://github.com/hanliutong/rewriter).

### Pull Request Readiness Checklist

See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request

- [ ] I agree to contribute to the project under Apache 2 License.
- [ ] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV
- [ ] The PR is proposed to the proper branch
- [ ] There is a reference to the original bug report and related work
- [ ] There is accuracy test, performance test and test data in opencv_extra repository, if applicable
      Patch to opencv_extra has the same branch name.
- [ ] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
HAN Liutong
2023-09-25 18:03:25 +08:00
committed by GitHub
parent 3889dcf3f8
commit aa143a3dd1
3 changed files with 316 additions and 316 deletions
+52 -52
View File
@@ -210,24 +210,24 @@ float calcOrientationHist(
cv::hal::magnitude32f(X, Y, Mag, len);
k = 0;
#if CV_SIMD
const int vecsize = v_float32::nlanes;
#if (CV_SIMD || CV_SIMD_SCALABLE)
const int vecsize = VTraits<v_float32>::vlanes();
v_float32 nd360 = vx_setall_f32(n/360.f);
v_int32 __n = vx_setall_s32(n);
int CV_DECL_ALIGNED(CV_SIMD_WIDTH) bin_buf[vecsize];
float CV_DECL_ALIGNED(CV_SIMD_WIDTH) w_mul_mag_buf[vecsize];
int CV_DECL_ALIGNED(CV_SIMD_WIDTH) bin_buf[VTraits<v_float32>::max_nlanes];
float CV_DECL_ALIGNED(CV_SIMD_WIDTH) w_mul_mag_buf[VTraits<v_float32>::max_nlanes];
for( ; k <= len - vecsize; k += vecsize )
{
v_float32 w = vx_load_aligned( W + k );
v_float32 mag = vx_load_aligned( Mag + k );
v_float32 ori = vx_load_aligned( Ori + k );
v_int32 bin = v_round( nd360 * ori );
v_int32 bin = v_round( v_mul(nd360, ori) );
bin = v_select(bin >= __n, bin - __n, bin);
bin = v_select(bin < vx_setzero_s32(), bin + __n, bin);
bin = v_select(v_ge(bin, __n), v_sub(bin, __n), bin);
bin = v_select(v_lt(bin, vx_setzero_s32()), v_add(bin, __n), bin);
w = w * mag;
w = v_mul(w, mag);
v_store_aligned(bin_buf, bin);
v_store_aligned(w_mul_mag_buf, w);
for(int vi = 0; vi < vecsize; vi++)
@@ -253,19 +253,19 @@ float calcOrientationHist(
temphist[n+1] = temphist[1];
i = 0;
#if CV_SIMD
#if (CV_SIMD || CV_SIMD_SCALABLE)
v_float32 d_1_16 = vx_setall_f32(1.f/16.f);
v_float32 d_4_16 = vx_setall_f32(4.f/16.f);
v_float32 d_6_16 = vx_setall_f32(6.f/16.f);
for( ; i <= n - v_float32::nlanes; i += v_float32::nlanes )
for( ; i <= n - VTraits<v_float32>::vlanes(); i += VTraits<v_float32>::vlanes() )
{
v_float32 tn2 = vx_load_aligned(temphist + i-2);
v_float32 tn1 = vx_load(temphist + i-1);
v_float32 t0 = vx_load(temphist + i);
v_float32 t1 = vx_load(temphist + i+1);
v_float32 t2 = vx_load(temphist + i+2);
v_float32 _hist = v_fma(tn2 + t2, d_1_16,
v_fma(tn1 + t1, d_4_16, t0 * d_6_16));
v_float32 _hist = v_fma(v_add(tn2, t2), d_1_16,
v_fma(v_add(tn1, t1), d_4_16, v_mul(t0, d_6_16)));
v_store(hist + i, _hist);
}
#endif
@@ -452,8 +452,8 @@ public:
const sift_wt* nextptr = next.ptr<sift_wt>(r);
int c = SIFT_IMG_BORDER;
#if CV_SIMD && !(DoG_TYPE_SHORT)
const int vecsize = v_float32::nlanes;
#if (CV_SIMD || CV_SIMD_SCALABLE) && !(DoG_TYPE_SHORT)
const int vecsize = VTraits<v_float32>::vlanes();
for( ; c <= cols-SIFT_IMG_BORDER - vecsize; c += vecsize)
{
v_float32 val = vx_load(&currptr[c]);
@@ -464,7 +464,7 @@ public:
v_float32 vmin,vmax;
v_float32 cond = v_abs(val) > vx_setall_f32((float)threshold);
v_float32 cond = v_gt(v_abs(val), vx_setall_f32((float)this->threshold));
if (!v_check_any(cond))
{
continue;
@@ -477,10 +477,10 @@ public:
vmax = v_max(v_max(v_max(_00,_01),v_max(_02,_10)),v_max(v_max(_12,_20),v_max(_21,_22)));
vmin = v_min(v_min(v_min(_00,_01),v_min(_02,_10)),v_min(v_min(_12,_20),v_min(_21,_22)));
v_float32 condp = cond & (val > vx_setall_f32(0)) & (val >= vmax);
v_float32 condm = cond & (val < vx_setall_f32(0)) & (val <= vmin);
v_float32 condp = v_and(v_and(cond, v_gt(val, vx_setall_f32(0))), v_ge(val, vmax));
v_float32 condm = v_and(v_and(cond, v_lt(val, vx_setall_f32(0))), v_le(val, vmin));
cond = condp | condm;
cond = v_or(condp, condm);
if (!v_check_any(cond))
{
continue;
@@ -493,10 +493,10 @@ public:
vmax = v_max(v_max(v_max(_00,_01),v_max(_02,_10)),v_max(v_max(_12,_20),v_max(_21,_22)));
vmin = v_min(v_min(v_min(_00,_01),v_min(_02,_10)),v_min(v_min(_12,_20),v_min(_21,_22)));
condp &= (val >= vmax);
condm &= (val <= vmin);
condp = v_and(condp, v_ge(val, vmax));
condm = v_and(condm, v_le(val, vmin));
cond = condp | condm;
cond = v_or(condp, condm);
if (!v_check_any(cond))
{
continue;
@@ -515,10 +515,10 @@ public:
vmax = v_max(v_max(v_max(_00,_01),v_max(_02,_10)),v_max(v_max(_12,_20),v_max(_21,_22)));
vmin = v_min(v_min(v_min(_00,_01),v_min(_02,_10)),v_min(v_min(_12,_20),v_min(_21,_22)));
condp &= (val >= v_max(vmax,max_middle));
condm &= (val <= v_min(vmin,min_middle));
condp = v_and(condp, v_ge(val, v_max(vmax, max_middle)));
condm = v_and(condm, v_le(val, v_min(vmin, min_middle)));
cond = condp | condm;
cond = v_or(condp, condm);
if (!v_check_any(cond))
{
continue;
@@ -777,11 +777,11 @@ void calcSIFTDescriptor(
cv::hal::exp32f(W, W, len);
k = 0;
#if CV_SIMD
#if (CV_SIMD || CV_SIMD_SCALABLE)
{
const int vecsize = v_float32::nlanes;
int CV_DECL_ALIGNED(CV_SIMD_WIDTH) idx_buf[vecsize];
float CV_DECL_ALIGNED(CV_SIMD_WIDTH) rco_buf[8*vecsize];
const int vecsize = VTraits<v_float32>::vlanes();
int CV_DECL_ALIGNED(CV_SIMD_WIDTH) idx_buf[VTraits<v_float32>::max_nlanes];
float CV_DECL_ALIGNED(CV_SIMD_WIDTH) rco_buf[8*VTraits<v_float32>::max_nlanes];
const v_float32 __ori = vx_setall_f32(ori);
const v_float32 __bins_per_rad = vx_setall_f32(bins_per_rad);
const v_int32 __n = vx_setall_s32(n);
@@ -792,28 +792,28 @@ void calcSIFTDescriptor(
{
v_float32 rbin = vx_load_aligned(RBin + k);
v_float32 cbin = vx_load_aligned(CBin + k);
v_float32 obin = (vx_load_aligned(Ori + k) - __ori) * __bins_per_rad;
v_float32 mag = vx_load_aligned(Mag + k) * vx_load_aligned(W + k);
v_float32 obin = v_mul(v_sub(vx_load_aligned(Ori + k), __ori), __bins_per_rad);
v_float32 mag = v_mul(vx_load_aligned(Mag + k), vx_load_aligned(W + k));
v_int32 r0 = v_floor(rbin);
v_int32 c0 = v_floor(cbin);
v_int32 o0 = v_floor(obin);
rbin -= v_cvt_f32(r0);
cbin -= v_cvt_f32(c0);
obin -= v_cvt_f32(o0);
rbin = v_sub(rbin, v_cvt_f32(r0));
cbin = v_sub(cbin, v_cvt_f32(c0));
obin = v_sub(obin, v_cvt_f32(o0));
o0 = v_select(o0 < vx_setzero_s32(), o0 + __n, o0);
o0 = v_select(o0 >= __n, o0 - __n, o0);
o0 = v_select(v_lt(o0, vx_setzero_s32()), v_add(o0, __n), o0);
o0 = v_select(v_ge(o0, __n), v_sub(o0, __n), o0);
v_float32 v_r1 = mag*rbin, v_r0 = mag - v_r1;
v_float32 v_rc11 = v_r1*cbin, v_rc10 = v_r1 - v_rc11;
v_float32 v_rc01 = v_r0*cbin, v_rc00 = v_r0 - v_rc01;
v_float32 v_rco111 = v_rc11*obin, v_rco110 = v_rc11 - v_rco111;
v_float32 v_rco101 = v_rc10*obin, v_rco100 = v_rc10 - v_rco101;
v_float32 v_rco011 = v_rc01*obin, v_rco010 = v_rc01 - v_rco011;
v_float32 v_rco001 = v_rc00*obin, v_rco000 = v_rc00 - v_rco001;
v_float32 v_r1 = v_mul(mag, rbin), v_r0 = v_sub(mag, v_r1);
v_float32 v_rc11 = v_mul(v_r1, cbin), v_rc10 = v_sub(v_r1, v_rc11);
v_float32 v_rc01 = v_mul(v_r0, cbin), v_rc00 = v_sub(v_r0, v_rc01);
v_float32 v_rco111 = v_mul(v_rc11, obin), v_rco110 = v_sub(v_rc11, v_rco111);
v_float32 v_rco101 = v_mul(v_rc10, obin), v_rco100 = v_sub(v_rc10, v_rco101);
v_float32 v_rco011 = v_mul(v_rc01, obin), v_rco010 = v_sub(v_rc01, v_rco011);
v_float32 v_rco001 = v_mul(v_rc00, obin), v_rco000 = v_sub(v_rc00, v_rco001);
v_int32 idx = v_muladd(v_muladd(r0+__1, __d_plus_2, c0+__1), __n_plus_2, o0);
v_int32 idx = v_muladd(v_muladd(v_add(r0, __1), __d_plus_2, v_add(c0, __1)), __n_plus_2, o0);
v_store_aligned(idx_buf, idx);
v_store_aligned(rco_buf, v_rco000);
@@ -894,11 +894,11 @@ void calcSIFTDescriptor(
float nrm2 = 0;
len = d*d*n;
k = 0;
#if CV_SIMD
#if (CV_SIMD || CV_SIMD_SCALABLE)
{
v_float32 __nrm2 = vx_setzero_f32();
v_float32 __rawDst;
for( ; k <= len - v_float32::nlanes; k += v_float32::nlanes )
for( ; k <= len - VTraits<v_float32>::vlanes(); k += VTraits<v_float32>::vlanes() )
{
__rawDst = vx_load_aligned(rawDst + k);
__nrm2 = v_fma(__rawDst, __rawDst, __nrm2);
@@ -949,15 +949,15 @@ void calcSIFTDescriptor(
if( dstMat.type() == CV_32F )
{
float* dst = dstMat.ptr<float>(row);
#if CV_SIMD
#if (CV_SIMD || CV_SIMD_SCALABLE)
v_float32 __dst;
v_float32 __min = vx_setzero_f32();
v_float32 __max = vx_setall_f32(255.0f); // max of uchar
v_float32 __nrm2 = vx_setall_f32(nrm2);
for( k = 0; k <= len - v_float32::nlanes; k += v_float32::nlanes )
for( k = 0; k <= len - VTraits<v_float32>::vlanes(); k += VTraits<v_float32>::vlanes() )
{
__dst = vx_load_aligned(rawDst + k);
__dst = v_min(v_max(v_cvt_f32(v_round(__dst * __nrm2)), __min), __max);
__dst = v_min(v_max(v_cvt_f32(v_round(v_mul(__dst, __nrm2))), __min), __max);
v_store(dst + k, __dst);
}
#endif
@@ -976,16 +976,16 @@ if( dstMat.type() == CV_32F )
else // CV_8U
{
uint8_t* dst = dstMat.ptr<uint8_t>(row);
#if CV_SIMD
#if (CV_SIMD || CV_SIMD_SCALABLE)
v_float32 __dst0, __dst1;
v_uint16 __pack01;
v_float32 __nrm2 = vx_setall_f32(nrm2);
for( k = 0; k <= len - v_float32::nlanes * 2; k += v_float32::nlanes * 2 )
for( k = 0; k <= len - VTraits<v_float32>::vlanes() * 2; k += VTraits<v_float32>::vlanes() * 2 )
{
__dst0 = vx_load_aligned(rawDst + k);
__dst1 = vx_load_aligned(rawDst + k + v_float32::nlanes);
__dst1 = vx_load_aligned(rawDst + k + VTraits<v_float32>::vlanes());
__pack01 = v_pack_u(v_round(__dst0 * __nrm2), v_round(__dst1 * __nrm2));
__pack01 = v_pack_u(v_round(v_mul(__dst0, __nrm2)), v_round(v_mul(__dst1, __nrm2)));
v_pack_store(dst + k, __pack01);
}
#endif