Пример #1
0
  float IC_Angle(const Mat& image, const int half_k, Point2f pt,
		 const vector<int> & u_max)
  {
    int m_01 = 0, m_10 = 0;
    
    const uchar* center = &image.at<uchar> (cvRound(pt.y), cvRound(pt.x));
    // Treat the center line differently, v=0                                                                                                               
    for (int u = -half_k; u <= half_k; ++u)
      m_10 += u * center[u];
    
    // Go line by line in the circular patch                                                                                                                
    int step = (int)image.step1();
    for (int v = 1; v <= half_k; ++v)
      {
	// Proceed over the two lines                                                                                                                       
	int v_sum = 0;
	int d = u_max[v];
	for (int u = -d; u <= d; ++u)
	  {
            int val_plus = center[u + v*step], val_minus = center[u - v*step];
            v_sum += (val_plus - val_minus);
            m_10 += u * (val_plus + val_minus);
	  }
        m_01 += v * v_sum;
      }
    
    return fastAtan2((float)m_01, (float)m_10);
  }
Пример #2
0
float Index::getKeyPointOrientation(const Mat& image, const KeyPoint &pnt)
{
    int half_k = ROTATION_PATCH_SIZE/2;
    Point2f pt = pnt.pt;
    
    int m_01 = 0, m_10 = 0;
    
    const uchar* center = image.ptr<uchar> (cvRound(pt.y), cvRound(pt.x));
    
    // Treat the center line differently, v=0
    for (int u = -half_k; u <= half_k; ++u)
        m_10 += u * center[u];
    
    // Go line by line in the circular patch
    int step = (int)image.step1();
    for (int v = 1; v <= half_k; ++v)
    {
        // Proceed over the two lines
        int v_sum = 0;
        int d = u_max[v];
        for (int u = -d; u <= d; ++u)
        {
            int val_plus = center[u + v*step], val_minus = center[u - v*step];
            v_sum += (val_plus - val_minus);
            m_10 += u * (val_plus + val_minus);
        }
        m_01 += v * v_sum;
    }
    
    return fastAtan2((float)m_01, (float)m_10);
}
Пример #3
0
void CControl::FilterLineAngle(vector<Point2f> n_inlinevct,
			       vector<Point2f>& n_outlinevct,float n_angle,
			       float n_threshold)
{
  for(int i=0;i<n_inlinevct.size();i++)
    {
      //get points
      Point2f n_pt1=n_inlinevct.at(i++);
      Point2f n_pt2=n_inlinevct.at(i);
      //cal angle
      float n_dy=n_pt1.y-n_pt2.y;
      float n_dx=n_pt1.x-n_pt2.x;
      float n_angleline=fastAtan2(n_dy,n_dx);
      if(IsAligned(n_angle,n_angleline,n_threshold))
	{
	  //add to out linevct
	  n_outlinevct.push_back(n_pt1);
	  n_outlinevct.push_back(n_pt2);
	}
    }
}
Пример #4
0
void cv::calcMotionGradient( InputArray _mhi, OutputArray _mask,
                             OutputArray _orientation,
                             double delta1, double delta2,
                             int aperture_size )
{
    static int runcase = 0; runcase++;

    Mat mhi = _mhi.getMat();
    Size size = mhi.size();

    _mask.create(size, CV_8U);
    _orientation.create(size, CV_32F);

    Mat mask = _mask.getMat();
    Mat orient = _orientation.getMat();

    if( aperture_size < 3 || aperture_size > 7 || (aperture_size & 1) == 0 )
        CV_Error( Error::StsOutOfRange, "aperture_size must be 3, 5 or 7" );

    if( delta1 <= 0 || delta2 <= 0 )
        CV_Error( Error::StsOutOfRange, "both delta's must be positive" );

    if( mhi.type() != CV_32FC1 )
        CV_Error( Error::StsUnsupportedFormat,
                 "MHI must be single-channel floating-point images" );

    if( orient.data == mhi.data )
    {
        _orientation.release();
        _orientation.create(size, CV_32F);
        orient = _orientation.getMat();
    }

    if( delta1 > delta2 )
        std::swap(delta1, delta2);

    float gradient_epsilon = 1e-4f * aperture_size * aperture_size;
    float min_delta = (float)delta1;
    float max_delta = (float)delta2;

    Mat dX_min, dY_max;

    // calc Dx and Dy
    Sobel( mhi, dX_min, CV_32F, 1, 0, aperture_size, 1, 0, BORDER_REPLICATE );
    Sobel( mhi, dY_max, CV_32F, 0, 1, aperture_size, 1, 0, BORDER_REPLICATE );

    int x, y;

    if( mhi.isContinuous() && orient.isContinuous() && mask.isContinuous() )
    {
        size.width *= size.height;
        size.height = 1;
    }

    // calc gradient
    for( y = 0; y < size.height; y++ )
    {
        const float* dX_min_row = dX_min.ptr<float>(y);
        const float* dY_max_row = dY_max.ptr<float>(y);
        float* orient_row = orient.ptr<float>(y);
        uchar* mask_row = mask.ptr<uchar>(y);

        fastAtan2(dY_max_row, dX_min_row, orient_row, size.width, true);

        // make orientation zero where the gradient is very small
        for( x = 0; x < size.width; x++ )
        {
            float dY = dY_max_row[x];
            float dX = dX_min_row[x];

            if( std::abs(dX) < gradient_epsilon && std::abs(dY) < gradient_epsilon )
            {
                mask_row[x] = (uchar)0;
                orient_row[x] = 0.f;
            }
            else
                mask_row[x] = (uchar)1;
        }
    }

    erode( mhi, dX_min, noArray(), Point(-1,-1), (aperture_size-1)/2, BORDER_REPLICATE );
    dilate( mhi, dY_max, noArray(), Point(-1,-1), (aperture_size-1)/2, BORDER_REPLICATE );

    // mask off pixels which have little motion difference in their neighborhood
    for( y = 0; y < size.height; y++ )
    {
        const float* dX_min_row = dX_min.ptr<float>(y);
        const float* dY_max_row = dY_max.ptr<float>(y);
        float* orient_row = orient.ptr<float>(y);
        uchar* mask_row = mask.ptr<uchar>(y);

        for( x = 0; x < size.width; x++ )
        {
            float d0 = dY_max_row[x] - dX_min_row[x];

            if( mask_row[x] == 0 || d0 < min_delta || max_delta < d0 )
            {
                mask_row[x] = (uchar)0;
                orient_row[x] = 0.f;
            }
        }
    }
}
Пример #5
0
	// Compute single tracking score
	TrackingScore* TrackingEvaluator::computeScore(const TrackedObject& tracked_object, const Mat& frame, int frame_number, TrackingScoreHistory *history)
	{
		// Create score
		TrackingScore* score = new TrackingScore(&nbc);
		// Add score to history
		history->addScore(score, frame_number);
		// Get blob
		const cvb::CvBlob& orig_blob = tracked_object.currentRegion();
		// Random move blobs - to test certainties
		cvb::CvBlob blob;
		cvCloneBlob(orig_blob, blob);
		// Save shape ratio
		score->setShapeRatio(((float)blob.width())/((float)blob.height()));
		// Save area
		score->setArea(blob.width()*blob.height());
		// Compute object's binary mask, for the histogram
		Mat mask = drawBlob(blob, true, frame.cols, frame.rows);
		// Get grayscale frame
		Mat frame_gs;
		cvtColor(frame, frame_gs, CV_BGR2GRAY);
		// Split the color channels
		Mat* channels = new Mat[3];
		split(frame, channels);
		Mat frame_b = channels[0];
		Mat frame_g = channels[1];
		Mat frame_r = channels[2];
		delete [] channels;
		// Compute histograms
		Histogram hist_gs(frame_gs, mask);
		Histogram hist_r(frame_r, mask);
		Histogram hist_g(frame_g, mask);
		Histogram hist_b(frame_b, mask);
		// Save histogram
		score->setHistograms(hist_gs, hist_r, hist_g, hist_b);
		// Select part of frame on which to compute the texture features
		Mat copy_gs = frame_gs.clone();
		// Blacken non-mask pixels
		for(unsigned int x=blob.x; x<=blob.maxx; x++)
		{
			for(unsigned int y=blob.y; y<=blob.maxy; y++)
			{
				if(mask.at<uchar>(y,x) == 0)
				{
					copy_gs.at<uchar>(y,x) = 0;
				}
			}
		}
		// Crop image
		Rect region(blob.x, blob.y, blob.width(), blob.height());
		Mat texture_input = copy_gs(region);
		// Compute texture features for this object
		vector<float> texture_features = GaborFilter::applyFilterSet(texture_input, gabor_scales, parameters.get<int>("num_orientations"), false, 1, 0.5, 101);
		// Save texture features
		score->setTextureFeatures(texture_features);
		// Set temporal score to the number of appearances
		score->temporal_score = history->numScores();
		// Get the frame number of the previous detection of this object, if available
		int prev_frame = -1;
		TrackingScore* prev_score = NULL;
		cvb::CvBlob prev_blob;
		if(history->numScores() > 1)
		{
			// Read frame number
			prev_frame = *(tracked_object.frameList().end() - 2);
			// Get previous score
			prev_score = (TrackingScore*) history->getScore(prev_frame);
			// Get previous blob
			prev_blob = *(tracked_object.regionList().end() - 2);
			// Compute shape ratio score
			score->shape_ratio_score = computeShapeRatioScore(prev_score->getShapeRatio(), score->getShapeRatio());
			// Compute area score
			score->area_score = computeAreaScore(prev_score->getArea(), score->getArea());
			// Compute histogram difference score
			score->histogram_diff_score = computeHistogramDiffScore(score, prev_score);
			// Compute texture difference score
			score->texture_diff_score = computeTextureDiffScore(score->getTextureFeatures(), prev_score->getTextureFeatures());
			// Compute velocity for this score
			Point2f prev_position((prev_blob.maxx+prev_blob.x)/2, (prev_blob.maxy+prev_blob.y)/2);
			Point2f curr_position((blob.maxx+blob.x)/2, (blob.maxy+blob.y)/2);
			float velocity = sqrt((prev_position.x-curr_position.x)*(prev_position.x-curr_position.x) + (prev_position.y-curr_position.y)*(prev_position.y-curr_position.y));
			score->setVelocity(velocity);
			// Add velocity to the accumulated velocity for this object (will be used to compute an average according to the number of detections)
			history->accumulateVelocity(velocity);
			// Check if the previous score has its velocity set
			if(prev_score->getVelocity() > 0)
			{
				//cout << "computing ms: " << score->getVelocity() << ", " << history->getAverageVelocity() << endl;
				// Compute motion smoothness score, based on current velocity and average velocity
				score->motion_smoothness = computeMotionSmoothnessScore(score->getVelocity(), history->getAverageVelocity());
			}
			else
			{
				// Set score to 0
				score->motion_smoothness = 0.0f;
				// Mark score as not full
				score->full = false;
			}
			// Compute direction for this score
			float direction = fastAtan2(-curr_position.y + prev_position.y, curr_position.x - prev_position.x);
			score->setDirection(direction);
			// Check if the previous score has its direction set
			//cout << "direction: " << direction << ", prev_score direction: " << prev_score->getDirection() << endl;
			if(prev_score->getDirection() > 0)
			{
				//cout << "computing d : " << prev_score->getDirection() << ", " << score->getDirection() << endl;
				// Compute direction score, based on current direction and previous direction
				score->direction_score = computeDirectionScore(score->getDirection(), prev_score->getDirection());
			}
			else
			{
				// Set score to 0
				score->direction_score = 0.0f;
				// Mark score as not full
				score->full = false;
			}
			//if(score->full)// && (frame_number % 10) == 0)
			//{
			//	out_file << score->shape_ratio_score << " " << score->area_score << " " << score->histogram_diff_score << " " << score->motion_smoothness << " " << score->direction_score << " " << score->texture_diff_score << " 1" << endl;
			//	cout << score->shape_ratio_score << " " << score->area_score << " " << score->histogram_diff_score << " " << score->motion_smoothness << " " << score->direction_score << " " << score->texture_diff_score << " 1" << endl;
			//}
			//out_file << score->shape_ratio_score << " " << score->histogram_diff_score << " 1";
			//if(pd)
			//	out_file << score->value() << endl;
		}
		else
		{
			// Set score as certain
			score->certain = true;
		}
		Log::debug() << "tracking score: " << score->value() << "(" << score->shape_ratio_score << ", " << score->area_score << ", " << score->histogram_diff_score << ", " << (score->full ? score->motion_smoothness : -1) << ", " << (score->full ? score->direction_score : -1 ) << ", " << score->texture_diff_score << ")" << endl;
		// Return score
		return score;
	}
