/** * @brief Is Camshift Tracker updated or not? * @param img * @param obj * @param hist * @return bool, whether Camshift tracker has been updated or not */ bool CTrackingAlgs::CamshiftUpdateTracker( const cv::Mat& img, const cv::Rect& obj, cv::MatND& hist) { cv::Mat hsv, hue, mask, backproject; cv::cvtColor( img, hsv, CV_BGR2HSV ); int _vmin = CTrackingAlgs::vmin, _vmax = CTrackingAlgs::vmax; cv::inRange( hsv, cv::Scalar(0,CTrackingAlgs::smin,MIN(_vmin,_vmax),0), cv::Scalar(180,256,MAX(_vmin,_vmax),0), mask ); std::vector<cv::Mat> vhsv(3); cv::split( hsv, vhsv ); vhsv[0].copyTo(hue); double max_val = 0.f; cv::Mat roi = hue( cv::Range(obj.y, obj.y+obj.height), cv::Range(obj.x, obj.x+obj.width) ); cv::Mat roi_mask= mask( cv::Range(obj.y, obj.y+obj.height), cv::Range(obj.x, obj.x+obj.width) ); cv::calcHist( &roi, 1, CTrackingAlgs::channels, roi_mask, hist, 1, CTrackingAlgs::histSize, CTrackingAlgs::ranges, true, // the histogram is uniform false ); cv::minMaxLoc(hist, 0, &max_val, 0, 0); hist.convertTo(hist, hist.type(), (max_val ? 255. / max_val : 0.), 0); return true; }
/** * Convert cv::MatND to MxArray * @param mat cv::MatND object * @param classid classid of mxArray. e.g., mxDOUBLE_CLASS. When mxUNKNOWN_CLASS * is specified, classid will be automatically determined from * the type of cv::Mat. default: mxUNKNOWN_CLASS * @return MxArray object */ MxArray::MxArray(const cv::MatND& mat, mxClassID classid) { if (mat.datastart==mat.dataend) { p_ = mxCreateNumericArray(0,0,mxDOUBLE_CLASS,mxREAL); return; } // Create a new mxArray int nchannels = mat.channels(); const int* dims_ = mat.size; vector<mwSize> d(dims_,dims_+mat.dims); d.push_back(nchannels); classid = (classid == mxUNKNOWN_CLASS) ? ClassIDOf[mat.depth()] : classid; std::swap(d[0],d[1]); p_ = mxCreateNumericArray(d.size(),&d[0],classid,mxREAL); if (!p_) mexErrMsgIdAndTxt("mexopencv:error","Allocation error"); // Copy int depth = CV_MAKETYPE(DepthOf[classid],1); cv::MatND m(mat.dims,mat.size,CV_MAKETYPE(depth,1)); uchar* _data = m.data; uchar* _datastart = m.datastart; uchar* _dataend = m.dataend; m.data = m.datastart = reinterpret_cast<uchar*>(mxGetData(p_)); m.dataend = reinterpret_cast<uchar*>( reinterpret_cast<size_t>(mxGetData(p_))+mxGetElementSize(p_)*numel()); mat.convertTo(m,CV_MAKETYPE(depth,1)); m.data = _data; m.datastart = _datastart; m.dataend = _dataend; }
cv::MatND MxArray::toMatND(int depth, bool transpose) const { // Create cv::MatND object (of the specified depth), equivalent to mxArray std::vector<int> d(dims(), dims()+ndims()); std::swap(d[0], d[1]); depth = (depth == CV_USRTYPE1) ? DepthOf[classID()] : depth; cv::MatND mat(d.size(), &d[0], CV_MAKETYPE(depth, 1)); // Copy from mxArray to cv::MatND (converting to specified depth) const int type = CV_MAKETYPE(DepthOf[classID()], 1); // source type const cv::MatND m(d.size(), &d[0], type, mxGetData(p_)); // only Mat header // Read from mxArray through m, writing into mat m.convertTo(mat, CV_MAKETYPE(depth, 1)); // transpose cv::MatND if needed if (mat.dims==2 && transpose) mat = mat.t(); return mat; }