46
46
#include " opencl_kernels_video.hpp"
47
47
#include " opencv2/core/hal/intrin.hpp"
48
48
49
+ #include " opencv2/core/openvx/ovx_defs.hpp"
50
+
49
51
#define CV_DESCALE (x,n ) (((x) + (1 << ((n)-1 ))) >> (n))
50
52
51
53
namespace
@@ -1055,8 +1057,159 @@ namespace
1055
1057
return sparse (_prevImg.getUMat (), _nextImg.getUMat (), _prevPts.getUMat (), umatNextPts, umatStatus, umatErr);
1056
1058
}
1057
1059
#endif
1060
+
1061
+ #ifdef HAVE_OPENVX
1062
+ bool openvx_pyrlk (InputArray _prevImg, InputArray _nextImg, InputArray _prevPts, InputOutputArray _nextPts,
1063
+ OutputArray _status, OutputArray _err)
1064
+ {
1065
+ using namespace ivx ;
1066
+
1067
+ // Pyramids as inputs are not acceptable because there's no (direct or simple) way
1068
+ // to build vx_pyramid on user data
1069
+ if (_prevImg.kind () != _InputArray::MAT || _nextImg.kind () != _InputArray::MAT)
1070
+ return false ;
1071
+
1072
+ Mat prevImgMat = _prevImg.getMat (), nextImgMat = _nextImg.getMat ();
1073
+
1074
+ if (prevImgMat.type () != CV_8UC1 || nextImgMat.type () != CV_8UC1)
1075
+ return false ;
1076
+
1077
+ CV_Assert (prevImgMat.size () == nextImgMat.size ());
1078
+ Mat prevPtsMat = _prevPts.getMat ();
1079
+ int checkPrev = prevPtsMat.checkVector (2 , CV_32F, false );
1080
+ CV_Assert ( checkPrev >= 0 );
1081
+ size_t npoints = checkPrev;
1082
+
1083
+ if ( !(flags & OPTFLOW_USE_INITIAL_FLOW) )
1084
+ _nextPts.create (prevPtsMat.size (), prevPtsMat.type (), -1 , true );
1085
+ Mat nextPtsMat = _nextPts.getMat ();
1086
+ CV_Assert ( nextPtsMat.checkVector (2 , CV_32F, false ) == (int )npoints );
1087
+
1088
+ _status.create ((int )npoints, 1 , CV_8U, -1 , true );
1089
+ Mat statusMat = _status.getMat ();
1090
+ uchar* status = statusMat.ptr ();
1091
+ for (size_t i = 0 ; i < npoints; i++ )
1092
+ status[i] = true ;
1093
+
1094
+ Mat errMat;
1095
+ if ( _err.needed () )
1096
+ {
1097
+ _err.create ((int )npoints, 1 , CV_32F, -1 , true );
1098
+ errMat = _err.getMat ();
1099
+ }
1100
+
1101
+ try
1102
+ {
1103
+ Context context = Context::create ();
1104
+
1105
+ if (context.vendorID () == VX_ID_KHRONOS)
1106
+ {
1107
+ // PyrLK in OVX 1.0.1 performs vxCommitImagePatch incorrecty and crashes
1108
+ if (VX_VERSION == VX_VERSION_1_0)
1109
+ return false ;
1110
+ // Implementation ignores border mode
1111
+ // So check that minimal size of image in pyramid is big enough
1112
+ int width = prevImgMat.cols , height = prevImgMat.rows ;
1113
+ for (int i = 0 ; i < maxLevel+1 ; i++)
1114
+ {
1115
+ if (width < winSize.width + 1 || height < winSize.height + 1 )
1116
+ return false ;
1117
+ else
1118
+ {
1119
+ width /= 2 ; height /= 2 ;
1120
+ }
1121
+ }
1122
+ }
1123
+
1124
+ Image prevImg = Image::createFromHandle (context, Image::matTypeToFormat (prevImgMat.type ()),
1125
+ Image::createAddressing (prevImgMat), (void *)prevImgMat.data );
1126
+ Image nextImg = Image::createFromHandle (context, Image::matTypeToFormat (nextImgMat.type ()),
1127
+ Image::createAddressing (nextImgMat), (void *)nextImgMat.data );
1128
+
1129
+ Graph graph = Graph::create (context);
1130
+
1131
+ Pyramid prevPyr = Pyramid::createVirtual (graph, (vx_size)maxLevel+1 , VX_SCALE_PYRAMID_HALF,
1132
+ prevImg.width (), prevImg.height (), prevImg.format ());
1133
+ Pyramid nextPyr = Pyramid::createVirtual (graph, (vx_size)maxLevel+1 , VX_SCALE_PYRAMID_HALF,
1134
+ nextImg.width (), nextImg.height (), nextImg.format ());
1135
+
1136
+ ivx::Node::create (graph, VX_KERNEL_GAUSSIAN_PYRAMID, prevImg, prevPyr);
1137
+ ivx::Node::create (graph, VX_KERNEL_GAUSSIAN_PYRAMID, nextImg, nextPyr);
1138
+
1139
+ Array prevPts = Array::create (context, VX_TYPE_KEYPOINT, npoints);
1140
+ Array estimatedPts = Array::create (context, VX_TYPE_KEYPOINT, npoints);
1141
+ Array nextPts = Array::create (context, VX_TYPE_KEYPOINT, npoints);
1142
+
1143
+ std::vector<vx_keypoint_t > vxPrevPts (npoints), vxEstPts (npoints), vxNextPts (npoints);
1144
+ for (size_t i = 0 ; i < npoints; i++)
1145
+ {
1146
+ vx_keypoint_t & prevPt = vxPrevPts[i]; vx_keypoint_t & estPt = vxEstPts[i];
1147
+ prevPt.x = prevPtsMat.at <Point2f>(i).x ; prevPt.y = prevPtsMat.at <Point2f>(i).y ;
1148
+ estPt.x = nextPtsMat.at <Point2f>(i).x ; estPt.y = nextPtsMat.at <Point2f>(i).y ;
1149
+ prevPt.tracking_status = estPt.tracking_status = vx_true_e;
1150
+ }
1151
+ prevPts.addItems (vxPrevPts); estimatedPts.addItems (vxEstPts);
1152
+
1153
+ if ( (criteria.type & TermCriteria::COUNT) == 0 )
1154
+ criteria.maxCount = 30 ;
1155
+ else
1156
+ criteria.maxCount = std::min (std::max (criteria.maxCount , 0 ), 100 );
1157
+ if ( (criteria.type & TermCriteria::EPS) == 0 )
1158
+ criteria.epsilon = 0.01 ;
1159
+ else
1160
+ criteria.epsilon = std::min (std::max (criteria.epsilon , 0 .), 10 .);
1161
+ criteria.epsilon *= criteria.epsilon ;
1162
+
1163
+ vx_enum termEnum = (criteria.type == TermCriteria::COUNT) ? VX_TERM_CRITERIA_ITERATIONS :
1164
+ (criteria.type == TermCriteria::EPS) ? VX_TERM_CRITERIA_EPSILON :
1165
+ VX_TERM_CRITERIA_BOTH;
1166
+
1167
+ // minEigThreshold is fixed to 0.0001f
1168
+ ivx::Scalar termination = ivx::Scalar::create<VX_TYPE_ENUM>(context, termEnum);
1169
+ ivx::Scalar epsilon = ivx::Scalar::create<VX_TYPE_FLOAT32>(context, criteria.epsilon );
1170
+ ivx::Scalar numIterations = ivx::Scalar::create<VX_TYPE_UINT32>(context, criteria.maxCount );
1171
+ ivx::Scalar useInitial = ivx::Scalar::create<VX_TYPE_BOOL>(context, (vx_bool)(flags & OPTFLOW_USE_INITIAL_FLOW));
1172
+ // assume winSize is square
1173
+ ivx::Scalar windowSize = ivx::Scalar::create<VX_TYPE_SIZE>(context, (vx_size)winSize.width );
1174
+
1175
+ ivx::Node::create (graph, VX_KERNEL_OPTICAL_FLOW_PYR_LK, prevPyr, nextPyr, prevPts, estimatedPts,
1176
+ nextPts, termination, epsilon, numIterations, useInitial, windowSize);
1177
+
1178
+ graph.verify ();
1179
+ graph.process ();
1180
+
1181
+ nextPts.copyTo (vxNextPts);
1182
+ for (size_t i = 0 ; i < npoints; i++)
1183
+ {
1184
+ vx_keypoint_t kp = vxNextPts[i];
1185
+ nextPtsMat.at <Point2f>(i) = Point2f (kp.x , kp.y );
1186
+ statusMat.at <uchar>(i) = (bool )kp.tracking_status ;
1187
+ // OpenVX doesn't return detection errors
1188
+ errMat.at <float >(i) = 0 ;
1189
+ }
1190
+
1191
+ #ifdef VX_VERSION_1_1
1192
+ // we should take user memory back before release
1193
+ // (it's not done automatically according to standard)
1194
+ prevImg.swapHandle (); nextImg.swapHandle ();
1195
+ #endif
1196
+ }
1197
+ catch (RuntimeError & e)
1198
+ {
1199
+ VX_DbgThrow (e.what ());
1200
+ }
1201
+ catch (WrapperError & e)
1202
+ {
1203
+ VX_DbgThrow (e.what ());
1204
+ }
1205
+
1206
+ return true ;
1207
+ }
1208
+ #endif
1058
1209
};
1059
1210
1211
+
1212
+
1060
1213
void SparsePyrLKOpticalFlowImpl::calc ( InputArray _prevImg, InputArray _nextImg,
1061
1214
InputArray _prevPts, InputOutputArray _nextPts,
1062
1215
OutputArray _status, OutputArray _err)
@@ -1068,6 +1221,10 @@ void SparsePyrLKOpticalFlowImpl::calc( InputArray _prevImg, InputArray _nextImg,
1068
1221
ocl::Image2D::isFormatSupported (CV_32F, 1 , false ),
1069
1222
ocl_calcOpticalFlowPyrLK (_prevImg, _nextImg, _prevPts, _nextPts, _status, _err))
1070
1223
1224
+ // Disabled due to bad accuracy
1225
+ CV_OVX_RUN (false ,
1226
+ openvx_pyrlk (_prevImg, _nextImg, _prevPts, _nextPts, _status, _err))
1227
+
1071
1228
Mat prevPtsMat = _prevPts.getMat ();
1072
1229
const int derivDepth = DataType<cv::detail::deriv_type>::depth;
1073
1230
0 commit comments