Пример #6
0
static void calcSIFTDescriptor( const Mat& img, Point2f ptf, float ori, float scl,
                               int d, int n, float* dst )
{
    Point pt(cvRound(ptf.x), cvRound(ptf.y));
    float cos_t = cosf(ori*(float)(CV_PI/180));
    float sin_t = sinf(ori*(float)(CV_PI/180));
    float bins_per_rad = n / 360.f;
    float exp_scale = -1.f/(d * d * 0.5f);
    float hist_width = SIFT_DESCR_SCL_FCTR * scl;
    int radius = cvRound(hist_width * 1.4142135623730951f * (d + 1) * 0.5f);
    // Clip the radius to the diagonal of the image to avoid autobuffer too large exception
    radius = std::min(radius, (int) sqrt((double) img.cols*img.cols + img.rows*img.rows));
    cos_t /= hist_width;
    sin_t /= hist_width;

    int i, j, k, len = (radius*2+1)*(radius*2+1), histlen = (d+2)*(d+2)*(n+2);
    int rows = img.rows, cols = img.cols;

    AutoBuffer<float> buf(len*6 + histlen);
    float *X = buf, *Y = X + len, *Mag = Y, *Ori = Mag + len, *W = Ori + len;
    float *RBin = W + len, *CBin = RBin + len, *hist = CBin + len;

    for( i = 0; i < d+2; i++ )
    {
        for( j = 0; j < d+2; j++ )
            for( k = 0; k < n+2; k++ )
                hist[(i*(d+2) + j)*(n+2) + k] = 0.;
    }

    for( i = -radius, k = 0; i <= radius; i++ )
        for( j = -radius; j <= radius; j++ )
        {
            // Calculate sample's histogram array coords rotated relative to ori.
            // Subtract 0.5 so samples that fall e.g. in the center of row 1 (i.e.
            // r_rot = 1.5) have full weight placed in row 1 after interpolation.
            float c_rot = j * cos_t - i * sin_t;
            float r_rot = j * sin_t + i * cos_t;
            float rbin = r_rot + d/2 - 0.5f;
            float cbin = c_rot + d/2 - 0.5f;
            int r = pt.y + i, c = pt.x + j;

            if( rbin > -1 && rbin < d && cbin > -1 && cbin < d &&
                r > 0 && r < rows - 1 && c > 0 && c < cols - 1 )
            {
                float dx = (float)(img.at<sift_wt>(r, c+1) - img.at<sift_wt>(r, c-1));
                float dy = (float)(img.at<sift_wt>(r-1, c) - img.at<sift_wt>(r+1, c));
                X[k] = dx; Y[k] = dy; RBin[k] = rbin; CBin[k] = cbin;
                W[k] = (c_rot * c_rot + r_rot * r_rot)*exp_scale;
                k++;
            }
        }

    len = k;
    fastAtan2(Y, X, Ori, len, true);
    magnitude(X, Y, Mag, len);
    exp(W, W, len);

    for( k = 0; k < len; k++ )
    {
        float rbin = RBin[k], cbin = CBin[k];
        float obin = (Ori[k] - ori)*bins_per_rad;
        float mag = Mag[k]*W[k];

        int r0 = cvFloor( rbin );
        int c0 = cvFloor( cbin );
        int o0 = cvFloor( obin );
        rbin -= r0;
        cbin -= c0;
        obin -= o0;

        if( o0 < 0 )
            o0 += n;
        if( o0 >= n )
            o0 -= n;

        // histogram update using tri-linear interpolation
        float v_r1 = mag*rbin, v_r0 = mag - v_r1;
        float v_rc11 = v_r1*cbin, v_rc10 = v_r1 - v_rc11;
        float v_rc01 = v_r0*cbin, v_rc00 = v_r0 - v_rc01;
        float v_rco111 = v_rc11*obin, v_rco110 = v_rc11 - v_rco111;
        float v_rco101 = v_rc10*obin, v_rco100 = v_rc10 - v_rco101;
        float v_rco011 = v_rc01*obin, v_rco010 = v_rc01 - v_rco011;
        float v_rco001 = v_rc00*obin, v_rco000 = v_rc00 - v_rco001;

        int idx = ((r0+1)*(d+2) + c0+1)*(n+2) + o0;
        hist[idx] += v_rco000;
        hist[idx+1] += v_rco001;
        hist[idx+(n+2)] += v_rco010;
        hist[idx+(n+3)] += v_rco011;
        hist[idx+(d+2)*(n+2)] += v_rco100;
        hist[idx+(d+2)*(n+2)+1] += v_rco101;
        hist[idx+(d+3)*(n+2)] += v_rco110;
        hist[idx+(d+3)*(n+2)+1] += v_rco111;
    }

    // finalize histogram, since the orientation histograms are circular
    for( i = 0; i < d; i++ )
        for( j = 0; j < d; j++ )
        {
            int idx = ((i+1)*(d+2) + (j+1))*(n+2);
            hist[idx] += hist[idx+n];
            hist[idx+1] += hist[idx+n+1];
            for( k = 0; k < n; k++ )
                dst[(i*d + j)*n + k] = hist[idx+k];
        }
    // copy histogram to the descriptor,
    // apply hysteresis thresholding
    // and scale the result, so that it can be easily converted
    // to byte array
    float nrm2 = 0;
    len = d*d*n;
    for( k = 0; k < len; k++ )
        nrm2 += dst[k]*dst[k];
    float thr = std::sqrt(nrm2)*SIFT_DESCR_MAG_THR;
    for( i = 0, nrm2 = 0; i < k; i++ )
    {
        float val = std::min(dst[i], thr);
        dst[i] = val;
        nrm2 += val*val;
    }
    nrm2 = SIFT_INT_DESCR_FCTR/std::max(std::sqrt(nrm2), FLT_EPSILON);

#if 1
    for( k = 0; k < len; k++ )
    {
        dst[k] = saturate_cast<uchar>(dst[k]*nrm2);
    }
#else
    float nrm1 = 0;
    for( k = 0; k < len; k++ )
    {
        dst[k] *= nrm2;
        nrm1 += dst[k];
    }
    nrm1 = 1.f/std::max(nrm1, FLT_EPSILON);
    for( k = 0; k < len; k++ )
    {
        dst[k] = std::sqrt(dst[k] * nrm1);//saturate_cast<uchar>(std::sqrt(dst[k] * nrm1)*SIFT_INT_DESCR_FCTR);
    }
#endif
}
Пример #7
0
// Computes a gradient orientation histogram at a specified pixel
static float calcOrientationHist( const Mat& img, Point pt, int radius,
                                  float sigma, float* hist, int n )
{
    int i, j, k, len = (radius*2+1)*(radius*2+1);

    float expf_scale = -1.f/(2.f * sigma * sigma);
    AutoBuffer<float> buf(len*4 + n+4);
    float *X = buf, *Y = X + len, *Mag = X, *Ori = Y + len, *W = Ori + len;
    float* temphist = W + len + 2;

    for( i = 0; i < n; i++ )
        temphist[i] = 0.f;

    for( i = -radius, k = 0; i <= radius; i++ )
    {
        int y = pt.y + i;
        if( y <= 0 || y >= img.rows - 1 )
            continue;
        for( j = -radius; j <= radius; j++ )
        {
            int x = pt.x + j;
            if( x <= 0 || x >= img.cols - 1 )
                continue;

            float dx = (float)(img.at<sift_wt>(y, x+1) - img.at<sift_wt>(y, x-1));
            float dy = (float)(img.at<sift_wt>(y-1, x) - img.at<sift_wt>(y+1, x));

            X[k] = dx; Y[k] = dy; W[k] = (i*i + j*j)*expf_scale;
            k++;
        }
    }

    len = k;

    // compute gradient values, orientations and the weights over the pixel neighborhood
    exp(W, W, len);
    fastAtan2(Y, X, Ori, len, true);
    magnitude(X, Y, Mag, len);

    for( k = 0; k < len; k++ )
    {
        int bin = cvRound((n/360.f)*Ori[k]);
        if( bin >= n )
            bin -= n;
        if( bin < 0 )
            bin += n;
        temphist[bin] += W[k]*Mag[k];
    }

    // smooth the histogram
    temphist[-1] = temphist[n-1];
    temphist[-2] = temphist[n-2];
    temphist[n] = temphist[0];
    temphist[n+1] = temphist[1];
    for( i = 0; i < n; i++ )
    {
        hist[i] = (temphist[i-2] + temphist[i+2])*(1.f/16.f) +
            (temphist[i-1] + temphist[i+1])*(4.f/16.f) +
            temphist[i]*(6.f/16.f);
    }

    float maxval = hist[0];
    for( i = 1; i < n; i++ )
        maxval = std::max(maxval, hist[i]);

    return maxval;
}