Vec2d predict2(InputArray _sample, OutputArray _probs) const { int ptype = CV_64F; Mat sample = _sample.getMat(); CV_Assert(isTrained()); CV_Assert(!sample.empty()); if(sample.type() != CV_64FC1) { Mat tmp; sample.convertTo(tmp, CV_64FC1); sample = tmp; } sample = sample.reshape(1, 1); Mat probs; if( _probs.needed() ) { if( _probs.fixedType() ) ptype = _probs.type(); _probs.create(1, nclusters, ptype); probs = _probs.getMat(); } return computeProbabilities(sample, !probs.empty() ? &probs : 0, ptype); }
void UMat::convertTo(OutputArray _dst, int _type, double alpha, double beta) const { bool noScale = std::fabs(alpha - 1) < DBL_EPSILON && std::fabs(beta) < DBL_EPSILON; int stype = type(), cn = CV_MAT_CN(stype); if( _type < 0 ) _type = _dst.fixedType() ? _dst.type() : stype; else _type = CV_MAKETYPE(CV_MAT_DEPTH(_type), cn); int sdepth = CV_MAT_DEPTH(stype), ddepth = CV_MAT_DEPTH(_type); if( sdepth == ddepth && noScale ) { copyTo(_dst); return; } #ifdef HAVE_OPENCL bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; bool needDouble = sdepth == CV_64F || ddepth == CV_64F; if( dims <= 2 && cn && _dst.isUMat() && ocl::useOpenCL() && ((needDouble && doubleSupport) || !needDouble) ) { int wdepth = std::max(CV_32F, sdepth), rowsPerWI = 4; char cvt[2][40]; ocl::Kernel k("convertTo", ocl::core::convert_oclsrc, format("-D srcT=%s -D WT=%s -D dstT=%s -D convertToWT=%s -D convertToDT=%s%s%s", ocl::typeToStr(sdepth), ocl::typeToStr(wdepth), ocl::typeToStr(ddepth), ocl::convertTypeStr(sdepth, wdepth, 1, cvt[0]), ocl::convertTypeStr(wdepth, ddepth, 1, cvt[1]), doubleSupport ? " -D DOUBLE_SUPPORT" : "", noScale ? " -D NO_SCALE" : "")); if (!k.empty()) { UMat src = *this; _dst.create( size(), _type ); UMat dst = _dst.getUMat(); float alphaf = (float)alpha, betaf = (float)beta; ocl::KernelArg srcarg = ocl::KernelArg::ReadOnlyNoSize(src), dstarg = ocl::KernelArg::WriteOnly(dst, cn); if (noScale) k.args(srcarg, dstarg, rowsPerWI); else if (wdepth == CV_32F) k.args(srcarg, dstarg, alphaf, betaf, rowsPerWI); else k.args(srcarg, dstarg, alpha, beta, rowsPerWI); size_t globalsize[2] = { (size_t)dst.cols * cn, ((size_t)dst.rows + rowsPerWI - 1) / rowsPerWI }; if (k.run(2, globalsize, NULL, false)) { CV_IMPL_ADD(CV_IMPL_OCL); return; } } } #endif Mat m = getMat(ACCESS_READ); m.convertTo(_dst, _type, alpha, beta); }
float predict(InputArray _inputs, OutputArray _outputs, int) const { bool needprobs = _outputs.needed(); Mat samples = _inputs.getMat(), probs, probsrow; int ptype = CV_64F; float firstres = 0.f; int i, nsamples = samples.rows; if( needprobs ) { if( _outputs.fixedType() ) ptype = _outputs.type(); _outputs.create(samples.rows, nclusters, ptype); } else nsamples = std::min(nsamples, 1); for( i = 0; i < nsamples; i++ ) { if( needprobs ) probsrow = probs.row(i); Vec2d res = computeProbabilities(samples.row(i), needprobs ? &probsrow : 0, ptype); if( i == 0 ) firstres = (float)res[1]; } return firstres; }
int fixedType_handler(OutputArray dst) { int type = CV_32FC2; // return points only {x, y} if (dst.fixedType()) { type = dst.type(); CV_Assert(type == CV_32FC2 || type == CV_32FC3); // allow points + confidence level: {x, y, confidence} } const int N = 100; dst.create(Size(1, N), type); Mat m = dst.getMat(); if (m.type() == CV_32FC2) { for (int i = 0; i < N; i++) m.at<Vec2f>(i) = Vec2f((float)i, (float)(i*2)); } else if (m.type() == CV_32FC3) { for (int i = 0; i < N; i++) m.at<Vec3f>(i) = Vec3f((float)i, (float)(i*2), 1.0f / (i + 1)); } else { CV_Assert(0 && "Internal error"); } return CV_MAT_CN(type); }
/* dst = src */ void Mat::copyTo( OutputArray _dst ) const { int dtype = _dst.type(); if( _dst.fixedType() && dtype != type() ) { CV_Assert( channels() == CV_MAT_CN(dtype) ); convertTo( _dst, dtype ); return; } if( empty() ) { _dst.release(); return; } if( dims <= 2 ) { _dst.create( rows, cols, type() ); Mat dst = _dst.getMat(); if( data == dst.data ) return; if( rows > 0 && cols > 0 ) { const uchar* sptr = data; uchar* dptr = dst.data; // to handle the copying 1xn matrix => nx1 std vector. Size sz = size() == dst.size() ? getContinuousSize(*this, dst) : getContinuousSize(*this); size_t len = sz.width*elemSize(); for( ; sz.height--; sptr += step, dptr += dst.step ) memcpy( dptr, sptr, len ); } return; } _dst.create( dims, size, type() ); Mat dst = _dst.getMat(); if( data == dst.data ) return; if( total() != 0 ) { const Mat* arrays[] = { this, &dst }; uchar* ptrs[2]; NAryMatIterator it(arrays, ptrs, 2); size_t sz = it.size*elemSize(); for( size_t i = 0; i < it.nplanes; i++, ++it ) memcpy(ptrs[1], ptrs[0], sz); } }
void cv::convertPointsHomogeneous( InputArray _src, OutputArray _dst ) { int stype = _src.type(), dtype = _dst.type(); CV_Assert( _dst.fixedType() ); if( CV_MAT_CN(stype) > CV_MAT_CN(dtype) ) convertPointsFromHomogeneous(_src, _dst); else convertPointsToHomogeneous(_src, _dst); }
void UMat::convertTo(OutputArray _dst, int _type, double alpha, double beta) const { bool noScale = std::fabs(alpha - 1) < DBL_EPSILON && std::fabs(beta) < DBL_EPSILON; int stype = type(), cn = CV_MAT_CN(stype); if( _type < 0 ) _type = _dst.fixedType() ? _dst.type() : stype; else _type = CV_MAKETYPE(CV_MAT_DEPTH(_type), cn); int sdepth = CV_MAT_DEPTH(stype), ddepth = CV_MAT_DEPTH(_type); if( sdepth == ddepth && noScale ) { copyTo(_dst); return; } bool doubleSupport = ocl::Device::getDefault().doubleFPConfig() > 0; bool needDouble = sdepth == CV_64F || ddepth == CV_64F; if( dims <= 2 && cn && _dst.isUMat() && ocl::useOpenCL() && ((needDouble && doubleSupport) || !needDouble) ) { char cvt[40]; ocl::Kernel k("convertTo", ocl::core::convert_oclsrc, format("-D srcT=%s -D dstT=%s -D convertToDT=%s%s", ocl::typeToStr(sdepth), ocl::typeToStr(ddepth), ocl::convertTypeStr(CV_32F, ddepth, 1, cvt), doubleSupport ? " -D DOUBLE_SUPPORT" : "")); if (!k.empty()) { UMat src = *this; _dst.create( size(), _type ); UMat dst = _dst.getUMat(); float alphaf = (float)alpha, betaf = (float)beta; k.args(ocl::KernelArg::ReadOnlyNoSize(src), ocl::KernelArg::WriteOnly(dst, cn), alphaf, betaf); size_t globalsize[2] = { dst.cols * cn, dst.rows }; if (k.run(2, globalsize, NULL, false)) return; } } Mat m = getMat(ACCESS_READ); m.convertTo(_dst, _type, alpha, beta); }
void UMat::copyTo(OutputArray _dst) const { int dtype = _dst.type(); if( _dst.fixedType() && dtype != type() ) { CV_Assert( channels() == CV_MAT_CN(dtype) ); convertTo( _dst, dtype ); return; } if( empty() ) { _dst.release(); return; } size_t i, sz[CV_MAX_DIM], srcofs[CV_MAX_DIM], dstofs[CV_MAX_DIM], esz = elemSize(); for( i = 0; i < (size_t)dims; i++ ) sz[i] = size.p[i]; sz[dims-1] *= esz; ndoffset(srcofs); srcofs[dims-1] *= esz; _dst.create( dims, size.p, type() ); if( _dst.isUMat() ) { UMat dst = _dst.getUMat(); if( u == dst.u && dst.offset == offset ) return; if (u->currAllocator == dst.u->currAllocator) { dst.ndoffset(dstofs); dstofs[dims-1] *= esz; u->currAllocator->copy(u, dst.u, dims, sz, srcofs, step.p, dstofs, dst.step.p, false); return; } } Mat dst = _dst.getMat(); u->currAllocator->download(u, dst.data, dims, sz, srcofs, step.p, dst.step.p); }
static bool openvx_harris(Mat image, OutputArray _corners, int _maxCorners, double _qualityLevel, double _minDistance, int _blockSize, int _gradientSize, double _harrisK) { using namespace ivx; if(image.type() != CV_8UC1) return false; //OpenVX implementations don't have to provide other sizes if(!(_blockSize == 3 || _blockSize == 5 || _blockSize == 7)) return false; try { Context context = ovx::getOpenVXContext(); Image ovxImage = Image::createFromHandle(context, Image::matTypeToFormat(image.type()), Image::createAddressing(image), image.data); //The minimum threshold which to eliminate Harris Corner scores (computed using the normalized Sobel kernel). //set to 0, we'll filter it later by threshold ivx::Scalar strengthThresh = ivx::Scalar::create<VX_TYPE_FLOAT32>(context, 0); //The gradient window size to use on the input. vx_int32 gradientSize = _gradientSize; //The block window size used to compute the harris corner score vx_int32 blockSize = _blockSize; //The scalar sensitivity threshold k from the Harris-Stephens equation ivx::Scalar sensivity = ivx::Scalar::create<VX_TYPE_FLOAT32>(context, _harrisK); //The radial Euclidean distance for non-maximum suppression ivx::Scalar minDistance = ivx::Scalar::create<VX_TYPE_FLOAT32>(context, _minDistance); vx_size capacity = image.cols * image.rows; Array corners = Array::create(context, VX_TYPE_KEYPOINT, capacity); ivx::Scalar numCorners = ivx::Scalar::create<VX_TYPE_SIZE>(context, 0); IVX_CHECK_STATUS(vxuHarrisCorners(context, ovxImage, strengthThresh, minDistance, sensivity, gradientSize, blockSize, corners, numCorners)); std::vector<vx_keypoint_t> vxKeypoints; corners.copyTo(vxKeypoints); std::sort(vxKeypoints.begin(), vxKeypoints.end(), VxKeypointsComparator()); vx_float32 maxStrength = 0.0f; if(vxKeypoints.size() > 0) maxStrength = vxKeypoints[0].strength; size_t maxKeypoints = min((size_t)_maxCorners, vxKeypoints.size()); std::vector<Point2f> keypoints; keypoints.reserve(maxKeypoints); for(size_t i = 0; i < maxKeypoints; i++) { vx_keypoint_t kp = vxKeypoints[i]; if(kp.strength < maxStrength*_qualityLevel) break; keypoints.push_back(Point2f((float)kp.x, (float)kp.y)); } Mat(keypoints).convertTo(_corners, _corners.fixedType() ? _corners.type() : CV_32F); #ifdef VX_VERSION_1_1 //we should take user memory back before release //(it's not done automatically according to standard) ovxImage.swapHandle(); #endif } catch (RuntimeError & e) { VX_DbgThrow(e.what()); } catch (WrapperError & e) { VX_DbgThrow(e.what()); } return true; }
void compute(InputArray leftarr, InputArray rightarr, OutputArray disparr) { int dtype = disparr.fixedType() ? disparr.type() : params.dispType; Size leftsize = leftarr.size(); if (leftarr.size() != rightarr.size()) CV_Error(Error::StsUnmatchedSizes, "All the images must have the same size"); if (leftarr.type() != CV_8UC1 || rightarr.type() != CV_8UC1) CV_Error(Error::StsUnsupportedFormat, "Both input images must have CV_8UC1"); if (dtype != CV_16SC1 && dtype != CV_32FC1) CV_Error(Error::StsUnsupportedFormat, "Disparity image must have CV_16SC1 or CV_32FC1 format"); if (params.preFilterType != PREFILTER_NORMALIZED_RESPONSE && params.preFilterType != PREFILTER_XSOBEL) CV_Error(Error::StsOutOfRange, "preFilterType must be = CV_STEREO_BM_NORMALIZED_RESPONSE"); if (params.preFilterSize < 5 || params.preFilterSize > 255 || params.preFilterSize % 2 == 0) CV_Error(Error::StsOutOfRange, "preFilterSize must be odd and be within 5..255"); if (params.preFilterCap < 1 || params.preFilterCap > 63) CV_Error(Error::StsOutOfRange, "preFilterCap must be within 1..63"); if (params.kernelSize < 5 || params.kernelSize > 255 || params.kernelSize % 2 == 0 || params.kernelSize >= std::min(leftsize.width, leftsize.height)) CV_Error(Error::StsOutOfRange, "kernelSize must be odd, be within 5..255 and be not larger than image width or height"); if (params.numDisparities <= 0 || params.numDisparities % 16 != 0) CV_Error(Error::StsOutOfRange, "numDisparities must be positive and divisble by 16"); if (params.textureThreshold < 0) CV_Error(Error::StsOutOfRange, "texture threshold must be non-negative"); if (params.uniquenessRatio < 0) CV_Error(Error::StsOutOfRange, "uniqueness ratio must be non-negative"); int FILTERED = (params.minDisparity - 1) << DISPARITY_SHIFT; Mat left0 = leftarr.getMat(), right0 = rightarr.getMat(); Mat disp0 = disparr.getMat(); int width = left0.cols; int height = left0.rows; if(previous_size != width * height) { previous_size = width * height; speckleX.create(height,width,CV_32SC4); speckleY.create(height,width,CV_32SC4); puss.create(height,width,CV_32SC4); censusImage[0].create(left0.rows,left0.cols,CV_32SC4); censusImage[1].create(left0.rows,left0.cols,CV_32SC4); partialSumsLR.create(left0.rows + 1,(left0.cols + 1) * (params.numDisparities + 1),CV_16S); agregatedHammingLRCost.create(left0.rows + 1,(left0.cols + 1) * (params.numDisparities + 1),CV_16S); hammingDistance.create(left0.rows, left0.cols * (params.numDisparities + 1),CV_16S); preFilteredImg0.create(left0.size(), CV_8U); preFilteredImg1.create(left0.size(), CV_8U); aux.create(height,width,CV_8UC1); } Mat left = preFilteredImg0, right = preFilteredImg1; int ndisp = params.numDisparities; int wsz = params.kernelSize; int bufSize0 = (int)((ndisp + 2)*sizeof(int)); bufSize0 += (int)((height + wsz + 2)*ndisp*sizeof(int)); bufSize0 += (int)((height + wsz + 2)*sizeof(int)); bufSize0 += (int)((height + wsz + 2)*ndisp*(wsz + 2)*sizeof(uchar) + 256); int bufSize1 = (int)((width + params.preFilterSize + 2) * sizeof(int) + 256); if(params.usePrefilter == true) { uchar *_buf = slidingSumBuf.ptr(); parallel_for_(Range(0, 2), PrefilterInvoker(left0, right0, left, right, _buf, _buf + bufSize1, ¶ms), 1); } else if(params.usePrefilter == false) { left = left0; right = right0; } if(params.kernelType == CV_SPARSE_CENSUS) { censusTransform(left,right,params.kernelSize,censusImage[0],censusImage[1],CV_SPARSE_CENSUS); } else if(params.kernelType == CV_DENSE_CENSUS) { censusTransform(left,right,params.kernelSize,censusImage[0],censusImage[1],CV_SPARSE_CENSUS); } else if(params.kernelType == CV_CS_CENSUS) { symetricCensusTransform(left,right,params.kernelSize,censusImage[0],censusImage[1],CV_CS_CENSUS); } else if(params.kernelType == CV_MODIFIED_CS_CENSUS) { symetricCensusTransform(left,right,params.kernelSize,censusImage[0],censusImage[1],CV_MODIFIED_CS_CENSUS); } else if(params.kernelType == CV_MODIFIED_CENSUS_TRANSFORM) { modifiedCensusTransform(left,right,params.kernelSize,censusImage[0],censusImage[1],CV_MODIFIED_CENSUS_TRANSFORM,0); } else if(params.kernelType == CV_MEAN_VARIATION) { parSumsIntensityImage[0].create(left0.rows, left0.cols,CV_32SC4); parSumsIntensityImage[1].create(left0.rows, left0.cols,CV_32SC4); Integral[0].create(left0.rows,left0.cols,CV_32SC4); Integral[1].create(left0.rows,left0.cols,CV_32SC4); integral(left, parSumsIntensityImage[0],CV_32S); integral(right, parSumsIntensityImage[1],CV_32S); imageMeanKernelSize(parSumsIntensityImage[0], params.kernelSize,Integral[0]); imageMeanKernelSize(parSumsIntensityImage[1], params.kernelSize, Integral[1]); modifiedCensusTransform(left,right,params.kernelSize,censusImage[0],censusImage[1],CV_MEAN_VARIATION,0,Integral[0], Integral[1]); } else if(params.kernelType == CV_STAR_KERNEL) { starCensusTransform(left,right,params.kernelSize,censusImage[0],censusImage[1]); } hammingDistanceBlockMatching(censusImage[0], censusImage[1], hammingDistance); costGathering(hammingDistance, partialSumsLR); blockAgregation(partialSumsLR, params.agregationWindowSize, agregatedHammingLRCost); dispartyMapFormation(agregatedHammingLRCost, disp0, 3); Median1x9Filter<uint8_t>(disp0, aux); Median9x1Filter<uint8_t>(aux,disp0); if(params.regionRemoval == CV_SPECKLE_REMOVAL_AVG_ALGORITHM) { smallRegionRemoval<uint8_t>(disp0,params.speckleWindowSize,disp0); } else if(params.regionRemoval == CV_SPECKLE_REMOVAL_ALGORITHM) { if (params.speckleRange >= 0 && params.speckleWindowSize > 0) filterSpeckles(disp0, FILTERED, params.speckleWindowSize, params.speckleRange, slidingSumBuf); } }
void convexHull( InputArray _points, OutputArray _hull, bool clockwise, bool returnPoints ) { CV_INSTRUMENT_REGION() CV_Assert(_points.getObj() != _hull.getObj()); Mat points = _points.getMat(); int i, total = points.checkVector(2), depth = points.depth(), nout = 0; int miny_ind = 0, maxy_ind = 0; CV_Assert(total >= 0 && (depth == CV_32F || depth == CV_32S)); if( total == 0 ) { _hull.release(); return; } returnPoints = !_hull.fixedType() ? returnPoints : _hull.type() != CV_32S; bool is_float = depth == CV_32F; AutoBuffer<Point*> _pointer(total); AutoBuffer<int> _stack(total + 2), _hullbuf(total); Point** pointer = _pointer; Point2f** pointerf = (Point2f**)pointer; Point* data0 = points.ptr<Point>(); int* stack = _stack; int* hullbuf = _hullbuf; CV_Assert(points.isContinuous()); for( i = 0; i < total; i++ ) pointer[i] = &data0[i]; // sort the point set by x-coordinate, find min and max y if( !is_float ) { std::sort(pointer, pointer + total, CHullCmpPoints<int>()); for( i = 1; i < total; i++ ) { int y = pointer[i]->y; if( pointer[miny_ind]->y > y ) miny_ind = i; if( pointer[maxy_ind]->y < y ) maxy_ind = i; } } else { std::sort(pointerf, pointerf + total, CHullCmpPoints<float>()); for( i = 1; i < total; i++ ) { float y = pointerf[i]->y; if( pointerf[miny_ind]->y > y ) miny_ind = i; if( pointerf[maxy_ind]->y < y ) maxy_ind = i; } } if( pointer[0]->x == pointer[total-1]->x && pointer[0]->y == pointer[total-1]->y ) { hullbuf[nout++] = 0; } else { // upper half int *tl_stack = stack; int tl_count = !is_float ? Sklansky_( pointer, 0, maxy_ind, tl_stack, -1, 1) : Sklansky_( pointerf, 0, maxy_ind, tl_stack, -1, 1); int *tr_stack = stack + tl_count; int tr_count = !is_float ? Sklansky_( pointer, total-1, maxy_ind, tr_stack, -1, -1) : Sklansky_( pointerf, total-1, maxy_ind, tr_stack, -1, -1); // gather upper part of convex hull to output if( !clockwise ) { std::swap( tl_stack, tr_stack ); std::swap( tl_count, tr_count ); } for( i = 0; i < tl_count-1; i++ ) hullbuf[nout++] = int(pointer[tl_stack[i]] - data0); for( i = tr_count - 1; i > 0; i-- ) hullbuf[nout++] = int(pointer[tr_stack[i]] - data0); int stop_idx = tr_count > 2 ? tr_stack[1] : tl_count > 2 ? tl_stack[tl_count - 2] : -1; // lower half int *bl_stack = stack; int bl_count = !is_float ? Sklansky_( pointer, 0, miny_ind, bl_stack, 1, -1) : Sklansky_( pointerf, 0, miny_ind, bl_stack, 1, -1); int *br_stack = stack + bl_count; int br_count = !is_float ? Sklansky_( pointer, total-1, miny_ind, br_stack, 1, 1) : Sklansky_( pointerf, total-1, miny_ind, br_stack, 1, 1); if( clockwise ) { std::swap( bl_stack, br_stack ); std::swap( bl_count, br_count ); } if( stop_idx >= 0 ) { int check_idx = bl_count > 2 ? bl_stack[1] : bl_count + br_count > 2 ? br_stack[2-bl_count] : -1; if( check_idx == stop_idx || (check_idx >= 0 && pointer[check_idx]->x == pointer[stop_idx]->x && pointer[check_idx]->y == pointer[stop_idx]->y) ) { // if all the points lie on the same line, then // the bottom part of the convex hull is the mirrored top part // (except the exteme points). bl_count = MIN( bl_count, 2 ); br_count = MIN( br_count, 2 ); } } for( i = 0; i < bl_count-1; i++ ) hullbuf[nout++] = int(pointer[bl_stack[i]] - data0); for( i = br_count-1; i > 0; i-- ) hullbuf[nout++] = int(pointer[br_stack[i]] - data0); } if( !returnPoints ) Mat(nout, 1, CV_32S, hullbuf).copyTo(_hull); else { _hull.create(nout, 1, CV_MAKETYPE(depth, 2)); Mat hull = _hull.getMat(); size_t step = !hull.isContinuous() ? hull.step[0] : sizeof(Point); for( i = 0; i < nout; i++ ) *(Point*)(hull.ptr() + i*step) = data0[hullbuf[i]]; } }
/* dst = src */ void Mat::copyTo( OutputArray _dst ) const { int dtype = _dst.type(); if( _dst.fixedType() && dtype != type() ) { CV_Assert( channels() == CV_MAT_CN(dtype) ); convertTo( _dst, dtype ); return; } if( empty() ) { _dst.release(); return; } if( _dst.isUMat() ) { _dst.create( dims, size.p, type() ); UMat dst = _dst.getUMat(); size_t i, sz[CV_MAX_DIM], dstofs[CV_MAX_DIM], esz = elemSize(); for( i = 0; i < (size_t)dims; i++ ) sz[i] = size.p[i]; sz[dims-1] *= esz; dst.ndoffset(dstofs); dstofs[dims-1] *= esz; dst.u->currAllocator->upload(dst.u, data, dims, sz, dstofs, dst.step.p, step.p); return; } if( dims <= 2 ) { _dst.create( rows, cols, type() ); Mat dst = _dst.getMat(); if( data == dst.data ) return; if( rows > 0 && cols > 0 ) { const uchar* sptr = data; uchar* dptr = dst.data; Size sz = getContinuousSize(*this, dst); size_t len = sz.width*elemSize(); for( ; sz.height--; sptr += step, dptr += dst.step ) memcpy( dptr, sptr, len ); } return; } _dst.create( dims, size, type() ); Mat dst = _dst.getMat(); if( data == dst.data ) return; if( total() != 0 ) { const Mat* arrays[] = { this, &dst }; uchar* ptrs[2]; NAryMatIterator it(arrays, ptrs, 2); size_t sz = it.size*elemSize(); for( size_t i = 0; i < it.nplanes; i++, ++it ) memcpy(ptrs[1], ptrs[0], sz); } }
void cv::goodFeaturesToTrack( InputArray _image, OutputArray _corners, int maxCorners, double qualityLevel, double minDistance, InputArray _mask, int blockSize, bool useHarrisDetector, double harrisK ) { Mat image = _image.getMat(), mask = _mask.getMat(); CV_Assert( qualityLevel > 0 && minDistance >= 0 && maxCorners >= 0 ); CV_Assert( mask.empty() || (mask.type() == CV_8UC1 && mask.size() == image.size()) ); Mat eig, tmp; if( useHarrisDetector ) cornerHarris( image, eig, blockSize, 3, harrisK ); else cornerMinEigenVal( image, eig, blockSize, 3 ); double maxVal = 0; minMaxLoc( eig, 0, &maxVal, 0, 0, mask ); threshold( eig, eig, maxVal*qualityLevel, 0, THRESH_TOZERO ); dilate( eig, tmp, Mat()); Size imgsize = image.size(); vector<const float*> tmpCorners; // collect list of pointers to features - put them into temporary image for( int y = 1; y < imgsize.height - 1; y++ ) { const float* eig_data = (const float*)eig.ptr(y); const float* tmp_data = (const float*)tmp.ptr(y); const uchar* mask_data = mask.data ? mask.ptr(y) : 0; for( int x = 1; x < imgsize.width - 1; x++ ) { float val = eig_data[x]; if( val != 0 && val == tmp_data[x] && (!mask_data || mask_data[x]) ) tmpCorners.push_back(eig_data + x); } } sort( tmpCorners, greaterThanPtr<float>() ); vector<Point2f> corners; size_t i, j, total = tmpCorners.size(), ncorners = 0; if(minDistance >= 1) { // Partition the image into larger grids int w = image.cols; int h = image.rows; const int cell_size = cvRound(minDistance); const int grid_width = (w + cell_size - 1) / cell_size; const int grid_height = (h + cell_size - 1) / cell_size; std::vector<std::vector<Point2f> > grid(grid_width*grid_height); minDistance *= minDistance; for( i = 0; i < total; i++ ) { int ofs = (int)((const uchar*)tmpCorners[i] - eig.data); int y = (int)(ofs / eig.step); int x = (int)((ofs - y*eig.step)/sizeof(float)); bool good = true; int x_cell = x / cell_size; int y_cell = y / cell_size; int x1 = x_cell - 1; int y1 = y_cell - 1; int x2 = x_cell + 1; int y2 = y_cell + 1; // boundary check x1 = std::max(0, x1); y1 = std::max(0, y1); x2 = std::min(grid_width-1, x2); y2 = std::min(grid_height-1, y2); for( int yy = y1; yy <= y2; yy++ ) { for( int xx = x1; xx <= x2; xx++ ) { vector <Point2f> &m = grid[yy*grid_width + xx]; if( m.size() ) { for(j = 0; j < m.size(); j++) { float dx = x - m[j].x; float dy = y - m[j].y; if( dx*dx + dy*dy < minDistance ) { good = false; goto break_out; } } } } } break_out: if(good) { // printf("%d: %d %d -> %d %d, %d, %d -- %d %d %d %d, %d %d, c=%d\n", // i,x, y, x_cell, y_cell, (int)minDistance, cell_size,x1,y1,x2,y2, grid_width,grid_height,c); grid[y_cell*grid_width + x_cell].push_back(Point2f((float)x, (float)y)); corners.push_back(Point2f((float)x, (float)y)); ++ncorners; if( maxCorners > 0 && (int)ncorners == maxCorners ) break; } } } else { for( i = 0; i < total; i++ ) { int ofs = (int)((const uchar*)tmpCorners[i] - eig.data); int y = (int)(ofs / eig.step); int x = (int)((ofs - y*eig.step)/sizeof(float)); corners.push_back(Point2f((float)x, (float)y)); ++ncorners; if( maxCorners > 0 && (int)ncorners == maxCorners ) break; } } Mat(corners).convertTo(_corners, _corners.fixedType() ? _corners.type() : CV_32F); /* for( i = 0; i < total; i++ ) { int ofs = (int)((const uchar*)tmpCorners[i] - eig.data); int y = (int)(ofs / eig.step); int x = (int)((ofs - y*eig.step)/sizeof(float)); if( minDistance > 0 ) { for( j = 0; j < ncorners; j++ ) { float dx = x - corners[j].x; float dy = y - corners[j].y; if( dx*dx + dy*dy < minDistance ) break; } if( j < ncorners ) continue; } corners.push_back(Point2f((float)x, (float)y)); ++ncorners; if( maxCorners > 0 && (int)ncorners == maxCorners ) break; } */ }